mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
Merge remote-tracking branch 'origin/main' into fix/1282
# Conflicts: # docs/CURRENT-STATE.md
This commit is contained in:
commit
be44f523e0
325 files changed
+20500
-1424
No files matched your search
@@ -9,7 +9,6 @@ import {
|
||||
FEED_STALE_AFTER_MS,
|
||||
MAX_VEHICLES_TOTAL,
|
||||
MISSED_POLLS_TO_DROP,
|
||||
TRANSIT_POLL_MS,
|
||||
isStaleVehicleFix,
|
||||
transitVehicleKey,
|
||||
vehicleReportTimeMs,
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
FEED_EVICT_AFTER_MS,
|
||||
FEED_STALE_AFTER_MS,
|
||||
MISSED_POLLS_TO_DROP,
|
||||
SELECTED_CARD_REFRESH_MS,
|
||||
TRANSIT_POLL_MS,
|
||||
VEHICLE_MAX_FIX_AGE_MS,
|
||||
} from './policy.js';
|
||||
@@ -1407,7 +1406,6 @@ test('the selected card lands where the vehicle stopped, not short of it', async
|
||||
// segment ends left it a few metres behind, and then the render hold was
|
||||
// released with no frame scheduled to close the gap.
|
||||
const app = harness(t);
|
||||
const start = Date.now();
|
||||
app.serve('mbta', () => ({
|
||||
status: 200,
|
||||
body: snapshot('mbta', 'MBTA', [vehicle('b', 42.36, -71.06, reported())], {
|
||||
|
||||
@@ -9,10 +9,7 @@ import {
|
||||
correctHeight,
|
||||
setTimeOffsetMs,
|
||||
} from '../../data/contactPlayback.js';
|
||||
export const FIX_HISTORY_MAX = 128;
|
||||
export const DISPLAY_LAG_MIN_MS = 25_000;
|
||||
export const DISPLAY_LAG_RESET_MS = 90_000;
|
||||
export const MODE_MAX_SPEED_MPS = Object.freeze({
|
||||
const MODE_MAX_SPEED_MPS = Object.freeze({
|
||||
bus: 36, // ~130 km/h — a coach on a motorway
|
||||
tram: 28, // ~100 km/h — interurban light rail
|
||||
subway: 42, // ~150 km/h
|
||||
@@ -32,22 +29,19 @@ export const MODE_MAX_SPEED_MPS = Object.freeze({
|
||||
* @param {boolean} [inferred] Whether the mode came from a feed default.
|
||||
* @returns {number} m/s
|
||||
*/
|
||||
export function speedCeilingMps(mode, inferred = false) {
|
||||
function speedCeilingMps(mode, inferred = false) {
|
||||
if (inferred) return MODE_MAX_SPEED_MPS.unknown;
|
||||
return MODE_MAX_SPEED_MPS[mode] ?? MODE_MAX_SPEED_MPS.unknown;
|
||||
}
|
||||
|
||||
/** Position deadband is disabled: even a short reported crawl is played. */
|
||||
export const FIX_NOISE_M = 0;
|
||||
|
||||
/**
|
||||
* Displacement (m) a glide must cover before its direction is worth believing.
|
||||
* Below this the course derived from it is noise; the last good one is held.
|
||||
*/
|
||||
export const COURSE_MIN_TRAVEL_M = 12;
|
||||
const COURSE_MIN_TRAVEL_M = 12;
|
||||
|
||||
/** Maximum display-course change per second (deg). A bus is not a gyroscope. */
|
||||
export const COURSE_MAX_RATE_DEG_PER_S = 120;
|
||||
const COURSE_MAX_RATE_DEG_PER_S = 120;
|
||||
/**
|
||||
* Longest stretch of elapsed time (s) one evaluation may spend. The limiter
|
||||
* used to bank the time since the course last CHANGED, so a vehicle that held
|
||||
@@ -56,15 +50,7 @@ export const COURSE_MAX_RATE_DEG_PER_S = 120;
|
||||
* EVALUATED, and capped here so that even a first look after a long idle
|
||||
* sweeps visibly instead of snapping.
|
||||
*/
|
||||
export const COURSE_STEP_MAX_S = 0.25;
|
||||
|
||||
/**
|
||||
* Consecutive fixes at the same place before a vehicle is called STOPPED.
|
||||
* One is not enough: a fifteen-second gap between identical fixes is also what
|
||||
* a vehicle waiting at a light looks like, and so is a feed that repeated
|
||||
* itself.
|
||||
*/
|
||||
export const STOPPED_FIXES = 2;
|
||||
const COURSE_STEP_MAX_S = 0.25;
|
||||
|
||||
/**
|
||||
* How long after its newest fix a vehicle stops being described as travelling.
|
||||
@@ -75,7 +61,7 @@ export const STOPPED_FIXES = 2;
|
||||
* otherwise is the same overreach as reading STOPPED off a stale status. Ninety
|
||||
* seconds matches the threshold at which a whole feed reads as gone quiet.
|
||||
*/
|
||||
export const MOTION_UNKNOWN_AFTER_MS = 90_000;
|
||||
const MOTION_UNKNOWN_AFTER_MS = 90_000;
|
||||
|
||||
const EARTH_M_PER_DEG = 111_320;
|
||||
|
||||
@@ -94,29 +80,13 @@ export function fixDistanceM(a, b) {
|
||||
return Math.hypot(dLat, dLon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Course in degrees clockwise from north, from one point to another.
|
||||
* @param {{lat:number, lon:number}} from
|
||||
* @param {{lat:number, lon:number}} to
|
||||
* @returns {number} 0-360
|
||||
*/
|
||||
export function courseBetween(from, to) {
|
||||
const dLat = (to.lat - from.lat) * EARTH_M_PER_DEG;
|
||||
const dLon =
|
||||
(to.lon - from.lon) *
|
||||
EARTH_M_PER_DEG *
|
||||
Math.cos((from.lat * Math.PI) / 180);
|
||||
const deg = (Math.atan2(dLon, dLat) * 180) / Math.PI;
|
||||
return (deg + 360) % 360;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortest signed difference between two courses, in degrees (-180, 180].
|
||||
* @param {number} from
|
||||
* @param {number} to
|
||||
* @returns {number}
|
||||
*/
|
||||
export function courseDelta(from, to) {
|
||||
function courseDelta(from, to) {
|
||||
let delta = ((to - from + 540) % 360) - 180;
|
||||
if (delta === -180) delta = 180;
|
||||
return delta;
|
||||
@@ -259,7 +229,7 @@ export function attachFloorToPlace(entry, fix, heightM) {
|
||||
correctHeight(entry.track, scratch.seq, heightM);
|
||||
}
|
||||
}
|
||||
export function displayCourse(entry, nowMs) {
|
||||
function displayCourse(entry, nowMs) {
|
||||
if (!entry) return null;
|
||||
const target = Number.isFinite(entry.sample?.segmentCourseDeg)
|
||||
? entry.sample.segmentCourseDeg
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
displacementPlausible,
|
||||
} from './movement.js';
|
||||
import { buildTransitSelectionCopy } from './policy.js';
|
||||
import { seek, sampleAt } from '../../data/contactPlayback.js';
|
||||
import { sampleAt } from '../../data/contactPlayback.js';
|
||||
const entry = () => {
|
||||
const e = { mode: 'bus', modeInferred: false, courseDeg: null };
|
||||
initializePlayback(e);
|
||||
|
||||
@@ -99,7 +99,7 @@ export const VISIBILITY_REFRESH_MS = 250;
|
||||
* on screen. Generous on purpose: a vehicle that crosses the edge mid-glide
|
||||
* should already have been moving, not pop into motion at the border.
|
||||
*/
|
||||
export const VIEW_MARGIN_RATIO = 0.6;
|
||||
const VIEW_MARGIN_RATIO = 0.6;
|
||||
|
||||
/**
|
||||
* Whether a vehicle is close enough to the camera's look-at area to be worth
|
||||
@@ -516,10 +516,10 @@ export function createTransitSelectedOverlayEntry(key, position, copy, mode) {
|
||||
}
|
||||
|
||||
/** Modes that ordinarily run below the street, drawn on the surface above themselves. */
|
||||
export const UNDERGROUND_MODES = new Set(['subway']);
|
||||
const UNDERGROUND_MODES = new Set(['subway']);
|
||||
|
||||
/** The mode in plain words, for a card a person reads rather than scans. */
|
||||
export const TRANSIT_MODE_WORD = Object.freeze({
|
||||
const TRANSIT_MODE_WORD = Object.freeze({
|
||||
bus: msg('Bus'),
|
||||
tram: msg('Tram'),
|
||||
subway: msg('Subway'),
|
||||
@@ -529,7 +529,7 @@ export const TRANSIT_MODE_WORD = Object.freeze({
|
||||
});
|
||||
|
||||
/** Short, fixed-width mode word for the detection card's class field. */
|
||||
export const TRANSIT_MODE_ABBR = Object.freeze({
|
||||
const TRANSIT_MODE_ABBR = Object.freeze({
|
||||
bus: 'BUS',
|
||||
tram: 'TRAM',
|
||||
subway: 'METRO',
|
||||
@@ -588,7 +588,7 @@ export function transitDetectionId(record, feed = null) {
|
||||
}
|
||||
|
||||
/** Longest route text the single-line detection label can carry. */
|
||||
export const DETECTION_ID_MAX_CHARS = 14;
|
||||
const DETECTION_ID_MAX_CHARS = 14;
|
||||
|
||||
/**
|
||||
* Cut long route text with an ellipsis, so a reader can see it was cut.
|
||||
@@ -600,7 +600,7 @@ export const DETECTION_ID_MAX_CHARS = 14;
|
||||
* @param {string} text
|
||||
* @returns {string} Uppercase, at most DETECTION_ID_MAX_CHARS characters.
|
||||
*/
|
||||
export function elideRouteText(text) {
|
||||
function elideRouteText(text) {
|
||||
const value = String(text || '').toUpperCase();
|
||||
if (value.length <= DETECTION_ID_MAX_CHARS) return value;
|
||||
return `${value.slice(0, DETECTION_ID_MAX_CHARS - 1)}\u2026`;
|
||||
@@ -659,6 +659,6 @@ export function transitDetectionMetric(
|
||||
* @param {number} [nowMs]
|
||||
* @returns {string}
|
||||
*/
|
||||
export function transitVehicleState(entry, nowMs = Date.now()) {
|
||||
function transitVehicleState(entry, nowMs = Date.now()) {
|
||||
return displayMotion(entry, nowMs).word;
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import {
|
||||
import {
|
||||
MARKER_PIXEL_SIZE,
|
||||
ROTATION_REFRESH_MS,
|
||||
SELECTED_CARD_REFRESH_MS,
|
||||
VISIBILITY_REFRESH_MS,
|
||||
SELECTED_PIXEL_SIZE,
|
||||
TRANSIT_MODE_COLORS,
|
||||
|
||||
Reference in new issue
Block a user