1
0

feat: v2
All checks were successful
Remote Deploy / deploy (push) Successful in 1m11s

Support of teacher absence format: "za Vn zastupuje Jk"
This commit is contained in:
2026-01-04 14:02:10 +01:00
parent 0325ce1815
commit 6b383b1af4
7 changed files with 95 additions and 12 deletions

View File

@@ -98,6 +98,7 @@ export default function parseAbsence(input, teacherMap = {}) {
const markConsumed = (start, end) => consumed.push([start, end]);
const isConsumed = (i) => consumed.some(([a, b]) => i >= a && i < b);
// 1. Teachers with specific hours (e.g. "Ab 1-4")
const teacherListThenSpecRe =
/([A-Za-z]+(?:[,;]\s?[A-Za-z]+)*)(?:\s*)(\d+(?:\+|-\d+|,\d+)?)(?![A-Za-z])/g;
@@ -115,6 +116,7 @@ export default function parseAbsence(input, teacherMap = {}) {
markConsumed(matchStart, matchEnd);
}
// 2. Teachers with "-exk" suffix
const teacherExkRe = /([A-Za-z]+)-exk/gi;
while ((m = teacherExkRe.exec(s)) !== null) {
const matchStart = m.index;
@@ -132,7 +134,34 @@ export default function parseAbsence(input, teacherMap = {}) {
markConsumed(matchStart, matchEnd);
}
// Standalone teachers → whole day
// ---------------------------------------------------------
// 3. Substitution Pattern: "za Vn zastupuje Jk"
// ---------------------------------------------------------
const substitutionRe = /za\s+([A-Za-z]+)\s+zastupuje\s+([A-Za-z]+)/gi;
while ((m = substitutionRe.exec(s)) !== null) {
const matchStart = m.index;
const matchEnd = substitutionRe.lastIndex;
if (isConsumed(matchStart)) continue;
const missingCode = m[1];
const substituteCode = m[2];
const missingResolved = resolveTeacher(missingCode, teacherMap);
const subResolved = resolveTeacher(substituteCode, teacherMap);
results.push({
teacher: missingResolved.name,
teacherCode: missingResolved.code.toLowerCase(),
type: "zastoupen",
zastupuje: {
teacher: subResolved.name,
teacherCode: subResolved.code.toLowerCase()
}
});
markConsumed(matchStart, matchEnd);
}
const teacherOnlyRe = /([A-Za-z]+(?:[,;]\s?[A-Za-z]+)*)/g;
while ((m = teacherOnlyRe.exec(s)) !== null) {
const matchStart = m.index;
@@ -141,6 +170,9 @@ export default function parseAbsence(input, teacherMap = {}) {
const tList = m[1].split(/[,;]\s*/).filter(Boolean);
tList.forEach((t) => {
const lowerT = t.toLowerCase();
if (lowerT === 'za' || lowerT === 'zastupuje') return;
if (isTeacherToken(t)) results.push(makeResult(t, null, teacherMap));
else
results.push({
@@ -154,12 +186,12 @@ export default function parseAbsence(input, teacherMap = {}) {
markConsumed(matchStart, matchEnd);
}
// Bare specs without teacher → invalid
// 5. Bare specs without teacher → invalid
const specOnlyRe = /\b(\d+(?:\+|-\d+|,\d+)?)\b/g;
while ((m = specOnlyRe.exec(s)) !== null) {
const matchStart = m.index;
if (isConsumed(matchStart)) continue;
if (m[1].trim() == "exk") continue; // Exkurze, will be implemented later
if (m[1].trim() == "exk") continue;
results.push({
type: "invalid",