From efcd6d14dd2b515c3c56c912457e9a23e9f307ed Mon Sep 17 00:00:00 2001 From: Julio Date: Thu, 28 Mar 2019 10:44:26 +0100 Subject: [PATCH] Add "allow_gradebook_stats" config to improve gradebook speed See BT#14357 Requires: - DB changes see configuration.dist.php - editing the entities: GradebookLink.php and GradebookEvaluation --- main/exercise/exercise.class.php | 149 ++++++- main/gradebook/gradebook_add_eval.php | 8 +- main/gradebook/gradebook_add_result.php | 13 +- main/gradebook/gradebook_display_summary.php | 93 ++++- main/gradebook/gradebook_edit_result.php | 11 + main/gradebook/gradebook_view_result.php | 6 +- main/gradebook/index.php | 133 ++++--- main/gradebook/lib/GradebookUtils.php | 40 +- main/gradebook/lib/be/abstractlink.class.php | 52 ++- main/gradebook/lib/be/category.class.php | 12 + main/gradebook/lib/be/evaluation.class.php | 111 ++++++ main/gradebook/lib/be/exerciselink.class.php | 72 ++++ main/gradebook/lib/be/linkfactory.class.php | 4 +- main/gradebook/lib/be/result.class.php | 5 +- .../gradebook/lib/fe/gradebooktable.class.php | 370 +++++++++++------- .../lib/gradebook_data_generator.class.php | 303 +++++++++----- main/inc/lib/exercise.lib.php | 10 + main/inc/lib/pdf.lib.php | 13 +- main/inc/lib/text.lib.php | 21 +- main/install/configuration.dist.php | 7 + .../CoreBundle/Entity/GradebookEvaluation.php | 112 ++++++ .../CoreBundle/Entity/GradebookLink.php | 112 ++++++ 22 files changed, 1309 insertions(+), 348 deletions(-) diff --git a/main/exercise/exercise.class.php b/main/exercise/exercise.class.php index ea9b25491a..57a3acd716 100755 --- a/main/exercise/exercise.class.php +++ b/main/exercise/exercise.class.php @@ -2767,6 +2767,7 @@ class Exercise */ public function cleanResults($cleanLpTests = false, $cleanResultBeforeDate = null) { + $sessionId = api_get_session_id(); $table_track_e_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES); $table_track_e_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT); @@ -2796,7 +2797,7 @@ class Exercise WHERE c_id = ".api_get_course_int_id()." AND exe_exo_id = ".$this->id." AND - session_id = ".api_get_session_id()." ". + session_id = ".$sessionId." ". $sql_where; $result = Database::query($sql); @@ -2814,15 +2815,16 @@ class Exercise } } - $session_id = api_get_session_id(); // delete TRACK_E_EXERCISES table $sql = "DELETE FROM $table_track_e_exercises WHERE c_id = ".api_get_course_int_id()." AND exe_exo_id = ".$this->id." $sql_where AND - session_id = ".$session_id; + session_id = ".$sessionId; Database::query($sql); + $this->generateStats($this->id, api_get_course_info(), $sessionId); + Event::addEvent( LOG_EXERCISE_RESULT_DELETE, LOG_EXERCISE_ID, @@ -2830,7 +2832,7 @@ class Exercise null, null, api_get_course_int_id(), - $session_id + $sessionId ); return $i; @@ -7962,6 +7964,145 @@ class Exercise return $questionList; } + /** + * @param int $exerciseId + * @param array $courseInfo + * @param int $sessionId + * + * @return bool + * @throws \Doctrine\ORM\OptimisticLockException + */ + public function generateStats($exerciseId, $courseInfo, $sessionId) + { + $allowStats = api_get_configuration_value('allow_gradebook_stats'); + if (!$allowStats) { + return false; + } + + if (empty($courseInfo)) { + return false; + } + + $courseId = $courseInfo['real_id']; + + $sessionId = (int) $sessionId; + $result = $this->read($exerciseId); + + if (empty($result)) { + api_not_allowed(true); + } + + $statusToFilter = empty($sessionId) ? STUDENT : 0; + + $studentList = CourseManager::get_user_list_from_course_code( + api_get_course_id(), + $sessionId, + null, + null, + $statusToFilter + ); + + if (empty($studentList)) { + Display::addFlash(Display::return_message(get_lang('NoUsersInCourse'))); + header('Location: '.api_get_path(WEB_CODE_PATH).'exercise/exercise.php?'.api_get_cidreq()); + exit; + } + + $tblStats = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES); + + $studentIdList = []; + if (!empty($studentList)) { + $studentIdList = array_column($studentList, 'user_id'); + } + + if ($this->exercise_was_added_in_lp == false) { + $sql = "SELECT * FROM $tblStats + WHERE + exe_exo_id = $exerciseId AND + orig_lp_id = 0 AND + orig_lp_item_id = 0 AND + status <> 'incomplete' AND + session_id = $sessionId AND + c_id = $courseId + "; + } else { + $lpId = null; + if (!empty($this->lpList)) { + // Taking only the first LP + $lpId = current($this->lpList); + $lpId = $lpId['lp_id']; + } + + $sql = "SELECT * + FROM $tblStats + WHERE + exe_exo_id = $exerciseId AND + orig_lp_id = $lpId AND + status <> 'incomplete' AND + session_id = $sessionId AND + c_id = $courseId "; + } + + $sql .= ' ORDER BY exe_id DESC'; + + $studentCount = 0; + $sum = 0; + $bestResult = 0; + $weight = 0; + $sumResult = 0; + $result = Database::query($sql); + while ($data = Database::fetch_array($result, 'ASSOC')) { + // Only take into account users in the current student list. + if (!empty($studentIdList)) { + if (!in_array($data['exe_user_id'], $studentIdList)) { + continue; + } + } + + if (!isset($students[$data['exe_user_id']])) { + if ($data['exe_weighting'] != 0) { + $students[$data['exe_user_id']] = $data['exe_result']; + $studentCount++; + if ($data['exe_result'] > $bestResult) { + $bestResult = $data['exe_result']; + } + $sum += $data['exe_result'] / $data['exe_weighting']; + $sumResult += $data['exe_result']; + $weight = $data['exe_weighting']; + } + } + } + + $count = count($studentList); + $average = $sumResult / $count; + $em = Database::getManager(); + + $links = AbstractLink::getGradebookLinksFromItem( + $this->selectId(), + LINK_EXERCISE, + api_get_course_id(), + api_get_session_id() + ); + + $repo = $em->getRepository('ChamiloCoreBundle:GradebookLink'); + + foreach ($links as $link) { + $linkId = $link['id']; + /** @var \Chamilo\CoreBundle\Entity\GradebookLink $exerciseLink */ + $exerciseLink = $repo->find($linkId); + if ($exerciseLink) { + $exerciseLink + ->setUserScoreList($students) + ->setBestScore($bestResult) + ->setAverageScore($average) + ->setScoreWeight($this->get_max_score()) + ; + $em->persist($exerciseLink); + $em->flush(); + } + } + } + /** * Gets the question list ordered by the question_order setting (drag and drop). * diff --git a/main/gradebook/gradebook_add_eval.php b/main/gradebook/gradebook_add_eval.php index 420ebb31a8..28f9255c81 100755 --- a/main/gradebook/gradebook_add_eval.php +++ b/main/gradebook/gradebook_add_eval.php @@ -19,7 +19,7 @@ $evaladd = new Evaluation(); $evaladd->set_user_id($_user['user_id']); if (!empty($select_cat)) { $evaladd->set_category_id($_GET['selectcat']); - $cat = Category :: load($_GET['selectcat']); + $cat = Category::load($_GET['selectcat']); $evaladd->set_course_code($cat[0]->get_course_code()); } else { $evaladd->set_category_id(0); @@ -49,18 +49,16 @@ if ($form->validate()) { $eval->set_course_code(api_get_course_id()); $eval->set_category_id($values['hid_category_id']); - $parent_cat = Category :: load($values['hid_category_id']); + $parent_cat = Category::load($values['hid_category_id']); $global_weight = $cat[0]->get_weight(); //$values['weight'] = $values['weight_mask']/$global_weight*$parent_cat[0]->get_weight(); $values['weight'] = $values['weight_mask']; $eval->set_weight($values['weight']); $eval->set_max($values['max']); - + $visible = 1; if (empty($values['visible'])) { $visible = 0; - } else { - $visible = 1; } $eval->set_visible($visible); $eval->add(); diff --git a/main/gradebook/gradebook_add_result.php b/main/gradebook/gradebook_add_result.php index 7f05f3fb42..f26f759b7e 100755 --- a/main/gradebook/gradebook_add_result.php +++ b/main/gradebook/gradebook_add_result.php @@ -37,18 +37,25 @@ if ($add_result_form->validate()) { header('Location: gradebook_view_result.php?addresultnostudents=&selecteval='.$selectEval.'&'.api_get_cidreq()); exit; } - $scores = ($values['score']); - foreach ($scores as $row) { + + $scores = $values['score']; + $sumResult = 0; + $bestResult = 0; + $studentScoreList = []; + foreach ($scores as $userId => $row) { $res = new Result(); $res->set_evaluation_id($values['evaluation_id']); $res->set_user_id(key($scores)); //if no scores are given, don't set the score - if ((!empty($row)) || ($row == '0')) { + if (!empty($row) || $row == '0') { $res->set_score($row); } $res->add(); next($scores); } + + Evaluation::generateStats($values['evaluation_id']); + Display::addFlash(Display::return_message(get_lang('ResultAdded'), 'confirmation', false)); header('Location: gradebook_view_result.php?addresult=&selecteval='.$selectEval.'&'.api_get_cidreq()); exit; diff --git a/main/gradebook/gradebook_display_summary.php b/main/gradebook/gradebook_display_summary.php index 9c4f7e9ebe..42a65d4407 100644 --- a/main/gradebook/gradebook_display_summary.php +++ b/main/gradebook/gradebook_display_summary.php @@ -9,7 +9,7 @@ use ChamiloSession as Session; require_once __DIR__.'/../inc/global.inc.php'; $current_course_tool = TOOL_GRADEBOOK; -api_protect_course_script(); +api_protect_course_script(true); api_set_more_memory_and_time_limits(); api_block_anonymous_users(); GradebookUtils::block_students(); @@ -18,6 +18,7 @@ $cat_id = isset($_GET['selectcat']) ? (int) $_GET['selectcat'] : null; $action = isset($_GET['action']) && $_GET['action'] ? $_GET['action'] : null; $sessionId = api_get_session_id(); +$courseInfo = api_get_course_info(); $statusToFilter = empty($sessionId) ? STUDENT : 0; $userList = CourseManager::get_user_list_from_course_code( @@ -28,19 +29,68 @@ $userList = CourseManager::get_user_list_from_course_code( $statusToFilter ); +$loadStats = []; +if (api_get_setting('gradebook_detailed_admin_view') === 'true') { + $loadStats = [1, 2, 3]; +} else { + if (api_get_configuration_value('gradebook_enable_best_score') !== false) { + $loadStats = [2]; + } +} + +/*Session::write('use_gradebook_cache', false); +$useCache = api_get_configuration_value('gradebook_use_apcu_cache'); +$cacheAvailable = api_get_configuration_value('apc') && $useCache; + +if ($cacheAvailable) { + $cacheDriver = new \Doctrine\Common\Cache\ApcuCache(); + $cacheDriver->deleteAll(); + $cacheDriver->flushAll(); +}*/ + switch ($action) { case 'export_all': + //Session::write('use_gradebook_cache', true); $cats = Category::load($cat_id, null, null, null, null, null, false); - $studentList = CourseManager::get_user_list_from_course_code( + /** @var Category $cat */ + $cat = $cats[0]; + $allcat = $cat->get_subcategories( + null, + api_get_course_id(), + api_get_session_id() + ); + $alleval = $cat->get_evaluations( + null, + true, api_get_course_id(), - $sessionId, + api_get_session_id() + ); + $alllink = $cat->get_links( null, + true, + api_get_course_id(), + api_get_session_id() + ); + + $gradebooktable = new GradebookTable( + $cat, + $allcat, + $alleval, + $alllink, + null, // params + true, // $exportToPdf + false, // showteacher null, - $statusToFilter + $userList, + $loadStats ); + $key = $gradebooktable->getPreloadDataKey(); + // preloads data + Session::erase($key); + $defaultData = $gradebooktable->preloadData(); + $tpl = new Template('', false, false, false); - $courseInfo = api_get_course_info(); $params = [ 'pdf_title' => sprintf(get_lang('GradeFromX'), $courseInfo['name']), 'session_info' => '', @@ -54,44 +104,53 @@ switch ($action) { 'orientation' => 'P', ]; $pdf = new PDF('A4', $params['orientation'], $params, $tpl); + $counter = 0; $htmlList = []; foreach ($userList as $index => $value) { $htmlList[] = GradebookUtils::generateTable( + $courseInfo, $value['user_id'], $cats, + false, true, - true, - $studentList, + $userList, $pdf ); + $counter++; } if (!empty($htmlList)) { - // Print certificates (without the common header/footer/watermark - // stuff) and return as one multiple-pages PDF - /*$address = api_get_setting('institution_address'); - $phone = api_get_setting('administratorTelephone'); - $address = str_replace('\n', '
', $address); - $pdf->custom_header = array('html' => "
$address
$phone
");*/ - // stuff) and return as one multiple-pages PDF + $counter = 0; + //error_log('Loading html list'); + $content = ''; + foreach ($htmlList as $value) { + $content .= $value.''; + //error_log('Loading html: '.$counter); + $counter++; + } + + $tempFile = api_get_path(SYS_ARCHIVE_PATH).uniqid('gradebook_export_all').'.html'; + file_put_contents($tempFile, $content); + //error_log('generating pdf'); $pdf->html_to_pdf( - $htmlList, + $tempFile, null, null, false, true, true ); + //error_log('End generating'); } // Delete calc_score session data Session::erase('calc_score'); - break; case 'download': + //Session::write('use_gradebook_cache', true); $userId = isset($_GET['user_id']) && $_GET['user_id'] ? $_GET['user_id'] : null; $cats = Category::load($cat_id, null, null, null, null, null, false); - GradebookUtils::generateTable($userId, $cats); + GradebookUtils::generateTable($courseInfo, $userId, $cats); break; } diff --git a/main/gradebook/gradebook_edit_result.php b/main/gradebook/gradebook_edit_result.php index 26a832da41..af6259a250 100755 --- a/main/gradebook/gradebook_edit_result.php +++ b/main/gradebook/gradebook_edit_result.php @@ -17,6 +17,9 @@ if (empty($select_eval)) { $resultedit = Result::load(null, null, $select_eval); $evaluation = Evaluation::load($select_eval); $evaluation[0]->check_lock_permissions(); +$courseInfo = api_get_course_info(); +$sessionId = api_get_session_id(); + $edit_result_form = new EvalForm( EvalForm::TYPE_ALL_RESULTS_EDIT, $evaluation[0], @@ -28,6 +31,8 @@ $edit_result_form = new EvalForm( if ($edit_result_form->validate()) { $values = $edit_result_form->exportValues(); $scores = $values['score']; + $bestResult = 0; + $scoreFinalList = []; foreach ($scores as $userId => $score) { /** @var array $resultedit */ $resultedit = Result::load($userId); @@ -37,6 +42,12 @@ if ($edit_result_form->validate()) { if (empty($score)) { $score = 0; } + + $scoreFinalList[$result->get_user_id()] = $score; + + if ($score > $bestResult) { + $bestResult = $score; + } $score = api_number_format($score, api_get_setting('gradebook_number_decimals')); $result->set_score($score); $result->save(); diff --git a/main/gradebook/gradebook_view_result.php b/main/gradebook/gradebook_view_result.php index d2c7398f43..eb80132d0f 100755 --- a/main/gradebook/gradebook_view_result.php +++ b/main/gradebook/gradebook_view_result.php @@ -25,13 +25,13 @@ $interbreadcrumb[] = [ ]; //load the evaluation & category -$select_eval = intval($_GET['selecteval']); +$select_eval = (int) $_GET['selecteval']; if (empty($select_eval)) { api_not_allowed(); } $displayscore = ScoreDisplay::instance(); -$eval = Evaluation :: load($select_eval); +$eval = Evaluation::load($select_eval); $overwritescore = 0; if ($eval[0]->get_category_id() < 0) { // if category id is negative, then the evaluation's origin is a link @@ -43,7 +43,7 @@ if ($eval[0]->get_category_id() < 0) { //load the result with the evaluation id if (isset($_GET['delete_mark'])) { - $result = Result :: load($_GET['delete_mark']); + $result = Result::load($_GET['delete_mark']); if (!empty($result[0])) { $result[0]->delete(); } diff --git a/main/gradebook/index.php b/main/gradebook/index.php index 81ae760948..6d997db3ca 100755 --- a/main/gradebook/index.php +++ b/main/gradebook/index.php @@ -17,12 +17,66 @@ $current_course_tool = TOOL_GRADEBOOK; api_block_anonymous_users(); api_protect_course_script(true); -ob_start(); - $course_code = api_get_course_id(); $stud_id = api_get_user_id(); $session_id = api_get_session_id(); $course_id = api_get_course_int_id(); +$courseInfo = api_get_course_info(); + +$action = isset($_GET['action']) ? $_GET['action'] : null; +$itemId = isset($_GET['itemId']) ? $_GET['itemId'] : 0; + +switch ($action) { + case 'generate_eval_stats': + if (!empty($itemId)) { + Evaluation::generateStats($itemId); + Display::addFlash(Display::return_message(get_lang('Updated'))); + } + header('Location: '.api_get_self().'?'.api_get_cidreq()); + exit; + break; + case 'generate_link_stats': + if (!empty($itemId)) { + $link = LinkFactory::create(LINK_EXERCISE); + $links = $link::load($itemId); + /** @var ExerciseLink $link */ + foreach ($links as $link) { + $exercise = new Exercise(api_get_course_int_id()); + $exercise->read($link->get_ref_id()); + $exercise->generateStats($link->get_ref_id(), api_get_course_info(), api_get_session_id()); + } + Display::addFlash(Display::return_message(get_lang('Updated'))); + } + header('Location: '.api_get_self().'?'.api_get_cidreq()); + exit; + break; + case 'lock': + $category_to_lock = Category::load($_GET['category_id']); + $category_to_lock[0]->lockAllItems(1); + $confirmation_message = get_lang('GradebookLockedAlert'); + break; + case 'unlock': + if (api_is_platform_admin()) { + $category_to_lock = Category::load($_GET['category_id']); + $category_to_lock[0]->lockAllItems(0); + $confirmation_message = get_lang('EvaluationHasBeenUnLocked'); + } + break; + case 'export_table': + $hidePdfReport = api_get_configuration_value('gradebook_hide_pdf_report_button'); + if ($hidePdfReport) { + api_not_allowed(true); + } + if (isset($_GET['category_id'])) { + $cats = Category::load($_GET['category_id'], null, null, null, null, null, false); + GradebookUtils::generateTable($courseInfo, api_get_user_id(), $cats); + exit; + } + break; +} + +ob_start(); + // Make sure the destination for scripts is index.php instead of gradebook.php Category::setUrl('index.php'); @@ -262,15 +316,16 @@ if (isset($_GET['moveeval'])) { //move a link if (isset($_GET['movelink'])) { + $moveLink = (int) $_GET['movelink']; GradebookUtils::block_students(); - $link = LinkFactory::load($_GET['movelink']); + $link = LinkFactory::load($moveLink); $move_form = new LinkForm( LinkForm::TYPE_MOVE, null, $link[0], 'move_link_form', null, - api_get_self().'?movelink='.$_GET['movelink'].'&selectcat='.$selectCat.'&'.api_get_cidreq() + api_get_self().'?movelink='.$moveLink.'&selectcat='.$selectCat.'&'.api_get_cidreq() ); if ($move_form->validate()) { @@ -323,10 +378,9 @@ if (isset($_GET['deletecat'])) { // Parameters for evaluations. if (isset($_GET['visibleeval'])) { GradebookUtils::block_students(); + $visibility_command = 0; if (isset($_GET['set_visible'])) { $visibility_command = 1; - } else { - $visibility_command = 0; } $eval = Evaluation::load($_GET['visibleeval']); $eval[0]->set_visible($visibility_command); @@ -344,7 +398,7 @@ if (isset($_GET['visibleeval'])) { // Parameters for evaluations. if (isset($_GET['lockedeval'])) { GradebookUtils::block_students(); - $locked = Security::remove_XSS($_GET['lockedeval']); + $locked = (int) $_GET['lockedeval']; if (isset($_GET['typelocked']) && api_is_platform_admin()) { $type_locked = 0; $confirmation_message = get_lang('EvaluationHasBeenUnLocked'); @@ -373,10 +427,9 @@ if (isset($_GET['deleteeval'])) { // Parameters for links. if (isset($_GET['visiblelink'])) { GradebookUtils::block_students(); + $visibility_command = 0; if (isset($_GET['set_visible'])) { $visibility_command = 1; - } else { - $visibility_command = 0; } $link = LinkFactory::load($_GET['visiblelink']); if (isset($link) && isset($link[0])) { @@ -395,7 +448,7 @@ if (isset($_GET['visiblelink'])) { if (isset($_GET['deletelink'])) { GradebookUtils::block_students(); - $get_delete_link = intval($_GET['deletelink']); + $get_delete_link = (int) $_GET['deletelink']; //fixing #5229 if (!empty($get_delete_link)) { $link = LinkFactory::load($get_delete_link); @@ -441,38 +494,13 @@ if (!empty($course_to_crsind) && !isset($_GET['confirm'])) { $filter_warning_msg = false; } -$action = isset($_GET['action']) ? $_GET['action'] : null; - -switch ($action) { - case 'lock': - $category_to_lock = Category::load($_GET['category_id']); - $category_to_lock[0]->lockAllItems(1); - $confirmation_message = get_lang('GradebookLockedAlert'); - break; - case 'unlock': - if (api_is_platform_admin()) { - $category_to_lock = Category::load($_GET['category_id']); - $category_to_lock[0]->lockAllItems(0); - $confirmation_message = get_lang('EvaluationHasBeenUnLocked'); - } - break; - case 'export_table': - $hidePdfReport = api_get_configuration_value('gradebook_hide_pdf_report_button'); - if ($hidePdfReport) { - api_not_allowed(true); - } - - //table will be export below - ob_start(); - break; -} // Actions on the sortabletable. if (isset($_POST['action'])) { GradebookUtils::block_students(); $number_of_selected_items = count($_POST['id']); - if ($number_of_selected_items == '0') { + if ($number_of_selected_items == 0) { $warning_message = get_lang('NoItemsSelected'); $filter_warning_msg = false; } else { @@ -751,11 +779,9 @@ if (isset($_GET['studentoverview'])) { } $cats = Category::load($selectCat, null, null, null, null, null, false); - //with this fix the teacher only can view 1 gradebook + // With this fix the teacher only can view 1 gradebook if (api_is_platform_admin()) { $stud_id = (api_is_allowed_to_edit() ? null : api_get_user_id()); - } else { - $stud_id = $stud_id; } $allcat = $cats[0]->get_subcategories($stud_id, $course_code, $session_id); @@ -787,7 +813,6 @@ if (!empty($selectCat)) { $cat = new Category(); $course_id = CourseManager::get_course_by_category($selectCat); $show_message = $cat->show_message_resource_delete($course_id); - if ($show_message == '') { // Student if (!api_is_allowed_to_edit() && !api_is_excluded_user_type()) { @@ -819,7 +844,7 @@ if (!api_is_allowed_to_edit(null, true)) { if ($allowButton) { $actionsLeft .= Display::url( Display::returnFontAwesomeIcon('file-pdf-o').get_lang('DownloadReportPdf'), - api_get_self().'?action=export_table&'.api_get_cidreq(), + api_get_self().'?action=export_table&'.api_get_cidreq().'&category_id='.$selectCat, ['class' => 'btn btn-default'] ); } @@ -960,7 +985,7 @@ if (isset($first_time) && $first_time == 1 && api_is_allowed_to_edit(null, true) if (api_is_allowed_to_edit(null, true) && api_get_setting('gradebook_enable_grade_model') === 'true' ) { - //Showing the grading system + // Showing the grading system if (!empty($grade_models[$grade_model_id])) { echo Display::return_message( get_lang('GradeModel').': '.$grade_models[$grade_model_id]['name'] @@ -1002,28 +1027,6 @@ if (isset($first_time) && $first_time == 1 && api_is_allowed_to_edit(null, true) $gradebookTable->td_attributes = [ 4 => 'class="text-center"', ]; - } else { - /*if (empty($model)) { - $gradebookTable->td_attributes = [ - 3 => 'class="text-right"', - 4 => 'class="text-center"', - ]; - - if (!empty($loadStats)) { - for ($z = 5; $z < count($loadStats); $z++) { - $gradebookTable->td_attributes[$z] = 'class="text-center"'; - } - } - } else { - $gradebookTable->td_attributes = [ - 3 => 'class="text-right"', - 4 => 'class="text-center"', - ]; - } - - if ($action == 'export_table') { - unset($gradebookTable->td_attributes[7]); - }*/ } $table = $gradebookTable->return_table(); @@ -1034,7 +1037,7 @@ if (isset($first_time) && $first_time == 1 && api_is_allowed_to_edit(null, true) $graph = $gradebookTable->getGraph(); } - if ($action == 'export_table') { + if ($action === 'export_table') { ob_clean(); $params = [ 'pdf_title' => sprintf(get_lang('GradeFromX'), $courseInfo['name']), diff --git a/main/gradebook/lib/GradebookUtils.php b/main/gradebook/lib/GradebookUtils.php index f3a41c214f..62c5c0b167 100644 --- a/main/gradebook/lib/GradebookUtils.php +++ b/main/gradebook/lib/GradebookUtils.php @@ -378,6 +378,7 @@ class GradebookUtils ICON_SIZE_SMALL ). ''; + if (api_is_allowed_to_edit(null, true)) { $modify_icons .= ' '. Display::return_icon( @@ -387,6 +388,14 @@ class GradebookUtils ICON_SIZE_SMALL ). ''; + + $allowStats = api_get_configuration_value('allow_gradebook_stats'); + if ($allowStats) { + $modify_icons .= Display::url( + Display::return_icon('reload.png', get_lang('GenerateStats')), + api_get_self().'?itemId='.$eval->get_id().'&action=generate_eval_stats&selectcat='.$selectcat.'&'.$courseParams + ); + } } if ($is_locked && !api_is_platform_admin()) { @@ -466,6 +475,7 @@ class GradebookUtils ICON_SIZE_SMALL ). ''; + $modify_icons .= ' '. Display::return_icon( 'history.png', @@ -475,6 +485,14 @@ class GradebookUtils ). ''; + $allowStats = api_get_configuration_value('allow_gradebook_stats'); + if ($allowStats && $link->get_type() == LINK_EXERCISE) { + $modify_icons .= Display::url( + Display::return_icon('reload.png', get_lang('GenerateStats')), + api_get_self().'?itemId='.$link->get_id().'&action=generate_link_stats&selectcat='.$selectcat.'&'.$courseParams + ); + } + //If a work is added in a gradebook you can only delete the link in the work tool if ($is_locked && !api_is_platform_admin()) { $modify_icons .= ' '. @@ -1523,16 +1541,19 @@ class GradebookUtils } /** - * @param int $userId - * @param array $cats - * @param bool $saveToFile - * @param bool $saveToHtmlFile - * @param array $studentList - * @param PDF $pdf + * @param GradebookTable $gradebooktable + * @param array $courseInfo + * @param int $userId + * @param array $cats + * @param bool $saveToFile + * @param bool $saveToHtmlFile + * @param array $studentList + * @param PDF $pdf * * @return string */ public static function generateTable( + $courseInfo, $userId, $cats, $saveToFile = false, @@ -1540,9 +1561,7 @@ class GradebookUtils $studentList = [], $pdf = null ) { - $courseInfo = api_get_course_info(); $userInfo = api_get_user_info($userId); - $cat = $cats[0]; $allcat = $cats[0]->get_subcategories( $userId, @@ -1577,9 +1596,6 @@ class GradebookUtils $gradebooktable->userId = $userId; if (api_is_allowed_to_edit(null, true)) { - /*$gradebooktable->td_attributes = [ - 4 => 'class=centered', - ];*/ } else { $gradebooktable->td_attributes = [ 3 => 'class=centered', @@ -1589,7 +1605,6 @@ class GradebookUtils 7 => 'class=centered', ]; } - $table = $gradebooktable->return_table(); $graph = $gradebooktable->getGraph(); @@ -1626,6 +1641,7 @@ class GradebookUtils ); if ($saveToHtmlFile) { + return $result; file_put_contents($file, $result); return $file; diff --git a/main/gradebook/lib/be/abstractlink.class.php b/main/gradebook/lib/be/abstractlink.class.php index 63f6d60833..1a2dbccf2c 100755 --- a/main/gradebook/lib/be/abstractlink.class.php +++ b/main/gradebook/lib/be/abstractlink.class.php @@ -28,6 +28,8 @@ abstract class AbstractLink implements GradebookItem protected $weight; protected $visible; protected $session_id; + /** @var \Chamilo\CoreBundle\Entity\GradebookLink */ + public $entity; /** * Constructor. @@ -699,6 +701,12 @@ abstract class AbstractLink implements GradebookItem private static function create_objects_from_sql_result($result) { $links = []; + $allow = api_get_configuration_value('allow_gradebook_stats'); + if ($allow) { + $em = Database::getManager(); + $repo = $em->getRepository('ChamiloCoreBundle:GradebookLink'); + } + while ($data = Database::fetch_array($result)) { $link = LinkFactory::create($data['type']); $link->set_id($data['id']); @@ -714,8 +722,11 @@ abstract class AbstractLink implements GradebookItem //session id should depend of the category --> $data['category_id'] $session_id = api_get_session_id(); - $link->set_session_id($session_id); + + if ($allow) { + $link->entity = $repo->find($data['id']); + } $links[] = $link; } @@ -745,4 +756,43 @@ abstract class AbstractLink implements GradebookItem return $targets; } + + /** + * @param int $itemId + * @param int $linkType + * @param string $courseCode + * @param int $sessionId + * + * @return array|bool|\Doctrine\DBAL\Driver\Statement + */ + public static function getGradebookLinksFromItem($itemId, $linkType, $courseCode, $sessionId = 0) + { + if (empty($courseCode) || empty($itemId) || empty($linkType)) { + return false; + } + $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK); + $tableCategory = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY); + $itemId = (int) $itemId; + $linkType = (int) $linkType; + $sessionId = (int) $sessionId; + $courseCode = Database::escape_string($courseCode); + + $sql = "SELECT DISTINCT l.* + FROM $table l INNER JOIN $tableCategory c + ON (c.course_code = l.course_code AND c.id = l.category_id) + WHERE + ref_id = $itemId AND + type = $linkType AND + l.course_code = '$courseCode' AND + c.session_id = $sessionId"; + + $result = Database::query($sql); + if (Database::num_rows($result)) { + $result = Database::store_result($result); + + return $result; + } + + return false; + } } diff --git a/main/gradebook/lib/be/category.class.php b/main/gradebook/lib/be/category.class.php index 48c6305522..9e086dca47 100755 --- a/main/gradebook/lib/be/category.class.php +++ b/main/gradebook/lib/be/category.class.php @@ -34,6 +34,8 @@ class Category implements GradebookItem private $minimumToValidate; /** @var int */ private $gradeBooksToValidateInDependence; + /** @var GradebookCategory */ + public $entity; /** * Consctructor. @@ -2571,6 +2573,12 @@ class Category implements GradebookItem private static function create_category_objects_from_sql_result($result) { $categories = []; + $allow = api_get_configuration_value('allow_gradebook_stats'); + if ($allow) { + $em = Database::getManager(); + $repo = $em->getRepository('ChamiloCoreBundle:GradebookCategory'); + } + while ($data = Database::fetch_array($result)) { $cat = new Category(); $cat->set_id($data['id']); @@ -2591,6 +2599,10 @@ class Category implements GradebookItem $cat->setMinimumToValidate(isset($data['minimum_to_validate']) ? $data['minimum_to_validate'] : null); $cat->setGradeBooksToValidateInDependence(isset($data['gradebooks_to_validate_in_dependence']) ? $data['gradebooks_to_validate_in_dependence'] : null); + if ($allow) { + $cat->entity = $repo->find($data['id']); + } + $categories[] = $cat; } diff --git a/main/gradebook/lib/be/evaluation.class.php b/main/gradebook/lib/be/evaluation.class.php index e380be7f03..6cbc562485 100755 --- a/main/gradebook/lib/be/evaluation.class.php +++ b/main/gradebook/lib/be/evaluation.class.php @@ -23,6 +23,8 @@ class Evaluation implements GradebookItem private $eval_max; private $visible; private $sessionId; + /** @var \Chamilo\CoreBundle\Entity\GradebookEvaluation */ + public $entity; /** * Construct. @@ -534,6 +536,55 @@ class Evaluation implements GradebookItem */ public function calc_score($stud_id = null, $type = null) { + $allowStats = api_get_configuration_value('allow_gradebook_stats'); + if ($allowStats) { + $evaluation = $this->entity; + if (!empty($evaluation)) { + $weight = $evaluation->getMax(); + switch ($type) { + case 'best': + $bestResult = $evaluation->getBestScore(); + $result = [$bestResult, $weight]; + + return $result; + break; + case 'average': + $count = count($evaluation->getUserScoreList()); + if (empty($count)) { + $result = [0, $weight]; + + return $result; + } + + $sumResult = array_sum($evaluation->getUserScoreList()); + $result = [$sumResult / $count, $weight]; + + return $result; + break; + case 'ranking': + $ranking = AbstractLink::getCurrentUserRanking($stud_id, $evaluation->getUserScoreList()); + return $ranking; + break; + default: + $weight = $evaluation->getMax(); + if (!empty($stud_id)) { + $scoreList = $evaluation->getUserScoreList(); + $result = [0, $weight]; + if (isset($scoreList[$stud_id])) { + $result = [$scoreList[$stud_id], $weight]; + } + return $result; + } else { + $studentCount = count($evaluation->getUserScoreList()); + $sumResult = array_sum($evaluation->getUserScoreList()); + $result = [$sumResult, $studentCount]; + } + return $result; + break; + } + } + } + $useSession = true; if (isset($stud_id) && empty($type)) { $key = 'result_score_student_list_'.api_get_course_int_id().'_'.api_get_session_id().'_'.$this->id.'_'.$stud_id; @@ -803,16 +854,66 @@ class Evaluation implements GradebookItem { } + /** + * @return mixed + */ public function getStudentList() { return $this->studentList; } + /** + * @param $list + */ public function setStudentList($list) { $this->studentList = $list; } + /** + * @param int $evaluationId + * + */ + public static function generateStats($evaluationId) + { + $allowStats = api_get_configuration_value('allow_gradebook_stats'); + if ($allowStats) { + $evaluation = self::load($evaluationId); + + $results = Result::load(null, null, $evaluationId); + $sumResult = 0; + $bestResult = 0; + $average = 0; + $scoreList = []; + + if (!empty($results)) { + /** @var Result $result */ + foreach ($results as $result) { + $score = $result->get_score(); + $scoreList[$result->get_user_id()] = $score; + $sumResult += $score; + if ($score > $bestResult) { + $bestResult = $score; + } + } + $average = $sumResult / count($results); + } + + /** @var Evaluation $evaluation */ + $evaluation = $evaluation[0]; + $evaluation = $evaluation->entity; + $evaluation + ->setBestScore($bestResult) + ->setAverageScore($average) + ->setUserScoreList($scoreList) + ; + + $em = Database::getManager(); + $em->persist($evaluation); + $em->flush(); + } + } + /** * @param array $result * @@ -821,6 +922,12 @@ class Evaluation implements GradebookItem private static function create_evaluation_objects_from_sql_result($result) { $alleval = []; + $allow = api_get_configuration_value('allow_gradebook_stats'); + if ($allow) { + $em = Database::getManager(); + $repo = $em->getRepository('ChamiloCoreBundle:GradebookEvaluation'); + } + if (Database::num_rows($result)) { while ($data = Database::fetch_array($result)) { $eval = new Evaluation(); @@ -838,6 +945,10 @@ class Evaluation implements GradebookItem $eval->set_locked($data['locked']); $eval->setSessionId(api_get_session_id()); + if ($allow) { + $eval->entity = $repo->find($data['id']); + } + $alleval[] = $eval; } } diff --git a/main/gradebook/lib/be/exerciselink.class.php b/main/gradebook/lib/be/exerciselink.class.php index fa8670e1a9..c6c1afac8b 100755 --- a/main/gradebook/lib/be/exerciselink.class.php +++ b/main/gradebook/lib/be/exerciselink.class.php @@ -1,6 +1,8 @@ entity; + if (!empty($link)) { + $weight = $link->getScoreWeight(); + + switch ($type) { + case 'best': + $bestResult = $link->getBestScore(); + $result = [$bestResult, $weight]; + + return $result; + break; + case 'average': + $count = count($this->getStudentList()); + if (empty($count)) { + $result = [0, $weight]; + + return $result; + } + $sumResult = array_sum($link->getUserScoreList()); + $result = [$sumResult / $count, $weight]; + return $result; + break; + case 'ranking': + return ''; + $newList = []; + var_dump($this->getStudentList());exit; + foreach ($this->getStudentList() as $userId) { + + } + $ranking = AbstractLink::getCurrentUserRanking($stud_id, $link->getUserScoreList()); + + return $ranking; + break; + default: + if (!empty($stud_id)) { + $scoreList = $link->getUserScoreList(); + $result = [0, $weight]; + if (isset($scoreList[$stud_id])) { + $result = [$scoreList[$stud_id], $weight]; + } + return $result; + } else { + $studentCount = count($this->getStudentList()); + $sumResult = array_sum($link->getUserScoreList()); + $result = [$sumResult, $studentCount]; + } + return $result; + break; + } + } + } + $tblStats = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES); $tblHp = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES); $tblDoc = Database::get_course_table(TABLE_DOCUMENT); @@ -185,6 +242,7 @@ class ExerciseLink extends AbstractLink $sessionId = $this->get_session_id(); $courseId = $this->getCourseId(); $exerciseData = $this->get_exercise_data(); + $exerciseId = isset($exerciseData['id']) ? $exerciseData['id'] : 0; $stud_id = (int) $stud_id; @@ -559,4 +617,18 @@ class ExerciseLink extends AbstractLink return $this->exercise_data; } + + public function getBestScore() + { + return $this->getStats('best'); + } + + public function getStats($type) + { + switch ($type) { + case 'best': + + break; + } + } } diff --git a/main/gradebook/lib/be/linkfactory.class.php b/main/gradebook/lib/be/linkfactory.class.php index 03f00cf51b..c1fc20d7cb 100755 --- a/main/gradebook/lib/be/linkfactory.class.php +++ b/main/gradebook/lib/be/linkfactory.class.php @@ -74,11 +74,11 @@ class LinkFactory /** * Static method to create specific link objects. * - * @param $type link type + * @param int $type link type */ public static function create($type) { - $type = intval($type); + $type = (int) $type; switch ($type) { case LINK_EXERCISE: return new ExerciseLink(); diff --git a/main/gradebook/lib/be/result.class.php b/main/gradebook/lib/be/result.class.php index 38f436e80b..7bad43a69f 100755 --- a/main/gradebook/lib/be/result.class.php +++ b/main/gradebook/lib/be/result.class.php @@ -179,7 +179,6 @@ class Result $sql .= ' WHERE'; } $sql .= ' gr.evaluation_id = '.intval($evaluation_id); - $paramcount++; } $sql .= ' ORDER BY u.lastname, u.firstname'; @@ -273,6 +272,8 @@ class Result $sql .= ' WHERE id = '.$this->id; // no need to update creation date Database::query($sql); + + Evaluation::generateStats($this->get_evaluation_id()); } /** @@ -289,6 +290,8 @@ class Result $sql = "DELETE FROM $table WHERE result_id = ".$this->id; Database::query($sql); } + + Evaluation::generateStats($this->get_evaluation_id()); } /** diff --git a/main/gradebook/lib/fe/gradebooktable.class.php b/main/gradebook/lib/fe/gradebooktable.class.php index b6a6146244..773031c700 100755 --- a/main/gradebook/lib/fe/gradebooktable.class.php +++ b/main/gradebook/lib/fe/gradebooktable.class.php @@ -4,6 +4,7 @@ use CpChart\Cache as pCache; use CpChart\Data as pData; use CpChart\Image as pImage; +use ChamiloSession as Session; /** * GradebookTable Class @@ -63,6 +64,7 @@ class GradebookTable extends SortableTable $this->teacherView = is_null($showTeacherView) ? api_is_allowed_to_edit(null, true) : $showTeacherView; $this->userId = is_null($userId) ? api_get_user_id() : $userId; $this->exportToPdf = $exportToPdf; + $this->studentList = $studentList; parent::__construct( 'gradebooklist', @@ -79,6 +81,8 @@ class GradebookTable extends SortableTable $this->cats = $cats; $this->loadStats = $loadStats; $this->datagen = new GradebookDataGenerator($cats, $evals, $links); + $this->datagen->preLoadDataKey = $this->getPreloadDataKey(); + $this->datagen->hidePercentage = api_get_configuration_value('hide_gradebook_percentage_user_result'); if (!empty($userId)) { @@ -182,6 +186,105 @@ class GradebookTable extends SortableTable return $this->datagen->get_total_items_count(); } + /** + * @return string + */ + public function getPreloadDataKey() + { + return 'default_data_'.api_get_course_id().'_'.api_get_session_id(); + } + + public function preloadData() + { + $allitems = $this->datagen->items; + usort($allitems, ['GradebookDataGenerator', 'sort_by_name']); + //$visibleItems = $this->datagen->items; + $visibleItems = array_merge($this->datagen->items, $this->evals_links); + + //Session::erase($this->getPreloadDataKey()); + $defaultDataFromSession = Session::read($this->getPreloadDataKey()); + if (empty($defaultDataFromSession)) { + $defaultData = []; + /** @var GradebookItem $item */ + foreach ($visibleItems as $item) { + $item->setStudentList($this->studentList); + $itemType = get_class($item); + switch ($itemType) { + case 'Evaluation': + // Best + $best = $this->datagen->buildBestResultColumn($item); + $defaultData[$item->get_id()]['best'] = $best; + // Average + $average = $this->datagen->buildAverageResultColumn($item); + $defaultData[$item->get_id()]['average'] = $average; + break; + case 'ExerciseLink': + /** @var ExerciseLink $item */ + // Best + $best = $this->datagen->buildBestResultColumn($item); + $defaultData[$item->get_id()]['best'] = $best; + // Average + $average = $this->datagen->buildAverageResultColumn($item); + $defaultData[$item->get_id()]['average'] = $average; + + // Ranking + /*if (!empty($this->studentList)) { + $invalidateRanking = true; + foreach ($this->studentList as $user) { + $score = $this->datagen->build_result_column( + $user['user_id'], + $item, + false, + true + ); + if (!empty($score['score'])) { + $invalidateRanking = false; + } + $rankingStudentList[$user['user_id']] = $score['score'][0]; + $defaultData[$item->get_id()]['ranking'] = $rankingStudentList; + $defaultData[$item->get_id()]['ranking_invalidate'] = $invalidateRanking; + } + }*/ + break; + default: + // Best + $best = $this->datagen->buildBestResultColumn($item); + $defaultData[$item->get_id()]['best'] = $best; + + // Average + $average = $this->datagen->buildAverageResultColumn($item); + $defaultData[$item->get_id()]['average'] = $average; + + // Ranking + if (!empty($this->studentList)) { + $invalidateRanking = true; + foreach ($this->studentList as $user) { + $score = $this->datagen->build_result_column( + $user['user_id'], + $item, + false, + true + ); + if (!empty($score['score'])) { + $invalidateRanking = false; + } + $rankingStudentList[$user['user_id']] = $score['score'][0]; + $defaultData[$item->get_id()]['ranking'] = $rankingStudentList; + $defaultData[$item->get_id()]['ranking_invalidate'] = $invalidateRanking; + } + //exit; + } + break; + } + } + Session::write($this->getPreloadDataKey(), $defaultData); + } else { + $defaultData = $defaultDataFromSession; + } + return $defaultData; + } + + /** * Function used by SortableTable to generate the data to display. * @@ -292,12 +395,16 @@ class GradebookTable extends SortableTable $userExerciseScoreInCategory = api_get_configuration_value( 'gradebook_use_exercise_score_settings_in_categories' ); + + $course_code = api_get_course_id(); + $session_id = api_get_session_id(); + $defaultData = Session::read($this->getPreloadDataKey()); + // Categories. if (!empty($data_array)) { foreach ($data_array as $data) { // list of items inside the gradebook (exercises, lps, forums, etc) $row = []; - /** @var AbstractLink $item */ $item = $mainCategory = $data[0]; @@ -316,7 +423,7 @@ class GradebookTable extends SortableTable $row[] = $this->build_type_column($item); // Name. - if (get_class($item) == 'Category') { + if (get_class($item) === 'Category') { $row[] = $invisibility_span_open.''.$item->get_name().''.$invisibility_span_close; $main_categories[$item->get_id()]['name'] = $item->get_name(); } else { @@ -383,94 +490,86 @@ class GradebookTable extends SortableTable } // Students get the results and certificates columns - if (1) { - $value_data = isset($data[4]) ? $data[4] : null; - $best = isset($data['best']) ? $data['best'] : null; - $average = isset($data['average']) ? $data['average'] : null; - $ranking = isset($data['ranking']) ? $data['ranking'] : null; - $totalResult = [ - $data['result_score'][0], - $data['result_score'][1], - ]; - - $totalUserResult[0] += $totalResult[0] / ($totalResult[1] ?: 1) * $data[3]; - $totalUserResult[1] += $data[3]; - - $totalBest = [ - $scoredisplay->format_score($totalBest[0] + $data['best_score'][0]), - $scoredisplay->format_score($totalBest[1] + $data['best_score'][1]), - ]; - - $totalAverage = [ - $data['average_score'][0], - $data['average_score'][1], - ]; - - // Student result - if (empty($model)) { - $row[] = $value_data; - } else { - $row[] = ExerciseLib::show_score( - $data['result_score'][0], - $data['result_score'][1] - ); - } + $value_data = isset($data[4]) ? $data[4] : null; + $best = isset($data['best']) ? $data['best'] : null; + $average = isset($data['average']) ? $data['average'] : null; + $ranking = isset($data['ranking']) ? $data['ranking'] : null; - $mode = SCORE_AVERAGE; - if ($userExerciseScoreInCategory) { - $mode = SCORE_SIMPLE; + $totalResult = [ + $data['result_score'][0], + $data['result_score'][1], + ]; - $result = ExerciseLib::convertScoreToPlatformSetting($totalAverage[0], $totalAverage[1]); - $totalAverage[0] = $result['score']; - $totalAverage[1] = $result['weight']; + $totalUserResult[0] += $totalResult[0] / ($totalResult[1] ?: 1) * $data[3]; + $totalUserResult[1] += $data[3]; - $result = ExerciseLib::convertScoreToPlatformSetting($totalResult[0], $totalResult[1]); - $totalResult[0] = $result['score']; - $totalResult[1] = $result['weight']; + $totalBest = [ + $scoredisplay->format_score($totalBest[0] + $data['best_score'][0]), + $scoredisplay->format_score($totalBest[1] + $data['best_score'][1]), + ]; - $result = ExerciseLib::convertScoreToPlatformSetting( - $data['result_score'][0], - $data['result_score'][1] - ); - $data['my_result_no_float'][0] = $result['score']; - } + $totalAverage = [ + $data['average_score'][0], + $data['average_score'][1], + ]; - $totalResultAverageValue = strip_tags($scoredisplay->display_score($totalResult, $mode)); - $totalAverageValue = strip_tags($scoredisplay->display_score($totalAverage, $mode)); + // Student result + if (empty($model)) { + $row[] = $value_data; + } else { + $row[] = ExerciseLib::show_score( + $data['result_score'][0], + $data['result_score'][1] + ); + } - $this->dataForGraph['my_result'][] = floatval($totalResultAverageValue); - $this->dataForGraph['average'][] = floatval($totalAverageValue); - $this->dataForGraph['my_result_no_float'][] = $data['result_score'][0]; + $mode = SCORE_AVERAGE; + if ($userExerciseScoreInCategory) { + $mode = SCORE_SIMPLE; - if (empty($model)) { - // Ranking - if (in_array(1, $this->loadStats)) { - $row[] = $ranking; - } + $result = ExerciseLib::convertScoreToPlatformSetting($totalAverage[0], $totalAverage[1]); + $totalAverage[0] = $result['score']; + $totalAverage[1] = $result['weight']; - // Best - if (in_array(2, $this->loadStats)) { - $row[] = $best; - } + $result = ExerciseLib::convertScoreToPlatformSetting($totalResult[0], $totalResult[1]); + $totalResult[0] = $result['score']; + $totalResult[1] = $result['weight']; - // Average - if (in_array(3, $this->loadStats)) { - $row[] = $average; - } + $result = ExerciseLib::convertScoreToPlatformSetting( + $data['result_score'][0], + $data['result_score'][1] + ); + $data['my_result_no_float'][0] = $result['score']; + } + + $totalResultAverageValue = strip_tags($scoredisplay->display_score($totalResult, $mode)); + $totalAverageValue = strip_tags($scoredisplay->display_score($totalAverage, $mode)); + + $this->dataForGraph['my_result'][] = floatval($totalResultAverageValue); + $this->dataForGraph['average'][] = floatval($totalAverageValue); + $this->dataForGraph['my_result_no_float'][] = $data['result_score'][0]; + + if (empty($model)) { + // Ranking + if (in_array(1, $this->loadStats)) { + $row[] = $ranking; } - if (get_class($item) == 'Category') { - if ($this->exportToPdf == false) { - $row[] = $this->build_edit_column($item); - } + // Best + if (in_array(2, $this->loadStats)) { + $row[] = $best; } - } else { - $row[] = $scoreToDisplay; - if (!empty($this->cats)) { - if ($this->exportToPdf == false) { - $row[] = $this->build_edit_column($item); - } + + // Average + if (in_array(3, $this->loadStats)) { + $row[] = $average; + } + } + + if (get_class($item) === 'Category') { + if ($this->exportToPdf == false) { + $row[] = $this->build_edit_column($item); } } } @@ -479,10 +578,9 @@ class GradebookTable extends SortableTable $sortable_data[] = $row; // Loading children - if (get_class($item) == 'Category') { - $course_code = api_get_course_id(); - $session_id = api_get_session_id(); + if (get_class($item) === 'Category') { $parent_id = $item->get_id(); + $cats = Category::load( $parent_id, null, @@ -500,6 +598,7 @@ class GradebookTable extends SortableTable $alllink = $subCategory->get_links($this->userId); $sub_cat_info = new GradebookDataGenerator($allcat, $alleval, $alllink); + $sub_cat_info->preLoadDataKey = $this->getPreloadDataKey(); $sub_cat_info->userId = $user_id; $data_array2 = $sub_cat_info->get_data( $sorting, @@ -534,7 +633,7 @@ class GradebookTable extends SortableTable $row[] = $this->build_type_column($item, ['style' => 'padding-left:5px']); // Name. - $row[] = $invisibility_span_open."    ". + $row[] = $invisibility_span_open.'    '. $this->build_name_link($item, $type).$invisibility_span_close; // Description. @@ -652,7 +751,7 @@ class GradebookTable extends SortableTable foreach ($main_cat as $myCat) { $myParentId = $myCat->get_parent_id(); if ($myParentId == 0) { - $main_weight = intval($myCat->get_weight()); + $main_weight = (int) $myCat->get_weight(); } } } @@ -682,22 +781,18 @@ class GradebookTable extends SortableTable } else { // Total for student. if (count($main_cat) > 1) { - $weights = []; - foreach ($main_categories as $cat) { - $weights[] = $cat['weight']; - } - $main_weight = intval($main_cat[0]->get_weight()); + $main_weight = (int) $main_cat[0]->get_weight(); $global = null; $average = null; $myTotal = 0; - foreach ($this->dataForGraph['my_result_no_float'] as $result) { - $myTotal += $scoredisplay->format_score($result); + $myTotal += $result; } $totalResult[0] = $myTotal; // Overwrite main weight $totalResult[1] = $main_weight; + $totalResult = $scoredisplay->display_score( $totalResult, SCORE_DIV @@ -714,24 +809,33 @@ class GradebookTable extends SortableTable $row[] = $main_weight; $row[] = $totalResult; + $categoryId = $main_cat[0]->get_id(); if (in_array(1, $this->loadStats)) { - $totalRanking = []; - $invalidateRanking = true; - $average = 0; - $main_cat[0]->setStudentList($this->studentList); - foreach ($this->studentList as $student) { - $score = $main_cat[0]->calc_score( - $student['user_id'], - null, - api_get_course_id(), - api_get_session_id() - ); - if (!empty($score[0])) { - $invalidateRanking = false; + if (isset($defaultData[$categoryId]) && isset($defaultData[$categoryId]['ranking'])) { + $totalRanking = $defaultData[$categoryId]['ranking']; + $invalidateRanking = $defaultData[$categoryId]['ranking_invalidate']; + } else { + $totalRanking = []; + $invalidateRanking = true; + $average = 0; + $main_cat[0]->setStudentList($this->studentList); + foreach ($this->studentList as $student) { + $score = $main_cat[0]->calc_score( + $student['user_id'], + null, + api_get_course_id(), + api_get_session_id() + ); + if (!empty($score[0])) { + $invalidateRanking = false; + } + $totalRanking[$student['user_id']] = $score[0]; + $average += $score[0]; } - $totalRanking[$student['user_id']] = $score[0]; - $average += $score[0]; + $defaultData[$categoryId]['ranking'] = $totalRanking; + $defaultData[$categoryId]['ranking_invalidate'] = $invalidateRanking; + Session::write($this->getPreloadDataKey(), $defaultData); } $totalRanking = AbstractLink::getCurrentUserRanking($user_id, $totalRanking); @@ -750,8 +854,13 @@ class GradebookTable extends SortableTable } if (in_array(2, $this->loadStats)) { - // Overwrite main weight - $totalBest[1] = $main_weight; + if (isset($defaultData[$categoryId]) && isset($defaultData[$categoryId]['best'])) { + $totalBest = $defaultData[$categoryId]['best']; + } else { + // Overwrite main weight + $totalBest[1] = $main_weight; + $defaultData[$categoryId]['best'] = $totalBest; + } $totalBest = $scoredisplay->display_score( $totalBest, SCORE_DIV, @@ -760,10 +869,17 @@ class GradebookTable extends SortableTable ); $row[] = $totalBest; } + if (in_array(3, $this->loadStats)) { - // Overwrite main weight - $totalAverage[0] = $average / count($this->studentList); - $totalAverage[1] = $main_weight; + if (isset($defaultData[$categoryId]) && isset($defaultData[$categoryId]['average'])) { + $totalAverage = $defaultData[$categoryId]['average']; + } else { + // Overwrite main weight + $totalAverage[0] = $average / count($this->studentList); + $totalAverage[1] = $main_weight; + $defaultData[$categoryId]['average'] = $totalBest; + } + $totalAverage = $scoredisplay->display_score( $totalAverage, SCORE_DIV, @@ -773,23 +889,25 @@ class GradebookTable extends SortableTable $row[] = $totalAverage; } + if (!empty($row)) { $sortable_data[] = $row; } } } + Session::write('default_data', $defaultData); + // Warning messages $view = isset($_GET['view']) ? $_GET['view'] : null; - if ($this->teacherView) { if (isset($_GET['selectcat']) && $_GET['selectcat'] > 0 && $view != 'presence' ) { - $id_cat = intval($_GET['selectcat']); + $id_cat = (int) $_GET['selectcat']; $category = Category::load($id_cat); - $weight_category = intval($this->build_weight($category[0])); + $weight_category = (int) $this->build_weight($category[0]); $course_code = $this->build_course_code($category[0]); $weight_total_links = round($weight_total_links); @@ -798,7 +916,8 @@ class GradebookTable extends SortableTable $weight_total_links > $weight_category ) { $warning_message = sprintf(get_lang('TotalWeightMustBeX'), $weight_category); - $modify_icons = ''. + $modify_icons = + ''. Display::return_icon('edit.png', $warning_message, [], ICON_SIZE_SMALL).''; $warning_message .= $modify_icons; echo Display::return_message($warning_message, 'warning', false); @@ -853,7 +972,9 @@ class GradebookTable extends SortableTable if (empty($certificate_min_score) || ($certificate_min_score > $weight_category) ) { - $warning_message .= $course_code.' - '.get_lang('CertificateMinimunScoreIsRequiredAndMustNotBeMoreThan').' '.$weight_category.'
'; + $warning_message .= $course_code. + ' - '.get_lang('CertificateMinimunScoreIsRequiredAndMustNotBeMoreThan'). + ' '.$weight_category.'
'; } } @@ -864,27 +985,6 @@ class GradebookTable extends SortableTable } } - if (!$this->teacherView) { - /*$rowTotal = []; - $rowTotal[] = ' '; - $rowTotal[] = ''.get_lang('FinalScore').''; - - if (!$this->exportToPdf) { - $rowTotal[] = ' '; - } - $rowTotal[] = ' '; - $rowTotal[] = $scoredisplay->display_score( - $totalUserResult, - SCORE_DIV_PERCENT_WITH_CUSTOM - ); - - foreach ($this->loadStats as $col) { - $rowTotal[] = ' '; - } - - $sortable_data[] = $rowTotal;*/ - } - return $sortable_data; } diff --git a/main/gradebook/lib/gradebook_data_generator.class.php b/main/gradebook/lib/gradebook_data_generator.class.php index b88f2404f1..f38ac7d0ac 100755 --- a/main/gradebook/lib/gradebook_data_generator.class.php +++ b/main/gradebook/lib/gradebook_data_generator.class.php @@ -1,6 +1,8 @@ preLoadDataKey); /** @var GradebookItem $item */ foreach ($visibleItems as $item) { @@ -124,91 +129,214 @@ class GradebookDataGenerator // on mouseover (https://support.chamilo.org/issues/6588) $row[] = ''. api_get_short_text_from_html($item->get_description(), 160).''; - $totalWeight += $item->get_weight(); $row[] = $item->get_weight(); $item->setStudentList($studentList); + $itemType = get_class($item); + + switch ($itemType) { + case 'Evaluation': + // Items inside a category. + $resultColumn = $this->build_result_column( + $userId, + $item, + $ignore_score_color + ); - if (get_class($item) == 'Evaluation') { - // Items inside a category. - $resultColumn = $this->build_result_column( - $userId, - $item, - $ignore_score_color - ); - - $row[] = $resultColumn['display']; - $row['result_score'] = $resultColumn['score']; - $row['result_score_weight'] = $resultColumn['score_weight']; - - // Best - $best = $this->buildBestResultColumn($item); - - $row['best'] = $best['display']; - $row['best_score'] = $best['score']; - - // Average - $average = $this->buildAverageResultColumn($item); - $row['average'] = $average['display']; - $row['average_score'] = $average['score']; - - // Ranking - $ranking = $this->buildRankingColumn($item, $userId, $userCount); - $row['ranking'] = $ranking['display']; - $row['ranking_score'] = $ranking['score']; - $row[] = $item; - } else { - // Category. - $result = $this->build_result_column( - $userId, - $item, - $ignore_score_color, - true - ); - $row[] = $result['display']; - $row['result_score'] = $result['score']; - $row['result_score_weight'] = $result['score']; - - // Best - $best = $this->buildBestResultColumn($item); - $row['best'] = $best['display']; - $row['best_score'] = $best['score']; - - $rankingStudentList = []; - $invalidateResults = true; - - // Average - $average = $this->buildAverageResultColumn($item); - $row['average'] = $average['display']; - $row['average_score'] = $average['score']; - - // Ranking - if (!empty($studentList)) { - foreach ($studentList as $user) { - $score = $this->build_result_column( - $user['user_id'], - $item, - $ignore_score_color, - true - ); - if (!empty($score['score'][0])) { - $invalidateResults = false; + $row[] = $resultColumn['display']; + $row['result_score'] = $resultColumn['score']; + $row['result_score_weight'] = $resultColumn['score_weight']; + + // Best + if (isset($defaultData[$item->get_id()]) && isset($defaultData[$item->get_id()]['best'])) { + $best = $defaultData[$item->get_id()]['best']; + } else { + $best = $this->buildBestResultColumn($item); + } + + $row['best'] = $best['display']; + $row['best_score'] = $best['score']; + + // Average + if (isset($defaultData[$item->get_id()]) && isset($defaultData[$item->get_id()]['average'])) { + $average = $defaultData[$item->get_id()]['average']; + } else { + $average = $this->buildBestResultColumn($item); + } + + $row['average'] = $average['display']; + $row['average_score'] = $average['score']; + + // Ranking + $ranking = $this->buildRankingColumn($item, $userId, $userCount); + $row['ranking'] = $ranking['display']; + $row['ranking_score'] = $ranking['score']; + $row[] = $item; + break; + case 'ExerciseLink': + /** @var ExerciseLink $item */ + // Category. + $result = $this->build_result_column( + $userId, + $item, + $ignore_score_color, + true + ); + $row[] = $result['display']; + $row['result_score'] = $result['score']; + $row['result_score_weight'] = $result['score']; + + // Best + if (isset($defaultData[$item->get_id()]) && isset($defaultData[$item->get_id()]['best'])) { + $best = $defaultData[$item->get_id()]['best']; + } else { + $best = $this->buildBestResultColumn($item); + } + + $row['best'] = $best['display']; + $row['best_score'] = $best['score']; + + $rankingStudentList = []; + $invalidateResults = false; + + $debug = $item->get_id() == 1177; + + // Average + if (isset($defaultData[$item->get_id()]) && isset($defaultData[$item->get_id()]['average'])) { + $average = $defaultData[$item->get_id()]['average']; + } else { + $average = $this->buildAverageResultColumn($item); + } + + $row['average'] = $average['display']; + $row['average_score'] = $average['score']; + + // Ranking + if ($allowStats) { + // Ranking + if (isset($defaultData[$item->get_id()]) && isset($defaultData[$item->get_id()]['ranking'])) { + $rankingStudentList = $defaultData[$item->get_id()]['ranking']; + $invalidateResults = $defaultData[$item->get_id()]['ranking_invalidate']; + $score = AbstractLink::getCurrentUserRanking($userId, $rankingStudentList); + } else { + if (!empty($studentList)) { + foreach ($studentList as $user) { + $score = $this->build_result_column( + $user['user_id'], + $item, + $ignore_score_color, + true + ); + if (!empty($score['score'][0])) { + $invalidateResults = false; + } + $rankingStudentList[$user['user_id']] = $score['score'][0]; + } + $defaultData[$item->get_id()]['ranking'] = $rankingStudentList; + $defaultData[$item->get_id()]['ranking_invalidate'] = $invalidateResults; + Session::write($this->preLoadDataKey, $defaultData); + } + $score = AbstractLink::getCurrentUserRanking($userId, $rankingStudentList); } - $rankingStudentList[$user['user_id']] = $score['score'][0]; + } else { + if (!empty($studentList)) { + foreach ($studentList as $user) { + $score = $this->build_result_column( + $user['user_id'], + $item, + $ignore_score_color, + true + ); + if (!empty($score['score'][0])) { + $invalidateResults = false; + } + $rankingStudentList[$user['user_id']] = $score['score'][0]; + } + } + $score = AbstractLink::getCurrentUserRanking($userId, $rankingStudentList); } - } - $scoreDisplay = ScoreDisplay::instance(); - $score = AbstractLink::getCurrentUserRanking($userId, $rankingStudentList); - $row['ranking'] = $scoreDisplay->display_score( - $score, - SCORE_DIV, - SCORE_BOTH, - true, - true - ); - if ($invalidateResults) { - $row['ranking'] = null; - } + $row['ranking'] = $scoreDisplay->display_score( + $score, + SCORE_DIV, + SCORE_BOTH, + true, + true + ); + if ($invalidateResults) { + $row['ranking'] = null; + } + break; + default: + // Category. + $result = $this->build_result_column( + $userId, + $item, + $ignore_score_color, + true + ); + $row[] = $result['display']; + $row['result_score'] = $result['score']; + $row['result_score_weight'] = $result['score']; + + // Best + if (isset($defaultData[$item->get_id()]) && isset($defaultData[$item->get_id()]['best'])) { + $best = $defaultData[$item->get_id()]['best']; + } else { + $best = $this->buildBestResultColumn($item); + } + + $row['best'] = $best['display']; + $row['best_score'] = $best['score']; + + $rankingStudentList = []; + $invalidateResults = true; + + // Average + if (isset($defaultData[$item->get_id()]) && isset($defaultData[$item->get_id()]['average'])) { + $average = $defaultData[$item->get_id()]['average']; + } else { + $average = $this->buildAverageResultColumn($item); + } + $row['average'] = $average['display']; + $row['average_score'] = $average['score']; + + // Ranking + if (isset($defaultData[$item->get_id()]) && isset($defaultData[$item->get_id()]['ranking'])) { + $rankingStudentList = $defaultData[$item->get_id()]['ranking']; + $invalidateResults = $defaultData[$item->get_id()]['ranking_invalidate']; + $invalidateResults = false; + $score = AbstractLink::getCurrentUserRanking($userId, $rankingStudentList); + } else { + if (!empty($studentList)) { + foreach ($studentList as $user) { + $score = $this->build_result_column( + $user['user_id'], + $item, + $ignore_score_color, + true + ); + if (!empty($score['score'][0])) { + $invalidateResults = false; + } + $rankingStudentList[$user['user_id']] = $score['score'][0]; + } + } + error_log('loading not cACHE'); + $score = AbstractLink::getCurrentUserRanking($userId, $rankingStudentList); + } + + $row['ranking'] = $scoreDisplay->display_score( + $score, + SCORE_DIV, + SCORE_BOTH, + true, + true + ); + + if ($invalidateResults) { + $row['ranking'] = null; + } + break; } $data[] = $row; } @@ -244,7 +372,7 @@ class GradebookDataGenerator * * @return int */ - public function sort_by_name($item1, $item2) + public static function sort_by_name($item1, $item2) { return api_strnatcmp($item1->get_name(), $item2->get_name()); } @@ -345,7 +473,7 @@ class GradebookDataGenerator * * @return array */ - private function buildBestResultColumn(GradebookItem $item) + public function buildBestResultColumn(GradebookItem $item) { $score = $item->calc_score( null, @@ -382,7 +510,7 @@ class GradebookDataGenerator * * @return array */ - private function buildAverageResultColumn(GradebookItem $item) + public function buildAverageResultColumn(GradebookItem $item) { $score = $item->calc_score(null, 'average'); $scoreDisplay = ScoreDisplay::instance(); @@ -421,7 +549,7 @@ class GradebookDataGenerator * * @return array */ - private function buildRankingColumn(GradebookItem $item, $userId = null, $userCount = 0) + public function buildRankingColumn(GradebookItem $item, $userId = null, $userCount = 0) { $score = $item->calc_score($userId, 'ranking'); $score[1] = $userCount; @@ -448,9 +576,9 @@ class GradebookDataGenerator * @param GradebookItem $item * @param bool $ignore_score_color * - * @return string|null + * @return null|string */ - private function build_result_column( + public function build_result_column( $userId, $item, $ignore_score_color, @@ -491,7 +619,6 @@ class GradebookDataGenerator ]; } break; - // evaluation and link case 'E': case 'L': //if ($parentId == 0) { diff --git a/main/inc/lib/exercise.lib.php b/main/inc/lib/exercise.lib.php index b3c0bc6c7a..9aab000eba 100644 --- a/main/inc/lib/exercise.lib.php +++ b/main/inc/lib/exercise.lib.php @@ -2847,6 +2847,7 @@ HOTSPOT; $weight = float_format($weight, 1, $decimalSeparator, $thousandSeparator); } + $html = ''; if ($show_percentage) { $percentageSign = '%'; if ($hidePercentageSign) { @@ -4828,6 +4829,15 @@ EOT; $exercise_stat_info['exe_duration'], $question_list ); + + $allowStats = api_get_configuration_value('allow_gradebook_stats'); + if ($allowStats) { + $objExercise->generateStats( + $objExercise->selectId(), + api_get_course_info(), + api_get_session_id() + ); + } } } diff --git a/main/inc/lib/pdf.lib.php b/main/inc/lib/pdf.lib.php index 13b9370ef9..15b1717dc2 100755 --- a/main/inc/lib/pdf.lib.php +++ b/main/inc/lib/pdf.lib.php @@ -147,12 +147,17 @@ class PDF $html = $tpl->fetch($tableTemplate); $html = api_utf8_encode($html); + if ($returnHtml) { + return $html; + } + $css_file = api_get_path(SYS_CSS_PATH).'themes/'.$tpl->theme.'/print.css'; if (!file_exists($css_file)) { $css_file = api_get_path(SYS_CSS_PATH).'print.css'; } $css = file_get_contents($css_file); - $html = self::content_to_pdf( + + self::content_to_pdf( $html, $css, $this->params['filename'], @@ -163,10 +168,6 @@ class PDF $returnHtml, $addDefaultCss ); - - if ($returnHtml) { - return $html; - } } /** @@ -382,7 +383,7 @@ class PDF return false; } - //clean styles and javascript document + // clean styles and javascript document $clean_search = [ '@]*?>.*?@si', '@]*?>.*?@siU', diff --git a/main/inc/lib/text.lib.php b/main/inc/lib/text.lib.php index 017abeb3b8..7eb9786367 100755 --- a/main/inc/lib/text.lib.php +++ b/main/inc/lib/text.lib.php @@ -73,12 +73,21 @@ function api_set_encoding_html(&$string, $encoding) } } else { $count = 1; - $string = str_ireplace( - '', - '', - $string, - $count - ); + if (strpos('', strtolower($string)) !== false) { + $string = str_ireplace( + '', + '', + $string, + $count + ); + } else { + $string = str_ireplace( + '', + '', + $string, + $count + ); + } } $string = api_convert_encoding($string, $encoding, $old_encoding); } diff --git a/main/install/configuration.dist.php b/main/install/configuration.dist.php index 3098807bdf..5360298949 100755 --- a/main/install/configuration.dist.php +++ b/main/install/configuration.dist.php @@ -1082,6 +1082,13 @@ VALUES (2, 13, 'session_courses_read_only_mode', 'Lock Course In Session', 1, 1, // Allow to session admins login as teachers //$_configuration['allow_session_admin_login_as_teacher'] = false; +// Allow gradebook stats +// Requires to edit the GradebookLink.php And GradebookEvaluation.php files adding the "@" in the ORM phpdoc block +/* ALTER TABLE gradebook_link ADD score_weight DOUBLE PRECISION DEFAULT NULL, ADD average_score DOUBLE PRECISION DEFAULT NULL, ADD best_score DOUBLE PRECISION DEFAULT NULL, ADD user_score_list LONGTEXT DEFAULT NULL COMMENT '(DC2Type:array)' ; +ALTER TABLE gradebook_evaluation ADD average_score DOUBLE PRECISION DEFAULT NULL, ADD best_score DOUBLE PRECISION DEFAULT NULL, ADD user_score_list LONGTEXT DEFAULT NULL COMMENT '(DC2Type:array)' ; + +//$_configuration['allow_gradebook_stats'] = false; + // Hide social media links //$_configuration['hide_social_media_links'] = false; diff --git a/src/Chamilo/CoreBundle/Entity/GradebookEvaluation.php b/src/Chamilo/CoreBundle/Entity/GradebookEvaluation.php index 41fa7db724..73e6c295a4 100644 --- a/src/Chamilo/CoreBundle/Entity/GradebookEvaluation.php +++ b/src/Chamilo/CoreBundle/Entity/GradebookEvaluation.php @@ -99,6 +99,34 @@ class GradebookEvaluation */ protected $locked; + /** + * @var float + * + * ORM\Column(name="best_score", type="float", precision=6, scale=2, nullable=true) + */ + protected $bestScore; + + /** + * @var float + * + * ORM\Column(name="average_score", type="float", precision=6, scale=2, nullable=true) + */ + protected $averageScore; + + /** + * @var float + * + * ORM\Column(name="score_weight", type="float", precision=6, scale=2, nullable=true) + */ + protected $scoreWeight; + + /** + * @var array + * + * ORM\Column(name="user_score_list", type="array", nullable=true) + */ + protected $userScoreList; + /** * Set name. * @@ -372,4 +400,88 @@ class GradebookEvaluation { return $this->id; } + + /** + * @return float + */ + public function getBestScore() + { + return $this->bestScore; + } + + /** + * @param float $bestScore + * + * @return GradebookEvaluation + */ + public function setBestScore($bestScore) + { + $this->bestScore = $bestScore; + + return $this; + } + + /** + * @return float + */ + public function getAverageScore() + { + return $this->averageScore; + } + + /** + * @param float $averageScore + * + * @return GradebookEvaluation + */ + public function setAverageScore($averageScore) + { + $this->averageScore = $averageScore; + + return $this; + } + + /** + * @return array + */ + public function getUserScoreList() + { + if (empty($this->userScoreList)) { + return []; + } + + return $this->userScoreList; + } + + /** + * @param array $userScoreList + * + * @return GradebookEvaluation + */ + public function setUserScoreList($userScoreList) + { + $this->userScoreList = $userScoreList; + + return $this; + } + + /** + * @return float + */ + public function getScoreWeight() + { + return $this->scoreWeight; + } + + /** + * @param float $scoreWeight + * + * @return GradebookEvaluation + */ + public function setScoreWeight($scoreWeight) + { + $this->scoreWeight = $scoreWeight; + + return $this; + } } diff --git a/src/Chamilo/CoreBundle/Entity/GradebookLink.php b/src/Chamilo/CoreBundle/Entity/GradebookLink.php index b26733a8af..c9975b631c 100644 --- a/src/Chamilo/CoreBundle/Entity/GradebookLink.php +++ b/src/Chamilo/CoreBundle/Entity/GradebookLink.php @@ -85,6 +85,34 @@ class GradebookLink */ protected $locked; + /** + * @var float + * + * ORM\Column(name="best_score", type="float", precision=6, scale=2, nullable=true) + */ + protected $bestScore; + + /** + * @var float + * + * ORM\Column(name="average_score", type="float", precision=6, scale=2, nullable=true) + */ + protected $averageScore; + + /** + * @var float + * + * ORM\Column(name="score_weight", type="float", precision=6, scale=2, nullable=true) + */ + protected $scoreWeight; + + /** + * @var array + * + * ORM\Column(name="user_score_list", type="array", nullable=true) + */ + protected $userScoreList; + /** * Set type. * @@ -310,4 +338,88 @@ class GradebookLink { return $this->id; } + + /** + * @return float + */ + public function getBestScore() + { + return $this->bestScore; + } + + /** + * @param float $bestScore + * + * @return GradebookLink + */ + public function setBestScore($bestScore) + { + $this->bestScore = $bestScore; + + return $this; + } + + /** + * @return float + */ + public function getAverageScore() + { + return $this->averageScore; + } + + /** + * @param float $averageScore + * + * @return GradebookLink + */ + public function setAverageScore($averageScore) + { + $this->averageScore = $averageScore; + + return $this; + } + + /** + * @return array + */ + public function getUserScoreList() + { + if (empty($this->userScoreList)) { + return []; + } + + return $this->userScoreList; + } + + /** + * @param array $userScoreList + * + * @return GradebookLink + */ + public function setUserScoreList($userScoreList) + { + $this->userScoreList = $userScoreList; + + return $this; + } + + /** + * @return float + */ + public function getScoreWeight() + { + return $this->scoreWeight; + } + + /** + * @param float $scoreWeight + * + * @return GradebookLink + */ + public function setScoreWeight($scoreWeight) + { + $this->scoreWeight = $scoreWeight; + + return $this; + } }