diff --git a/scrape/parse.js b/scrape/parse.js index be58096..e71ae50 100644 --- a/scrape/parse.js +++ b/scrape/parse.js @@ -205,4 +205,4 @@ export default async function parseThisShit(downloadedFilePath) { fs.writeFileSync("db/current.json", JSON.stringify(data, null, 2)); } -// parseThisShit("downloads/table.xlsx") +parseThisShit("downloads/table.xlsx") diff --git a/scrape/scraper.js b/scrape/scraper.js index 76cb39e..7cd313f 100644 --- a/scrape/scraper.js +++ b/scrape/scraper.js @@ -61,7 +61,7 @@ async function handleError(page, err) { const downloadPath = path.resolve('./downloads'); if (!fs.existsSync(downloadPath)) fs.mkdirSync(downloadPath); - const client = await page.target().createCDPSession(); + const client = await page.createCDPSession(); await client.send('Page.setDownloadBehavior', { behavior: 'allow', downloadPath: downloadPath, diff --git a/scrape/utils/parseAbsence.js b/scrape/utils/parseAbsence.js index 3c833cb..2668943 100644 --- a/scrape/utils/parseAbsence.js +++ b/scrape/utils/parseAbsence.js @@ -9,6 +9,16 @@ export const isTeacherToken = (t) => /^[A-Za-z]+$/.test(t); export const parseSpec = (spec) => { if (!spec) return null; let m; + + // Handle "6,7" + if ((m = spec.match(/^(\d+),(\d+)$/))) { + const from = Number(m[1]); + const to = Number(m[2]); + return from >= 1 && to >= from && to <= LAST_HOUR + ? { kind: "range", value: { from, to } } + : null; + } + if ((m = spec.match(/^(\d+)\+$/))) { const from = Number(m[1]); return from >= 1 && from <= LAST_HOUR @@ -50,18 +60,15 @@ const processTeacherList = (teacherListStr, spec, teacherMap) => { let results = []; if (teacherListStr.includes(",")) { - // Comma = spec applies to all const teachers = teacherListStr.split(/\s*,\s*/).filter(Boolean); results = teachers.map((t) => makeResult(t, spec, teacherMap)); } else if (teacherListStr.includes(";")) { - // Semicolon = spec applies only to last, others = whole day const teachers = teacherListStr.split(/\s*;\s*/).filter(Boolean); teachers.forEach((t, i) => { const resSpec = i === teachers.length - 1 ? spec : null; results.push(makeResult(t, resSpec, teacherMap)); }); } else { - // Single teacher results.push(makeResult(teacherListStr, spec, teacherMap)); } @@ -80,8 +87,9 @@ 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); - // Regex: teacher-list [+ optional spec] - const teacherListThenSpecRe = /([A-Za-z]+(?:[,;]\s?[A-Za-z]+)*)(?:\s*)?(\d+(?:\+|-\d+)?)/g; + const teacherListThenSpecRe = + /([A-Za-z]+(?:[,;]\s?[A-Za-z]+)*)(?:\s*)(\d+(?:\+|-\d+|,\d+)?)(?![A-Za-z])/g; + let m; while ((m = teacherListThenSpecRe.exec(s)) !== null) { const matchStart = m.index; @@ -119,7 +127,7 @@ export default function parseAbsence(input, teacherMap = {}) { } // Bare specs without teacher → invalid - const specOnlyRe = /\b(\d+(?:\+|-\d+)?)\b/g; + const specOnlyRe = /\b(\d+(?:\+|-\d+|,\d+)?)\b/g; while ((m = specOnlyRe.exec(s)) !== null) { const matchStart = m.index; if (isConsumed(matchStart)) continue;