@@ -8,7 +8,8 @@ export class ExamModeUI extends UIScreen {
88 public static readonly EXAM_PASSWORD : string = 'exam' ;
99
1010 public readonly _form : UIExamModeElements ;
11- private _exam : ExamForHost | null = null ;
11+ private _examMode : boolean = false ;
12+ private _examIds : number [ ] = [ ] ;
1213 private _loginScreen : LoginScreenUI ;
1314 protected _events : AuthenticatorEvents = {
1415 authenticationStart : ( ) => {
@@ -30,7 +31,7 @@ export class ExamModeUI extends UIScreen {
3031 } ,
3132 } ;
3233
33- public constructor ( auth : Authenticator , loginUI : LoginScreenUI , exam : ExamForHost | null = null ) {
34+ public constructor ( auth : Authenticator , loginUI : LoginScreenUI ) {
3435 super ( auth ) ;
3536
3637 // Keep a reference to the login screen so that we can show it when the exam is over
@@ -45,35 +46,46 @@ export class ExamModeUI extends UIScreen {
4546 } as UIExamModeElements ;
4647
4748 this . _initForm ( ) ;
49+ }
4850
49- if ( exam !== null ) {
50- this . setExam ( exam ) ;
51+ /**
52+ * Enable exam mode for a list of exams currently ongoing (usually just 1).
53+ * If the array of exams is empty, nothing will happen.
54+ */
55+ public enableExamMode ( exams : ExamForHost [ ] ) : void {
56+ if ( exams . length === 0 ) {
57+ return ;
5158 }
59+ this . _examMode = true ;
60+ this . _examIds = exams . map ( ( exam ) => exam . id ) ;
61+ this . _populateData ( exams ) ;
62+ this . _loginScreen . hideForm ( ) ;
63+ this . showForm ( ) ;
5264 }
5365
5466 /**
55- * Set the exam to display on the exam mode screen.
56- * If no exam is given, the exam mode screen will be hidden and the login screen will be shown instead.
57- * @returns true if the exam mode screen should be shown, false if the login screen is shown instead
67+ * Disable exam mode and show the default login screen instead.
5868 */
59- public setExam ( exam : ExamForHost | null ) : boolean {
60- this . _exam = exam ;
61- this . _populateData ( ) ;
62-
63- if ( this . _exam === null ) {
64- this . hideForm ( ) ;
65- this . _loginScreen . showForm ( ) ;
66- return false ;
67- }
68- else {
69- this . _loginScreen . hideForm ( ) ;
70- this . showForm ( ) ;
71- return true ;
72- }
69+ public disableExamMode ( ) : void {
70+ this . _examMode = false ;
71+ this . _examIds = [ ] ;
72+ this . _populateData ( [ ] ) ;
73+ this . hideForm ( ) ;
74+ this . _loginScreen . showForm ( ) ;
75+ }
76+
77+ /**
78+ * Get whether the exam mode screen is currently displayed.
79+ */
80+ public get examMode ( ) : boolean {
81+ return this . _examMode ;
7382 }
7483
75- public get exam ( ) : ExamForHost | null {
76- return this . _exam ;
84+ /**
85+ * Get the ids of the exams that are currently displayed on the exam mode screen.
86+ */
87+ public get examIds ( ) : number [ ] {
88+ return this . _examIds ;
7789 }
7890
7991 protected _initForm ( ) : void {
@@ -82,40 +94,56 @@ export class ExamModeUI extends UIScreen {
8294 // This event gets called when the user clicks the unlock button or submits the lock screen form in any other way
8395 form . examStartButton . addEventListener ( 'click' , ( event : Event ) => {
8496 event . preventDefault ( ) ;
85- if ( this . _exam !== null ) {
86- // Always log in with the username and password given by the back-end server.
87- // If no username and password are given, use the default username and password.
97+ if ( this . _examMode ) {
8898 this . _auth . login ( ExamModeUI . EXAM_USERNAME , ExamModeUI . EXAM_PASSWORD ) ;
8999 }
90- else {
91- console . error ( 'Exam is null' ) ;
92- window . ui . setDebugInfo ( 'Exam is null' ) ;
93- }
94100 } ) ;
95101 }
96102
97- private _populateData ( ) : void {
103+ private _populateData ( examsToPopulate : ExamForHost [ ] ) : void {
98104 const form = this . _form as UIExamModeElements ;
99105
100- if ( this . _exam === null ) {
106+ if ( examsToPopulate . length === 0 ) {
101107 // Unset text that states which exams can be started today
102108 form . examProjectsText . innerText = '' ;
109+ form . examStartText . innerText = 'unknown' ;
110+ form . examEndText . innerText = 'unknown' ;
103111 }
104112 else {
105- // Populate text that states which exams can be started today
106- const exam = window . data . dataJson ?. exams . find ( ( exam ) => exam . id === this . _exam ?. id ) ;
107- if ( exam === undefined ) {
108- console . error ( 'Exam not found in data.json' ) ;
109- window . ui . setDebugInfo ( 'Exam not found in data.json' ) ;
113+ // Find all exams in the data.json file that match the ids in the exams variable
114+ const exams = window . data . dataJson ?. exams . filter ( ( exam ) => examsToPopulate . some ( ( examToPopulate ) => exam . id === examToPopulate . id ) ) ;
115+
116+ if ( exams === undefined ) {
117+ console . error ( 'Failed to find exams in data.json' ) ;
118+ window . ui . setDebugInfo ( 'Failed to find exams in data.json' ) ;
110119 return ;
111120 }
112- const projectsText = exam . projects . map ( ( project ) => project . name ) . join ( ', ' ) ;
113- form . examProjectsText . innerText = projectsText ;
114121
115- const examStart = new Date ( this . _exam . begin_at ) ;
116- const examEnd = new Date ( this . _exam . end_at ) ;
117- form . examStartText . innerText = examStart . toLocaleTimeString ( "en-NL" , { hour : '2-digit' , minute : '2-digit' } ) ;
118- form . examEndText . innerText = examEnd . toLocaleTimeString ( "en-NL" , { hour : '2-digit' , minute : '2-digit' } ) ;
122+ // Find the earliest start time for an exam that should be displayed right now
123+ const earliestExam = exams . reduce ( ( earliest , exam ) => {
124+ const beginAt = new Date ( exam . begin_at ) ;
125+ if ( earliest === null || beginAt < earliest ) {
126+ return beginAt ;
127+ }
128+ return earliest ;
129+ } , new Date ( exams [ 0 ] . begin_at ) ) ;
130+
131+ // Find the latest end time for an exam that should be displayed right now
132+ const latestExam = exams . reduce ( ( latest , exam ) => {
133+ const endAt = new Date ( exam . end_at ) ;
134+ if ( latest === null || endAt > latest ) {
135+ return endAt ;
136+ }
137+ return latest ;
138+ } , new Date ( exams [ 0 ] . end_at ) ) ;
139+
140+ // Combine all possible projects for exams that can be started right now
141+ const projectsText = exams . flatMap ( ( exam ) => exam . projects . map ( ( project ) => project . name ) ) . join ( ', ' ) ;
142+
143+ // Display the projects and the time range in which the exams can be started
144+ form . examProjectsText . innerText = projectsText ;
145+ form . examStartText . innerText = earliestExam . toLocaleTimeString ( "en-NL" , { hour : '2-digit' , minute : '2-digit' } ) ;
146+ form . examEndText . innerText = latestExam . toLocaleTimeString ( "en-NL" , { hour : '2-digit' , minute : '2-digit' } ) ;
119147 }
120148 }
121149
0 commit comments