Files
psu-schedule/test/weeks.test.js
Zakhar Timoshenko e38c388462 Add course schedules for ISF and ITZS programs for 2026 and 2024 sessions
- Created new snapshot files for ISF credits and daily schedules for the 26-АРХ and 26-ПГС programs.
- Added summer 2026 and winter 2024 exam schedules for the 23-ИТзс program, detailing lectures, labs, and consultations.
2026-10-19 22:55:28 +03:00

141 lines
5.4 KiB
JavaScript
Raw Permalink 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.
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("1-4н.;6-12н."), [[1, 4], [6, 12]]);
assert.deepEqual(parseWeekRanges("1-6н , 13-18н"), [[1, 6], [13, 18]]);
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);
});
test("Даты числами: «10.09;15.10;19.11;17.12», но не время пары", () => {
// ИСФ пишет дни информирования списком дат, как в 23-АРХ.
assert.deepEqual(parseTextDates("Единый день информирования 10.09;15.10;19.11;17.12", 2026), [
"2026-09-10",
"2026-10-15",
"2026-11-19",
"2026-12-17",
]);
assert.deepEqual(parseTextDates("03.10, 17.10. Физика", 2026), ["2026-10-03", "2026-10-17"]);
assert.deepEqual(parseTextDates("12.01.2027; 19.01.2027 Экзамен", 2026), ["2027-01-12", "2027-01-19"]);
// One number pair alone or a time range is a time, not a date.
for (const time of ["10.05 Лекция", "10.05-11.30", "16.50 Информационный час", "09.11 по 06.12 практика"])
assert.deepEqual(parseTextDates(time, 2026), [], time);
});