fix(year-level): prefer units-passed standing over calendar-year history count
The grade-history method counted distinct academic years, which over-advanced standing for students who repeated/failed a year (e.g. showing Year 5 when the student is genuinely Year 4, since a partial 2025 year didn't advance them). Reorder the hybrid so the UNITS math (total prospectus units minus still-lacking units = units actually passed) is primary, and View Grades history is only a fallback when units data is unavailable.
This commit is contained in:
+14
-9
@@ -179,15 +179,10 @@
|
|||||||
|
|
||||||
const yearNum = parseInt(year, 10);
|
const yearNum = parseInt(year, 10);
|
||||||
|
|
||||||
// 1. View Grades history matching.
|
// 1. UNITS MATH — primary. Standing from units actually passed:
|
||||||
const gradesHtml = await fetchText('/ViewGrades');
|
// total prospectus units minus still-lacking units. This reflects real
|
||||||
if (gradesHtml) {
|
// earned units and is correct even for students who repeated or failed
|
||||||
const history = ISMIStools.parseGradeHistory(gradesHtml);
|
// a year (the naive grade-history count would over-advance them).
|
||||||
const level = ISMIStools.yearLevelForSemester(history, yearNum);
|
|
||||||
if (level != null) return String(level);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Units math: prospectus total minus lacking units.
|
|
||||||
const [prospectusHtml, lackingHtml] = await Promise.all([
|
const [prospectusHtml, lackingHtml] = await Promise.all([
|
||||||
fetchText('/prospectus/StudentProspectus'),
|
fetchText('/prospectus/StudentProspectus'),
|
||||||
fetchText('/Extras/ViewLackingSubjectsStudent1')
|
fetchText('/Extras/ViewLackingSubjectsStudent1')
|
||||||
@@ -199,6 +194,16 @@
|
|||||||
if (level != null) return String(level);
|
if (level != null) return String(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. GRADE HISTORY — fallback only when the units path is unavailable.
|
||||||
|
// It counts distinct academic years, so it is only an approximation for
|
||||||
|
// the printed semester and is not used when units data is present.
|
||||||
|
const gradesHtml = await fetchText('/ViewGrades');
|
||||||
|
if (gradesHtml) {
|
||||||
|
const history = ISMIStools.parseGradeHistory(gradesHtml);
|
||||||
|
const level = ISMIStools.yearLevelForSemester(history, yearNum);
|
||||||
|
if (level != null) return String(level);
|
||||||
|
}
|
||||||
|
|
||||||
// 3. Profile-scraped value as a last resort.
|
// 3. Profile-scraped value as a last resort.
|
||||||
if (header.yearLevel) return String(header.yearLevel);
|
if (header.yearLevel) return String(header.yearLevel);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
+7
-6
@@ -101,12 +101,13 @@
|
|||||||
return history;
|
return history;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Standing for the study load printed at (semester, year): it is the number
|
// Standing for a study load printed in `year` from the View Grades history.
|
||||||
// of distinct academic years strictly before that term's year + 1. SUMMER of
|
// It is the number of distinct academic years strictly before that year + 1
|
||||||
// year Y is the same standing as the rest of year Y (the student has just
|
// (FIRST/SECOND/SUMMER of a year share the same standing), clamped to at most
|
||||||
// finished the preceding level during Y's regular semesters). Clamped to at
|
// the number of distinct years in history. NOTE: this is only an
|
||||||
// most the number of distinct years in history (a student cannot be past the
|
// approximation for the printed semester — it counts calendar years present,
|
||||||
// final level recorded).
|
// not units passed — so a repeated/failed year can over-advance. It is used
|
||||||
|
// only as a fallback when the units-based standing is unavailable.
|
||||||
function yearLevelForSemester(history, year) {
|
function yearLevelForSemester(history, year) {
|
||||||
if (!history || !history.length || !Number.isFinite(year)) return null;
|
if (!history || !history.length || !Number.isFinite(year)) return null;
|
||||||
const distinctYears = [...new Set(history.map((t) => t.year))].sort((a, b) => a - b);
|
const distinctYears = [...new Set(history.map((t) => t.year))].sort((a, b) => a - b);
|
||||||
|
|||||||
Reference in New Issue
Block a user