Files
website/src/lib/math.ts
Stan Runge d99245e9fc
Some checks failed
Deploy production / deploy (push) Failing after 9s
Math tracker (/trackers/math): Evan Chen's Napkin, chapter by chapter
Schema math (parts, chapters, sections, activity), seeded with all 100 chapters
(Ch 0-94, appendix A-E), 647 sections, PDF pages, exercise counts and approximate
prereqs. Triggers stamp started_at/completed_at and log status/exercise/note/section
changes; math.apply_progress(jsonb) applies the JSON format bots send. Private by
default via MATH_PRIVATE in #lib/math (owner-only prefix + lock in every tracker list).
Overall + per-part progress, current chapter, prereq hints, quick status buttons,
exercises stepper, notes, optional section ticks, activity log, dependency chart.
Deploy preflight checks the math schema (4 tables, 100 chapters).
2026-10-26 10:55:16 +00:00

40 lines
1.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Math tracker (/trackers/math): Evan Chen's "An Infinitely Large Napkin". Shared by the
// server (owner gate, loads) and the page.
/**
* The privacy switch. true: owner-only (404 for everyone else, lock icon in every tracker
* list). false: a public, read-only page for everyone else (notes stay owner-only, edits
* are always owner-only). Flip this one constant; owner.ts and projects.ts read it.
*/
export const MATH_PRIVATE = true;
export const MATH_STATUSES = ['not_started', 'reading', 'exercises', 'done', 'skipped'] as const;
export type MathStatus = (typeof MATH_STATUSES)[number];
export const STATUS_LABEL: Record<MathStatus, string> = {
not_started: 'not started',
reading: 'reading',
exercises: 'exercises',
done: 'done',
skipped: 'skipped'
};
/** The free PDF of the book; chapters link to it with #page=N (PDF page numbers). */
export const NAPKIN_PDF = 'https://venhance.github.io/napkin/Napkin.pdf';
export const pdfPage = (page: number) => `${NAPKIN_PDF}#page=${page}`;
/** "9,10,11,12,18" → "9–12, 18" (numeric keys only; letters are listed as-is). */
export function compactKeys(keys: readonly string[]): string {
const nums = keys.filter((k) => /^\d+$/.test(k)).map(Number);
const other = keys.filter((k) => !/^\d+$/.test(k));
nums.sort((a, b) => a - b);
const out: string[] = [];
for (let i = 0; i < nums.length;) {
let j = i;
while (j + 1 < nums.length && nums[j + 1] === nums[j] + 1) j++;
out.push(j - i >= 2 ? `${nums[i]}–${nums[j]}` : nums.slice(i, j + 1).join(', '));
i = j + 1;
}
return [...out, ...other].join(', ');
}