Files
TPSchedule/mobile/lib/domain/schedule_engine.dart
T

80 lines
2.3 KiB
Dart

import 'course.dart';
import 'semester.dart';
import 'course_occurrence.dart';
import 'lesson_times.dart';
import 'package:timezone/timezone.dart' as tz;
export 'course.dart';
export 'semester.dart';
export 'lesson_times.dart';
export 'course_occurrence.dart';
class ScheduleEngine {
static DateTime schoolDate(DateTime instant) {
final local = tz.TZDateTime.from(instant, tz.getLocation('Asia/Shanghai'));
return DateTime.utc(local.year, local.month, local.day);
}
static int? weekNumber(Semester semester, DateTime schoolDate) {
final date = DateTime.utc(
schoolDate.year,
schoolDate.month,
schoolDate.day,
);
final delta = date.difference(semester.firstMonday).inDays;
if (delta < 0 || delta >= semester.totalWeeks * 7) return null;
return delta ~/ 7 + 1;
}
static List<CourseOccurrence> occurrences(
List<Course> courses,
Semester semester,
) {
final result = <CourseOccurrence>[];
final zone = tz.getLocation('Asia/Shanghai');
for (final course in courses) {
for (final week in course.weeks) {
if (week > semester.totalWeeks) continue;
final day = semester.firstMonday.add(
Duration(days: (week - 1) * 7 + course.weekday - 1),
);
if (day.isBefore(semester.startDate)) continue;
final first = lessonSlots[course.startPeriod - 1].startMinute;
final last = lessonSlots[course.endPeriod - 1].endMinute;
result.add(
CourseOccurrence(
key: '${course.id}/${day.toIso8601String().substring(0, 10)}',
course: course,
week: week,
start: tz.TZDateTime(
zone,
day.year,
day.month,
day.day,
first ~/ 60,
first % 60,
),
end: tz.TZDateTime(
zone,
day.year,
day.month,
day.day,
last ~/ 60,
last % 60,
),
),
);
}
}
result.sort((a, b) {
final order = a.start.compareTo(b.start);
return order == 0 ? a.key.compareTo(b.key) : order;
});
return result;
}
static bool overlaps(CourseOccurrence a, CourseOccurrence b) =>
a.start.isBefore(b.end) && b.start.isBefore(a.end);
}