public function geotest() { $point11 = array('x' => 1, 'y' => 1); $point12 = array('x' => 1, 'y' => 2); $point21 = array('x' => 2, 'y' => 1); $point22 = array('x' => 2, 'y' => 2); $point23 = array('x' => 2, 'y' => 3); $point31 = array('x' => 3, 'y' => 1); $point32 = array('x' => 3, 'y' => 2); $point33 = array('x' => 3, 'y' => 3); $point43 = array('x' => 4, 'y' => 3); $point75 = array('x' => 7, 'y' => 5); $line1 = array($point31, $point43); $line2 = array($point12, $point43); $line3 = array($point11, $point23); $line4 = array($point32, $point33); $line5 = array($point43, $point75); $polygon1 = array($point11, $point21, $point32, $point33, $point23); // var_dump(Geometry::lineCuttingPolygon($line1, $polygon1)); // var_dump(Geometry::lineCuttingPolygon($line2, $polygon1)); // var_dump(Geometry::segmentIntersectSegment($line1, $line4)); // var_dump(Geometry::segmentCuttingPolygon($line1, $polygon1)); // var_dump(Geometry::segmentCuttingPolygon($line5, $polygon1)); // var_dump(Geometry::pointDistancePoint($point12, $point23)); var_dump(Geometry::pointDistanceLine($point31, array($point21, $point32))); // var_dump(Geometry::pointDistanceSegment($point12, array($point23, $point11))); // var_dump(Geometry::pointPedalSegment($point12, array($point23, $point33))); // var_dump(Geometry::pointDistancePolyline($point22, $polygon1)); var_dump(Geometry::pointDistancePolygon($point31, $polygon1)); }
public static function fromWkt($wkt) { $wktArgument = Geometry::getWKTArgument($wkt); return static::fromString($wktArgument); }
/** * Convert the geometry to geohash. * @return string the geohash or null when the $geometry is not a Point * @param Point $geometry * @see GeoAdapter::write() */ public function write(Geometry $geometry, $precision = NULL) { if ($geometry->geometryType() === 'Point') { return $this->encodePoint($geometry, $precision); } else { // The geohash is the hash grid ID that fits the envelope $envelope = $geometry->envelope(); $geohashes = array(); $geohash = ''; foreach ($envelope->getPoints() as $point) { $geohashes[] = $this->encodePoint($point, 1.0E-7); } $i = 0; while ($i < strlen($geohashes[0])) { $char = $geohashes[0][$i]; foreach ($geohashes as $hash) { if ($hash[$i] != $char) { return $geohash; } } $geohash .= $char; $i++; } return $geohash; } }
public function toExtGeoJSON() { $json_data = parent::toExtGeoJSON(); if (isset($this->geometry)) { $json_data = array_merge($json_data, array('type' => 'Feature', 'geometry' => $this->geometry->toJSON())); } return $json_data; }
/** * Calculates the centers of two points and * applies the function to the two points, * * @param Geometry $point_a The first point. * @param Geometry $point_b The second point. * @param closure $f Function to apply. * @return float Result of application of $f. */ private static function apply($point_a, $point_b, $f) { $center_a = $point_a->centroid(); $center_b = $point_b->centroid(); $coor_a = new Coordinate($center_a->y(), $center_a->x()); $coor_b = new Coordinate($center_b->y(), $center_b->x()); return $f($coor_a, $coor_b); }
/** * Serialize geometries into a GPX string. * * @param Geometry $geometry * * @return string The GPX string representation of the input geometries */ public function write(Geometry $geometry, $namespace = FALSE) { if ($geometry->isEmpty()) { return NULL; } if ($namespace) { $this->namespace = $namespace; $this->nss = $namespace . ':'; } return '<' . $this->nss . 'gpx creator="geoPHP" version="1.0">' . $this->geometryToGPX($geometry) . '</' . $this->nss . 'gpx>'; }
/** * Serialize geometries into an EWKT string. * * @param Geometry $geometry * * @return string The Extended-WKT string representation of the input geometries */ public function write(Geometry $geometry) { $srid = $geometry->SRID(); $wkt = ''; if ($srid) { $wkt = 'SRID=' . $srid . ';'; $wkt .= $geometry->out('wkt'); return $wkt; } else { return $geometry->out('wkt'); } }
/** * Serialize geometries into a WKT string. * * @param Geometry $geometry * * @return string The WKT string representation of the input geometries */ public function write(Geometry $geometry) { // If geos is installed, then we take a shortcut and let it write the WKT if (geoPHP::geosInstalled()) { $writer = new GEOSWKTWriter(); return $writer->write($geometry->geos()); } $type = strtolower($geometry->geometryType()); if (is_null($data = $this->extract($geometry))) { return null; } return strtoupper($type) . ' (' . $data . ')'; }
public function __construct($srid = null, $with_z = false, $with_m = false) { parent::__construct($srid, $with_z, $with_m); $this->binary_type = 7; $this->text_type = 'GEOMETRYCOLLECTION'; $this->geometries = array(); }
public function __construct($srid = null, $with_z = false, $with_m = false) { parent::__construct($srid, $with_z, $with_m); $this->binary_type = 3; $this->text_type = 'POLYGON'; $this->rings = array(); }
public function __construct($srid = null, $with_z = false, $with_m = false) { parent::__construct($srid, $with_z, $with_m); $this->binary_type = 2; $this->text_type = 'LINESTRING'; $this->points = array(); }
/** * Serialize geometries into a WKT string. * * @param Geometry $geometry * @param string $return_type Should be either 'string' or 'array' * * @return string Does a reverse geocode of the geometry */ public function write(Geometry $geometry, $return_type = 'string') { $centroid = $geometry->getCentroid(); $lat = $centroid->getY(); $lon = $centroid->getX(); $url = "http://maps.googleapis.com/maps/api/geocode/json"; $url .= '?latlng=' . $lat . ',' . $lon; $url .= '&sensor=false'; $this->result = json_decode(@file_get_contents($url)); if ($this->result->status == 'OK') { if ($return_type == 'string') { return $this->result->results[0]->formatted_address; } if ($return_type == 'array') { return $this->result->results[0]->address_components; } } }
public function __toString() { $parent_string = parent::__toString(); $output = array(); $output[] = sprintf("<Model%s>", isset($this->id) ? sprintf(" id=\"%s\"", $this->id) : ""); $output[] = $parent_string; $output[] = "</Model>"; return implode("\n", $output); }
public function __construct($srid = null, $with_z = false, $with_m = false) { parent::__construct($srid, $with_z, $with_m); $this->binary_type = 1; $this->text_type = 'POINT'; $this->x = 0; $this->y = 0; $this->z = 0; $this->m = 0; }
/** * Serialize geometries into an EWKB binary string. * * @param Geometry $geometry * * @return string The Extended-WKB binary string representation of the input geometries */ public function write(Geometry $geometry, $write_as_hex = FALSE) { // We always write into NDR (little endian) $wkb = pack('c', 1); switch ($geometry->getGeomType()) { case 'Point': $wkb .= pack('L', 1); $wkb .= $this->writePoint($geometry); break; case 'LineString': $wkb .= pack('L', 2); $wkb .= $this->writeLineString($geometry); break; case 'Polygon': $wkb .= pack('L', 3); $wkb .= $this->writePolygon($geometry); break; case 'MultiPoint': $wkb .= pack('L', 4); $wkb .= $this->writeMulti($geometry); break; case 'MultiLineString': $wkb .= pack('L', 5); $wkb .= $this->writeMulti($geometry); break; case 'MultiPolygon': $wkb .= pack('L', 6); $wkb .= $this->writeMulti($geometry); break; case 'GeometryCollection': $wkb .= pack('L', 7); $wkb .= $this->writeMulti($geometry); break; } if ($write_as_hex) { $unpacked = unpack('H*', $wkb); return $unpacked[1]; } else { return $wkb; } }
/** * Parse a line (from xrandr's output) containing a screen * * @param string $line Line to be parsed * * @return Screen */ public static function parseLine($line) { trim($line); if (preg_match(Screen::LINE_REGEX, $line, $result)) { return new Screen($result["id"], Geometry::parseString($result["minimumGeometry"]), Geometry::parseString($result["currentGeometry"]), Geometry::parseString($result["maximumGeometry"])); } // ToDo: Exeption handling if (Xrandr::DEBUG) { echo "Screen line could not be parsed!\n"; } return null; }
/** * Creates a new model. * If creation is successful, the browser will be redirected to the 'view' page. */ public function actionCreate() { if (!Yii::app()->user->checkAccess('giveEvaluation')) { //throw new CHttpException(403,Yii::t('http_status', '403')); Yii::app()->user->setState('redirect', Yii::app()->request->requestUri); $this->redirect(array('/site/login')); } $model_quality = new WaterQualityOpinions(); $model_fault = new WaterFaultOpinions(); if (isset($_POST) && !empty($_POST)) { var_dump($_POST); if (empty($_POST['geom'])) { Yii::app()->user->setFlash('warning', 'ATTENTION: set a point on the map.'); } else { if ($_POST['geom_type'] == 1) { if (!empty($_POST['qualities_list'])) { $model = new WaterQualityOpinions(); $model->quality = $_POST['qualities_list']; //$model->geom = new CDbExpression(Geometry::Transform(Geometry::ST_GeomFromText($_POST['geom']))); $model->geom = new CDbExpression(Geometry::Transform(Geometry::ST_GeomFromText($_POST['geom']), 4326)); $model->username = Yii::app()->user->id; if ($model->save()) { $this->redirect(array('view')); } else { Yii::app()->user->setFlash('error', 'An error occurred in data storage. Please try again.'); } } else { Yii::app()->user->setFlash('warning', 'ATTENTION: to point out the quality of the water service.'); } } else { if (!empty($_POST['faults_list'])) { $model = new WaterFaultOpinions(); $model->fault = $_POST['faults_list']; //$model->geom = new CDbExpression(Geometry::Transform(Geometry::ST_GeomFromText($_POST['geom']))); $model->geom = new CDbExpression(Geometry::Transform(Geometry::ST_GeomFromText($_POST['geom']), 4326)); $model->username = Yii::app()->user->id; if ($model->save()) { $this->redirect(array('view')); } else { Yii::app()->user->setFlash('error', 'An error occurred in data storage. Please try again.'); } } else { Yii::app()->user->setFlash('warning', 'ATTENTION: to point out the fault of the water network.'); } } } } $this->render('create'); }
public function __toString() { $parent_string = parent::__toString(); $output = array(); $output[] = sprintf("<MultiGeometry%s>", isset($this->id) ? sprintf(" id=\"%s\"", $this->id) : ""); $output[] = $parent_string; if (isset($this->geometries) && is_array($this->geometries)) { $geometries_strings = array(); foreach ($this->geometries as $geometry) { $geometries_strings[] = $geometry->__toString(); } $output[] = sprintf("\t<coordinates>%s</coordinates>", implode(" ", $geometries_strings)); } $output[] = "</MultiGeometry>"; return implode("\n", $output); }
/** * Updates a particular model. * If update is successful, the browser will be redirected to the 'view' page. * @param integer $id the ID of the model to be updated */ public function actionUpdate($id) { $model = $this->loadModel($id); if ($this->deleteIfOrphan($model)) { throw new CHttpException(404, 'The requested page does not exist.'); } // TODO: si potrebbe fare una "getParentWr($model, $destroyOrphan=true)" per evitare la doppia findByPk $wr_model = WaterRequests::model()->findByPk($model->wr_id); if (!Yii::app()->user->checkAccess('updateWaterRequest', array('waterRequest' => $wr_model))) { throw new CHttpException(403, Yii::t('http_status', '403')); } // Uncomment the following line if AJAX validation is needed // $this->performAjaxValidation($model); if (isset($_POST['WaterRequestGeometries'])) { $model->attributes = $_POST['WaterRequestGeometries']; $model->geom = new CDbExpression(Geometry::Transform(Geometry::ST_GeomFromText($_POST['WaterRequestGeometries']['geom']))); $model->altitude = null; if ($model->save()) { echo 'ok'; } //$this->redirect(array('view','id'=>$model->id)); } //$this->render('update',array('model'=>$model,)); }
/** * Extract geometry to a WKT string * * @param Geometry $geometry A Geometry object * * @return string */ public function extractData($geometry) { $parts = array(); switch ($geometry->geometryType()) { case 'Point': return $geometry->getX() . ' ' . $geometry->getY(); case 'LineString': foreach ($geometry->getComponents() as $component) { $parts[] = $this->extractData($component); } return implode(', ', $parts); case 'Polygon': case 'MultiPoint': case 'MultiLineString': case 'MultiPolygon': foreach ($geometry->getComponents() as $component) { $parts[] = '(' . $this->extractData($component) . ')'; } return implode(', ', $parts); case 'GeometryCollection': foreach ($geometry->getComponents() as $component) { $parts[] = strtoupper($component->geometryType()) . ' (' . $this->extractData($component) . ')'; } return implode(', ', $parts); } }
public function geometryToDatabaseValue(\Geometry $value = null) { return $value === null ? null : pg_escape_bytea($value->out('ewkt')); }
/** * This function was originally found in the exercise_show.php * @param int $exeId * @param int $questionId * @param int $choice the user selected * @param string $from function is called from 'exercise_show' or 'exercise_result' * @param array $exerciseResultCoordinates the hotspot coordinates $hotspot[$question_id] = coordinates * @param bool $saved_results save results in the DB or just show the reponse * @param bool $from_database gets information from DB or from the current selection * @param bool $show_result show results or not * @param int $propagate_neg * @param array $hotspot_delineation_result * * @todo reduce parameters of this function * @return string html code */ public function manage_answer($exeId, $questionId, $choice, $from = 'exercise_show', $exerciseResultCoordinates = array(), $saved_results = true, $from_database = false, $show_result = true, $propagate_neg = 0, $hotspot_delineation_result = array()) { global $debug; //needed in order to use in the exercise_attempt() for the time global $learnpath_id, $learnpath_item_id; require_once api_get_path(LIBRARY_PATH) . 'geometry.lib.php'; $feedback_type = $this->selectFeedbackType(); $results_disabled = $this->selectResultsDisabled(); if ($debug) { error_log("<------ manage_answer ------> "); error_log('exe_id: ' . $exeId); error_log('$from: ' . $from); error_log('$saved_results: ' . intval($saved_results)); error_log('$from_database: ' . intval($from_database)); error_log('$show_result: ' . $show_result); error_log('$propagate_neg: ' . $propagate_neg); error_log('$exerciseResultCoordinates: ' . print_r($exerciseResultCoordinates, 1)); error_log('$hotspot_delineation_result: ' . print_r($hotspot_delineation_result, 1)); error_log('$learnpath_id: ' . $learnpath_id); error_log('$learnpath_item_id: ' . $learnpath_item_id); error_log('$choice: ' . print_r($choice, 1)); } $extra_data = array(); $final_overlap = 0; $final_missing = 0; $final_excess = 0; $overlap_color = 0; $missing_color = 0; $excess_color = 0; $threadhold1 = 0; $threadhold2 = 0; $threadhold3 = 0; $arrques = null; $arrans = null; $questionId = intval($questionId); $exeId = intval($exeId); $TBL_TRACK_ATTEMPT = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT); $table_ans = Database::get_course_table(TABLE_QUIZ_ANSWER); // Creates a temporary Question object $course_id = $this->course_id; $objQuestionTmp = Question::read($questionId, $course_id); if ($objQuestionTmp === false) { return false; } $questionName = $objQuestionTmp->selectTitle(); $questionWeighting = $objQuestionTmp->selectWeighting(); $answerType = $objQuestionTmp->selectType(); $quesId = $objQuestionTmp->selectId(); $extra = $objQuestionTmp->extra; $next = 1; //not for now // Extra information of the question if (!empty($extra)) { $extra = explode(':', $extra); if ($debug) { error_log(print_r($extra, 1)); } // Fixes problems with negatives values using intval $true_score = floatval(trim($extra[0])); $false_score = floatval(trim($extra[1])); $doubt_score = floatval(trim($extra[2])); } $totalWeighting = 0; $totalScore = 0; // Destruction of the Question object unset($objQuestionTmp); // Construction of the Answer object $objAnswerTmp = new Answer($questionId); $nbrAnswers = $objAnswerTmp->selectNbrAnswers(); if ($debug) { error_log('Count of answers: ' . $nbrAnswers); error_log('$answerType: ' . $answerType); } if ($answerType == FREE_ANSWER || $answerType == ORAL_EXPRESSION || $answerType == CALCULATED_ANSWER) { $nbrAnswers = 1; } $nano = null; if ($answerType == ORAL_EXPRESSION) { $exe_info = Event::get_exercise_results_by_attempt($exeId); $exe_info = isset($exe_info[$exeId]) ? $exe_info[$exeId] : null; $params = array(); $params['course_id'] = $course_id; $params['session_id'] = api_get_session_id(); $params['user_id'] = isset($exe_info['exe_user_id']) ? $exe_info['exe_user_id'] : api_get_user_id(); $params['exercise_id'] = isset($exe_info['exe_exo_id']) ? $exe_info['exe_exo_id'] : $this->id; $params['question_id'] = $questionId; $params['exe_id'] = isset($exe_info['exe_id']) ? $exe_info['exe_id'] : $exeId; $nano = new Nanogong($params); //probably this attempt came in an exercise all question by page if ($feedback_type == 0) { $nano->replace_with_real_exe($exeId); } } $user_answer = ''; // Get answer list for matching $sql = "SELECT id_auto, id, answer\n FROM {$table_ans}\n WHERE c_id = {$course_id} AND question_id = {$questionId}"; $res_answer = Database::query($sql); $answerMatching = array(); while ($real_answer = Database::fetch_array($res_answer)) { $answerMatching[$real_answer['id_auto']] = $real_answer['answer']; } $real_answers = array(); $quiz_question_options = Question::readQuestionOption($questionId, $course_id); $organs_at_risk_hit = 0; $questionScore = 0; if ($debug) { error_log('Start answer loop '); } $answer_correct_array = array(); for ($answerId = 1; $answerId <= $nbrAnswers; $answerId++) { $answer = $objAnswerTmp->selectAnswer($answerId); $answerComment = $objAnswerTmp->selectComment($answerId); $answerCorrect = $objAnswerTmp->isCorrect($answerId); $answerWeighting = (double) $objAnswerTmp->selectWeighting($answerId); $answerAutoId = $objAnswerTmp->selectAutoId($answerId); $answer_correct_array[$answerId] = (bool) $answerCorrect; if ($debug) { error_log("answer auto id: {$answerAutoId} "); error_log("answer correct: {$answerCorrect} "); } // Delineation $delineation_cord = $objAnswerTmp->selectHotspotCoordinates(1); $answer_delineation_destination = $objAnswerTmp->selectDestination(1); switch ($answerType) { // for unique answer case UNIQUE_ANSWER: case UNIQUE_ANSWER_IMAGE: case UNIQUE_ANSWER_NO_OPTION: if ($from_database) { $sql = "SELECT answer FROM {$TBL_TRACK_ATTEMPT}\n WHERE\n exe_id = '" . $exeId . "' AND\n question_id= '" . $questionId . "'"; $result = Database::query($sql); $choice = Database::result($result, 0, "answer"); $studentChoice = $choice == $answerAutoId ? 1 : 0; if ($studentChoice) { $questionScore += $answerWeighting; $totalScore += $answerWeighting; } } else { $studentChoice = $choice == $answerAutoId ? 1 : 0; if ($studentChoice) { $questionScore += $answerWeighting; $totalScore += $answerWeighting; } } break; // for multiple answers // for multiple answers case MULTIPLE_ANSWER_TRUE_FALSE: if ($from_database) { $choice = array(); $sql = "SELECT answer FROM {$TBL_TRACK_ATTEMPT}\n WHERE\n exe_id = {$exeId} AND\n question_id = " . $questionId; $result = Database::query($sql); while ($row = Database::fetch_array($result)) { $ind = $row['answer']; $values = explode(':', $ind); $my_answer_id = isset($values[0]) ? $values[0] : ''; $option = isset($values[1]) ? $values[1] : ''; $choice[$my_answer_id] = $option; } } $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null; if (!empty($studentChoice)) { if ($studentChoice == $answerCorrect) { $questionScore += $true_score; } else { if ($quiz_question_options[$studentChoice]['name'] == "Don't know" || $quiz_question_options[$studentChoice]['name'] == "DoubtScore") { $questionScore += $doubt_score; } else { $questionScore += $false_score; } } } else { // If no result then the user just hit don't know $studentChoice = 3; $questionScore += $doubt_score; } $totalScore = $questionScore; break; case MULTIPLE_ANSWER: //2 if ($from_database) { $choice = array(); $sql = "SELECT answer FROM " . $TBL_TRACK_ATTEMPT . "\n WHERE exe_id = '" . $exeId . "' AND question_id= '" . $questionId . "'"; $resultans = Database::query($sql); while ($row = Database::fetch_array($resultans)) { $ind = $row['answer']; $choice[$ind] = 1; } $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null; $real_answers[$answerId] = (bool) $studentChoice; if ($studentChoice) { $questionScore += $answerWeighting; } } else { $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null; $real_answers[$answerId] = (bool) $studentChoice; if (isset($studentChoice)) { $questionScore += $answerWeighting; } } $totalScore += $answerWeighting; if ($debug) { error_log("studentChoice: {$studentChoice}"); } break; case GLOBAL_MULTIPLE_ANSWER: if ($from_database) { $choice = array(); $sql = "SELECT answer FROM {$TBL_TRACK_ATTEMPT}\n WHERE exe_id = '" . $exeId . "' AND question_id= '" . $questionId . "'"; $resultans = Database::query($sql); while ($row = Database::fetch_array($resultans)) { $ind = $row['answer']; $choice[$ind] = 1; } $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null; $real_answers[$answerId] = (bool) $studentChoice; if ($studentChoice) { $questionScore += $answerWeighting; } } else { $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null; if (isset($studentChoice)) { $questionScore += $answerWeighting; } $real_answers[$answerId] = (bool) $studentChoice; } $totalScore += $answerWeighting; if ($debug) { error_log("studentChoice: {$studentChoice}"); } break; case MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE: if ($from_database) { $sql = "SELECT answer FROM " . $TBL_TRACK_ATTEMPT . "\n WHERE exe_id = {$exeId} AND question_id= " . $questionId; $resultans = Database::query($sql); while ($row = Database::fetch_array($resultans)) { $ind = $row['answer']; $result = explode(':', $ind); if (isset($result[0])) { $my_answer_id = isset($result[0]) ? $result[0] : ''; $option = isset($result[1]) ? $result[1] : ''; $choice[$my_answer_id] = $option; } } $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : ''; if ($answerCorrect == $studentChoice) { //$answerCorrect = 1; $real_answers[$answerId] = true; } else { //$answerCorrect = 0; $real_answers[$answerId] = false; } } else { $studentChoice = $choice[$answerAutoId]; if ($answerCorrect == $studentChoice) { //$answerCorrect = 1; $real_answers[$answerId] = true; } else { //$answerCorrect = 0; $real_answers[$answerId] = false; } } break; case MULTIPLE_ANSWER_COMBINATION: if ($from_database) { $sql = "SELECT answer FROM {$TBL_TRACK_ATTEMPT}\n WHERE exe_id = {$exeId} AND question_id= {$questionId}"; $resultans = Database::query($sql); while ($row = Database::fetch_array($resultans)) { $ind = $row['answer']; $choice[$ind] = 1; } $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null; if ($answerCorrect == 1) { if ($studentChoice) { $real_answers[$answerId] = true; } else { $real_answers[$answerId] = false; } } else { if ($studentChoice) { $real_answers[$answerId] = false; } else { $real_answers[$answerId] = true; } } } else { $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null; if ($answerCorrect == 1) { if ($studentChoice) { $real_answers[$answerId] = true; } else { $real_answers[$answerId] = false; } } else { if ($studentChoice) { $real_answers[$answerId] = false; } else { $real_answers[$answerId] = true; } } } break; case FILL_IN_BLANKS: $str = ''; if ($from_database) { $sql = "SELECT answer\n FROM {$TBL_TRACK_ATTEMPT}\n WHERE\n exe_id = {$exeId} AND\n question_id= " . intval($questionId); $result = Database::query($sql); $str = Database::result($result, 0, 'answer'); } if ($saved_results == false && strpos($str, 'font color') !== false) { // the question is encoded like this // [A] B [C] D [E] F::10,10,10@1 // number 1 before the "@" means that is a switchable fill in blank question // [A] B [C] D [E] F::10,10,10@ or [A] B [C] D [E] F::10,10,10 // means that is a normal fill blank question // first we explode the "::" $pre_array = explode('::', $answer); // is switchable fill blank or not $last = count($pre_array) - 1; $is_set_switchable = explode('@', $pre_array[$last]); $switchable_answer_set = false; if (isset($is_set_switchable[1]) && $is_set_switchable[1] == 1) { $switchable_answer_set = true; } $answer = ''; for ($k = 0; $k < $last; $k++) { $answer .= $pre_array[$k]; } // splits weightings that are joined with a comma $answerWeighting = explode(',', $is_set_switchable[0]); // we save the answer because it will be modified $temp = $answer; $answer = ''; $j = 0; //initialise answer tags $user_tags = $correct_tags = $real_text = array(); // the loop will stop at the end of the text while (1) { // quits the loop if there are no more blanks (detect '[') if (($pos = api_strpos($temp, '[')) === false) { // adds the end of the text $answer = $temp; $real_text[] = $answer; break; //no more "blanks", quit the loop } // adds the piece of text that is before the blank //and ends with '[' into a general storage array $real_text[] = api_substr($temp, 0, $pos + 1); $answer .= api_substr($temp, 0, $pos + 1); //take the string remaining (after the last "[" we found) $temp = api_substr($temp, $pos + 1); // quit the loop if there are no more blanks, and update $pos to the position of next ']' if (($pos = api_strpos($temp, ']')) === false) { // adds the end of the text $answer .= $temp; break; } if ($from_database) { $queryfill = "SELECT answer FROM " . $TBL_TRACK_ATTEMPT . "\n WHERE\n exe_id = '" . $exeId . "' AND\n question_id= " . intval($questionId) . ""; $resfill = Database::query($queryfill); $str = Database::result($resfill, 0, 'answer'); api_preg_match_all('#\\[([^[]*)\\]#', $str, $arr); $str = str_replace('\\r\\n', '', $str); $choice = $arr[1]; if (isset($choice[$j])) { $tmp = api_strrpos($choice[$j], ' / '); $choice[$j] = api_substr($choice[$j], 0, $tmp); $choice[$j] = trim($choice[$j]); // Needed to let characters ' and " to work as part of an answer $choice[$j] = stripslashes($choice[$j]); } else { $choice[$j] = null; } } else { // This value is the user input, not escaped while correct answer is escaped by fckeditor $choice[$j] = api_htmlentities(trim($choice[$j])); } $user_tags[] = $choice[$j]; //put the contents of the [] answer tag into correct_tags[] $correct_tags[] = api_substr($temp, 0, $pos); $j++; $temp = api_substr($temp, $pos + 1); } $answer = ''; $real_correct_tags = $correct_tags; $chosen_list = array(); for ($i = 0; $i < count($real_correct_tags); $i++) { if ($i == 0) { $answer .= $real_text[0]; } if (!$switchable_answer_set) { // Needed to parse ' and " characters $user_tags[$i] = stripslashes($user_tags[$i]); if ($correct_tags[$i] == $user_tags[$i]) { // gives the related weighting to the student $questionScore += $answerWeighting[$i]; // increments total score $totalScore += $answerWeighting[$i]; // adds the word in green at the end of the string $answer .= $correct_tags[$i]; } elseif (!empty($user_tags[$i])) { // else if the word entered by the student IS NOT the same as the one defined by the professor // adds the word in red at the end of the string, and strikes it $answer .= '<font color="red"><s>' . $user_tags[$i] . '</s></font>'; } else { // adds a tabulation if no word has been typed by the student $answer .= ''; // remove that causes issue } } else { // switchable fill in the blanks if (in_array($user_tags[$i], $correct_tags)) { $chosen_list[] = $user_tags[$i]; $correct_tags = array_diff($correct_tags, $chosen_list); // gives the related weighting to the student $questionScore += $answerWeighting[$i]; // increments total score $totalScore += $answerWeighting[$i]; // adds the word in green at the end of the string $answer .= $user_tags[$i]; } elseif (!empty($user_tags[$i])) { // else if the word entered by the student IS NOT the same as the one defined by the professor // adds the word in red at the end of the string, and strikes it $answer .= '<font color="red"><s>' . $user_tags[$i] . '</s></font>'; } else { // adds a tabulation if no word has been typed by the student $answer .= ''; // remove that causes issue } } // adds the correct word, followed by ] to close the blank $answer .= ' / <font color="green"><b>' . $real_correct_tags[$i] . '</b></font>]'; if (isset($real_text[$i + 1])) { $answer .= $real_text[$i + 1]; } } } else { // insert the student result in the track_e_attempt table, field answer // $answer is the answer like in the c_quiz_answer table for the question // student data are choice[] $listCorrectAnswers = FillBlanks::getAnswerInfo($answer); $switchableAnswerSet = $listCorrectAnswers["switchable"]; $answerWeighting = $listCorrectAnswers["tabweighting"]; // user choices is an array $choice // get existing user data in n the BDD if ($from_database) { $sql = "SELECT answer\n FROM {$TBL_TRACK_ATTEMPT}\n WHERE\n exe_id = {$exeId} AND\n question_id= " . intval($questionId); $result = Database::query($sql); $str = Database::result($result, 0, 'answer'); $listStudentResults = FillBlanks::getAnswerInfo($str, true); $choice = $listStudentResults['studentanswer']; } // loop other all blanks words if (!$switchableAnswerSet) { // not switchable answer, must be in the same place than teacher order for ($i = 0; $i < count($listCorrectAnswers['tabwords']); $i++) { $studentAnswer = isset($choice[$i]) ? trim($choice[$i]) : ''; // This value is the user input, not escaped while correct answer is escaped by fckeditor // Works with cyrillic alphabet and when using ">" chars see #7718 #7610 #7618 if (!$from_database) { $studentAnswer = htmlentities(api_utf8_encode($studentAnswer)); } $correctAnswer = $listCorrectAnswers['tabwords'][$i]; $isAnswerCorrect = 0; if (FillBlanks::isGoodStudentAnswer($studentAnswer, $correctAnswer)) { // gives the related weighting to the student $questionScore += $answerWeighting[$i]; // increments total score $totalScore += $answerWeighting[$i]; $isAnswerCorrect = 1; } $listCorrectAnswers['studentanswer'][$i] = $studentAnswer; $listCorrectAnswers['studentscore'][$i] = $isAnswerCorrect; } } else { // switchable answer $listStudentAnswerTemp = $choice; $listTeacherAnswerTemp = $listCorrectAnswers['tabwords']; // for every teacher answer, check if there is a student answer for ($i = 0; $i < count($listStudentAnswerTemp); $i++) { $studentAnswer = trim($listStudentAnswerTemp[$i]); $found = false; for ($j = 0; $j < count($listTeacherAnswerTemp); $j++) { $correctAnswer = $listTeacherAnswerTemp[$j]; if (!$found) { if (FillBlanks::isGoodStudentAnswer($studentAnswer, $correctAnswer)) { $questionScore += $answerWeighting[$i]; $totalScore += $answerWeighting[$i]; $listTeacherAnswerTemp[$j] = ""; $found = true; } } } $listCorrectAnswers['studentanswer'][$i] = $studentAnswer; if (!$found) { $listCorrectAnswers['studentscore'][$i] = 0; } else { $listCorrectAnswers['studentscore'][$i] = 1; } } } $answer = FillBlanks::getAnswerInStudentAttempt($listCorrectAnswers); } break; // for calculated answer // for calculated answer case CALCULATED_ANSWER: $calculatedAnswer = Session::read('calculatedAnswerId'); $answer = $objAnswerTmp->selectAnswer($calculatedAnswer[$questionId]); $preArray = explode('@@', $answer); $last = count($preArray) - 1; $answer = ''; for ($k = 0; $k < $last; $k++) { $answer .= $preArray[$k]; } $answerWeighting = array($answerWeighting); // we save the answer because it will be modified $temp = $answer; $answer = ''; $j = 0; //initialise answer tags $userTags = $correctTags = $realText = array(); // the loop will stop at the end of the text while (1) { // quits the loop if there are no more blanks (detect '[') if (($pos = api_strpos($temp, '[')) === false) { // adds the end of the text $answer = $temp; $realText[] = $answer; break; //no more "blanks", quit the loop } // adds the piece of text that is before the blank //and ends with '[' into a general storage array $realText[] = api_substr($temp, 0, $pos + 1); $answer .= api_substr($temp, 0, $pos + 1); //take the string remaining (after the last "[" we found) $temp = api_substr($temp, $pos + 1); // quit the loop if there are no more blanks, and update $pos to the position of next ']' if (($pos = api_strpos($temp, ']')) === false) { // adds the end of the text $answer .= $temp; break; } if ($from_database) { $queryfill = "SELECT answer FROM " . $TBL_TRACK_ATTEMPT . "\n WHERE\n exe_id = '" . $exeId . "' AND\n question_id= " . intval($questionId) . ""; $resfill = Database::query($queryfill); $str = Database::result($resfill, 0, 'answer'); api_preg_match_all('#\\[([^[]*)\\]#', $str, $arr); $str = str_replace('\\r\\n', '', $str); $choice = $arr[1]; if (isset($choice[$j])) { $tmp = api_strrpos($choice[$j], ' / '); $choice[$j] = api_substr($choice[$j], 0, $tmp); $choice[$j] = trim($choice[$j]); // Needed to let characters ' and " to work as part of an answer $choice[$j] = stripslashes($choice[$j]); } else { $choice[$j] = null; } } else { // This value is the user input, not escaped while correct answer is escaped by fckeditor $choice[$j] = api_htmlentities(trim($choice[$j])); } $userTags[] = $choice[$j]; //put the contents of the [] answer tag into correct_tags[] $correctTags[] = api_substr($temp, 0, $pos); $j++; $temp = api_substr($temp, $pos + 1); } $answer = ''; $realCorrectTags = $correctTags; for ($i = 0; $i < count($realCorrectTags); $i++) { if ($i == 0) { $answer .= $realText[0]; } // Needed to parse ' and " characters $userTags[$i] = stripslashes($userTags[$i]); if ($correctTags[$i] == $userTags[$i]) { // gives the related weighting to the student $questionScore += $answerWeighting[$i]; // increments total score $totalScore += $answerWeighting[$i]; // adds the word in green at the end of the string $answer .= $correctTags[$i]; } elseif (!empty($userTags[$i])) { // else if the word entered by the student IS NOT the same as the one defined by the professor // adds the word in red at the end of the string, and strikes it $answer .= '<font color="red"><s>' . $userTags[$i] . '</s></font>'; } else { // adds a tabulation if no word has been typed by the student $answer .= ''; // remove that causes issue } // adds the correct word, followed by ] to close the blank $answer .= ' / <font color="green"><b>' . $realCorrectTags[$i] . '</b></font>]'; if (isset($realText[$i + 1])) { $answer .= $realText[$i + 1]; } } break; // for free answer // for free answer case FREE_ANSWER: if ($from_database) { $query = "SELECT answer, marks FROM " . $TBL_TRACK_ATTEMPT . "\n WHERE exe_id = '" . $exeId . "' AND question_id= '" . $questionId . "'"; $resq = Database::query($query); $data = Database::fetch_array($resq); $choice = $data['answer']; $choice = str_replace('\\r\\n', '', $choice); $choice = stripslashes($choice); $questionScore = $data['marks']; if ($questionScore == -1) { $totalScore += 0; } else { $totalScore += $questionScore; } if ($questionScore == '') { $questionScore = 0; } $arrques = $questionName; $arrans = $choice; } else { $studentChoice = $choice; if ($studentChoice) { //Fixing negative puntation see #2193 $questionScore = 0; $totalScore += 0; } } break; case ORAL_EXPRESSION: if ($from_database) { $query = "SELECT answer, marks FROM " . $TBL_TRACK_ATTEMPT . "\n WHERE exe_id = '" . $exeId . "' AND question_id= '" . $questionId . "'"; $resq = Database::query($query); $choice = Database::result($resq, 0, 'answer'); $choice = str_replace('\\r\\n', '', $choice); $choice = stripslashes($choice); $questionScore = Database::result($resq, 0, "marks"); if ($questionScore == -1) { $totalScore += 0; } else { $totalScore += $questionScore; } $arrques = $questionName; $arrans = $choice; } else { $studentChoice = $choice; if ($studentChoice) { //Fixing negative puntation see #2193 $questionScore = 0; $totalScore += 0; } } break; case DRAGGABLE: //no break //no break case MATCHING_DRAGGABLE: //no break //no break case MATCHING: if ($from_database) { $sql = 'SELECT id, answer, id_auto FROM ' . $table_ans . ' WHERE c_id = ' . $course_id . ' AND question_id = "' . $questionId . '" AND correct = 0'; $res_answer = Database::query($sql); // Getting the real answer $real_list = array(); while ($real_answer = Database::fetch_array($res_answer)) { $real_list[$real_answer['id_auto']] = $real_answer['answer']; } $sql = 'SELECT id, answer, correct, id_auto, ponderation FROM ' . $table_ans . ' WHERE c_id = ' . $course_id . ' AND question_id="' . $questionId . '" AND correct <> 0 ORDER BY id_auto'; $res_answers = Database::query($sql); $questionScore = 0; while ($a_answers = Database::fetch_array($res_answers)) { $i_answer_id = $a_answers['id']; //3 $s_answer_label = $a_answers['answer']; // your daddy - your mother $i_answer_correct_answer = $a_answers['correct']; //1 - 2 $i_answer_id_auto = $a_answers['id_auto']; // 3 - 4 $sql = "SELECT answer FROM {$TBL_TRACK_ATTEMPT}\n WHERE\n exe_id = '{$exeId}' AND\n question_id = '{$questionId}' AND\n position = '{$i_answer_id_auto}'"; $res_user_answer = Database::query($sql); if (Database::num_rows($res_user_answer) > 0) { // rich - good looking $s_user_answer = Database::result($res_user_answer, 0, 0); } else { $s_user_answer = 0; } $i_answerWeighting = $a_answers['ponderation']; $user_answer = ''; if (!empty($s_user_answer)) { if ($answerType == DRAGGABLE) { if ($s_user_answer == $i_answer_correct_answer) { $questionScore += $i_answerWeighting; $totalScore += $i_answerWeighting; $user_answer = Display::label(get_lang('Correct'), 'success'); } else { $user_answer = Display::label(get_lang('Incorrect'), 'danger'); } } else { if ($s_user_answer == $i_answer_correct_answer) { $questionScore += $i_answerWeighting; $totalScore += $i_answerWeighting; if (isset($real_list[$i_answer_id])) { $user_answer = Display::span($real_list[$i_answer_id]); } } else { $user_answer = Display::span($real_list[$s_user_answer], ['style' => 'color: #FF0000; text-decoration: line-through;']); } } } elseif ($answerType == DRAGGABLE) { $user_answer = Display::label(get_lang('Incorrect'), 'danger'); } if ($show_result) { echo '<tr>'; echo '<td>' . $s_answer_label . '</td>'; echo '<td>' . $user_answer; if (in_array($answerType, [MATCHING, MATCHING_DRAGGABLE])) { if (isset($real_list[$i_answer_correct_answer])) { echo Display::span($real_list[$i_answer_correct_answer], ['style' => 'color: #008000; font-weight: bold;']); } } echo '</td>'; echo '</tr>'; } } break 2; // break the switch and the "for" condition } else { if ($answerCorrect) { if (isset($choice[$answerAutoId]) && $answerCorrect == $choice[$answerAutoId]) { $questionScore += $answerWeighting; $totalScore += $answerWeighting; $user_answer = Display::span($answerMatching[$choice[$answerAutoId]]); } else { if (isset($answerMatching[$choice[$answerAutoId]])) { $user_answer = Display::span($answerMatching[$choice[$answerAutoId]], ['style' => 'color: #FF0000; text-decoration: line-through;']); } } $matching[$answerAutoId] = $choice[$answerAutoId]; } break; } case HOT_SPOT: if ($from_database) { $TBL_TRACK_HOTSPOT = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT); $sql = "SELECT hotspot_correct\n FROM {$TBL_TRACK_HOTSPOT}\n WHERE\n hotspot_exe_id = '" . $exeId . "' AND\n hotspot_question_id= '" . $questionId . "' AND\n hotspot_answer_id = " . intval($answerAutoId) . ""; $result = Database::query($sql); $studentChoice = Database::result($result, 0, "hotspot_correct"); if ($studentChoice) { $questionScore += $answerWeighting; $totalScore += $answerWeighting; } } else { if (!isset($choice[$answerAutoId])) { $choice[$answerAutoId] = 0; } else { $studentChoice = $choice[$answerAutoId]; $choiceIsValid = false; if (!empty($studentChoice)) { $hotspotType = $objAnswerTmp->selectHotspotType($answerId); $hotspotCoordinates = $objAnswerTmp->selectHotspotCoordinates($answerId); $choicePoint = Geometry::decodePoint($studentChoice); switch ($hotspotType) { case 'square': $hotspotProperties = Geometry::decodeSquare($hotspotCoordinates); $choiceIsValid = Geometry::pointIsInSquare($hotspotProperties, $choicePoint); break; case 'circle': $hotspotProperties = Geometry::decodeEllipse($hotspotCoordinates); $choiceIsValid = Geometry::pointIsInEllipse($hotspotProperties, $choicePoint); break; case 'poly': $hotspotProperties = Geometry::decodePolygon($hotspotCoordinates); $choiceIsValid = Geometry::pointIsInPolygon($hotspotProperties, $choicePoint); break; } } $choice[$answerAutoId] = 0; if ($choiceIsValid) { $questionScore += $answerWeighting; $totalScore += $answerWeighting; $choice[$answerAutoId] = 1; } } } break; // @todo never added to chamilo //for hotspot with fixed order // @todo never added to chamilo //for hotspot with fixed order case HOT_SPOT_ORDER: $studentChoice = $choice['order'][$answerId]; if ($studentChoice == $answerId) { $questionScore += $answerWeighting; $totalScore += $answerWeighting; $studentChoice = true; } else { $studentChoice = false; } break; // for hotspot with delineation // for hotspot with delineation case HOT_SPOT_DELINEATION: if ($from_database) { // getting the user answer $TBL_TRACK_HOTSPOT = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT); $query = "SELECT hotspot_correct, hotspot_coordinate\n FROM {$TBL_TRACK_HOTSPOT}\n WHERE\n hotspot_exe_id = '" . $exeId . "' AND\n hotspot_question_id= '" . $questionId . "' AND\n hotspot_answer_id='1'"; //by default we take 1 because it's a delineation $resq = Database::query($query); $row = Database::fetch_array($resq, 'ASSOC'); $choice = $row['hotspot_correct']; $user_answer = $row['hotspot_coordinate']; // THIS is very important otherwise the poly_compile will throw an error!! // round-up the coordinates $coords = explode('/', $user_answer); $user_array = ''; foreach ($coords as $coord) { list($x, $y) = explode(';', $coord); $user_array .= round($x) . ';' . round($y) . '/'; } $user_array = substr($user_array, 0, -1); } else { if (!empty($studentChoice)) { $newquestionList[] = $questionId; } if ($answerId === 1) { $studentChoice = $choice[$answerId]; $questionScore += $answerWeighting; if ($hotspot_delineation_result[1] == 1) { $totalScore += $answerWeighting; //adding the total } } } $_SESSION['hotspot_coord'][1] = $delineation_cord; $_SESSION['hotspot_dest'][1] = $answer_delineation_destination; break; } // end switch Answertype if ($show_result) { if ($debug) { error_log('show result ' . $show_result); } if ($from == 'exercise_result') { if ($debug) { error_log('Showing questions $from ' . $from); } //display answers (if not matching type, or if the answer is correct) if (!in_array($answerType, [MATCHING, DRAGGABLE, MATCHING_DRAGGABLE]) || $answerCorrect) { if (in_array($answerType, array(UNIQUE_ANSWER, UNIQUE_ANSWER_IMAGE, UNIQUE_ANSWER_NO_OPTION, MULTIPLE_ANSWER, MULTIPLE_ANSWER_COMBINATION, GLOBAL_MULTIPLE_ANSWER))) { //if ($origin != 'learnpath') { ExerciseShowFunctions::display_unique_or_multiple_answer($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, 0, 0, 0, $results_disabled); //} } elseif ($answerType == MULTIPLE_ANSWER_TRUE_FALSE) { //if ($origin!='learnpath') { ExerciseShowFunctions::display_multiple_answer_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, 0, $questionId, 0, $results_disabled); //} } elseif ($answerType == MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE) { // if ($origin!='learnpath') { ExerciseShowFunctions::display_multiple_answer_combination_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, 0, 0, 0, $results_disabled); //} } elseif ($answerType == FILL_IN_BLANKS) { //if ($origin!='learnpath') { ExerciseShowFunctions::display_fill_in_blanks_answer($feedback_type, $answer, 0, 0, $results_disabled); // } } elseif ($answerType == CALCULATED_ANSWER) { //if ($origin!='learnpath') { ExerciseShowFunctions::display_calculated_answer($feedback_type, $answer, 0, 0); // } } elseif ($answerType == FREE_ANSWER) { //if($origin != 'learnpath') { ExerciseShowFunctions::display_free_answer($feedback_type, $choice, $exeId, $questionId, $questionScore); //} } elseif ($answerType == ORAL_EXPRESSION) { // to store the details of open questions in an array to be used in mail //if ($origin != 'learnpath') { ExerciseShowFunctions::display_oral_expression_answer($feedback_type, $choice, 0, 0, $nano); //} } elseif ($answerType == HOT_SPOT) { //if ($origin != 'learnpath') { ExerciseShowFunctions::display_hotspot_answer($feedback_type, $answerId, $answer, $studentChoice, $answerComment, $results_disabled); // } } elseif ($answerType == HOT_SPOT_ORDER) { //if ($origin != 'learnpath') { ExerciseShowFunctions::display_hotspot_order_answer($feedback_type, $answerId, $answer, $studentChoice, $answerComment); //} } elseif ($answerType == HOT_SPOT_DELINEATION) { $user_answer = $_SESSION['exerciseResultCoordinates'][$questionId]; //round-up the coordinates $coords = explode('/', $user_answer); $user_array = ''; foreach ($coords as $coord) { list($x, $y) = explode(';', $coord); $user_array .= round($x) . ';' . round($y) . '/'; } $user_array = substr($user_array, 0, -1); if ($next) { $user_answer = $user_array; // we compare only the delineation not the other points $answer_question = $_SESSION['hotspot_coord'][1]; $answerDestination = $_SESSION['hotspot_dest'][1]; //calculating the area $poly_user = convert_coordinates($user_answer, '/'); $poly_answer = convert_coordinates($answer_question, '|'); $max_coord = poly_get_max($poly_user, $poly_answer); $poly_user_compiled = poly_compile($poly_user, $max_coord); $poly_answer_compiled = poly_compile($poly_answer, $max_coord); $poly_results = poly_result($poly_answer_compiled, $poly_user_compiled, $max_coord); $overlap = $poly_results['both']; $poly_answer_area = $poly_results['s1']; $poly_user_area = $poly_results['s2']; $missing = $poly_results['s1Only']; $excess = $poly_results['s2Only']; //$overlap = round(polygons_overlap($poly_answer,$poly_user)); // //this is an area in pixels if ($debug > 0) { error_log(__LINE__ . ' - Polygons results are ' . print_r($poly_results, 1), 0); } if ($overlap < 1) { //shortcut to avoid complicated calculations $final_overlap = 0; $final_missing = 100; $final_excess = 100; } else { // the final overlap is the percentage of the initial polygon // that is overlapped by the user's polygon $final_overlap = round((double) $overlap / (double) $poly_answer_area * 100); if ($debug > 1) { error_log(__LINE__ . ' - Final overlap is ' . $final_overlap, 0); } // the final missing area is the percentage of the initial polygon // that is not overlapped by the user's polygon $final_missing = 100 - $final_overlap; if ($debug > 1) { error_log(__LINE__ . ' - Final missing is ' . $final_missing, 0); } // the final excess area is the percentage of the initial polygon's size // that is covered by the user's polygon outside of the initial polygon $final_excess = round(((double) $poly_user_area - (double) $overlap) / (double) $poly_answer_area * 100); if ($debug > 1) { error_log(__LINE__ . ' - Final excess is ' . $final_excess, 0); } } //checking the destination parameters parsing the "@@" $destination_items = explode('@@', $answerDestination); $threadhold_total = $destination_items[0]; $threadhold_items = explode(';', $threadhold_total); $threadhold1 = $threadhold_items[0]; // overlap $threadhold2 = $threadhold_items[1]; // excess $threadhold3 = $threadhold_items[2]; //missing // if is delineation if ($answerId === 1) { //setting colors if ($final_overlap >= $threadhold1) { $overlap_color = true; //echo 'a'; } //echo $excess.'-'.$threadhold2; if ($final_excess <= $threadhold2) { $excess_color = true; //echo 'b'; } //echo '--------'.$missing.'-'.$threadhold3; if ($final_missing <= $threadhold3) { $missing_color = true; //echo 'c'; } // if pass if ($final_overlap >= $threadhold1 && $final_missing <= $threadhold3 && $final_excess <= $threadhold2) { $next = 1; //go to the oars $result_comment = get_lang('Acceptable'); $final_answer = 1; // do not update with update_exercise_attempt } else { $next = 0; $result_comment = get_lang('Unacceptable'); $comment = $answerDestination = $objAnswerTmp->selectComment(1); $answerDestination = $objAnswerTmp->selectDestination(1); //checking the destination parameters parsing the "@@" $destination_items = explode('@@', $answerDestination); } } elseif ($answerId > 1) { if ($objAnswerTmp->selectHotspotType($answerId) == 'noerror') { if ($debug > 0) { error_log(__LINE__ . ' - answerId is of type noerror', 0); } //type no error shouldn't be treated $next = 1; continue; } if ($debug > 0) { error_log(__LINE__ . ' - answerId is >1 so we\'re probably in OAR', 0); } //check the intersection between the oar and the user //echo 'user'; print_r($x_user_list); print_r($y_user_list); //echo 'official';print_r($x_list);print_r($y_list); //$result = get_intersection_data($x_list,$y_list,$x_user_list,$y_user_list); $inter = $result['success']; //$delineation_cord=$objAnswerTmp->selectHotspotCoordinates($answerId); $delineation_cord = $objAnswerTmp->selectHotspotCoordinates($answerId); $poly_answer = convert_coordinates($delineation_cord, '|'); $max_coord = poly_get_max($poly_user, $poly_answer); $poly_answer_compiled = poly_compile($poly_answer, $max_coord); $overlap = poly_touch($poly_user_compiled, $poly_answer_compiled, $max_coord); if ($overlap == false) { //all good, no overlap $next = 1; continue; } else { if ($debug > 0) { error_log(__LINE__ . ' - Overlap is ' . $overlap . ': OAR hit', 0); } $organs_at_risk_hit++; //show the feedback $next = 0; $comment = $answerDestination = $objAnswerTmp->selectComment($answerId); $answerDestination = $objAnswerTmp->selectDestination($answerId); $destination_items = explode('@@', $answerDestination); $try_hotspot = $destination_items[1]; $lp_hotspot = $destination_items[2]; $select_question_hotspot = $destination_items[3]; $url_hotspot = $destination_items[4]; } } } else { // the first delineation feedback if ($debug > 0) { error_log(__LINE__ . ' first', 0); } } } elseif (in_array($answerType, [MATCHING, MATCHING_DRAGGABLE])) { echo '<tr>'; echo Display::tag('td', $answerMatching[$answerId]); echo Display::tag('td', "{$user_answer} / " . Display::tag('strong', $answerMatching[$answerCorrect], ['style' => 'color: #008000; font-weight: bold;'])); echo '</tr>'; } } } else { if ($debug) { error_log('Showing questions $from ' . $from); } switch ($answerType) { case UNIQUE_ANSWER: case UNIQUE_ANSWER_IMAGE: case UNIQUE_ANSWER_NO_OPTION: case MULTIPLE_ANSWER: case GLOBAL_MULTIPLE_ANSWER: case MULTIPLE_ANSWER_COMBINATION: if ($answerId == 1) { ExerciseShowFunctions::display_unique_or_multiple_answer($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, $exeId, $questionId, $answerId, $results_disabled); } else { ExerciseShowFunctions::display_unique_or_multiple_answer($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, $exeId, $questionId, "", $results_disabled); } break; case MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE: if ($answerId == 1) { ExerciseShowFunctions::display_multiple_answer_combination_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, $exeId, $questionId, $answerId, $results_disabled); } else { ExerciseShowFunctions::display_multiple_answer_combination_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, $exeId, $questionId, "", $results_disabled); } break; case MULTIPLE_ANSWER_TRUE_FALSE: if ($answerId == 1) { ExerciseShowFunctions::display_multiple_answer_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, $exeId, $questionId, $answerId, $results_disabled); } else { ExerciseShowFunctions::display_multiple_answer_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, $exeId, $questionId, "", $results_disabled); } break; case FILL_IN_BLANKS: ExerciseShowFunctions::display_fill_in_blanks_answer($feedback_type, $answer, $exeId, $questionId, $results_disabled, $str); break; case CALCULATED_ANSWER: ExerciseShowFunctions::display_calculated_answer($feedback_type, $answer, $exeId, $questionId); break; case FREE_ANSWER: echo ExerciseShowFunctions::display_free_answer($feedback_type, $choice, $exeId, $questionId, $questionScore); break; case ORAL_EXPRESSION: echo '<tr> <td valign="top">' . ExerciseShowFunctions::display_oral_expression_answer($feedback_type, $choice, $exeId, $questionId, $nano) . '</td> </tr> </table>'; break; case HOT_SPOT: ExerciseShowFunctions::display_hotspot_answer($feedback_type, $answerId, $answer, $studentChoice, $answerComment, $results_disabled); break; case HOT_SPOT_DELINEATION: $user_answer = $user_array; if ($next) { //$tbl_track_e_hotspot = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT); // Save into db /* $sql = "INSERT INTO $tbl_track_e_hotspot ( * hotspot_user_id, * hotspot_course_code, * hotspot_exe_id, * hotspot_question_id, * hotspot_answer_id, * hotspot_correct, * hotspot_coordinate * ) VALUES ( * '".Database::escape_string($_user['user_id'])."', * '".Database::escape_string($_course['id'])."', * '".Database::escape_string($exeId)."', '".Database::escape_string($questionId)."', * '".Database::escape_string($answerId)."', * '".Database::escape_string($studentChoice)."', * '".Database::escape_string($user_array)."')"; $result = Database::query($sql,__FILE__,__LINE__); */ $user_answer = $user_array; // we compare only the delineation not the other points $answer_question = $_SESSION['hotspot_coord'][1]; $answerDestination = $_SESSION['hotspot_dest'][1]; //calculating the area $poly_user = convert_coordinates($user_answer, '/'); $poly_answer = convert_coordinates($answer_question, '|'); $max_coord = poly_get_max($poly_user, $poly_answer); $poly_user_compiled = poly_compile($poly_user, $max_coord); $poly_answer_compiled = poly_compile($poly_answer, $max_coord); $poly_results = poly_result($poly_answer_compiled, $poly_user_compiled, $max_coord); $overlap = $poly_results['both']; $poly_answer_area = $poly_results['s1']; $poly_user_area = $poly_results['s2']; $missing = $poly_results['s1Only']; $excess = $poly_results['s2Only']; //$overlap = round(polygons_overlap($poly_answer,$poly_user)); //this is an area in pixels if ($debug > 0) { error_log(__LINE__ . ' - Polygons results are ' . print_r($poly_results, 1), 0); } if ($overlap < 1) { //shortcut to avoid complicated calculations $final_overlap = 0; $final_missing = 100; $final_excess = 100; } else { // the final overlap is the percentage of the initial polygon that is overlapped by the user's polygon $final_overlap = round((double) $overlap / (double) $poly_answer_area * 100); if ($debug > 1) { error_log(__LINE__ . ' - Final overlap is ' . $final_overlap, 0); } // the final missing area is the percentage of the initial polygon that is not overlapped by the user's polygon $final_missing = 100 - $final_overlap; if ($debug > 1) { error_log(__LINE__ . ' - Final missing is ' . $final_missing, 0); } // the final excess area is the percentage of the initial polygon's size that is covered by the user's polygon outside of the initial polygon $final_excess = round(((double) $poly_user_area - (double) $overlap) / (double) $poly_answer_area * 100); if ($debug > 1) { error_log(__LINE__ . ' - Final excess is ' . $final_excess, 0); } } //checking the destination parameters parsing the "@@" $destination_items = explode('@@', $answerDestination); $threadhold_total = $destination_items[0]; $threadhold_items = explode(';', $threadhold_total); $threadhold1 = $threadhold_items[0]; // overlap $threadhold2 = $threadhold_items[1]; // excess $threadhold3 = $threadhold_items[2]; //missing // if is delineation if ($answerId === 1) { //setting colors if ($final_overlap >= $threadhold1) { $overlap_color = true; //echo 'a'; } //echo $excess.'-'.$threadhold2; if ($final_excess <= $threadhold2) { $excess_color = true; //echo 'b'; } //echo '--------'.$missing.'-'.$threadhold3; if ($final_missing <= $threadhold3) { $missing_color = true; //echo 'c'; } // if pass if ($final_overlap >= $threadhold1 && $final_missing <= $threadhold3 && $final_excess <= $threadhold2) { $next = 1; //go to the oars $result_comment = get_lang('Acceptable'); $final_answer = 1; // do not update with update_exercise_attempt } else { $next = 0; $result_comment = get_lang('Unacceptable'); $comment = $answerDestination = $objAnswerTmp->selectComment(1); $answerDestination = $objAnswerTmp->selectDestination(1); //checking the destination parameters parsing the "@@" $destination_items = explode('@@', $answerDestination); } } elseif ($answerId > 1) { if ($objAnswerTmp->selectHotspotType($answerId) == 'noerror') { if ($debug > 0) { error_log(__LINE__ . ' - answerId is of type noerror', 0); } //type no error shouldn't be treated $next = 1; continue; } if ($debug > 0) { error_log(__LINE__ . ' - answerId is >1 so we\'re probably in OAR', 0); } //check the intersection between the oar and the user //echo 'user'; print_r($x_user_list); print_r($y_user_list); //echo 'official';print_r($x_list);print_r($y_list); //$result = get_intersection_data($x_list,$y_list,$x_user_list,$y_user_list); $inter = $result['success']; //$delineation_cord=$objAnswerTmp->selectHotspotCoordinates($answerId); $delineation_cord = $objAnswerTmp->selectHotspotCoordinates($answerId); $poly_answer = convert_coordinates($delineation_cord, '|'); $max_coord = poly_get_max($poly_user, $poly_answer); $poly_answer_compiled = poly_compile($poly_answer, $max_coord); $overlap = poly_touch($poly_user_compiled, $poly_answer_compiled, $max_coord); if ($overlap == false) { //all good, no overlap $next = 1; continue; } else { if ($debug > 0) { error_log(__LINE__ . ' - Overlap is ' . $overlap . ': OAR hit', 0); } $organs_at_risk_hit++; //show the feedback $next = 0; $comment = $answerDestination = $objAnswerTmp->selectComment($answerId); $answerDestination = $objAnswerTmp->selectDestination($answerId); $destination_items = explode('@@', $answerDestination); $try_hotspot = $destination_items[1]; $lp_hotspot = $destination_items[2]; $select_question_hotspot = $destination_items[3]; $url_hotspot = $destination_items[4]; } } } else { // the first delineation feedback if ($debug > 0) { error_log(__LINE__ . ' first', 0); } } break; case HOT_SPOT_ORDER: ExerciseShowFunctions::display_hotspot_order_answer($feedback_type, $answerId, $answer, $studentChoice, $answerComment); break; case DRAGGABLE: //no break //no break case MATCHING_DRAGGABLE: //no break //no break case MATCHING: echo '<tr>'; echo Display::tag('td', $answerMatching[$answerId]); echo Display::tag('td', "{$user_answer} / " . Display::tag('strong', $answerMatching[$answerCorrect], ['style' => 'color: #008000; font-weight: bold;'])); echo '</tr>'; break; } } } if ($debug) { error_log(' ------ '); } } // end for that loops over all answers of the current question if ($debug) { error_log('-- end answer loop --'); } $final_answer = true; foreach ($real_answers as $my_answer) { if (!$my_answer) { $final_answer = false; } } //we add the total score after dealing with the answers if ($answerType == MULTIPLE_ANSWER_COMBINATION || $answerType == MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE) { if ($final_answer) { //getting only the first score where we save the weight of all the question $answerWeighting = $objAnswerTmp->selectWeighting(1); $questionScore += $answerWeighting; $totalScore += $answerWeighting; } } //Fixes multiple answer question in order to be exact //if ($answerType == MULTIPLE_ANSWER || $answerType == GLOBAL_MULTIPLE_ANSWER) { /* if ($answerType == GLOBAL_MULTIPLE_ANSWER) { $diff = @array_diff($answer_correct_array, $real_answers); // All good answers or nothing works like exact $counter = 1; $correct_answer = true; foreach ($real_answers as $my_answer) { if ($debug) error_log(" my_answer: $my_answer answer_correct_array[counter]: ".$answer_correct_array[$counter]); if ($my_answer != $answer_correct_array[$counter]) { $correct_answer = false; break; } $counter++; } if ($debug) error_log(" answer_correct_array: ".print_r($answer_correct_array, 1).""); if ($debug) error_log(" real_answers: ".print_r($real_answers, 1).""); if ($debug) error_log(" correct_answer: ".$correct_answer); if ($correct_answer == false) { $questionScore = 0; } // This makes the result non exact if (!empty($diff)) { $questionScore = 0; } }*/ $extra_data = array('final_overlap' => $final_overlap, 'final_missing' => $final_missing, 'final_excess' => $final_excess, 'overlap_color' => $overlap_color, 'missing_color' => $missing_color, 'excess_color' => $excess_color, 'threadhold1' => $threadhold1, 'threadhold2' => $threadhold2, 'threadhold3' => $threadhold3); if ($from == 'exercise_result') { // if answer is hotspot. To the difference of exercise_show.php, // we use the results from the session (from_db=0) // TODO Change this, because it is wrong to show the user // some results that haven't been stored in the database yet if ($answerType == HOT_SPOT || $answerType == HOT_SPOT_ORDER || $answerType == HOT_SPOT_DELINEATION) { if ($debug) { error_log('$from AND this is a hotspot kind of question '); } $my_exe_id = 0; $from_database = 0; if ($answerType == HOT_SPOT_DELINEATION) { if (0) { if ($overlap_color) { $overlap_color = 'green'; } else { $overlap_color = 'red'; } if ($missing_color) { $missing_color = 'green'; } else { $missing_color = 'red'; } if ($excess_color) { $excess_color = 'green'; } else { $excess_color = 'red'; } if (!is_numeric($final_overlap)) { $final_overlap = 0; } if (!is_numeric($final_missing)) { $final_missing = 0; } if (!is_numeric($final_excess)) { $final_excess = 0; } if ($final_overlap > 100) { $final_overlap = 100; } $table_resume = '<table class="data_table"> <tr class="row_odd" > <td></td> <td ><b>' . get_lang('Requirements') . '</b></td> <td><b>' . get_lang('YourAnswer') . '</b></td> </tr> <tr class="row_even"> <td><b>' . get_lang('Overlap') . '</b></td> <td>' . get_lang('Min') . ' ' . $threadhold1 . '</td> <td><div style="color:' . $overlap_color . '">' . ($final_overlap < 0 ? 0 : intval($final_overlap)) . '</div></td> </tr> <tr> <td><b>' . get_lang('Excess') . '</b></td> <td>' . get_lang('Max') . ' ' . $threadhold2 . '</td> <td><div style="color:' . $excess_color . '">' . ($final_excess < 0 ? 0 : intval($final_excess)) . '</div></td> </tr> <tr class="row_even"> <td><b>' . get_lang('Missing') . '</b></td> <td>' . get_lang('Max') . ' ' . $threadhold3 . '</td> <td><div style="color:' . $missing_color . '">' . ($final_missing < 0 ? 0 : intval($final_missing)) . '</div></td> </tr> </table>'; if ($next == 0) { $try = $try_hotspot; $lp = $lp_hotspot; $destinationid = $select_question_hotspot; $url = $url_hotspot; } else { //show if no error //echo 'no error'; $comment = $answerComment = $objAnswerTmp->selectComment($nbrAnswers); $answerDestination = $objAnswerTmp->selectDestination($nbrAnswers); } echo '<h1><div style="color:#333;">' . get_lang('Feedback') . '</div></h1> <p style="text-align:center">'; $message = '<p>' . get_lang('YourDelineation') . '</p>'; $message .= $table_resume; $message .= '<br />' . get_lang('ResultIs') . ' ' . $result_comment . '<br />'; if ($organs_at_risk_hit > 0) { $message .= '<p><b>' . get_lang('OARHit') . '</b></p>'; } $message .= '<p>' . $comment . '</p>'; echo $message; } else { echo $hotspot_delineation_result[0]; //prints message $from_database = 1; // the hotspot_solution.swf needs this variable } //save the score attempts if (1) { //getting the answer 1 or 0 comes from exercise_submit_modal.php $final_answer = $hotspot_delineation_result[1]; if ($final_answer == 0) { $questionScore = 0; } // we always insert the answer_id 1 = delineation Event::saveQuestionAttempt($questionScore, 1, $quesId, $exeId, 0); //in delineation mode, get the answer from $hotspot_delineation_result[1] Event::saveExerciseAttemptHotspot($exeId, $quesId, 1, $hotspot_delineation_result[1], $exerciseResultCoordinates[$quesId]); } else { if ($final_answer == 0) { $questionScore = 0; $answer = 0; Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0); if (is_array($exerciseResultCoordinates[$quesId])) { foreach ($exerciseResultCoordinates[$quesId] as $idx => $val) { Event::saveExerciseAttemptHotspot($exeId, $quesId, $idx, 0, $val); } } } else { Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0); if (is_array($exerciseResultCoordinates[$quesId])) { foreach ($exerciseResultCoordinates[$quesId] as $idx => $val) { Event::saveExerciseAttemptHotspot($exeId, $quesId, $idx, $choice[$idx], $val); } } } } $my_exe_id = $exeId; } } if ($answerType == HOT_SPOT || $answerType == HOT_SPOT_ORDER) { // We made an extra table for the answers if ($show_result) { // if ($origin != 'learnpath') { echo '</table></td></tr>'; echo "\n <tr>\n <td colspan=\"2\">\n <p><em>" . get_lang('HotSpot') . "</em></p>\n <div id=\"hotspot-solution-{$questionId}\"></div>\n\n <script>\n \$(document).on('ready', function () {\n new HotspotQuestion({\n questionId: {$questionId},\n exerciseId: {$exeId},\n selector: '#hotspot-solution-{$questionId}',\n for: 'solution'\n });\n });\n </script>\n </td>\n </tr>\n "; // } } } //if ($origin != 'learnpath') { if ($show_result) { echo '</table>'; } // } } unset($objAnswerTmp); $totalWeighting += $questionWeighting; // Store results directly in the database // For all in one page exercises, the results will be // stored by exercise_results.php (using the session) if ($saved_results) { if ($debug) { error_log("Save question results {$saved_results}"); } if ($debug) { error_log(print_r($choice, 1)); } if (empty($choice)) { $choice = 0; } if ($answerType == MULTIPLE_ANSWER_TRUE_FALSE || $answerType == MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE) { if ($choice != 0) { $reply = array_keys($choice); for ($i = 0; $i < sizeof($reply); $i++) { $ans = $reply[$i]; Event::saveQuestionAttempt($questionScore, $ans . ':' . $choice[$ans], $quesId, $exeId, $i, $this->id); if ($debug) { error_log('result =>' . $questionScore . ' ' . $ans . ':' . $choice[$ans]); } } } else { Event::saveQuestionAttempt($questionScore, 0, $quesId, $exeId, 0, $this->id); } } elseif ($answerType == MULTIPLE_ANSWER || $answerType == GLOBAL_MULTIPLE_ANSWER) { if ($choice != 0) { $reply = array_keys($choice); if ($debug) { error_log("reply " . print_r($reply, 1) . ""); } for ($i = 0; $i < sizeof($reply); $i++) { $ans = $reply[$i]; Event::saveQuestionAttempt($questionScore, $ans, $quesId, $exeId, $i, $this->id); } } else { Event::saveQuestionAttempt($questionScore, 0, $quesId, $exeId, 0, $this->id); } } elseif ($answerType == MULTIPLE_ANSWER_COMBINATION) { if ($choice != 0) { $reply = array_keys($choice); for ($i = 0; $i < sizeof($reply); $i++) { $ans = $reply[$i]; Event::saveQuestionAttempt($questionScore, $ans, $quesId, $exeId, $i, $this->id); } } else { Event::saveQuestionAttempt($questionScore, 0, $quesId, $exeId, 0, $this->id); } } elseif (in_array($answerType, [MATCHING, DRAGGABLE, MATCHING_DRAGGABLE])) { if (isset($matching)) { foreach ($matching as $j => $val) { Event::saveQuestionAttempt($questionScore, $val, $quesId, $exeId, $j, $this->id); } } } elseif ($answerType == FREE_ANSWER) { $answer = $choice; Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0, $this->id); } elseif ($answerType == ORAL_EXPRESSION) { $answer = $choice; Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0, $this->id, $nano); } elseif (in_array($answerType, [UNIQUE_ANSWER, UNIQUE_ANSWER_IMAGE, UNIQUE_ANSWER_NO_OPTION])) { $answer = $choice; Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0, $this->id); // } elseif ($answerType == HOT_SPOT || $answerType == HOT_SPOT_DELINEATION) { } elseif ($answerType == HOT_SPOT) { $answer = []; if (isset($exerciseResultCoordinates[$questionId]) && !empty($exerciseResultCoordinates[$questionId])) { Database::delete(Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT), ['hotspot_exe_id = ? AND hotspot_question_id = ? AND c_id = ?' => [$exeId, $questionId, api_get_course_int_id()]]); foreach ($exerciseResultCoordinates[$questionId] as $idx => $val) { $answer[] = $val; Event::saveExerciseAttemptHotspot($exeId, $quesId, $idx, $choice[$idx], $val, false, $this->id); } } Event::saveQuestionAttempt($questionScore, implode('|', $answer), $quesId, $exeId, 0, $this->id); } else { Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0, $this->id); } } if ($propagate_neg == 0 && $questionScore < 0) { $questionScore = 0; } if ($saved_results) { $stat_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES); $sql = 'UPDATE ' . $stat_table . ' SET exe_result = exe_result + ' . floatval($questionScore) . ' WHERE exe_id = ' . $exeId; if ($debug) { error_log($sql); } Database::query($sql); } $return_array = array('score' => $questionScore, 'weight' => $questionWeighting, 'extra' => $extra_data, 'open_question' => $arrques, 'open_answer' => $arrans, 'answer_type' => $answerType); return $return_array; }
public function __construct($x, $y) { $this->x = $x; $this->y = $y; parent::__construct(__CLASS__); }
/** * Serialize geometries into a WKT string. * * @param Geometry $geometry * @param string $return_type Should be either 'string' or 'array' * * @return string Does a reverse geocode of the geometry */ public function write(Geometry $geometry, $return_type = 'string') { $centroid = $geometry->getCentroid(); $lat = $centroid->getY(); $lon = $centroid->getX(); $url = "http://maps.googleapis.com/maps/api/geocode/json"; $url .= '?latlng=' . $lat . ',' . $lon; $url .= '&sensor=false'; $this->result = json_decode(@file_get_contents($url)); if ($this->result->status == 'OK') { if ($return_type == 'string') { return $this->result->results[0]->formatted_address; } if ($return_type == 'array') { return $this->result->results[0]->address_components; } } elseif ($this->result->status == 'ZERO_RESULTS') { if ($return_type == 'string') { return ''; } if ($return_type == 'array') { return $this->result->results; } } else { if ($this->result->status) { throw new Exception('Error in Google Reverse Geocoder: ' . $this->result->status); } else { throw new Exception('Unknown error in Google Reverse Geocoder'); } return FALSE; } }
public function project(Geometry $point, $normalized = NULL) { if ($this->geos()) { return $this->geos()->project($point->geos(), $normalized); } }
/** * 区域班列查询 */ public function inarea() { //先获取到参数 $starttime = $this->_get('starttime'); $endtime = $this->_get('endtime'); $points = json_decode($_GET['area']); if (empty($starttime)) { return_value_json(false, 'msg', '系统出错:开始时间为空'); } if (strlen($starttime) != 19 || strtotime($starttime) === false) { return_value_json(false, 'msg', '系统出错:开始时间格式不正确'); } if (!empty($endtime) && (strlen($endtime) != 19 || strtotime($endtime) === false)) { return_value_json(false, 'msg', '系统出错:结束时间格式不正确'); } if (empty($points) || !is_array($points) || count($points) < 2) { return_value_json(false, 'msg', '系统出错:多边形端点数量不够'); } foreach ($points as $index => $point) { $points[$index] = (array) $point; //把对象转成数组 } //首先查询数据库里指定时间内所有的定位信息 $Location = M('Location'); check_error($Location); $condition = array('_string' => " `location`.`time`>='{$starttime}' AND `train`.`number` IS NOT NULL "); if (!empty($endtime)) { $condition['_string'] .= " AND `location`.`time`<='{$endtime}' "; } $Location->join('`device` on `device`.`id`=`location`.`device_id`')->join("`train` on (`train`.`id`=`device`.`target_id` AND `device`.`target_type`='班列')")->join('`department` on `department`.`id`=`train`.`department_id`')->field(array('`location`.`id`', '`department`.`id`' => 'department_id', '`department`.`name`' => 'department', '`train`.`id`' => 'train_id', '`train`.`number`', '`train`.`due_date`', '`train`.`due_time`', '`location`.`device_id`', '`device`.`type`', '`device`.`label`', '`location`.`time`', 'state', 'online', '`location`.`address`', 'baidu_lat', 'baidu_lng', 'speed', 'direction', 'mcc', 'mnc', 'lac', 'cellid', '`location`.`range`'))->where($condition)->order('`department`.`sequence`, `train`.`id`, `time` ASC'); //先按班列id,然后按时间顺序 // $page = $_REQUEST['page'] + 0; // $limit = $_REQUEST['limit'] + 0; // if($page && $limit) $Location->limit($limit)->page($page); //这里不用数据库的分页,而是用我们自己的分页(目前没法分页了) $locations = $Location->select(); check_error($Location); $total = 0; $results = array(); $curTrain = null; //当前在区域内的班列 $alreadyIn = false; //目前是否已经在区域内 $lastLocation = null; foreach ($locations as $location) { $in = Geometry::geoPointInPolygon(array('lat' => $location['baidu_lat'], 'lng' => $location['baidu_lng']), $points); //TODO 考虑当前点与上一个定位点的轨迹线段是否切割多边形? if ($in) { if ($alreadyIn && $curTrain != $location['train_id']) { //已经在区域内,但是现在来了个不同的车(原来的车不知道跑哪里去了,这个车不知道是从哪里来的) //那么我们认为前车的离开点就是他轨迹的最后一个点,并且它现在离开区域了 $lastTrainLocationsCount = count($results[$total - 1]['locations']); if ($lastTrainLocationsCount > 0) { $results[$total - 1]['time_out'] = $results[$total - 1]['locations'][$lastTrainLocationsCount - 1]['time']; $results[$total - 1]['duration'] = $this->_getFriendlyDurationText($results[$total - 1]['time_in'], $results[$total - 1]['time_out']); $alreadyIn = false; $curTrain = null; } } if (!$alreadyIn && $curTrain === null) { //首次进入 $alreadyIn = true; $curTrain = $location['train_id']; $results[] = array('id' => $location['id'], 'department_id' => $location['department_id'], 'department' => $location['department'], 'train_id' => $location['train_id'], 'number' => $location['number'], 'device_id' => $location['device_id'], 'label' => $location['label'], 'time_in' => $location['time'], 'time_out' => '', 'duration' => '', 'locations' => array(), 'first_isout' => false, 'last_isout' => false); $total++; if ($lastLocation !== null && $lastLocation['train_id'] == $location['train_id']) { $results[$total - 1]['locations'][] = $lastLocation; $results[$total - 1]['first_isout'] = true; } } $results[$total - 1]['locations'][] = $location; } else { //出了区域 if ($alreadyIn) { if ($curTrain != $location['train_id']) { //原来的车不知道跑哪里去了 $lastTrainLocationsCount = count($results[$total - 1]['locations']); if ($lastTrainLocationsCount > 0) { $results[$total - 1]['time_out'] = $results[$total - 1]['locations'][$lastTrainLocationsCount - 1]['time']; } else { //这是不可能的。 $results[$total - 1]['time_out'] = $location['time']; } } else { //记录班列离开的点 $results[$total - 1]['time_out'] = $location['time']; $results[$total - 1]['locations'][] = $location; $results[$total - 1]['last_isout'] = true; } $results[$total - 1]['duration'] = $this->_getFriendlyDurationText($results[$total - 1]['time_in'], $results[$total - 1]['time_out']); $alreadyIn = false; $curTrain = null; } } $lastLocation = $location; } return_json(true, $total, 'results', $results); }
/** * Update the uploaded EPANET file adding thw WaterRequest info and sends it to the client * @param string $id string representing the ID of a WaterRequest */ public function actionEpanet($id) { $this->layout = '//layouts/column1'; //retrieve water request $wr = $this->loadModel($id); if (Yii::app()->user->checkAccess('epanetWaterRequest', array('waterRequest' => $wr))) { $model = new EpanetForm(); //parametrized values available $replaceable_parameters = array('first_name' => 'First name of water request\'s owner', 'last_name' => 'Last name of water request\'s owner', 'date' => 'Water Request date', 'project' => 'Water Request project name', 'index' => 'Autoincrement index'); //parametrized values marker $replaceable_parameters_marker = '$'; //form field in which user can insert parametrized values $form_elements = array('tag', 'demand_pattern', 'demand_categories', 'emitter_coeff', 'initial_quality', 'source_quality', 'srid', 'other_srid'); if (isset($_POST['EpanetForm'])) { //setting directory to retrieve the uploaded file and to store the new file $up_dir = Yii::getPathOfAlias('webroot') . DIRECTORY_SEPARATOR . Yii::app()->params['EPANET']['upload_dir'] . DIRECTORY_SEPARATOR; $down_dir = Yii::getPathOfAlias('webroot') . DIRECTORY_SEPARATOR . Yii::app()->params['EPANET']['download_dir'] . DIRECTORY_SEPARATOR; //retrieving information about uploaded file $file_info = pathinfo($_POST['EpanetForm']['filename']); $filename = $file_info['filename']; $ext = $file_info['extension']; //setting upload and download directory-filename $up_file_dir = $up_dir . $filename . '.' . $ext; $down_filename = $filename . Yii::app()->params['EPANET']['download_filename_suffix']; $down_file_dir = $down_dir . $down_filename . '.' . $ext; //read epanet network from file $epanet = new EPANET($up_file_dir); //retrieving some parameters from water request $first_name = $wr->username; $last_name = $wr->username; $date = $wr->dateHR; $project = $wr->project; $wr_id = $wr->id; // setting prefix $junction_prefix = Yii::app()->params['EPANET']['junction_prefix']; if ($junction_prefix !== '') { $junction_prefix = substr(Yii::app()->params['EPANET']['junction_prefix'], 0, 3) . '_'; } $junction_prefix = $junction_prefix . $wr_id; $index = 0; //loop into geometries foreach ($wr->geometries() as $geom) { $water_demand = 0; $description = ''; $zones_array = array(); //loop into zones to calculate total water demand for each geometry foreach ($geom->zones() as $zone) { $water_demand += $zone->water_demand; if (array_search($zone->zone_name, $zones_array) === false) { array_push($zones_array, $zone->zone_name); } } foreach ($zones_array as $zs) { $description = $description . $zs . ' '; } //substitute, from form elements, water request parameters foreach ($form_elements as $element) { $str = $_POST['EpanetForm'][$element]; foreach ($replaceable_parameters as $param => $text) { ${$element} = str_replace($replaceable_parameters_marker . $param, ${$param}, $str); $str = ${$element}; } } //be sure to have all parameters before invoking addJunction // junction_id is in config file //if (!isset($junction_id)) // $junction_id = 'a'; // La descrizione viene generata a partire dalle Zone della geometria //if (!isset($description)) // $description = 'b'; if (!isset($tag)) { $tag = 'c'; } if (!isset($demand_pattern)) { $demand_pattern = 'd'; } if (!isset($demand_categories)) { $demand_categories = ''; } if (!isset($emitter_coeff)) { $emitter_coeff = ''; } if (!isset($initial_quality)) { $initial_quality = ''; } if (!isset($source_quality)) { $source_quality = ''; } //check if srid passed exists if (isset($srid) && $srid == 'other') { if (isset($other_srid) && Geometry::Srid_Exists($other_srid)) { $srid = $other_srid; Yii::app()->user->usedSrid($srid); } else { echo 'Incorrect srid'; Yii::app()->end(); } } $elevation = $geom->elevation; //Yii::log('Elevation: '.print_r($elevation, true) , CLogger::LEVEL_INFO, 'actionEpanet'); // DEBUG if (isset($srid) && $srid != Yii::app()->params['geoserver']['water_request_geometries_srid']) { $centroid = $geom->getCentroid($srid); } else { $centroid = $geom->centroid; } //$junction_id = $junction_prefix.'_'.$geom->id.'_'.$junction_id; $junction_id = $junction_prefix . '_' . $geom->id; //add geometry centroid and parameters to epanet $epanet->addJunction($junction_id, $centroid['x'], $centroid['y'], $description, $tag, $elevation, $water_demand, $demand_pattern, $demand_categories, $emitter_coeff, $initial_quality, $source_quality); $index++; } //write epanet network into file $epanet->finalize($down_file_dir); //send file Yii::app()->request->sendFile($down_filename . '.' . $ext, file_get_contents($down_file_dir), $ext, true); // Non riesce a fare il redirect e appende al file .inp la pagina wr/view //$this->redirect('view',array('id'=>$wr->id)); return; } $this->render('epanet', array('wr' => $wr, 'model' => $model, 'replaceable_parameters' => $replaceable_parameters, 'replaceable_parameters_marker' => $replaceable_parameters_marker)); } else { throw new CHttpException(403, Yii::t('http_status', '403')); } }
/** * @see http://php.net/manual/en/jsonserializable.jsonserialize.php */ public function jsonSerialize() { return array_merge(parent::jsonSerialize(), array('geometries' => array_map(function (Geometry $geometry) { return $geometry->jsonSerialize(); }, $this->geometries))); }
public function SaveGeometries() { if ($this->supporting_geometry == true) { $this->DeleteGeometries(); $this->loadGeometriesFromPost(); if (is_array($this->geometries)) { //$this->geometries = array_unique($this->geometries); foreach ($this->geometries as $key => $geometries) { $geometries = array_unique($geometries); foreach ($geometries as $geometry) { $geometryObject = new Geometry($this->entity); $geometryObject->geometry_record_number = shn_create_uuid('mlt_geometry'); $geometryObject->entity_id = $this->{$this->keyName}; //$field = Browse::getFieldByName($this->entity,$key); $geometryObject->field_name = $key; $geometryObject->geometry = $geometry; $geometryObject->Save(); } } } } }
/** * Create and return a location * * @param array $input * * @return \Location */ private function createLocation($input) { if (!empty($input['geometry'])) { $location = new \Location(); $location->save(); if (empty($input['label'])) { \App::abort(400, 'Geographical label cannot be empty.'); } $label = \Label::create(['label' => $input['label']]); $geometry = \Geometry::create(['type' => 'geojson', 'geometry' => $input['geometry']]); $location->geometry()->save($geometry); $location->label()->save($label); return $location; } else { return null; } }