/** * Calculate the user's mark for the question. * * Must handle exclusions * * @return integer Status value from marking calculation */ public function calculate_user_mark() { $returnstatus = null; if (is_null($this->useranswer)) { $this->error = 'No User Answer'; $this->qmark = 0; return Q_MARKING_UNANSWERABLE; } if (!isset($this->useranswer['vars'])) { $this->error = 'No Variables stored'; $this->qmark = 0; return Q_MARKING_UNCALC_ANSWER; } if (!is_array($this->useranswer)) { $this->useranswer = json_decode($this->useranswer, true); } if (isset($this->useranswer['uans'])) { $return = $this->split_numb_from_unit($this->useranswer['uans']); $this->useranswer['uansunit'] = $return[1]; $this->useranswer['uansnumb'] = $return[0]; } if (isset($this->useranswer['uansunit'])) { $this->useranswer['ans']['guessedunits'] = $this->useranswer['uansunit']; } // Are the units correct? $this->useranswer['status']['units'] = $this->are_units_correct($this->useranswer['uansunit']); if ($this->useranswer['status']['units'] === false) { // We can't match the units so this question must be wrong! However, we need to have a formula and a unit to calculate the feedback // so just use the first one! foreach ($this->settings['answersexp'] as $unit => $formula) { $this->useranswer['ans']['formula_used'] = $formula; $this->useranswer['ans']['units_used'] = $unit; break; } } else { // Setup the fomula and units for the calculation $this->useranswer['ans']['formula_used'] = $this->settings['answersexp'][$this->useranswer['uansunit']]; $this->useranswer['ans']['units_used'] = $this->useranswer['uansunit']; } $enhancedcalcType = $this->configObj->get('enhancedcalc_type'); if (!is_null($enhancedcalcType)) { require_once $enhancedcalcType . '.php'; $name = 'enhancedcalc_' . $enhancedcalcType; $enhancedcalcObj = new $name($this->configObj->getbyref('enhancedcalculation')); } else { require_once 'Rrserve.php'; $enhancedcalcObj = new EnhancedCalc_Rrserve($this->configObj->getbyref('enhancedcalculation')); } if (is_array($this->useranswer['vars'])) { foreach ($this->useranswer['vars'] as $key => $variablessplit) { if ($variablessplit === 'ERROR') { $this->error = "variable {$key} is ERROR"; $this->qmark = 0; return Q_MARKING_UNANSWERABLE; } } } // Run calculate through the external interface if errors catch exception and indicate its still unmarked. try { /* * * CALCULATE REQURED NUMERIC VALUES * */ $this->useranswer['cans'] = $enhancedcalcObj->calculate_correct_ans($this->useranswer['vars'], $this->useranswer['ans']['formula_used']); } catch (Exception $e) { //TODO: catch different errors "no connection", "unable to evaluate" if (stripos($e->getMessage(), 'connect') !== false) { $returnstatus = Q_MARKING_UNMARKED; // Set to unmarked as there is no connection to R serve. } else { $returnstatus = Q_MARKING_UNCALC_ANSWER; $this->useranswer['status']['error'] = true; $this->useranswer['ans']['error'] = $enhancedcalcObj->get_error(); $this->useranswer['status']['e'] = $e->getCode() . " - " . $e->getMessage(); } $this->useranswer['status']['overall'] = $returnstatus; return $returnstatus; } try { if (isset($this->settings['tolerance_full'])) { $this->settings['tolerance_full'] = $this->set_blank_to_zero($this->settings['tolerance_full']); switch ($this->settings['fulltoltyp']) { case "%": $res = $enhancedcalcObj->calculate_tolerance_percent($this->useranswer['cans'], $this->settings['tolerance_full']); break; case "#": $res = $enhancedcalcObj->calculate_tolerance_absolute($this->useranswer['cans'], $this->settings['tolerance_full']); break; } $this->useranswer['ans']['tolerance_full'] = $res['tolerance']; $this->useranswer['ans']['tolerance_fullans'] = $res['tolerance_ans']; $this->useranswer['ans']['tolerance_fullansneg'] = $res['tolerance_ansneg']; } } catch (Exception $e) { //TODO: catch different errors "no connection", "unable to evaluate" if (stripos($e->getMessage(), 'connect') !== false) { $returnstatus = Q_MARKING_UNMARKED; // Set to unmarked as there is no connection to R serve. } else { $returnstatus = Q_MARKING_UNCALC_FULL_TOLLERANCE; $this->useranswer['status']['error'] = true; $this->useranswer['ans']['error'] = $enhancedcalcObj->get_error(); $this->useranswer['status']['e'] = $e->getCode() . " - " . $e->getMessage(); } $this->useranswer['status']['overall'] = $returnstatus; return $returnstatus; } try { if (isset($this->settings['tolerance_partial'])) { $this->settings['tolerance_partial'] = $this->set_blank_to_zero($this->settings['tolerance_partial']); switch ($this->settings['parttoltyp']) { case "%": $res = $enhancedcalcObj->calculate_tolerance_percent($this->useranswer['cans'], $this->settings['tolerance_partial']); break; case "#": $res = $enhancedcalcObj->calculate_tolerance_absolute($this->useranswer['cans'], $this->settings['tolerance_partial']); break; } $this->useranswer['ans']['tolerance_partial'] = $res['tolerance']; $this->useranswer['ans']['tolerance_partialans'] = $res['tolerance_ans']; $this->useranswer['ans']['tolerance_partialansneg'] = $res['tolerance_ansneg']; } } catch (Exception $e) { //TODO: catch different errors "no connection", "unable to evaluate" if (stripos($e->getMessage(), 'connect') !== false) { $returnstatus = Q_MARKING_UNMARKED; // Set to unmarked as there is no connection to R serve. } else { $returnstatus = Q_MARKING_UNCALC_PARTIAL_TOLLERANCE; $this->useranswer['status']['error'] = true; $this->useranswer['ans']['error'] = $enhancedcalcObj->get_error(); $this->useranswer['status']['e'] = $e->getCode() . " - " . $e->getMessage(); } $this->useranswer['status']['overall'] = $returnstatus; return $returnstatus; } /* * * FORMAT CALCULATED ANS * */ try { if ($this->settings['strictdisplay'] === true and isset($this->settings['dp'])) { $function = 'format_number_dp'; $arg = $this->settings['dp']; if ($this->settings['strictzeros'] === true) { $function = 'format_number_dp_strict_zeros'; } } elseif ($this->settings['strictdisplay'] === true and isset($this->settings['sf'])) { $function = 'format_number_sf'; $arg = $this->settings['sf']; } else { //round to student precision $function = 'format_number_to_precision_of_other_number'; $arg = $this->useranswer['uansnumb']; } $this->useranswer['cans'] = $enhancedcalcObj->{$function}($this->useranswer['cans'], $arg); $this->useranswer['ans']['tolerance_full'] = $enhancedcalcObj->{$function}($this->useranswer['ans']['tolerance_full'], $arg); $this->useranswer['ans']['tolerance_fullans'] = $enhancedcalcObj->{$function}($this->useranswer['ans']['tolerance_fullans'], $arg); $this->useranswer['ans']['tolerance_fullansneg'] = $enhancedcalcObj->{$function}($this->useranswer['ans']['tolerance_fullansneg'], $arg); $this->useranswer['ans']['tolerance_partial'] = $enhancedcalcObj->{$function}($this->useranswer['ans']['tolerance_partial'], $arg); $this->useranswer['ans']['tolerance_partialans'] = $enhancedcalcObj->{$function}($this->useranswer['ans']['tolerance_partialans'], $arg); $this->useranswer['ans']['tolerance_partialansneg'] = $enhancedcalcObj->{$function}($this->useranswer['ans']['tolerance_partialansneg'], $arg); } catch (Exception $e) { //TODO: catch different errors "no connection", "unable to evaluate" if (stripos($e->getMessage(), 'connect') !== false) { $returnstatus = Q_MARKING_UNMARKED; // Set to unmarked as there is no connection to R serve. } else { $returnstatus = Q_MARKING_UNCALC_FORMAT; $this->useranswer['status']['error'] = true; $this->useranswer['ans']['error'] = $enhancedcalcObj->get_error(); $this->useranswer['status']['e'] = $e->getCode() . " - " . $e->getMessage(); } $this->useranswer['status']['overall'] = $returnstatus; return $returnstatus; } /* * * MARKING * */ if (!isset($this->useranswer['uansnumb']) or isset($this->useranswer['uansnumb']) and trim($this->useranswer['uansnumb']) == '') { // Not answered $this->qmark = 0; $returnstatus = Q_MARKING_NOTANS; $this->useranswer['status']['overall'] = $returnstatus; return $returnstatus; } if ($this->useranswer['status']['units'] === false) { // We can't mach the units so this question must be wrong! $this->qmark = $this->settings['marks_incorrect']; $this->useranswer['status']['exact'] = false; $returnstatus = Q_MARKING_WRONG; $this->useranswer['status']['overall'] = $returnstatus; return $returnstatus; } try { $this->useranswer['status']['exact'] = $enhancedcalcObj->is_useranswer_correct($this->useranswer['uansnumb'], $this->useranswer['cans'], $this->settings['strictdisplay'] !== true); } catch (Exception $e) { //TODO: catch different errors "no connection", "unable to evaluate" if (stripos($e->getMessage(), 'connect') !== false) { $returnstatus = Q_MARKING_UNMARKED; // Set to unmarked as there is no connection to R serve. } else { $returnstatus = Q_MARKING_UNCALC_USER_ANSWER; $this->useranswer['status']['error'] = true; $this->useranswer['ans']['error'] = $enhancedcalcObj->get_error(); $this->useranswer['status']['e'] = $e->getCode() . " - " . $e->getMessage(); } $this->useranswer['status']['overall'] = $returnstatus; return $returnstatus; } try { // Calculate distance from correct if needed if ($this->useranswer['status']['exact'] === false) { $this->useranswer['cans_dist'] = $enhancedcalcObj->distance_from_correct_answer($this->useranswer['uansnumb'], $this->useranswer['cans']); } else { $this->useranswer['cans_dist'] = '0'; } } catch (Exception $e) { //TODO: catch different errors "no connection", "unable to evaluate" if (stripos($e->getMessage(), 'connect') !== false) { $returnstatus = Q_MARKING_UNMARKED; // Set to unmarked as there is no connection to R serve. } else { $returnstatus = Q_MARKING_UNCALC_DIST_FROM_ANSWER; $this->useranswer['status']['error'] = true; $this->useranswer['ans']['error'] = $enhancedcalcObj->get_error(); $this->useranswer['status']['e'] = $e->getCode() . " - " . $e->getMessage(); } $this->useranswer['status']['overall'] = $returnstatus; return $returnstatus; } if ($this->useranswer['status']['exact'] === false) { try { $this->useranswer['status']['tolerance_full'] = $enhancedcalcObj->is_useranswer_within_tolerance($this->useranswer['uansnumb'], $this->useranswer['ans']['tolerance_fullansneg'], $this->useranswer['ans']['tolerance_fullans']); } catch (Exception $e) { //TODO: catch different errors "no connection", "unable to evaluate" if (stripos($e->getMessage(), 'connect') !== false) { $returnstatus = Q_MARKING_UNMARKED; // Set to unmarked as there is no connection to R serve. } else { $returnstatus = Q_MARKING_UNCALC_WITHIN_FULL_TOLERANCE; $this->useranswer['status']['error'] = true; $this->useranswer['ans']['error'] = $enhancedcalcObj->get_error(); $this->useranswer['status']['e'] = $e->getCode() . " - " . $e->getMessage(); } $this->useranswer['status']['overall'] = $returnstatus; return $returnstatus; } if ($this->useranswer['status']['tolerance_full'] === false) { try { $this->useranswer['status']['tolerance_partial'] = $enhancedcalcObj->is_useranswer_within_tolerance($this->useranswer['uansnumb'], $this->useranswer['ans']['tolerance_partialansneg'], $this->useranswer['ans']['tolerance_partialans']); } catch (Exception $e) { //TODO: catch different errors "no connection", "unable to evaluate" if (stripos($e->getMessage(), 'connect') !== false) { $returnstatus = Q_MARKING_UNMARKED; // Set to unmarked as there is no connection to R serve. } else { $returnstatus = Q_MARKING_UNCALC_WITHIN_PARTIAL_TOLERANCE; $this->useranswer['status']['error'] = true; $this->useranswer['ans']['error'] = $enhancedcalcObj->get_error(); $this->useranswer['status']['e'] = $e->getCode() . " - " . $e->getMessage(); } $this->useranswer['status']['overall'] = $returnstatus; return $returnstatus; } } } else { $this->useranswer['status']['tolerance_partial'] = true; $this->useranswer['status']['tolerance_full'] = true; } try { // Strict dp marking if ($this->is_strict_dp_enabled()) { if ($this->is_strict_dp_strictzeros_enabled()) { $this->useranswer['status']['strictdp'] = $enhancedcalcObj->is_useranswer_correct_decimal_places_strictzeros($this->useranswer['uansnumb'], $this->settings['dp']); } else { $this->useranswer['status']['strictdp'] = $enhancedcalcObj->is_useranswer_correct_decimal_places($this->useranswer['uansnumb'], $this->settings['dp']); } if ($this->useranswer['status']['strictdp'] === false) { $this->qmark = $this->settings['marks_incorrect']; $returnstatus = Q_MARKING_WRONG; $this->useranswer['status']['overall'] = $returnstatus; return $returnstatus; } } } catch (Exception $e) { //TODO: catch different errors "no connection", "unable to evaluate" if (stripos($e->getMessage(), 'connect') !== false) { $returnstatus = Q_MARKING_UNMARKED; // Set to unmarked as there is no connection to R serve. } else { $returnstatus = Q_MARKING_UNCALC_STRICT_DP_CHECK; $this->useranswer['status']['error'] = true; $this->useranswer['ans']['error'] = $enhancedcalcObj->get_error(); $this->useranswer['status']['e'] = $e->getCode() . " - " . $e->getMessage(); } $this->useranswer['status']['overall'] = $returnstatus; return $returnstatus; } try { // Sheck for strict sf if ($this->is_strict_sf_enabled()) { $this->useranswer['status']['strictsf'] = $enhancedcalcObj->is_useranswer_within_significant_figures($this->useranswer['uansnumb'], $this->settings['sf']); if ($this->useranswer['status']['strictsf'] === false) { $this->qmark = $this->settings['marks_incorrect']; $returnstatus = Q_MARKING_WRONG; $this->useranswer['status']['overall'] = $returnstatus; return $returnstatus; } } // Assume its wrong wrong !! $returnstatus = Q_MARKING_WRONG; $this->qmark = $this->settings['marks_incorrect']; // Part tolerance range if ($this->is_user_ans_within_partial_tolerance()) { $this->qmark = $this->settings['marks_partial']; $returnstatus = Q_MARKING_PART_TOL; } // Full tolerance range if ($this->is_user_ans_within_fullmark_tolerance()) { $this->qmark = $this->settings['marks_correct']; $returnstatus = Q_MARKING_FULL_TOL; } // Exact answer if ($this->is_user_ans_correct()) { $this->qmark = $this->settings['marks_correct']; $returnstatus = Q_MARKING_EXACT; } // Remove marks for incorrect unit if (isset($this->settings['unit_marks']) and !($this->settings['unit_marks'] == 0 or $this->settings['unit_marks'] == 'invalidate') and $this->useranswer['status']['units'] !== true) { $this->qmark = $this->qmark - $this->settings['unit_marks']; $returnstatus = Q_MARKING_PART_UNITS_WRONG; } $this->useranswer['status']['overall'] = $returnstatus; } catch (Exception $e) { //TODO: catch different errors "no connection", "unable to evaluate" if (stripos($e->getMessage(), 'connect') !== false) { $returnstatus = Q_MARKING_UNMARKED; // Set to unmarked as there is no connection to R serve. } else { $returnstatus = Q_MARKING_ERROR; $this->useranswer['status']['error'] = true; $this->useranswer['ans']['error'] = $enhancedcalcObj->get_error(); $this->useranswer['status']['e'] = $e->getCode() . " - " . $e->getMessage() . " - " . $e->getTraceAsString(); } $this->useranswer['status']['overall'] = $returnstatus; return $returnstatus; } return $returnstatus; }
echo "<li>Settings are {$sets}</li>"; $data = array(); $data[] = array(array('$A' => 2, '$B' => 2), '$A+$B', '4'); $data[] = array(array('$A' => 2, '$B' => 2), '$A*$B', '4'); $data[] = array(array('$A' => 3, '$B' => 3), '$A+$B', '6'); $data[] = array(array('$A' => 3, '$B' => 3), '$A*$B', '9'); $data[] = array(array('$A' => 4, '$B' => 4), '$A+$B', '8'); $data[] = array(array('$A' => 4, '$B' => 4), '$A*$B', '16'); $data[] = array(array('$A' => 8, '$B' => 2), '$A/$B', '4'); $data[] = array(array('$A' => 8, '$B' => 2), '$A-$B', '6'); foreach ($data as $individual) { $vars = $individual[0]; $formula = $individual[1]; $cans = $individual[2]; try { $ans = $enhancedcalcObj1->calculate_correct_ans($vars, $formula); } catch (Exception $e) { $ans = false; } $check = false; $correct = false; if (!is_null($cans)) { $check = true; if ($ans === $cans) { $correct = true; } } $varlist = 'Where '; foreach ($vars as $key => $value) { $varlist .= "{$key}={$value}, "; }