6de2455917
- Added GLOBAL_MARKETS_TITLE to all translation files - Updated footer with 12 markets (4 active + 8 upcoming) - Translated market section to: zh-cn, zh-tw, ja, ko, th, vi, id, ms, hi - Built and deployed to production - CloudFront invalidation: I3RTMXVFDJXWLG3SYX208OP1CC
215 lines
6.6 KiB
JavaScript
215 lines
6.6 KiB
JavaScript
/**
|
||
* Reality Alert™ Full Demo
|
||
* Demonstrates complete pipeline with simulated AI responses
|
||
*/
|
||
|
||
const { RealityAlertService, ALERT_SEVERITY, ALERT_CATEGORIES } = require('../src/services/realityAlert');
|
||
|
||
// Mock the AI services for demo
|
||
class MockObjectDetectionService {
|
||
async detect(imageSource, options) {
|
||
// Simulate detection based on image URL hints
|
||
const url = imageSource.toString();
|
||
|
||
if (url.includes('diesel')) {
|
||
return {
|
||
objects: [
|
||
{ type: 'pump_station', confidence: 0.92 },
|
||
{ type: 'spill', confidence: 0.87 }
|
||
],
|
||
confidence: 0.92,
|
||
objectId: 'pump-station-001'
|
||
};
|
||
}
|
||
|
||
if (url.includes('missing')) {
|
||
return {
|
||
objects: [
|
||
{ type: 'manhole', confidence: 0.78 }
|
||
],
|
||
confidence: 0.78,
|
||
objectId: 'manhole-123'
|
||
};
|
||
}
|
||
|
||
if (url.includes('ice')) {
|
||
return {
|
||
objects: [
|
||
{ type: 'heat_pump', confidence: 0.85 },
|
||
{ type: 'ice_formation', confidence: 0.91 }
|
||
],
|
||
confidence: 0.91,
|
||
objectId: 'heatpump-456'
|
||
};
|
||
}
|
||
|
||
return {
|
||
objects: [{ type: 'unknown', confidence: 0.3 }],
|
||
confidence: 0.3,
|
||
objectId: null
|
||
};
|
||
}
|
||
}
|
||
|
||
class MockChangeDetectionService {
|
||
async compare(imageSource, options) {
|
||
const url = imageSource.toString();
|
||
|
||
if (url.includes('diesel')) {
|
||
return {
|
||
anomalies: [{
|
||
type: 'spill',
|
||
severity: 'critical',
|
||
description: 'Diesel spill detected near pump station',
|
||
confidence: 0.87
|
||
}],
|
||
comparison: { overallDifference: 0.45 }
|
||
};
|
||
}
|
||
|
||
if (url.includes('missing')) {
|
||
return {
|
||
anomalies: [{
|
||
type: 'missing',
|
||
severity: 'high',
|
||
description: 'Manhole cover missing',
|
||
confidence: 0.78
|
||
}],
|
||
comparison: { overallDifference: 0.32 }
|
||
};
|
||
}
|
||
|
||
if (url.includes('ice')) {
|
||
return {
|
||
anomalies: [{
|
||
type: 'ice_formation',
|
||
severity: 'medium',
|
||
description: 'Excessive ice formation on heat pump',
|
||
confidence: 0.91
|
||
}],
|
||
comparison: { overallDifference: 0.28 }
|
||
};
|
||
}
|
||
|
||
return {
|
||
anomalies: [],
|
||
comparison: { overallDifference: 0.05 }
|
||
};
|
||
}
|
||
}
|
||
|
||
class MockRiskClassifierService {
|
||
classify(analysis) {
|
||
const anomalies = analysis.changes?.anomalies || [];
|
||
if (anomalies.some(a => a.severity === 'critical')) return { level: 'red' };
|
||
if (anomalies.some(a => a.severity === 'high')) return { level: 'orange' };
|
||
if (anomalies.some(a => a.severity === 'medium')) return { level: 'yellow' };
|
||
return { level: 'green' };
|
||
}
|
||
}
|
||
|
||
async function runFullDemo() {
|
||
console.log('🚨 Landvex Reality Alert™ - Full Pipeline Demo');
|
||
console.log('===============================================\n');
|
||
|
||
// Create service with mocked AI
|
||
const service = new RealityAlertService();
|
||
service.objectDetection = new MockObjectDetectionService();
|
||
service.changeDetection = new MockChangeDetectionService();
|
||
service.riskClassifier = new MockRiskClassifierService();
|
||
|
||
// Test scenarios
|
||
const scenarios = [
|
||
{
|
||
name: 'Diesel Spill',
|
||
observation: {
|
||
imageUrl: 'https://example.com/photos/diesel-spill-001.jpg',
|
||
gpsLocation: { lat: 59.3293, lng: 18.0686, address: 'Stureplan, Stockholm' },
|
||
zoomerId: 'zoomer-123',
|
||
description: 'Dark liquid leaking from pump station'
|
||
}
|
||
},
|
||
{
|
||
name: 'Missing Manhole Cover',
|
||
observation: {
|
||
imageUrl: 'https://example.com/photos/missing-manhole-001.jpg',
|
||
gpsLocation: { lat: 59.3421, lng: 18.0554, address: 'Drottninggatan 12, Stockholm' },
|
||
zoomerId: 'zoomer-456',
|
||
description: 'Manhole cover is missing, dangerous hole in sidewalk'
|
||
}
|
||
},
|
||
{
|
||
name: 'Ice Formation on Heat Pump',
|
||
observation: {
|
||
imageUrl: 'https://example.com/photos/ice-heatpump-001.jpg',
|
||
gpsLocation: { lat: 59.3123, lng: 18.0234, address: 'Ringvägen 45, Stockholm' },
|
||
zoomerId: 'zoomer-789',
|
||
description: 'Heat pump covered in thick ice'
|
||
}
|
||
}
|
||
];
|
||
|
||
for (const scenario of scenarios) {
|
||
console.log(`\n📸 SCENARIO: ${scenario.name}`);
|
||
console.log('─'.repeat(50));
|
||
console.log(` Location: ${scenario.observation.gpsLocation.address}`);
|
||
console.log(` Description: ${scenario.observation.description}`);
|
||
console.log(` Zoomer: ${scenario.observation.zoomerId}\n`);
|
||
|
||
const result = await service.processObservation(scenario.observation);
|
||
|
||
if (result.status === 'verified') {
|
||
console.log('✅ OBSERVATION VERIFIED BY AI');
|
||
console.log(`\n🚨 REALITY ALERT: ${result.alert.id}`);
|
||
console.log(` Severity: ${result.alert.severity.toUpperCase()}`);
|
||
console.log(` Category: ${result.alert.category}`);
|
||
console.log(` Risk Score: ${result.alert.riskScore}/100`);
|
||
console.log(` AI Description: ${result.alert.description}`);
|
||
|
||
console.log(`\n📡 ROUTING INTELLIGENCE`);
|
||
console.log(` Primary: ${result.alert.routing.primary}`);
|
||
console.log(` Secondary: ${result.alert.routing.secondary.join(', ')}`);
|
||
console.log(` Emergency: ${result.alert.routing.emergency ? '⚠️ YES' : 'No'}`);
|
||
|
||
console.log(`\n💰 ZOOMER REWARD`);
|
||
console.log(` Amount: $${result.reward.amount}`);
|
||
console.log(` Breakdown: base $${result.reward.breakdown.base} × severity ${result.reward.breakdown.severityBonus} × category ${result.reward.breakdown.categoryBonus}`);
|
||
|
||
} else if (result.status === 'rejected') {
|
||
console.log('❌ REJECTED:', result.message);
|
||
}
|
||
}
|
||
|
||
console.log('\n\n📊 DASHBOARD SUMMARY');
|
||
console.log('═'.repeat(50));
|
||
const allAlerts = service.getPendingAlerts();
|
||
console.log(`Total Active Alerts: ${allAlerts.length}`);
|
||
|
||
const bySeverity = {};
|
||
const byCategory = {};
|
||
allAlerts.forEach(a => {
|
||
bySeverity[a.severity] = (bySeverity[a.severity] || 0) + 1;
|
||
byCategory[a.category] = (byCategory[a.category] || 0) + 1;
|
||
});
|
||
|
||
console.log('\nBy Severity:');
|
||
Object.entries(bySeverity).forEach(([sev, count]) => {
|
||
const icon = sev === 'critical' ? '🔴' : sev === 'high' ? '🟠' : sev === 'medium' ? '🟡' : '🟢';
|
||
console.log(` ${icon} ${sev}: ${count}`);
|
||
});
|
||
|
||
console.log('\nBy Category:');
|
||
Object.entries(byCategory).forEach(([cat, count]) => {
|
||
console.log(` • ${cat}: ${count}`);
|
||
});
|
||
|
||
console.log('\n✅ Demo complete!');
|
||
}
|
||
|
||
// Run if called directly
|
||
if (require.main === module) {
|
||
runFullDemo().catch(console.error);
|
||
}
|
||
|
||
module.exports = { runFullDemo };
|