From 898b152755321c08b04758b734875992030d5251 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 29 Sep 2026 10:24:54 +0000 Subject: [PATCH] Daily dead-code sweep 2026-09-29: directions.matrix, TERM_NAMES Both had no caller outside their own declaration and tests. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01GCaTB3nB6X3MkbBCyge5aD --- js/directions.js | 46 ---------------------- js/state.js | 1 - scripts/test/directions.test.mjs | 67 +++----------------------------- sw.js | 6 +-- 4 files changed, 9 insertions(+), 111 deletions(-) diff --git a/js/directions.js b/js/directions.js index 11d2d34..c8d6734 100644 --- a/js/directions.js +++ b/js/directions.js @@ -13,15 +13,6 @@ // about buildings, and it answers null rather than throwing. Null is the // caller's signal to keep the routed number it already has, which is the whole // point -- the graph is the floor this sits on, not the thing it replaces. -// -// docs/research/walking-routes-115.md is why the ranking half is opt-in and not -// the default: measured against OSU's own service, Google disagreed with it more -// than the bundled graph does, so a live matrix is not obviously more accurate. -// It is here because #115's successor asks for steps, and a matrix is nearly -// free once the script is loaded. - -// Google's own ceiling on destinations per DistanceMatrix request. -export const MATRIX_MAX = 25; // Long enough for a cold script fetch on campus wifi, short enough that a // student does not watch a spinner instead of reading the walk they already @@ -149,42 +140,5 @@ export function createDirections({ key, consent = () => false, maps = loadMaps, return null; } }, - - // Walking seconds to many buildings in one request, for ranking. Returns a - // Map of code to seconds, or null. - // - // Buildings and not rooms: 425 rooms share 50 buildings, and the ranking - // only ever needs the building. Over MATRIX_MAX destinations it returns - // null rather than paging, because a half-filled matrix would sort one list - // on two models -- the failure mode #115 names. - async matrix(origin, buildings) { - const at = generation; - const codes = Object.keys(buildings ?? {}); - if (!codes.length || codes.length > MATRIX_MAX) return null; - try { - const g = await withTimeout(ready(), TIMEOUT_MS); - const service = new g.DistanceMatrixService(); - const res = await withTimeout( - service.getDistanceMatrix({ - origins: [{ lat: origin.lat, lng: origin.lon }], - destinations: codes.map((c) => ({ lat: buildings[c].lat, lng: buildings[c].lon })), - travelMode: 'WALKING', - }), - TIMEOUT_MS, - ); - if (at !== generation) return null; - const row = res?.rows?.[0]?.elements; - if (!row || row.length !== codes.length) return null; - const out = new Map(); - row.forEach((el, i) => { - if (el?.status === 'OK' && Number.isFinite(el.duration?.value)) out.set(codes[i], el.duration.value); - }); - // All or nothing, for the same reason the graph's fallback is per origin - // and never per building. - return out.size === codes.length ? out : null; - } catch { - return null; - } - }, }; } diff --git a/js/state.js b/js/state.js index 0083a4b..96e20a5 100644 --- a/js/state.js +++ b/js/state.js @@ -101,7 +101,6 @@ export function daysBetween(fromIso, toIso) { // which a Spring index carrying 200 rooms walks straight through, so the app // checks per term digit instead. const ROOM_FLOOR = { 2: 400, 4: 100, 8: 400 }; -export const TERM_NAMES = { 2: 'Spring', 4: 'Summer', 8: 'Autumn' }; export function floorFor(term) { return ROOM_FLOOR[Number(String(term ?? '').slice(-1))] ?? 150; diff --git a/scripts/test/directions.test.mjs b/scripts/test/directions.test.mjs index 1b75f33..0478def 100644 --- a/scripts/test/directions.test.mjs +++ b/scripts/test/directions.test.mjs @@ -4,10 +4,9 @@ // What this file is really guarding is the FALLBACK. js/directions.js exists to // add steps the bundled graph cannot produce, and the graph stays the floor // underneath it: every failure -- no key, no consent, offline, quota, timeout, -// a stale answer, a half-filled matrix -- has to come back as null, because -// null is what makes js/app.js keep the routed minutes it already had. A -// provider that threw, or that returned a partial matrix, would either break -// the screen or sort one list on two models, which is the failure #115 names. +// a stale answer -- has to come back as null, because null is what makes +// js/app.js keep the routed minutes it already had. A provider that threw +// would break the screen instead of falling back to it. // // The consent tests are the other half. This app sent no position anywhere // before this module, and the rule is that no coordinate leaves the device @@ -16,11 +15,11 @@ import { test } from 'node:test'; import assert from 'node:assert/strict'; -import { MATRIX_MAX, createDirections, plainText } from '../../js/directions.js'; +import { createDirections, plainText } from '../../js/directions.js'; // A stand-in for google.maps, counting what it was asked. -const fakeMaps = ({ leg, elements, fail, hang } = {}) => { - const calls = { route: 0, matrix: 0, origins: [] }; +const fakeMaps = ({ leg, fail, hang } = {}) => { + const calls = { route: 0, origins: [] }; const g = { TravelMode: { WALKING: 'WALKING' }, DirectionsService: class { @@ -32,15 +31,6 @@ const fakeMaps = ({ leg, elements, fail, hang } = {}) => { return Promise.resolve({ routes: [{ legs: [leg] }] }); } }, - DistanceMatrixService: class { - getDistanceMatrix(req) { - calls.matrix += 1; - calls.origins.push(req.origins[0]); - if (fail) return Promise.reject(new Error('quota')); - if (hang) return new Promise(() => {}); - return Promise.resolve({ rows: [{ elements }] }); - } - }, }; return { maps: () => Promise.resolve(g), calls }; }; @@ -84,9 +74,7 @@ test('without consent no coordinate is sent and the answer is null', async () => const { maps, calls } = fakeMaps({ leg: LEG }); const d = createDirections({ key: 'k', consent: no, maps }); assert.equal(await d.steps(ORIGIN, BUILDING), null); - assert.equal(await d.matrix(ORIGIN, { 106: BUILDING }), null); assert.equal(calls.route, 0); - assert.equal(calls.matrix, 0); assert.deepEqual(calls.origins, []); }); @@ -123,7 +111,6 @@ test('a rejected request is null rather than a throw', async () => { const { maps } = fakeMaps({ fail: true }); const d = createDirections({ key: 'k', consent: yes, maps }); assert.equal(await d.steps(ORIGIN, BUILDING), null); - assert.equal(await d.matrix(ORIGIN, { 106: BUILDING }), null); }); // --- the stale answer, which is the one that would corrupt a screen @@ -145,48 +132,6 @@ test('invalidate counts up so a caller can tell generations apart', () => { assert.equal(d.generation, 2); }); -// --- the matrix, all or nothing - -test('a full row becomes seconds per building code', async () => { - const { maps } = fakeMaps({ - elements: [ - { status: 'OK', duration: { value: 200 } }, - { status: 'OK', duration: { value: 310 } }, - ], - }); - const d = createDirections({ key: 'k', consent: yes, maps }); - const m = await d.matrix(ORIGIN, { 106: BUILDING, 110: BUILDING }); - assert.equal(m.get('106'), 200); - assert.equal(m.get('110'), 310); - assert.equal(m.size, 2); -}); - -test('one unreachable destination voids the whole matrix', async () => { - // Half a matrix would rank part of one list on Google and part on the graph. - const { maps } = fakeMaps({ - elements: [{ status: 'OK', duration: { value: 200 } }, { status: 'ZERO_RESULTS' }], - }); - const d = createDirections({ key: 'k', consent: yes, maps }); - assert.equal(await d.matrix(ORIGIN, { 106: BUILDING, 110: BUILDING }), null); -}); - -test('more destinations than Google allows is null and is not sent', async () => { - const { maps, calls } = fakeMaps({ elements: [] }); - const d = createDirections({ key: 'k', consent: yes, maps }); - const many = {}; - for (let i = 0; i <= MATRIX_MAX; i += 1) many[String(i)] = BUILDING; - assert.equal(Object.keys(many).length, MATRIX_MAX + 1); - assert.equal(await d.matrix(ORIGIN, many), null); - assert.equal(calls.matrix, 0); -}); - -test('no buildings asks nothing', async () => { - const { maps, calls } = fakeMaps({ elements: [] }); - const d = createDirections({ key: 'k', consent: yes, maps }); - assert.equal(await d.matrix(ORIGIN, {}), null); - assert.equal(calls.matrix, 0); -}); - // --- offline test('offline answers null without asking', async () => { diff --git a/sw.js b/sw.js index eeea51d..5235e61 100644 --- a/sw.js +++ b/sw.js @@ -7,8 +7,8 @@ // One cache would either re-download the room index on every deploy or pin an // installed icon to last month's app.js forever. // -// Measured on 2026-09-16 over the committed blobs, which is the copy Pages serves: -// `git show HEAD: | gzip -9 -c | wc -c`. Shell 164,286 bytes, data 115,160. +// Measured on 2026-09-29 over the committed blobs, which is the copy Pages serves: +// `git show HEAD: | gzip -9 -c | wc -c`. Shell 163,573 bytes, data 115,028. // Run it exactly as written, through the pipe. `gzip -9 -c ` with the // name as an argument stores each basename in the gzip FNAME header and reads // 176 bytes higher across these seventeen files, which is most of a percent of @@ -88,7 +88,7 @@ // placeholder is __BUILD_ID__, and a committed sw.js still carrying it means the // stamp did not run. scripts/test/sw.test.mjs fails on exactly that. Spelled out // rather than built from CACHE_PREFIX, because the stamper rewrites this line. -const SHELL_CACHE = 'vacant-shell-c344401'; +const SHELL_CACHE = 'vacant-shell-a1ede09'; const DATA_CACHE = 'vacant-data-v1'; // CacheStorage is per origin, not per path, and enesyilmazcode.github.io also