Skip to content

Commit

Permalink
timing mode, new player version support and bugfixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Jenkins committed Apr 25, 2023
1 parent 9179ad6 commit 8763412
Show file tree
Hide file tree
Showing 40 changed files with 1,742 additions and 188 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ Enrich your videos by the powerful features of the social video player. Create p

# Changelog

### v1.16
* added Timing Mode
* bug fixes
* ``ep5 version 2.6``

### v1.15
* added Gradebook integration
* added Multiple-choice questions to Quiz-mode
Expand Down
8 changes: 4 additions & 4 deletions amd/src/ivs_activity_settings_page.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ define(['jquery', 'core/notification', 'core/custom_interaction_events', 'core/m

set_display_option('#id_annotations_enabled_value', '#id_mod_ivsnotification');
set_display_option('#id_exam_mode_enabled_value', '#id_mod_ivsgrades');
set_display_option_timing_mode( '#id_match_question_enabled_value', '#fgroup_id_show_videotest_feedback');
set_display_option_timing_mode('#id_match_question_enabled_value', '#fgroup_id_show_videotest_solution');
set_display_option_timing_mode( '#id_match_question_enabled_value', '#fgroup_id_show_realtime_results');
set_display_option_timing_mode('#id_match_question_enabled_value', '#fgroup_id_show_timing_take_summary');

$('#id_match_question_enabled_value').change(function () {
//Show timing mode checkboxes
set_display_option_timing_mode( $('#id_match_question_enabled_value'), '#fgroup_id_show_videotest_feedback');
set_display_option_timing_mode($('#id_match_question_enabled_value'), '#fgroup_id_show_videotest_solution');
set_display_option_timing_mode( $('#id_match_question_enabled_value'), '#fgroup_id_show_realtime_results');
set_display_option_timing_mode($('#id_match_question_enabled_value'), '#fgroup_id_show_timing_take_summary');

return;
});
Expand Down
488 changes: 413 additions & 75 deletions classes/MoodleMatchController.php

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions classes/StatisticsService.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ private function numIVSMatchQuestionsTypes() {
$this->database->count_records_sql("SELECT COUNT(id) FROM {ivs_matchquestion} WHERE type='click_question'");
$questiontypes['text_question'] =
$this->database->count_records_sql("SELECT COUNT(id) FROM {ivs_matchquestion} WHERE type='text_question'");
$questiontypes['timing_question'] =
$this->database->count_records_sql("SELECT COUNT(id) FROM {ivs_matchquestion} WHERE type='timing_question'");
return $questiontypes;
}

Expand Down
2 changes: 1 addition & 1 deletion classes/UpdateService.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public function settingInvertUpdate() {
* @return void
*/
public function alterVideocommentTableForCommentType() {
$this->database->execute("ALTER TABLE {ivs_videocomment} ADD comment_type VARCHAR(255) DEFAULT 'comment'");
$this->database->execute("ALTER TABLE {ivs_videocomment} ADD COLUMN IF NOT EXISTS comment_type VARCHAR(255) DEFAULT 'comment'");

$allcomments = $this->database->get_records_sql("SELECT id FROM {ivs_videocomment}");
foreach ($allcomments as $comment) {
Expand Down
3 changes: 2 additions & 1 deletion classes/admin_setting_configtext_ivs_custom.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public function validate($data) {
if ($data > IVS_SETTING_PLAYER_ANNOTATION_AUDIO_MAX_DURATION || $data < 0) {
return get_string('ivs_setting_annotation_audio_max_duration_validation', 'mod_ivs');
}

return true;
}
}
}
26 changes: 21 additions & 5 deletions classes/admin_setting_configtext_ivs_custom_with_lock.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

use admin_setting_configtext;
use admin_setting_flag;
use mod_ivs\settings\SettingsDefinition;

class admin_setting_configtext_ivs_custom_with_lock extends admin_setting_configtext {
/**
Expand All @@ -36,13 +37,28 @@ public function __construct($name, $visiblename, $description, $defaultsetting,
}

public function validate($data) {
if (!is_numeric($data)) {
return get_string('ivs_setting_annotation_audio_max_duration_validation', 'mod_ivs');


if ($this->name == SettingsDefinition::SETTING_PLAYER_ANNOTATION_AUDIO_MAX_DURATION){
if (!is_numeric($data)) {
return get_string('ivs_setting_annotation_audio_max_duration_validation', 'mod_ivs');
}

if ($data > IVS_SETTING_PLAYER_ANNOTATION_AUDIO_MAX_DURATION || $data < 0) {
return get_string('ivs_setting_annotation_audio_max_duration_validation', 'mod_ivs');
}
}

if ($data > IVS_SETTING_PLAYER_ANNOTATION_AUDIO_MAX_DURATION || $data < 0) {
return get_string('ivs_setting_annotation_audio_max_duration_validation', 'mod_ivs');
if ($this->name == SettingsDefinition::SETTING_PLAYER_VIDEOTEST_GRADE_TO_PASS){
if (!is_numeric($data)) {
return get_string('ivs_setting_grade_to_pass_validation', 'mod_ivs');
}

if ($data > 100 || $data < 0) {
return get_string('ivs_setting_grade_to_pass_validation', 'mod_ivs');
}
}

return true;
}
}
}
171 changes: 152 additions & 19 deletions classes/gradebook/GradebookService.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@
namespace mod_ivs\gradebook;

use core_course\analytics\target\course_gradetopass;
use core_table\local\filter\string_filter;
use enrol_self\self_test;
use Helper\MoodleHelper;
use mod_ivs\exception\ivs_exception;
use mod_ivs\ivs_match\AssessmentConfig;
use mod_ivs\ivs_match\timing\MatchTimingTakeResult;
use mod_ivs\MoodleMatchController;
use mod_ivs\settings\SettingsDefinition;
use mod_ivs\settings\SettingsService;
Expand Down Expand Up @@ -106,10 +109,9 @@ public function ivs_get_attempt_options() {
* @param $takes
* @return mixed|null
*/
private function get_grade_item_best_attempt($takes) {
public function get_best_score_by_takes($takes) {

$score = null;

foreach ($takes as $take) {
if (isset($take->score) && ($score === null || $take->score > $score)) {
$score = $take->score;
Expand All @@ -124,7 +126,7 @@ private function get_grade_item_best_attempt($takes) {
* @param $takes
* @return float|int
*/
private function get_grade_item_average($takes) {
private function get_average_score_by_takes($takes) {

$total = 0;
$count = 0;
Expand All @@ -146,18 +148,20 @@ private function get_grade_item_average($takes) {
* @param $takes
* @return int
*/
private function get_grade_item_first_attempt($takes) {
return $takes[0]->score ?? 0;
private function get_first_score_by_takes($takes) {
$score = $takes[0]->score ?? 0;
return $score;
}

/**
* returns score of last attempt of an ivs activity
* @param $takes
* @return int
*/
private function get_grade_item_last_attempt($takes) {
private function get_last_score_by_takes($takes) {
$take = end($takes);
return $take->score ?? 0;
$score = $take->score ?? 0;
return $score;
}

/**
Expand Down Expand Up @@ -266,36 +270,165 @@ public function ivs_get_grade_settings($ivs){
* Returns score and description for ivs activity quiz view
* @param $takes
* @param $ivs
* @return array
* @return float
* @throws \coding_exception
*/
public function ivs_gradebook_get_score_info_by_takes($takes, $ivs) {
public function ivs_gradebook_get_score_by_takes($takes, $ivs) {
$settingsservice = new SettingsService();
$activitysettings = $settingsservice->get_settings_for_activity($ivs->id, $ivs->course);
$gradingmethod = $activitysettings[SettingsDefinition::SETTING_PLAYER_VIDEOTEST_GRADE_METHOD]->value;

switch ($gradingmethod) {
case self::GRADE_METHOD_BEST_ATTEMPT:
$score = $this->get_best_score_by_takes($takes);
break;
case self::GRADE_METHOD_AVERAGE:
$score = $this->get_average_score_by_takes($takes);
break;
case self::GRADE_METHOD_FIRST_ATTEMPT:
$score = $this->get_first_score_by_takes($takes);
break;
case self::GRADE_METHOD_LAST_ATTEMPT:
$score = $this->get_last_score_by_takes($takes);
break;
}

return round($score, 2 );
}

public function ivs_gradebook_get_timing_take_summary_data_by_grade_method($takes, $ivs){
$settingsservice = new SettingsService();
$activitysettings = $settingsservice->get_settings_for_activity($ivs->id, $ivs->course);
$score = 0;
$gradingmethod = $activitysettings[SettingsDefinition::SETTING_PLAYER_VIDEOTEST_GRADE_METHOD]->value;

switch ($gradingmethod) {
case self::GRADE_METHOD_BEST_ATTEMPT:
$score = $this->get_grade_item_best_attempt($takes);
$desc = get_string('ivs_match_config_grade_mode_best_score_label', 'ivs');
$matchtimingresult = $this->get_best_timing_take_summary_by_takes($takes);
break;
case self::GRADE_METHOD_AVERAGE:
$score = $this->get_grade_item_average($takes);
$desc = get_string('ivs_match_config_grade_mode_average_score_label', 'ivs');
$matchtimingresult = $this->get_average_timing_take_summary_by_takes($takes);
break;
case self::GRADE_METHOD_FIRST_ATTEMPT:
$score = $this->get_grade_item_first_attempt($takes);
$desc = get_string('ivs_match_config_grade_mode_first_attempt_score_label', 'ivs');
$matchtimingresult = $this->get_first_timing_take_summary_by_takes($takes);
break;
case self::GRADE_METHOD_LAST_ATTEMPT:
$score = $this->get_grade_item_last_attempt($takes);
$desc = get_string('ivs_match_config_grade_mode_last_attempt_score_label', 'ivs');
$matchtimingresult = $this->get_last_timing_take_summary_by_takes($takes);
break;
}
return ['score' => round($score, 2 ), 'desc' => $desc];

return $matchtimingresult;
}

private function get_best_timing_take_summary_by_takes($takes){
$score = null;
foreach ($takes as $take) {
if (isset($take->score) && ($score === null || $take->score > $score)) {
$score = $take->score;
$besttake = $take;
}
}

$matchtimingresult = $this->get_evaluated_timing_type_result_by_take($besttake);

return $matchtimingresult;

}



private function get_average_timing_take_summary_by_takes($takes){

$numtakes = count($takes);
$matchtimingtakeresultavg = new MatchTimingTakeResult();

foreach ($takes as $take) {
$matchtimingtakeresult = $this->get_evaluated_timing_type_result_by_take($take);

$matchtimingtakeresultavg->pointsuser += $matchtimingtakeresult->pointsuser;
$matchtimingtakeresultavg->pointstotal += $matchtimingtakeresult->pointstotal;

foreach($matchtimingtakeresult->summary as $k => $v){
$matchtimingtakeresultavg->summary[$k]['timing_type'] = $v['timing_type'];
if (array_key_exists('sum_points', $matchtimingtakeresultavg->summary[$k])){
$matchtimingtakeresultavg->summary[$k]['sum_points'] += $v['sum_points'];
}else{
$matchtimingtakeresultavg->summary[$k]['sum_points'] = $v['sum_points'];
}

if (array_key_exists('num_correct', $matchtimingtakeresultavg->summary[$k])){
$matchtimingtakeresultavg->summary[$k]['num_correct'] += $v['num_correct'];
}else{
$matchtimingtakeresultavg->summary[$k]['num_correct'] = $v['num_correct'];
}
}

}

$matchtimingtakeresultavg->pointsuser = $matchtimingtakeresultavg->pointsuser / $numtakes;
$matchtimingtakeresultavg->pointstotal = $matchtimingtakeresultavg->pointstotal / $numtakes;
foreach($matchtimingtakeresultavg->summary as $k => $v){

$matchtimingtakeresultavg->summary[$k]['num_correct'] = $v['num_correct'] / $numtakes;
$matchtimingtakeresultavg->summary[$k]['sum_points'] = $v['num_correct'] * $v['timing_type']->score / $numtakes;
}

$matchtimingtakeresultavg->calculate_score();

return $matchtimingtakeresultavg;

}

private function get_first_timing_take_summary_by_takes($takes){
$firsttake = $takes[0];
$matchtimingresult = $this->get_evaluated_timing_type_result_by_take($firsttake);
return $matchtimingresult;
}

private function get_last_timing_take_summary_by_takes($takes){
$lasttake = end($takes);
$matchtimingresult = $this->get_evaluated_timing_type_result_by_take($lasttake);
return $matchtimingresult;
}

private function get_evaluated_timing_type_result_by_take($take){
$matchcontroller = new MoodleMatchController();

$matchtake = $matchcontroller->match_take_get_db($take->id);
$takeanswers = $matchcontroller->match_question_answers_get_by_take($take->id);
$questions = $matchcontroller->match_questions_get_by_video_db($matchtake->videoid, 'timecode', true);
$timingtypes = $matchcontroller->match_timing_type_get_db($matchtake->videoid);
$matchtimingresult = MatchTimingTakeResult::evaluate_take($timingtypes, $questions,$takeanswers);

return $matchtimingresult;
}

public function get_rendered_timing_take_summary($takes, $ivs) {
global $DB;
$course = $DB->get_record('course', array('id' => $ivs->course), '*', MUST_EXIST);
$settingscontroller = new SettingsService();
$activitysettings = $settingscontroller->get_settings_for_activity($ivs->id, $course->id);
$timingtakesummaryenabled = $activitysettings['show_timing_take_summary']->value;

if ($timingtakesummaryenabled) {

$timingtakesummary = '</li></ul><hr><ul>';
$matchtimingresult = $this->ivs_gradebook_get_timing_take_summary_data_by_grade_method($takes, $ivs);

foreach ($matchtimingresult->summary as $k => $v) {
$timingtakesummary .= '<li>' . $v['timing_type']->label . ': <br>' . $v['num_correct'] . ' ' . get_string('ivs_grademethod_timing_take_summary_korrekt', 'ivs') . ' (' . $v['sum_points'] . ' ' . get_string('ivs_grademethod_timing_take_summary_points', 'ivs') . ')</li>';
}
$timingtakesummary .= '<li><strong>' . get_string('ivs_grademethod_timing_take_summary_pointsuser', 'ivs') . ' ' . $matchtimingresult->score . '% (' . $matchtimingresult->pointsuser . ' ' . get_string('ivs_grademethod_timing_take_summary_points', 'ivs') . ')</strong></li>';
$timingtakesummary .= '</ul><ul>';

return $timingtakesummary;

}else{
$timingtakesummary = '</li></ul><hr><br>' . get_string('ivs_grademethod_timing_take_summary_thanks', 'ivs') . '<ul>';
return $timingtakesummary;
}
}


}


2 changes: 1 addition & 1 deletion classes/ivs_match/IIvsMatch.php
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ public function permission_match_question($op, $videoid, $contextid = null, $use
*/
public function assessment_config_get_by_user_and_video($userid, $videoid, $includesimulation = false);

public function match_timing_type_get_db($ivs, $skip_access = FALSE);
public function match_timing_type_get_db($videoid, $skip_access = FALSE);
public function match_timing_type_insert_db($videoid, $data, $user_id = NULL, $skip_access = FALSE);
public function match_timing_type_update_db($videoid, $data, $user_id = NULL, $skip_access = FALSE);
public function match_timing_type_delete_db($videoid, $timingtypeid, $skip_access = FALSE);
Expand Down
Loading

0 comments on commit 8763412

Please sign in to comment.