mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 18:34:02 +00:00
From the re-shot Russian screenshots:
- Translated: weather frame/imagery status errors, HUD summary provenance
("НЕДОСТУПНО: СУДА AIS ОНЛАЙН"), Bhote Koshi map labels, cockpit signal
distances (КМ). The HUD summary fields are separated with " · " in every
language, so the style name and view band no longer read as one phrase.
- Numbers follow the locale: cockpit altitude ("26 175"), precipitation.
- No breaks inside codes and dates: ADS-B and similar in layer rows,
Sentinel-2, cyclone issue dates (word joiner; the UI font has no U+2011),
no-break space after label colons in cyclone details.
- Layout: count lines under ALPR, short unavailable chip (context
"status chip"), roomier draw segments, tighter CCTV calibration chips,
two-line beat titles and media card titles, wrapping weather status.
- Wording: ru advisory is «сводка» (was «бюллетень»; "Advisory center" is
«Центр циклона по сводке»), Street View is «Просмотр улиц», OPACITY
«НЕПРОЗР.», synced «синхр.», Area «Зона»; the import dialog no longer says
"this scene" for several scenes. Glossary updated.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
115 lines
4.2 KiB
JavaScript
115 lines
4.2 KiB
JavaScript
import {
|
|
feedProvenanceEnvelope,
|
|
layerSnapshots,
|
|
} from './data/layerSnapshot.js';
|
|
|
|
export const HUD_SUMMARY_UNCONFIGURED_CODE = 'OPENAI_NOT_CONFIGURED';
|
|
|
|
/**
|
|
* Describe the optional HUD summary capability without turning a deliberately
|
|
* keyless boot into an HTTP failure.
|
|
*
|
|
* @param {unknown} apiKey - Candidate server-side OpenAI credential.
|
|
* @returns {{ statusCode: 200, payload: { configured: false, code: string, error: null, summary: null } }|null}
|
|
* A graceful unconfigured response, or null when the provider is configured.
|
|
*/
|
|
export function keylessHudSummaryResponse(apiKey) {
|
|
if (String(apiKey ?? '').trim()) return null;
|
|
return {
|
|
statusCode: 200,
|
|
payload: {
|
|
configured: false,
|
|
code: HUD_SUMMARY_UNCONFIGURED_CODE,
|
|
error: null,
|
|
summary: null,
|
|
},
|
|
};
|
|
}
|
|
|
|
/** Return true only for the deliberate, successful no-key capability response. */
|
|
export function isHudSummaryUnconfigured(status, data) {
|
|
const keys =
|
|
data !== null && typeof data === 'object' && !Array.isArray(data)
|
|
? Object.keys(data)
|
|
: [];
|
|
return (
|
|
keys.length === 4 &&
|
|
status === 200 &&
|
|
data?.configured === false &&
|
|
data?.code === HUD_SUMMARY_UNCONFIGURED_CODE &&
|
|
data?.error === null &&
|
|
data?.summary === null
|
|
);
|
|
}
|
|
|
|
/**
|
|
* HUD summary model instructions. The five-word line may only describe
|
|
* supplied labels, and must carry feed-state when any enabled layer is not
|
|
* nominal.
|
|
*/
|
|
export const HUD_SUMMARY_INSTRUCTIONS = [
|
|
"Write one concise intelligence-HUD summary for God's Eye View.",
|
|
'Use only the supplied place, street, nearby-place, enabled-layer labels, and feedProvenance.',
|
|
'Prefer the clearest named place and include a relevant enabled layer only when useful.',
|
|
'If any enabled layer is not nominal, the five words MUST include that feedState token (STALE, DEGRADED, FALLBACK, LOADING, or UNAVAILABLE) and must not present the view as live.',
|
|
'Do not infer from coordinates or invent a place or feed state.',
|
|
'Output exactly five words with no title, punctuation, markdown, or introductory phrase.',
|
|
].join(' ');
|
|
|
|
/**
|
|
* Stamp HUD summary context with the same layer snapshots voice tools use.
|
|
* @param {Array<object>} [layers] `DataLayerManager.getAll()` rows.
|
|
* @param {{ now?: number }} [options]
|
|
* @returns {{
|
|
* enabledLayerLabels: string[],
|
|
* enabledLayers: Array<{id: string|null, name: string|null, feedState: string, source: string|null, count: number}>,
|
|
* feedProvenance: object,
|
|
* }}
|
|
*/
|
|
export function hudSummaryLayerContext(layers = [], options) {
|
|
const snapshots = layerSnapshots(layers, options).filter((s) => s.enabled);
|
|
const envelope = feedProvenanceEnvelope(snapshots, options);
|
|
return {
|
|
enabledLayerLabels: snapshots.map((s) => s.name).filter(Boolean),
|
|
enabledLayers: snapshots.map((s) => ({
|
|
id: s.id,
|
|
name: s.name,
|
|
feedState: s.feedState,
|
|
source: s.source,
|
|
count: s.count,
|
|
})),
|
|
feedProvenance: envelope,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* The feed state and up to two layer names for the HUD telemetry suffix when
|
|
* an enabled feed is not nominal. Values stay English (`state` is a feed-state
|
|
* id, `names` are `layer.name`); the HUD translates them for display.
|
|
* @param {Array<object>} [layers]
|
|
* @param {{ now?: number }} [options]
|
|
* @returns {{ state: string, names: string[] }|null}
|
|
*/
|
|
export function hudTelemetryProvenance(layers = [], options) {
|
|
const snapshots = layerSnapshots(layers, options).filter((s) => s.enabled);
|
|
const envelope = feedProvenanceEnvelope(snapshots, options);
|
|
if (!envelope.overall || envelope.overall === 'nominal') return null;
|
|
const names = envelope.layers
|
|
.filter(
|
|
(s) => s.feedState && s.feedState !== 'nominal' && s.feedState !== 'off',
|
|
)
|
|
.map((s) => String(s.name || s.id || 'LAYER'))
|
|
.slice(0, 2);
|
|
return { state: envelope.overall, names };
|
|
}
|
|
|
|
/** Require the supplied non-nominal state before showing an AI summary. */
|
|
export function hudSummaryMatchesProvenance(summary, provenance) {
|
|
const state = provenance?.overall;
|
|
if (!state || state === 'nominal' || state === 'off') return true;
|
|
return String(summary || '')
|
|
.toUpperCase()
|
|
.split(/\W+/)
|
|
.includes(String(state).toUpperCase());
|
|
}
|