feat: keep undergraduate exams independent of course terms

This commit is contained in:
Codex
2026-10-14 23:19:11 +08:00
parent 48367b8273
commit 141436f545
9 changed files with 419 additions and 99 deletions
+38 -15
View File
@@ -3,8 +3,10 @@ import 'school_identity.dart';
/// School-specific term numbers, independent of teaching-week dates.
class SchoolTerm {
SchoolTerm(this.id, {this.school = SupportedSchool.uestcGraduate}) {
if (id < 1 || id > 9999 ||
(school == SupportedSchool.uestcUndergraduate && (id < 3 || (id-3)%20 != 0))) {
if (id < 1 ||
id > 9999 ||
(school == SupportedSchool.uestcUndergraduate &&
(id < 3 || (id - 3) % 20 != 0))) {
throw ArgumentError('学校学期编号无效');
}
}
@@ -13,7 +15,7 @@ class SchoolTerm {
String get label {
if (school == SupportedSchool.uestcUndergraduate) {
final n = (id - 3) ~/ 20, year = 2013 + ((id - 3) ~/ 40);
return '$year-${year+1}${n.isEven ? '第一学期' : '第二学期'}';
return '$year-${year + 1}${n.isEven ? '第一学期' : '第二学期'}';
}
final year = 1990 + ((id - 1) ~/ 2);
return '$year-${year + 1}年${id.isOdd ? '秋' : '春'}';
@@ -21,34 +23,55 @@ class SchoolTerm {
static List<SchoolTerm> get choices =>
List.generate(73, (index) => SchoolTerm(73 - index));
static List<SchoolTerm> undergraduateChoices(DateTime now, {SchoolTerm? saved}) {
final maxN = (now.year + 1 - 2013)*2+1;
final ids = {for(var n=0;n<=maxN;n++) 3+n*20,
if(saved?.school == SupportedSchool.uestcUndergraduate) saved!.id}.toList()
..sort((a,b)=>b.compareTo(a));
return ids.where((id)=>id<=9999).map((id)=>SchoolTerm(id,school:SupportedSchool.uestcUndergraduate)).toList();
static List<SchoolTerm> undergraduateChoices(
DateTime now, {
SchoolTerm? saved,
}) {
final maxN = (now.year + 1 - 2013) * 2 + 1;
final ids = {
for (var n = 0; n <= maxN; n++) 3 + n * 20,
if (saved?.school == SupportedSchool.uestcUndergraduate) saved!.id,
}.toList()..sort((a, b) => b.compareTo(a));
return ids
.where((id) => id <= 9999)
.map((id) => SchoolTerm(id, school: SupportedSchool.uestcUndergraduate))
.toList();
}
void _graduateOnly() {
if (school != SupportedSchool.uestcGraduate) throw StateError('本科查询不能使用研究生链接');
if (school != SupportedSchool.uestcGraduate)
throw StateError('本科查询不能使用研究生链接');
}
Uri get timetableUri {
_graduateOnly();
return Uri.https('yjsjy.uestc.edu.cn', '/pyxx/pygl/xskbcx/index/$id');
}
Uri get examUri {
_graduateOnly();
return Uri.https('yjsjy.uestc.edu.cn', '/pyxx/pygl/kskcxx/index', {'xq': '$id'});
return Uri.https('yjsjy.uestc.edu.cn', '/pyxx/pygl/kskcxx/index', {
'xq': '$id',
});
}
Map<String, dynamic> toJson() => {'id': id, 'schoolId': school.id};
factory SchoolTerm.fromJson(Map<String, dynamic> json) {
if (json['id'] is! int) throw const FormatException('学校学期无效');
try {
return SchoolTerm(json['id'] as int, school: json['schoolId'] == null
? SupportedSchool.uestcGraduate : SupportedSchool.fromId(json['schoolId'] as String));
} catch (_) { throw const FormatException('学校学期无效'); }
return SchoolTerm(
json['id'] as int,
school: json['schoolId'] == null
? SupportedSchool.uestcGraduate
: SupportedSchool.fromId(json['schoolId'] as String),
);
} catch (_) {
throw const FormatException('学校学期无效');
}
}
@override
bool operator ==(Object other) => other is SchoolTerm && other.id == id && other.school == school;
bool operator ==(Object other) =>
other is SchoolTerm && other.id == id && other.school == school;
@override
int get hashCode => Object.hash(id, school);
}