Skip to content

Commit d4326b5

Browse files
committed
fix(parser): classify 9-16 as lower half
1 parent b53c9b1 commit d4326b5

2 files changed

Lines changed: 39 additions & 5 deletions

File tree

app/scripts/selftest-jwxt-parsers.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
parseSelectionRoundTabs,
1010
parseEnrollmentBreakdownHtml
1111
} from '../shared/jwxtCrawler';
12+
import { resolveParser } from '../src/lib/data/parsers';
1213

1314
async function readFixture(relativePathFromRepoRoot: string): Promise<string> {
1415
const __filename = fileURLToPath(import.meta.url);
@@ -48,6 +49,36 @@ async function main() {
4849
assert.equal(breakdown.total, 18, 'breakdown total should parse');
4950
assert.equal(breakdown.userBatchLabel, '其他已选人数', 'should capture ★ user batch label');
5051

52+
{
53+
const parser = resolveParser('2025-2026 春');
54+
assert.ok(parser, 'should resolve 2025Spring parser');
55+
const raw = {
56+
backendOrigin: 'selftest',
57+
termName: '2025-2026 春',
58+
updateTimeMs: Date.now(),
59+
hash: 'selftest',
60+
courses: [
61+
{
62+
courseId: 'C1',
63+
courseName: '编译原理',
64+
credit: '1',
65+
teacherId: 'T1',
66+
teacherName: 'Teacher',
67+
classTime: '星期一第1节{第9-16周}',
68+
campus: '宝山',
69+
position: 'A-101',
70+
capacity: '1',
71+
number: '0',
72+
limitations: [],
73+
teachingClassId: 'S1'
74+
}
75+
]
76+
};
77+
const data = parser.parse(raw as any);
78+
const slot = data.courses[0]!.sections[0]!.classtime[0]![0]!;
79+
assert.equal(slot.weekPattern.span, '下半学期', '9-16 weeks should be 下半学期');
80+
}
81+
5182
// eslint-disable-next-line no-console
5283
console.log('[selftest] jwxt parsers ok');
5384
}

app/src/lib/data/parsers/2025Spring.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@ export const parser2025Spring: CourseParser = {
4545
timezone: 'Asia/Shanghai'
4646
};
4747
const calendar = extendCalendar(baseCalendar, stats);
48-
// 2025-16 is a 16-week term; this value affects upper/lower splitting for clip-path rendering.
49-
const weeks = stats.maxWeek > 0 ? stats.maxWeek : 16;
48+
// 2025-16 is a 16-week term; do NOT infer the term length from week tokens, as some entries may
49+
// contain out-of-band numbers that would break half-term classification (e.g. 9-16 should be 下半学期).
50+
const weeks = 16;
5051

5152
const courses = new Map<string, CourseRecord>();
5253
const courseHashMap = new Map<string, string>();
@@ -315,14 +316,16 @@ function projectToMatrix(chunks: ScheduleChunk[], calendar: CalendarConfig, maxW
315316

316317
function buildWeekPattern(descriptor: WeekDescriptor, maxWeeks: number): WeekPattern {
317318
const weeks = expandWeeks(descriptor, maxWeeks);
318-
const half = Math.ceil(maxWeeks / 2);
319+
// SHU half-term convention: the "second half" starts at week floor(maxWeeks/2)+1.
320+
// Example (16 weeks): upper = 1-8, lower = 9-16, so "9-16" should be 下半学期.
321+
const secondHalfStart = Math.floor(maxWeeks / 2) + 1;
319322

320323
const span: WeekPattern['span'] =
321324
!weeks || weeks.length === 0
322325
? '全学期'
323-
: weeks.every((week) => week <= half)
326+
: weeks.every((week) => week < secondHalfStart)
324327
? '上半学期'
325-
: weeks.every((week) => week > half)
328+
: weeks.every((week) => week >= secondHalfStart)
326329
? '下半学期'
327330
: '全学期';
328331

0 commit comments

Comments
 (0)