Files
boc/quixzoom-capture-pipeline/pilot/ontology-validation.js
T

354 lines
11 KiB
JavaScript
Raw Normal View History

/**
* Urban Ontology Validation
*
* Testar om relationerna ger nytta med verkliga observationer.
*
* Exempel:
* - Om ett elskåp markeras som ur funktion vilka objekt påverkas?
* - Om en gatlykta försvinner vilka vägavsnitt tappar belysning?
* - Om ett träd växer vilka skyltar riskerar att skymmas?
*/
const UrbanOntology = require('../urban-ontology/ontology');
class OntologyValidation {
constructor() {
this.ontology = new UrbanOntology();
this.results = [];
}
/**
* ============================================================
* TEST 1: Power Failure Impact
* ============================================================
*/
testPowerFailure() {
console.log('\n=== TEST 1: Power Failure Impact ===\n');
// Skapa scenario: Elskåp EC-001 går sönder
const cabinetId = 'cabinet_sukhumvit_001';
// Lägg till relationer
this.ontology.addRelation(cabinetId, 'lamp_sukhumvit_001', 'powers', {
voltage: 230,
capacity: 1000,
});
this.ontology.addRelation(cabinetId, 'lamp_sukhumvit_002', 'powers', {
voltage: 230,
capacity: 1000,
});
this.ontology.addRelation(cabinetId, 'lamp_sukhumvit_003', 'powers', {
voltage: 230,
capacity: 1000,
});
this.ontology.addRelation('lamp_sukhumvit_001', 'road_sukhumvit_001', 'illuminates', {
intensity: 50,
coverage: 10,
});
this.ontology.addRelation('lamp_sukhumvit_002', 'road_sukhumvit_002', 'illuminates', {
intensity: 50,
coverage: 10,
});
// Kör impact analysis
const impact = this.ontology.impactAnalysis(cabinetId, 'power');
console.log(`Source: ${impact.source}`);
console.log(`Failure type: ${impact.failureType}`);
console.log(`Impacted objects: ${impact.impactCount}`);
console.log(`Objects: ${impact.impactedObjects.join(', ')}`);
// Validering
const expectedImpacted = 4; // 3 lamps + 2 roads (via illuminates)
const passed = impact.impactCount >= 3; // Minst 3 lampor
this.results.push({
test: 'Power Failure Impact',
passed,
impactCount: impact.impactCount,
expectedMin: 3,
});
console.log(`\nResult: ${passed ? 'PASS' : 'FAIL'}`);
console.log(`Expected: At least 3 impacted objects`);
console.log(`Actual: ${impact.impactCount} impacted objects`);
return impact;
}
/**
* ============================================================
* TEST 2: Street Lamp Outage
* ============================================================
*/
testStreetLampOutage() {
console.log('\n=== TEST 2: Street Lamp Outage ===\n');
// Scenario: Gatlykta SL-042 släcks
const lampId = 'lamp_sukhumvit_042';
// Lägg till relationer
this.ontology.addRelation(lampId, 'road_sukhumvit_042', 'illuminates', {
intensity: 50,
coverage: 15,
});
this.ontology.addRelation(lampId, 'crosswalk_sukhumvit_042', 'illuminates', {
intensity: 30,
coverage: 5,
});
this.ontology.addRelation('traffic_light_sukhumvit_042', 'crosswalk_sukhumvit_042', 'regulates', {
regulationType: 'pedestrian_crossing',
});
// Kör impact analysis
const impact = this.ontology.impactAnalysis(lampId, 'lighting');
console.log(`Source: ${impact.source}`);
console.log(`Failure type: ${impact.failureType}`);
console.log(`Impacted objects: ${impact.impactCount}`);
console.log(`Objects: ${impact.impactedObjects.join(', ')}`);
// Validering
const hasRoad = impact.impactedObjects.some(id => id.includes('road'));
const hasCrosswalk = impact.impactedObjects.some(id => id.includes('crosswalk'));
const passed = hasRoad && hasCrosswalk;
this.results.push({
test: 'Street Lamp Outage',
passed,
hasRoad,
hasCrosswalk,
});
console.log(`\nResult: ${passed ? 'PASS' : 'FAIL'}`);
console.log(`Road impacted: ${hasRoad}`);
console.log(`Crosswalk impacted: ${hasCrosswalk}`);
return impact;
}
/**
* ============================================================
* TEST 3: Tree Growth Risk
* ============================================================
*/
testTreeGrowthRisk() {
console.log('\n=== TEST 3: Tree Growth Risk ===\n');
// Scenario: Träd växer och riskerar skymma skylt
const treeId = 'tree_sukhumvit_017';
// Lägg till relationer
this.ontology.addRelation(treeId, 'sign_sukhumvit_017', 'may_obscure', {
currentObscuration: 0.3,
growthRate: 0.5, // meters/year
projectedObscuration: 0.85,
});
this.ontology.addRelation(treeId, 'sign_sukhumvit_018', 'may_obscure', {
currentObscuration: 0.1,
growthRate: 0.3,
projectedObscuration: 0.45,
});
// Kör growth risk analysis
const risk = this.ontology.growthRiskAnalysis(treeId, 5);
console.log(`Vegetation: ${risk.vegetationId}`);
console.log(`Time horizon: ${risk.timeHorizonYears} years`);
console.log(`High risk count: ${risk.highRiskCount}`);
console.log('\nRisks:');
risk.risks.forEach(r => {
console.log(` ${r.targetId}: ${r.riskLevel}`);
console.log(` Current: ${r.currentObscuration}`);
console.log(` Projected: ${r.projectedObscuration}`);
console.log(` Action: ${r.recommendedAction}`);
});
// Validering
const hasHighRisk = risk.highRiskCount > 0;
const hasAction = risk.risks.some(r => r.recommendedAction.includes('Prune'));
const passed = hasHighRisk && hasAction;
this.results.push({
test: 'Tree Growth Risk',
passed,
highRiskCount: risk.highRiskCount,
hasAction,
});
console.log(`\nResult: ${passed ? 'PASS' : 'FAIL'}`);
console.log(`High risk found: ${hasHighRisk}`);
console.log(`Action recommended: ${hasAction}`);
return risk;
}
/**
* ============================================================
* TEST 4: Path Analysis
* ============================================================
*/
testPathAnalysis() {
console.log('\n=== TEST 4: Path Analysis ===\n');
// Scenario: Hitta väg från elskåp till väg
const cabinetId = 'cabinet_sukhumvit_001';
const roadId = 'road_sukhumvit_001';
// Kör path analysis
const path = this.ontology.findPath(cabinetId, roadId, 5);
console.log(`From: ${cabinetId}`);
console.log(`To: ${roadId}`);
console.log(`Found: ${path.found}`);
console.log(`Length: ${path.length}`);
if (path.found) {
console.log('\nPath:');
path.path.forEach((step, i) => {
console.log(` Step ${i + 1}: ${step.objectId} via ${step.relation?.type || 'direct'}`);
});
}
// Validering
const passed = path.found && path.length > 0;
this.results.push({
test: 'Path Analysis',
passed,
pathLength: path.length,
found: path.found,
});
console.log(`\nResult: ${passed ? 'PASS' : 'FAIL'}`);
console.log(`Path found: ${path.found}`);
console.log(`Path length: ${path.length}`);
return path;
}
/**
* ============================================================
* TEST 5: Network Analysis
* ============================================================
*/
testNetworkAnalysis() {
console.log('\n=== TEST 5: Network Analysis ===\n');
// Scenario: Hitta alla objekt i nätverket runt elskåp
const cabinetId = 'cabinet_sukhumvit_001';
// Kör network analysis
const network = this.ontology.networkAnalysis(cabinetId, { maxDepth: 3 });
console.log(`Seed: ${network.seedObjectId}`);
console.log(`Network size: ${network.networkSize}`);
console.log(`Objects: ${network.objects.join(', ')}`);
// Validering
const hasLamps = network.objects.some(id => id.includes('lamp'));
const hasRoads = network.objects.some(id => id.includes('road'));
const passed = hasLamps && hasRoads;
this.results.push({
test: 'Network Analysis',
passed,
networkSize: network.networkSize,
hasLamps,
hasRoads,
});
console.log(`\nResult: ${passed ? 'PASS' : 'FAIL'}`);
console.log(`Network size: ${network.networkSize}`);
console.log(`Has lamps: ${hasLamps}`);
console.log(`Has roads: ${hasRoads}`);
return network;
}
/**
* ============================================================
* SUMMARY
* ============================================================
*/
generateReport() {
console.log('\n╔════════════════════════════════════════════════════════════╗');
console.log('║ ONTOLOGY VALIDATION REPORT ║');
console.log('╚════════════════════════════════════════════════════════════╝\n');
const passed = this.results.filter(r => r.passed).length;
const total = this.results.length;
console.log(`Tests run: ${total}`);
console.log(`Passed: ${passed}`);
console.log(`Failed: ${total - passed}`);
console.log(`Success rate: ${(passed / total * 100).toFixed(1)}%\n`);
console.log('Detailed Results:');
this.results.forEach((result, i) => {
console.log(`\n${i + 1}. ${result.test}`);
console.log(` Status: ${result.passed ? 'PASS' : 'FAIL'}`);
if (result.impactCount !== undefined) {
console.log(` Impact count: ${result.impactCount}`);
}
if (result.highRiskCount !== undefined) {
console.log(` High risk count: ${result.highRiskCount}`);
}
if (result.pathLength !== undefined) {
console.log(` Path length: ${result.pathLength}`);
}
if (result.networkSize !== undefined) {
console.log(` Network size: ${result.networkSize}`);
}
});
console.log('\n' + '='.repeat(60));
console.log(`OVERALL: ${passed === total ? 'ALL TESTS PASSED' : 'SOME TESTS FAILED'}`);
console.log('='.repeat(60));
return {
total,
passed,
failed: total - passed,
successRate: passed / total,
results: this.results,
};
}
}
// Run validation
if (require.main === module) {
const validation = new OntologyValidation();
console.log('╔════════════════════════════════════════════════════════════╗');
console.log('║ URBAN ONTOLOGY VALIDATION ║');
console.log('╚════════════════════════════════════════════════════════════╝');
validation.testPowerFailure();
validation.testStreetLampOutage();
validation.testTreeGrowthRisk();
validation.testPathAnalysis();
validation.testNetworkAnalysis();
const report = validation.generateReport();
console.log('\n✅ Ontology Validation complete!');
}
module.exports = OntologyValidation;