Files
boc/quixzoom-capture-pipeline/pilot/ontology-validation.js
T
Bernt bae705aa97 ARCHITECTURE: NFC roadmap, edge AI, audit logging
- Add NFC ePassport roadmap (ICAO 9303, eIDAS)
- Add TensorFlow.js edge face detection (BlazeFace)
- Add structured audit logger (GDPR-compliant)
- Risk scoring support

Part of KYC Apple Native UX v1.1.0
2026-06-29 16:24:48 +00:00

354 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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;