Skip to content

Commit 0d00ecd

Browse files
authored
Term codes no longer abort course processing (#30)
Unexpected term codes get logged, but the row is now ignored rather than aborting processing for that course.
1 parent 8b5b2e8 commit 0d00ecd

File tree

2 files changed

+83
-40
lines changed

2 files changed

+83
-40
lines changed

student_auto_feed/ssaf_validate.php

-4
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,6 @@ public static function validate_row($row, $row_num) : bool {
4848
case $num_fields === $validate_num_fields:
4949
self::$error = "Row {$row_num} has {$num_fields} columns. {$validate_num_fields} expected.";
5050
return false;
51-
// Check term code (skips when set to null).
52-
case is_null(EXPECTED_TERM_CODE) ? true : $row[COLUMN_TERM_CODE] === EXPECTED_TERM_CODE:
53-
self::$error = "Row {$row_num} failed validation for unexpected term code \"{$row[COLUMN_TERM_CODE]}\".";
54-
return false;
5551
// User ID must contain only alpha characters, numbers, underscore, hyphen, and period.
5652
case boolval(preg_match("/^[a-z0-9_\-\.]+$/i", $row[COLUMN_USER_ID])):
5753
self::$error = "Row {$row_num} failed user ID validation \"{$row[COLUMN_USER_ID]}\".";

student_auto_feed/submitty_student_auto_feed.php

+83-36
Original file line numberDiff line numberDiff line change
@@ -158,60 +158,97 @@ private function get_csv_data() {
158158
$row_num = 1;
159159
}
160160

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+
161167
// Read and assign csv rows into $this->data array
162168
$row = fgetcsv($this->fh, 0, CSV_DELIM_CHAR);
163169
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.
165174
array_walk($row, function(&$val, $key) { $val = trim($val); });
166175

167176
// Remove any leading zeroes from "integer" registration sections.
168177
if (ctype_digit($row[COLUMN_SECTION])) $row[COLUMN_SECTION] = ltrim($row[COLUMN_SECTION], "0");
169178

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;
171199

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'];
180217
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.
183223
if ($row[COLUMN_EMAIL] === "") {
184224
$this->log_it("Blank email found for user {$row[COLUMN_USER_ID]}, row {$row_num}.");
185225
}
186226
} 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;
188229
$this->log_it(validate::$error);
189230
}
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-
}
208231
}
209-
}
232+
break;
233+
234+
default:
235+
// Skip row by default.
236+
break;
237+
238+
} // END switch (true)
210239

211240
$row = fgetcsv($this->fh, 0, CSV_DELIM_CHAR);
212241
$row_num++;
213242
}
214243

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+
215252
/* ---------------------------------------------------------------------
216253
There may be "fake" or "practice" courses in Submitty that shouldn't be
217254
altered by the autofeed. These courses will have no enrollments in the
@@ -262,6 +299,16 @@ private function check_for_duplicate_user_ids() {
262299
return true;
263300
}
264301

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+
*/
265312
private function check_for_excessive_dropped_users() {
266313
$is_validated = true;
267314
$invalid_courses = array(); // intentional local array
@@ -280,10 +327,10 @@ private function check_for_excessive_dropped_users() {
280327
array_unshift($invalid_courses, array('course' => "COURSE", 'diff' => "DIFF", 'ratio' => "RATIO")); // Header
281328
foreach ($invalid_courses as $invalid_course) {
282329
$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;
287334
}
288335
$msg .= " No upsert performed on any/all courses in Submitty due to suspicious data sheet.";
289336

0 commit comments

Comments
 (0)