initial commit

This commit is contained in:
2026-10-16 22:08:45 +03:00
commit 19ee41411b
97 changed files with 15141 additions and 0 deletions

123
test/weeks.test.js Normal file
View File

@@ -0,0 +1,123 @@
import test from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { parseDocx } from "../server/parser.js";
import { parseWeeksDocx, parseBellsDocx } from "../server/calendar.js";
import {
parseWeekRanges,
parseTextDates,
lessonWeeks,
lessonDates,
dateInWeek,
weekIndexOf,
todayIso,
} from "../shared/weeks.js";
const fixture = (name) =>
readFileSync(new URL(`./fixtures/${name}.docx`, import.meta.url));
const calendar = {
weeks: parseWeeksDocx(fixture("weeks")),
bells: parseBellsDocx(fixture("bells")),
};
const fef = () =>
parseDocx(fixture("fef-23-ba"), { name: "23-ЛГ_23-БА.docx" }).lessons.filter(
(l) => l.groups.includes("23-БА"),
);
test("Таблица недель: 18 недель, нечётные белые, неделя 1 со вторника", () => {
const { weeks } = calendar;
assert.equal(weeks.length, 18);
assert.deepEqual(weeks[0], {
n: 1,
start: "2026-09-01",
end: "2026-09-06",
color: "white",
});
assert.deepEqual(weeks.at(-1), {
n: 18,
start: "2026-12-28",
end: "2027-01-03",
color: "green",
});
assert.ok(weeks.every((w) => (w.n % 2 ? "white" : "green") === w.color));
assert.equal(dateInWeek(weeks[0], 1), null);
assert.equal(dateInWeek(weeks[0], 2), "2026-09-01");
assert.equal(weekIndexOf(calendar, "2026-10-16"), 6);
assert.equal(weekIndexOf(calendar, "2027-02-01"), -1);
assert.equal(todayIso(new Date("2026-10-15T22:30:00Z")), "2026-10-16");
});
test("Звонки: восемь пар с половинами", () => {
assert.equal(calendar.bells.length, 8);
assert.deepEqual(calendar.bells[1], {
pair: 2,
start: "10:05",
end: "11:30",
halves: [
["10:05", "10:45"],
["10:50", "11:30"],
],
});
});
test("Пометки недель: диапазоны, «с N», опечатки остаются для сверки", () => {
assert.deepEqual(parseWeekRanges("1-4,6-11н."), [
[1, 4],
[6, 11],
]);
assert.deepEqual(parseWeekRanges("со 2 нед."), [[2, null]]);
assert.deepEqual(parseWeekRanges("с 4-16н"), [[4, 16]]);
assert.deepEqual(parseWeekRanges("1-8,10-17"), [
[1, 8],
[10, 17],
]);
assert.equal(parseWeekRanges("2,6-12-16н"), null);
assert.equal(parseWeekRanges("26.10"), null);
assert.equal(parseWeekRanges(""), null);
});
test("Цвет строки ограничивает диапазон чётностью недели", () => {
const white = { day: 2, date: null, condition: "13-17н", variant: "upper" };
const green = { day: 4, date: null, condition: "4-12н", variant: "lower" };
const every = { day: 5, date: null, condition: "6-13н", variant: "all" };
const plain = { day: 1, date: null, condition: "", variant: "lower" };
assert.deepEqual(lessonWeeks(white, 18), [13, 15, 17]);
assert.deepEqual(lessonWeeks(green, 18), [4, 6, 8, 10, 12]);
assert.deepEqual(lessonWeeks(every, 18), [6, 7, 8, 9, 10, 11, 12, 13]);
assert.deepEqual(lessonWeeks(plain, 18), [2, 4, 6, 8, 10, 12, 14, 16, 18]);
assert.equal(
lessonWeeks({ ...white, condition: "2,6-12-16н" }, 18),
null,
);
assert.deepEqual(lessonDates(every, calendar).slice(0, 2), [
"2026-10-09",
"2026-10-16",
]);
});
test("Парсер: 23-БА получает номера недель и даты дня информирования", () => {
const lessons = fef();
const friday = lessons.filter((l) => l.day === 5 && l.start === "10:05");
assert.deepEqual(
friday.map((l) => l.weekRanges),
[[[1, 4], [6, 11]], [[12, 15]], [[16, 16]]],
);
const week7 = friday.filter((l) => lessonWeeks(l, 18).includes(7));
assert.deepEqual(
week7.map((l) => l.subject),
["PR-менеджмент"],
);
const info = lessons.find((l) =>
l.subject.startsWith("Единый день информирования"),
);
assert.deepEqual(info.dates, [
"2026-09-10",
"2026-10-15",
"2026-11-19",
"2026-12-17",
]);
assert.deepEqual(parseTextDates("17 декабря и 14 января", 2026), [
"2026-12-17",
"2027-01-14",
]);
// Every coloured-row mark in the real document agrees with the week table.
for (const l of lessons.filter((l) => l.variant !== "all" && l.weekRanges))
for (const [a, b] of l.weekRanges)
for (const n of [a, b ?? a])
assert.equal(n % 2, l.variant === "upper" ? 1 : 0, l.raw);
});