| import type { UcdpViolenceEvent as ProtoUcdpEvent } from '@/generated/client/worldmonitor/conflict/v1/service_client'; |
|
|
| export type ConflictIntensity = 'none' | 'minor' | 'war'; |
|
|
| export interface UcdpConflictStatus { |
| location: string; |
| intensity: ConflictIntensity; |
| year: number; |
| sideA?: string; |
| sideB?: string; |
| } |
|
|
| |
| |
| |
| |
| |
|
|
| function isRecentUcdpClassificationDate(dateStart: unknown, now: number, windowMs: number): boolean { |
| const eventMs = Number(dateStart); |
| return Number.isFinite(eventMs) |
| && Number.isFinite(now) |
| && eventMs <= now |
| && now - eventMs < windowMs; |
| } |
|
|
| |
| |
| |
| export function deriveUcdpClassifications(events: ProtoUcdpEvent[], now = Date.now()): Map<string, UcdpConflictStatus> { |
| const byCountry = new Map<string, ProtoUcdpEvent[]>(); |
| for (const e of events) { |
| const country = e.country; |
| if (!byCountry.has(country)) byCountry.set(country, []); |
| byCountry.get(country)!.push(e); |
| } |
|
|
| const twoYearsMs = 2 * 365 * 24 * 60 * 60 * 1000; |
| const result = new Map<string, UcdpConflictStatus>(); |
|
|
| for (const [country, countryEvents] of byCountry) { |
| |
| const recentEvents = countryEvents.filter(e => isRecentUcdpClassificationDate(e.dateStart, now, twoYearsMs)); |
| const totalDeaths = recentEvents.reduce((sum, e) => sum + e.deathsBest, 0); |
| const eventCount = recentEvents.length; |
|
|
| let intensity: ConflictIntensity; |
| if (totalDeaths > 1000 || eventCount > 100) { |
| intensity = 'war'; |
| } else if (eventCount > 10) { |
| intensity = 'minor'; |
| } else { |
| intensity = 'none'; |
| } |
|
|
| |
| let maxDeathEvent: ProtoUcdpEvent | undefined; |
| for (const e of recentEvents) { |
| if (!maxDeathEvent || e.deathsBest > maxDeathEvent.deathsBest) { |
| maxDeathEvent = e; |
| } |
| } |
|
|
| |
| const mostRecentEvent = recentEvents.reduce<ProtoUcdpEvent | undefined>( |
| (latest, e) => (!latest || e.dateStart > latest.dateStart) ? e : latest, |
| undefined, |
| ); |
| const year = mostRecentEvent ? new Date(mostRecentEvent.dateStart).getFullYear() : new Date(now).getFullYear(); |
|
|
| result.set(country, { |
| location: country, |
| intensity, |
| year, |
| sideA: maxDeathEvent?.sideA, |
| sideB: maxDeathEvent?.sideB, |
| }); |
| } |
|
|
| return result; |
| } |
|
|