@@ -158,60 +158,97 @@ private function get_csv_data() {
158
158
$ row_num = 1 ;
159
159
}
160
160
161
+ $ graded_reg_codes = STUDENT_REGISTERED_CODES ;
162
+ $ audit_reg_codes = is_null (STUDENT_AUDIT_CODES ) ? array () : STUDENT_AUDIT_CODES ;
163
+ $ latedrop_reg_codes = is_null (STUDENT_LATEDROP_CODES ) ? array () : STUDENT_LATEDROP_CODES ;
164
+ $ all_valid_reg_codes = array_merge ($ graded_reg_codes , $ audit_reg_codes , $ latedrop_reg_codes );
165
+ $ unexpected_term_codes = array ();
166
+
161
167
// Read and assign csv rows into $this->data array
162
168
$ row = fgetcsv ($ this ->fh , 0 , CSV_DELIM_CHAR );
163
169
while (!feof ($ this ->fh )) {
164
- //Trim whitespace from all fields in $row
170
+ // Course is comprised of an alphabetic prefix and a numeric suffix.
171
+ $ course = strtolower ($ row [COLUMN_COURSE_PREFIX ] . $ row [COLUMN_COURSE_NUMBER ]);
172
+
173
+ // Trim whitespace from all fields in $row.
165
174
array_walk ($ row , function (&$ val , $ key ) { $ val = trim ($ val ); });
166
175
167
176
// Remove any leading zeroes from "integer" registration sections.
168
177
if (ctype_digit ($ row [COLUMN_SECTION ])) $ row [COLUMN_SECTION ] = ltrim ($ row [COLUMN_SECTION ], "0 " );
169
178
170
- $ course = strtolower ($ row [COLUMN_COURSE_PREFIX ] . $ row [COLUMN_COURSE_NUMBER ]);
179
+ switch (true ) {
180
+ // Check that $row has an appropriate student registration.
181
+ case array_search ($ row [COLUMN_REGISTRATION ], $ all_valid_reg_codes ) === false :
182
+ // Skip row.
183
+ break ;
184
+
185
+ // Check that $row is associated with the current term (if check is enabled)
186
+ // Assume this check is OK, when EXPECTED_TERM_CODE is null (check disabled)
187
+ case is_null (EXPECTED_TERM_CODE ) ? false : $ row [COLUMN_TERM_CODE ] !== EXPECTED_TERM_CODE :
188
+ // Note the unexpected term code for logging, if not already noted.
189
+ if (array_search ($ row [COLUMN_TERM_CODE ], $ unexpected_term_codes ) === false ) {
190
+ $ unexpected_term_codes [] = $ row [COLUMN_TERM_CODE ];
191
+ }
192
+ break ;
193
+
194
+ // Check that $row is associated with the course list.
195
+ case array_search ($ course , $ this ->course_list ) !== false :
196
+ if (validate::validate_row ($ row , $ row_num )) {
197
+ // Include $row
198
+ $ this ->data [$ course ][] = $ row ;
171
199
172
- // Does $row have a valid registration code?
173
- $ graded_codes = STUDENT_REGISTERED_CODES ;
174
- $ audit_codes = is_null (STUDENT_AUDIT_CODES ) ? array () : STUDENT_AUDIT_CODES ;
175
- $ latedrop_codes = is_null (STUDENT_LATEDROP_CODES ) ? array () : STUDENT_LATEDROP_CODES ;
176
- $ all_valid_codes = array_merge ($ graded_codes , $ audit_codes , $ latedrop_codes );
177
- if (array_search ($ row [COLUMN_REGISTRATION ], $ all_valid_codes ) !== false ) {
178
- // Check that $row is associated with the course list
179
- if (array_search ($ course , $ this ->course_list ) !== false ) {
200
+ // $row with a blank email is included, but it is also logged.
201
+ if ($ row [COLUMN_EMAIL ] === "" ) {
202
+ $ this ->log_it ("Blank email found for user {$ row [COLUMN_USER_ID ]}, row {$ row_num }. " );
203
+ }
204
+ } else {
205
+ // There is a problem with $row, so log the problem and skip.
206
+ $ this ->invalid_courses [$ course ] = true ;
207
+ $ this ->log_it (validate::$ error );
208
+ }
209
+ break ;
210
+
211
+ // Check that the $row is associated with a mapped course.
212
+ case array_key_exists ($ course , $ this ->mapped_courses ):
213
+ // Also verify that the section is mapped.
214
+ $ section = $ row [COLUMN_SECTION ];
215
+ if (array_key_exists ($ section , $ this ->mapped_courses [$ course ])) {
216
+ $ m_course = $ this ->mapped_courses [$ course ][$ section ]['mapped_course ' ];
180
217
if (validate::validate_row ($ row , $ row_num )) {
181
- $ this ->data [$ course ][] = $ row ;
182
- // Rows with blank emails are allowed, but they are being logged.
218
+ // Include $row.
219
+ $ row [COLUMN_SECTION ] = $ this ->mapped_courses [$ course ][$ section ]['mapped_section ' ];
220
+ $ this ->data [$ m_course ][] = $ row ;
221
+
222
+ // $row with a blank email is allowed, but it is also logged.
183
223
if ($ row [COLUMN_EMAIL ] === "" ) {
184
224
$ this ->log_it ("Blank email found for user {$ row [COLUMN_USER_ID ]}, row {$ row_num }. " );
185
225
}
186
226
} else {
187
- $ this ->invalid_courses [$ course ] = true ;
227
+ // There is a problem with $row, so log the problem and skip.
228
+ $ this ->invalid_courses [$ m_course ] = true ;
188
229
$ this ->log_it (validate::$ error );
189
230
}
190
- // Instead, check that the $row is associated with mapped course
191
- } else if (array_key_exists ($ course , $ this ->mapped_courses )) {
192
- $ section = $ row [COLUMN_SECTION ];
193
- // Also verify that the section is mapped.
194
- if (array_key_exists ($ section , $ this ->mapped_courses [$ course ])) {
195
- $ m_course = $ this ->mapped_courses [$ course ][$ section ]['mapped_course ' ];
196
- if (validate::validate_row ($ row , $ row_num )) {
197
- $ row [COLUMN_SECTION ] = $ this ->mapped_courses [$ course ][$ section ]['mapped_section ' ];
198
- $ this ->data [$ m_course ][] = $ row ;
199
- // Rows with blank emails are allowed, but they are being logged.
200
- if ($ row [COLUMN_EMAIL ] === "" ) {
201
- $ this ->log_it ("Blank email found for user {$ row [COLUMN_USER_ID ]}, row {$ row_num }. " );
202
- }
203
- } else {
204
- $ this ->invalid_courses [$ m_course ] = true ;
205
- $ this ->log_it (validate::$ error );
206
- }
207
- }
208
231
}
209
- }
232
+ break ;
233
+
234
+ default :
235
+ // Skip row by default.
236
+ break ;
237
+
238
+ } // END switch (true)
210
239
211
240
$ row = fgetcsv ($ this ->fh , 0 , CSV_DELIM_CHAR );
212
241
$ row_num ++;
213
242
}
214
243
244
+ // Log any unexpected term codes.
245
+ // This may provide a notice that the next term's data is available.
246
+ if (!empty ($ unexpected_term_codes )) {
247
+ $ msg = "Unexpected term codes in CSV: " ;
248
+ $ msg .= implode (", " , $ unexpected_term_codes );
249
+ $ this ->log_it ($ msg );
250
+ }
251
+
215
252
/* ---------------------------------------------------------------------
216
253
There may be "fake" or "practice" courses in Submitty that shouldn't be
217
254
altered by the autofeed. These courses will have no enrollments in the
@@ -262,6 +299,16 @@ private function check_for_duplicate_user_ids() {
262
299
return true ;
263
300
}
264
301
302
+ /**
303
+ * An excessive ratio of dropped users may indicate bad data in the CSV.
304
+ *
305
+ * The confidence ratio is defined in config.php as VALIDATE_DROP_RATIO.
306
+ * Confidence value is a float between 0 and 1.0.
307
+ *
308
+ * @see validate::check_for_excessive_dropped_users() Found in ssaf_validate.php
309
+ *
310
+ * @return bool True when check is within confidence ratio. False otherwise.
311
+ */
265
312
private function check_for_excessive_dropped_users () {
266
313
$ is_validated = true ;
267
314
$ invalid_courses = array (); // intentional local array
@@ -280,10 +327,10 @@ private function check_for_excessive_dropped_users() {
280
327
array_unshift ($ invalid_courses , array ('course ' => "COURSE " , 'diff ' => "DIFF " , 'ratio ' => "RATIO " )); // Header
281
328
foreach ($ invalid_courses as $ invalid_course ) {
282
329
$ msg .= " " .
283
- str_pad ($ invalid_course ['course ' ], 18 , " " , STR_PAD_RIGHT ) .
284
- str_pad ($ invalid_course ['diff ' ], 6 , " " , STR_PAD_LEFT ) .
285
- str_pad ($ invalid_course ['ratio ' ], 8 , " " , STR_PAD_LEFT ) .
286
- PHP_EOL ;
330
+ str_pad ($ invalid_course ['course ' ], 18 , " " , STR_PAD_RIGHT ) .
331
+ str_pad ($ invalid_course ['diff ' ], 6 , " " , STR_PAD_LEFT ) .
332
+ str_pad ($ invalid_course ['ratio ' ], 8 , " " , STR_PAD_LEFT ) .
333
+ PHP_EOL ;
287
334
}
288
335
$ msg .= " No upsert performed on any/all courses in Submitty due to suspicious data sheet. " ;
289
336
0 commit comments