implemented a comprehensive client-side demo mode triggered by a "demo@" username prefix, serving curated fixture data for all app modules
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
import '../../marianumconnect/queries/timetable_get_holidays/timetable_get_holidays_response.dart';
|
||||
import '../../marianumconnect/queries/timetable_get_rooms/timetable_get_rooms_response.dart';
|
||||
import '../../marianumconnect/queries/timetable_get_schoolyear/timetable_get_schoolyear_response.dart';
|
||||
import '../../marianumconnect/queries/timetable_get_subjects/timetable_get_subjects_response.dart';
|
||||
import '../../marianumconnect/queries/timetable_get_timegrid/timetable_get_timegrid_response.dart';
|
||||
import '../../marianumconnect/queries/timetable_get_week/timetable_get_week_response.dart';
|
||||
import '../../mhsl/custom_timetable_event/get/get_custom_timetable_event_response.dart';
|
||||
import '../demo_persona.dart';
|
||||
|
||||
/// Curated timetable fixtures for the demo mode. Everything is derived from
|
||||
/// [DemoPersona] so subjects, teachers and rooms line up with the rest of the
|
||||
/// demo app, and every week is generated relative to the requested range so
|
||||
/// navigating forward/backward always lands on a populated 10b schedule.
|
||||
class DemoTimetable {
|
||||
const DemoTimetable._();
|
||||
|
||||
/// Period → (startHour, startMinute, endHour, endMinute).
|
||||
static const Map<int, (int, int, int, int)> _periods = {
|
||||
1: (7, 55, 8, 40),
|
||||
2: (8, 40, 9, 25),
|
||||
3: (9, 45, 10, 30),
|
||||
4: (10, 30, 11, 15),
|
||||
5: (11, 35, 12, 20),
|
||||
6: (12, 20, 13, 5),
|
||||
7: (13, 50, 14, 35),
|
||||
8: (14, 35, 15, 20),
|
||||
};
|
||||
|
||||
/// Weekday (DateTime.monday..friday) → period → subject short code.
|
||||
static const Map<int, Map<int, String>> _plan = {
|
||||
DateTime.monday: {1: 'M', 2: 'M', 3: 'D', 4: 'E', 5: 'BIO', 6: 'GE', 7: 'SP', 8: 'SP'},
|
||||
DateTime.tuesday: {1: 'E', 2: 'E', 3: 'PH', 4: 'M', 5: 'D', 6: 'REL', 7: 'GE'},
|
||||
DateTime.wednesday: {1: 'BIO', 2: 'BIO', 3: 'M', 4: 'D', 5: 'E', 6: 'PH'},
|
||||
DateTime.thursday: {1: 'D', 2: 'GE', 3: 'M', 4: 'M', 5: 'REL', 6: 'BIO', 7: 'SP', 8: 'SP'},
|
||||
DateTime.friday: {1: 'PH', 2: 'PH', 3: 'E', 4: 'M', 5: 'D', 6: 'GE'},
|
||||
};
|
||||
|
||||
static const Map<String, String> _roomBySubject = {
|
||||
'M': 'A101',
|
||||
'D': 'A101',
|
||||
'E': 'A102',
|
||||
'BIO': 'B201',
|
||||
'PH': 'B203',
|
||||
'GE': 'A101',
|
||||
'SP': 'Turnhalle 1',
|
||||
'REL': 'C305',
|
||||
};
|
||||
|
||||
static TimetableGetWeekResponse week(DateTime from, DateTime until) {
|
||||
final monday = _mondayOf(from);
|
||||
final entries = <McTimetableEntry>[];
|
||||
var id = 1;
|
||||
|
||||
for (final weekday in _plan.keys) {
|
||||
final date = monday.add(Duration(days: weekday - DateTime.monday));
|
||||
final day = _plan[weekday]!;
|
||||
for (final entry in day.entries) {
|
||||
entries.add(_entry(id++, date, weekday, entry.key, entry.value));
|
||||
}
|
||||
}
|
||||
|
||||
return TimetableGetWeekResponse(from: from, until: until, entries: entries);
|
||||
}
|
||||
|
||||
static McTimetableEntry _entry(
|
||||
int id,
|
||||
DateTime date,
|
||||
int weekday,
|
||||
int period,
|
||||
String subjectShort,
|
||||
) {
|
||||
final times = _periods[period]!;
|
||||
final teacher = _teacherFor(subjectShort);
|
||||
|
||||
// A couple of recurring irregularities so the demo shows off the cancelled
|
||||
// and substitution rendering.
|
||||
final cancelled = weekday == DateTime.monday && period == 4;
|
||||
final substituted = weekday == DateTime.tuesday && period == 3;
|
||||
|
||||
return McTimetableEntry(
|
||||
id: id,
|
||||
date: date,
|
||||
startTime: DateTime(1970, 1, 1, times.$1, times.$2),
|
||||
endTime: DateTime(1970, 1, 1, times.$3, times.$4),
|
||||
subjects: [subjectShort],
|
||||
teachers: [
|
||||
if (substituted)
|
||||
McTimetableTeacher(
|
||||
shortName: 'MÜL',
|
||||
displayName: 'Herr Müller',
|
||||
originalShortName: teacher.short,
|
||||
originalDisplayName: teacher.name,
|
||||
)
|
||||
else
|
||||
McTimetableTeacher(shortName: teacher.short, displayName: teacher.name),
|
||||
],
|
||||
rooms: [_roomBySubject[subjectShort] ?? DemoPersona.rooms.first],
|
||||
classNames: [DemoPersona.className],
|
||||
lessonType: 'LESSON',
|
||||
status: cancelled
|
||||
? 'CANCELLED'
|
||||
: substituted
|
||||
? 'IRREGULAR'
|
||||
: 'REGULAR',
|
||||
substitutionText: substituted ? 'Vertretung für ${teacher.name}' : null,
|
||||
lessonText: null,
|
||||
infoText: cancelled ? 'Fällt aus' : null,
|
||||
);
|
||||
}
|
||||
|
||||
static TimetableGetRoomsResponse rooms() => TimetableGetRoomsResponse(
|
||||
result: [
|
||||
for (var i = 0; i < DemoPersona.rooms.length; i++)
|
||||
McRoom(id: i + 1, shortName: DemoPersona.rooms[i], longName: DemoPersona.rooms[i]),
|
||||
],
|
||||
);
|
||||
|
||||
static TimetableGetSubjectsResponse subjects() => TimetableGetSubjectsResponse(
|
||||
result: [
|
||||
for (var i = 0; i < DemoPersona.subjects.length; i++)
|
||||
McSubject(
|
||||
id: i + 1,
|
||||
shortName: DemoPersona.subjects[i].short,
|
||||
longName: DemoPersona.subjects[i].name,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
static TimetableGetTimegridResponse timegrid() {
|
||||
final units = <McTimegridUnit>[];
|
||||
for (final day in _weekdays) {
|
||||
for (final period in _periods.entries) {
|
||||
final t = period.value;
|
||||
units.add(
|
||||
McTimegridUnit(
|
||||
dayOfWeek: day,
|
||||
label: '${period.key}',
|
||||
startTime: DateTime(1970, 1, 1, t.$1, t.$2),
|
||||
endTime: DateTime(1970, 1, 1, t.$3, t.$4),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
return TimetableGetTimegridResponse(result: units);
|
||||
}
|
||||
|
||||
static TimetableGetSchoolyearResponse schoolyear() {
|
||||
final startYear = _schoolyearStart(DateTime.now());
|
||||
return TimetableGetSchoolyearResponse(
|
||||
id: 1,
|
||||
name: '$startYear/${startYear + 1}',
|
||||
startDate: DateTime(startYear, 8, 1),
|
||||
endDate: DateTime(startYear + 1, 7, 31),
|
||||
);
|
||||
}
|
||||
|
||||
static TimetableGetHolidaysResponse holidays() {
|
||||
final startYear = _schoolyearStart(DateTime.now());
|
||||
return TimetableGetHolidaysResponse(
|
||||
result: [
|
||||
McHoliday(
|
||||
shortName: 'Herbst',
|
||||
longName: 'Herbstferien',
|
||||
startDate: DateTime(startYear, 10, 20),
|
||||
endDate: DateTime(startYear, 10, 31),
|
||||
),
|
||||
McHoliday(
|
||||
shortName: 'Weihnachten',
|
||||
longName: 'Weihnachtsferien',
|
||||
startDate: DateTime(startYear, 12, 22),
|
||||
endDate: DateTime(startYear + 1, 1, 6),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
static GetCustomTimetableEventResponse customEvents() =>
|
||||
GetCustomTimetableEventResponse([]);
|
||||
|
||||
static const List<McDayOfWeek> _weekdays = [
|
||||
McDayOfWeek.monday,
|
||||
McDayOfWeek.tuesday,
|
||||
McDayOfWeek.wednesday,
|
||||
McDayOfWeek.thursday,
|
||||
McDayOfWeek.friday,
|
||||
];
|
||||
|
||||
static DemoTeacher _teacherFor(String subjectShort) {
|
||||
final subjectName = DemoPersona.subjects
|
||||
.firstWhere((s) => s.short == subjectShort)
|
||||
.name;
|
||||
return DemoPersona.teachers.firstWhere((t) => t.subject == subjectName);
|
||||
}
|
||||
|
||||
static DateTime _mondayOf(DateTime date) {
|
||||
final day = DateTime(date.year, date.month, date.day);
|
||||
return day.subtract(Duration(days: day.weekday - DateTime.monday));
|
||||
}
|
||||
|
||||
static int _schoolyearStart(DateTime now) =>
|
||||
now.month >= 8 ? now.year : now.year - 1;
|
||||
}
|
||||
Reference in New Issue
Block a user