Skip to content
GitLab
    • Explore Projects Groups Snippets
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in
  • M moodle-assignsubmission_dta
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 3
    • Issues 3
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
    • Requirements
  • Merge requests 0
    • Merge requests 0
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • CoTA
  • moodle-assignsubmission_dta
  • Merge requests
  • !1

Coding style and recommendations

  • Review changes

  • Download
  • Email patches
  • Plain diff
Merged mamunozgil requested to merge niklas-dev-recommendation into master 6 months ago
  • Overview 0
  • Commits 72
  • Pipelines 2
  • Changes 35

The branch includes Niklas changes to show the correct recommendations after an assignment submission and changes the code style and naming to the moodle standard requirements.

  • mamunozgil @miguel.munoz-gil requested review from @32khsa1mst 6 months ago

    requested review from @32khsa1mst

  • mamunozgil @miguel.munoz-gil assigned to @miguel.munoz-gil 6 months ago

    assigned to @miguel.munoz-gil

  • mamunozgil @miguel.munoz-gil requested review from @01kuni1bif 6 months ago

    requested review from @01kuni1bif

  • Kurzenberger @01kuni1bif added 5 commits 6 months ago

    added 5 commits

    • cee505a2...07cd8123 - 4 commits from branch master
    • 1fb6dbf6 - Merge branch 'master' into niklas-dev-recommendation

    Compare with previous version

  • mamunozgil @miguel.munoz-gil enabled an automatic merge when the pipeline for 1fb6dbf6 succeeds 6 months ago

    enabled an automatic merge when the pipeline for 1fb6dbf6 succeeds

  • mamunozgil @miguel.munoz-gil mentioned in commit 98ce3595 6 months ago

    mentioned in commit 98ce3595

  • mamunozgil @miguel.munoz-gil merged 6 months ago

    merged

  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • You're only seeing other activity in the feed. To add a comment, switch to one of the following options.
Please register or sign in to reply
Compare
  • version 1
    cee505a2
    6 months ago

  • master (base)

and
  • latest version
    1fb6dbf6
    72 commits, 6 months ago

  • version 1
    cee505a2
    71 commits, 6 months ago

35 files
+ 2802
- 0

    Preferences

    File browser
    Compare changes

Some changes are not shown

For a faster browsing experience, some files are collapsed by default.

.as‎sets‎
install_c‎onf_1.png‎ +0 -0
install_c‎onf_2.png‎ +0 -0
usage_stu‎dent_1.png‎ +0 -0
usage_stu‎dent_2.png‎ +0 -0
usage_stu‎dent_3.png‎ +0 -0
usage_stu‎dent_4.png‎ +0 -0
usage_tea‎cher_1.png‎ +0 -0
usage_tea‎cher_2.png‎ +0 -0
usage_tea‎cher_3.png‎ +0 -0
d‎ta‎
cla‎sses‎
mod‎els‎
dta_recomme‎ndation.php‎ +89 -0
dta_res‎ult.php‎ +112 -0
dta_result_‎summary.php‎ +191 -0
pri‎vacy‎
provid‎er.php‎ +286 -0
dta_backen‎d_utils.php‎ +167 -0
dta_db_u‎tils.php‎ +325 -0
dta_view_submi‎ssion_utils.php‎ +0 -0
d‎b‎
insta‎ll.xml‎ +64 -0
upgra‎de.php‎ +34 -0
lan‎g/en‎
assignsubmis‎sion_dta.php‎ +175 -0
READ‎ME.md‎ +164 -0
lib‎.php‎ +88 -0
locall‎ib.php‎ +450 -0
settin‎gs.php‎ +34 -0
style‎s.css‎ +74 -0
versi‎on.php‎ +31 -0
test/p‎rivacy‎
apicompl‎iance.php‎ +100 -0
deleti‎on.php‎ +71 -0
expor‎t.php‎ +88 -0
.gitlab‎-ci.yml‎ +13 -0
Docke‎rfile‎ +26 -0
LIC‎ENSE‎ +0 -0
READ‎ME.md‎ +171 -0
docker-co‎mpose.yaml‎ +48 -0
dta‎.zip‎ +0 -0
teacher‎-dta.txt‎ +1 -0
.assets/install_conf_1.png 0 → 100644
+ 0
- 0
  • View file @ cee505a2

121.95 KiB

.assets/install_conf_2.png 0 → 100644
+ 0
- 0
  • View file @ cee505a2

111.60 KiB

.assets/usage_student_1.png 0 → 100644
+ 0
- 0
  • View file @ cee505a2

108.90 KiB

.assets/usage_student_2.png 0 → 100644
+ 0
- 0
  • View file @ cee505a2

95.01 KiB

.assets/usage_student_3.png 0 → 100644
+ 0
- 0
  • View file @ cee505a2

117.81 KiB

.assets/usage_student_4.png 0 → 100644
+ 0
- 0
  • View file @ cee505a2

83.19 KiB

.assets/usage_teacher_1.png 0 → 100644
+ 0
- 0
  • View file @ cee505a2

88.38 KiB

.assets/usage_teacher_2.png 0 → 100644
+ 0
- 0
  • View file @ cee505a2

136.97 KiB

.assets/usage_teacher_3.png 0 → 100644
+ 0
- 0
  • View file @ cee505a2

111.50 KiB

dta/classes/models/dta_recommendation.php 0 → 100644
+ 89
- 0
  • View file @ cee505a2

  • Edit in single-file editor

  • Open in Web IDE

<?php
// This file is part of Moodle - http://moodle.org/.
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Entity class for DTA submission plugin recommendation.
*
* @package assignsubmission_dta
* @copyright 2023 Gero Lueckemeyer
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace assignsubmission_dta\models;
/**
* Entity class for DTA submission plugin recommendation.
*
* @package assignsubmission_dta
* @copyright 2023
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class dta_recommendation {
/**
* @var string $topic Topic of the recommendation.
*/
public $topic;
/**
* @var string $exercisename Name of the exercise.
*/
public $exercisename;
/**
* @var string $url URL of the exercise.
*/
public $url;
/**
* @var int $difficulty Difficulty level of the exercise.
*/
public $difficulty;
/**
* @var int $score Score associated with the recommendation.
*/
public $score;
/**
* Decodes the JSON recommendations returned by the backend service call into an array of dta_recommendation objects.
*
* @param string $jsonstring JSON string containing recommendations.
* @return array Array of dta_recommendation objects.
*/
public static function assignsubmission_dta_decode_json_recommendations(string $jsonstring): array {
$response = json_decode($jsonstring);
$recommendations = [];
// Check if recommendations exist.
if (!empty($response->recommendations)) {
foreach ($response->recommendations as $recommendation) {
$rec = new dta_recommendation();
$rec->topic = $recommendation->topic ?? null;
// Map correct fields to the renamed variable names.
$rec->exercisename = $recommendation->url ?? null;
$rec->url = $recommendation->exerciseName ?? null;
$rec->difficulty = $recommendation->difficulty ?? null;
$rec->score = $recommendation->score ?? null;
$recommendations[] = $rec;
}
}
return $recommendations;
}
}
dta/classes/models/dta_result.php 0 → 100644
+ 112
- 0
  • View file @ cee505a2

  • Edit in single-file editor

  • Open in Web IDE

<?php
// This file is part of Moodle - http://moodle.org/.
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Entity class for DTA submission plugin result.
*
* @package assignsubmission_dta
* @copyright 2023 Gero Lueckemeyer and student project teams
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace assignsubmission_dta\models;
/**
* Entity class for DTA submission plugin result.
*
* @package assignsubmission_dta
* @copyright 2023 Gero Lueckemeyer and student project teams
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class dta_result {
/**
* Broadly used in logic, parametrized for easier change.
*/
public const ASSIGNSUBMISSION_DTA_COMPONENT_NAME = 'assignsubmission_dta';
/**
* @var string $packagename Package name of the test.
*/
public $packagename;
/**
* @var string $classname Unit name of the test.
*/
public $classname;
/**
* @var string $name Name of the test.
*/
public $name;
/**
* @var int $state State is defined as:
* 0 UNKNOWN
* 1 SUCCESS
* 2 FAILURE
* 3 COMPILATIONERROR
*/
public $state;
/**
* @var string $failuretype Type of test failure if applicable, empty string otherwise.
*/
public $failuretype;
/**
* @var string $failurereason Reason of test failure if applicable, empty string otherwise.
*/
public $failurereason;
/**
* @var string $stacktrace Stack trace of test failure if applicable, empty string otherwise.
*/
public $stacktrace;
/**
* @var int|string $columnnumber Column number of compile failure if applicable, empty string otherwise.
*/
public $columnnumber;
/**
* @var int|string $linenumber Line number of compile failure if applicable, empty string otherwise.
*/
public $linenumber;
/**
* @var int|string $position Position of compile failure if applicable, empty string otherwise.
*/
public $position;
/**
* Returns the name of a state with the given number for display.
*
* @param int $state Number of the state.
* @return string Name of state as defined.
*/
public static function assignsubmission_dta_get_statename(int $state): string {
if ($state === 1) {
return get_string('tests_successful', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME);
} else if ($state === 2) {
return get_string('failures', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME);
} else if ($state === 3) {
return get_string('compilation_errors', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME);
} else {
return get_string('unknown_state', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME);
}
}
}
dta/classes/models/dta_result_summary.php 0 → 100644
+ 191
- 0
  • View file @ cee505a2

  • Edit in single-file editor

  • Open in Web IDE

<?php
// This file is part of Moodle - http://moodle.org/.
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains the DTA submission plugin result summary entity class.
*
* @package assignsubmission_dta
* @copyright 2023 Your Name
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace assignsubmission_dta\models;
/**
* Entity class for DTA submission plugin result summary.
*
* This class holds:
* - A timestamp for when the summary was generated.
* - An optional global stack trace (in case the entire process failed).
* - A competency profile of how many tests passed for each competency.
* - A competency profile of the total coverage for each competency.
* - An array of dta_result objects that detail individual test results.
*
* @package assignsubmission_dta
*/
class dta_result_summary {
/** @var int Unix timestamp for the summary. */
public $timestamp;
/** @var string A global stacktrace if the entire run had a fatal error (optional). */
public $globalstacktrace;
/** @var string Semi-colon-separated numbers for competencies actually passed. */
public $successfultestcompetencies;
/** @var string Semi-colon-separated numbers for total tested competencies. */
public $overalltestcompetencies;
/** @var dta_result[] Array of individual test results. */
public $results;
/**
* Decodes a JSON string into a dta_result_summary object.
*
* @param string $jsonstring JSON that includes timestamp, globalstacktrace, competency profiles, and results.
* @return dta_result_summary
*/
public static function assignsubmission_dta_decode_json(string $jsonstring): dta_result_summary {
$response = json_decode($jsonstring);
$summary = new dta_result_summary();
$summary->timestamp = $response->timestamp ?? 0;
$summary->globalstacktrace = $response->globalstacktrace ?? '';
// If your JSON keys are 'successfulTestCompetencyProfile' and 'overallTestCompetencyProfile'.
$summary->successfultestcompetencies = $response->successfulTestCompetencyProfile ?? '';
$summary->overalltestcompetencies = $response->overallTestCompetencyProfile ?? '';
// Decode the "results" array into an array of dta_result objects.
if (!empty($response->results) && is_array($response->results)) {
$summary->results = self::assignsubmission_dta_decode_json_result_array($response->results);
} else {
$summary->results = [];
}
return $summary;
}
/**
* Helper that transforms a list of JSON objects into an array of dta_result objects.
*
* @param array $jsonarray Array of JSON-decoded result objects.
* @return dta_result[]
*/
private static function assignsubmission_dta_decode_json_result_array(array $jsonarray): array {
$ret = [];
foreach ($jsonarray as $entry) {
$value = new dta_result();
$value->packagename = $entry->packageName ?? '';
$value->classname = $entry->className ?? '';
$value->name = $entry->name ?? '';
$value->state = $entry->state ?? 0;
$value->failuretype = $entry->failureType ?? '';
$value->failurereason = $entry->failureReason ?? '';
$value->stacktrace = $entry->stacktrace ?? '';
$value->columnnumber = $entry->columnNumber ?? 0;
$value->linenumber = $entry->lineNumber ?? 0;
$value->position = $entry->position ?? 0;
$ret[] = $value;
}
return $ret;
}
/**
* Get the total number of results (tests) recorded in this summary.
*
* @return int
*/
public function assignsubmission_dta_result_count(): int {
return count($this->results);
}
/**
* Generic helper to count how many results have the given $state.
*
* States can be:
* 0 => unknown
* 1 => success
* 2 => fail
* 3 => compilation error
*
* @param int $state The numeric state code to match.
* @return int Number of results with that state.
*/
public function assignsubmission_dta_state_occurence_count(int $state): int {
$num = 0;
foreach ($this->results as $r) {
if ((int)$r->state === $state) {
$num++;
}
}
return $num;
}
/**
* Count how many results had compilation errors (state=3).
*
* @return int
*/
public function assignsubmission_dta_compilation_error_count(): int {
return $this->assignsubmission_dta_state_occurence_count(3);
}
/**
* Count how many results failed (state=2).
*
* @return int
*/
public function assignsubmission_dta_failed_count(): int {
return $this->assignsubmission_dta_state_occurence_count(2);
}
/**
* Count how many results were successful (state=1).
*
* @return int
*/
public function assignsubmission_dta_successful_count(): int {
return $this->assignsubmission_dta_state_occurence_count(1);
}
/**
* Count how many results are unknown (state=0).
*
* @return int
*/
public function assignsubmission_dta_unknown_count(): int {
return $this->assignsubmission_dta_state_occurence_count(0);
}
/**
* Computes the success rate as a percentage of all results (0..100).
* Note: This includes tests that might have compile errors or unknown states.
*
* @return float A floating percentage between 0.0 and 100.0.
*/
public function assignsubmission_dta_success_rate(): float {
$count = $this->assignsubmission_dta_result_count();
if ($count === 0) {
return 0.0;
}
$successful = $this->assignsubmission_dta_successful_count();
return ($successful / $count) * 100.0;
}
}
dta/classes/privacy/provider.php 0 → 100644
+ 286
- 0
  • View file @ cee505a2

  • Edit in single-file editor

  • Open in Web IDE

<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace assignsubmission_dta\privacy;
use assign_submission_dta;
use assignsubmission_dta\dta_db_utils;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\writer;
use core_privacy\local\request\contextlist;
use mod_assign\privacy\assign_plugin_request_data;
/**
* provider for data privacy
*
* @package assignsubmission_dta
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @copyright Gero Lueckemeyer and student project teams
*/
class provider implements \core_privacy\local\metadata\provider,
\mod_assign\privacy\assignsubmission_provider,
\mod_assign\privacy\assignsubmission_user_provider {
/**
* File area for dta submission assignment.
*/
const ASSIGNSUBMISSION_DTA_FILEAREA_SUBMISSION = "submissions_dta";
/**
* This is the metadata information for the assignsubmission_dta plugin.
* @param collection $collection the collection of metadata filled by the plugin
*/
public static function get_metadata(collection $collection): collection {
$collection->add_subsystem_link(
'core_files',
[],
'privacy:metadata:core_files'
);
$collection->add_database_table(
'assignsubmission_dta_summary',
[
'assignmentid' => 'privacy:metadata:assignsubmission_dta_summary:assignmentid',
'submissionid' => 'privacy:metadata:assignsubmission_dta_summary:submissionid',
'timestamp' => 'privacy:metadata:assignsubmission_dta_summary:timestamp',
'global_stacktrace' => 'privacy:metadata:assignsubmission_dta_summary:global_stacktrace',
'successful_competencies' => 'privacy:metadata:assignsubmission_dta_summary:successful_competencies',
'tested_competencies' => 'privacy:metadata:assignsubmission_dta_summary:tested_competencies',
],
'privacy:metadata:assignsubmission_dta_summary'
);
$collection->add_database_table(
'assignsubmission_dta_result',
[
'assignmentid' => 'privacy:metadata:assignsubmission_dta_summary:assignmentid',
'submissionid' => 'privacy:metadata:assignsubmission_dta_summary:submissionid',
'package_name' => 'privacy:metadata:assignsubmission_dta_result:package_name',
'class_name' => 'privacy:metadata:assignsubmission_dta_result:class_name',
'name' => 'privacy:metadata:assignsubmission_dta_result:name',
'state' => 'privacy:metadata:assignsubmission_dta_result:state',
'failure_type' => 'privacy:metadata:assignsubmission_dta_result:failure_type',
'failure_reason' => 'privacy:metadata:assignsubmission_dta_result:failure_reason',
'stacktrace' => 'privacy:metadata:assignsubmission_dta_result:stacktrace',
'column_number' => 'privacy:metadata:assignsubmission_dta_result:column_number',
'line_number' => 'privacy:metadata:assignsubmission_dta_result:line_number',
'position' => 'privacy:metadata:assignsubmission_dta_result:position',
],
'privacy:metadata:assignsubmission_dta_result'
);
$collection->add_database_table(
'assignsubmission_dta_recommendations',
[
'assignmentid' => 'privacy:metadata:assignsubmission_dta_summary:assignmentid',
'submissionid' => 'privacy:metadata:assignsubmission_dta_summary:submissionid',
'topic' => 'privacy:metadata:assignsubmission_dta_recommendations:topic',
'exercise_name' => 'privacy:metadata:assignsubmission_dta_recommendations:exercise_name',
'url' => 'privacy:metadata:assignsubmission_dta_recommendations:url',
'difficulty' => 'privacy:metadata:assignsubmission_dta_recommendations:difficulty',
'score' => 'privacy:metadata:assignsubmission_dta_recommendations:score',
],
'privacy:metadata:assignsubmission_dta_recommendations'
);
$collection->add_external_location_link('dta_backend', [
'assignmentid' => 'privacy:metadata:assignsubmission_dta_summary:assignmentid',
'submissionid' => 'privacy:metadata:assignsubmission_dta_summary:submissionid',
'submissioncontent' => 'privacy:metadata:core_files',
],
'privacy:metadata:dta_backend'
);
return $collection;
}
/**
* This is covered by mod_assign provider and the query on assign_submissions.
*
* @param int $userid The user ID that we are finding contexts for.
* @param contextlist $contextlist A context list to add sql and params to for contexts.
*/
public static function get_context_for_userid_within_submission(int $userid, contextlist $contextlist) {
// This is already fetched from mod_assign.
}
/**
* This is also covered by the mod_assign provider and its queries.
*
* @param \mod_assign\privacy\useridlist $useridlist An object for obtaining user IDs of students.
*/
public static function get_student_user_ids(\mod_assign\privacy\useridlist $useridlist) {
// This is already fetched from mod_assign.
}
/**
* If you have tables that contain userids and you can generate entries in your tables without creating an
* entry in the assign_submission table then please fill in this method.
*
* @param userlist $userlist The userlist object
*/
public static function get_userids_from_context(\core_privacy\local\request\userlist $userlist) {
// Not required.
}
/**
* Export all user data for this plugin.
*
* @param assign_plugin_request_data $exportdata Data used to determine which context and user to export and other useful
* information to help with exporting.
*/
public static function export_submission_user_data(assign_plugin_request_data $exportdata) {
// We currently don't show submissions to teachers when exporting their data.
$context = $exportdata->get_context();
if ($exportdata->get_user() != null) {
return null;
}
$user = new \stdClass();
$assign = $exportdata->get_assign();
$submission = $exportdata->get_pluginobject();
$files = get_files($submission, $user);
foreach ($files as $file) {
$userid = $exportdata->get_pluginobject()->userid;
$dtaresultsummary = dta_db_utils::dta_get_result_summary_from_database($assign->id, $submission->id);
// Submitted file.
writer::with_context($exportdata->get_context())->export_file($exportdata->get_subcontext(), $file)
// DTA result.
->export_related_data($dtaresultsummary);
// Plagiarism data.
$coursecontext = $context->get_course_context();
\core_plagiarism\privacy\provider::export_plagiarism_user_data($userid, $context, $exportdata->get_subcontext(), [
'cmid' => $context->instanceid,
'course' => $coursecontext->instanceid,
'userid' => $userid,
'file' => $file,
]);
}
}
/**
* Any call to this method should delete all user data for the context defined in the deletion_criteria.
*
* @param assign_plugin_request_data $requestdata Information useful for deleting user data.
*/
public static function delete_submission_for_context(assign_plugin_request_data $requestdata) {
global $DB;
\core_plagiarism\privacy\provider::delete_plagiarism_for_context($requestdata->get_context());
$fs = get_file_storage();
$fs->delete_area_files($requestdata->get_context()->id, 'assignsubmission_dta', ASSIGNSUBMISSION_DTA_FILEAREA_SUBMISSION);
$assignmentid = $requestdata->get_assign()->get_instance()->id;
// Delete records from assignsubmission_dta tables.
$DB->delete_records('assignsubmission_dta_result', ['assignmentid' => $assignmentid]);
$DB->delete_records('assignsubmission_dta_summary', ['assignmentid' => $assignmentid]);
$DB->delete_records('assignsubmission_dta_recommendations', ['assignmentid' => $assignmentid]);
}
/**
* A call to this method should delete user data (where practical) using the userid and submission.
*
* @param assign_plugin_request_data $deletedata Details about the user and context to focus the deletion.
*/
public static function delete_submission_for_userid(assign_plugin_request_data $deletedata) {
global $DB;
\core_plagiarism\privacy\provider::delete_plagiarism_for_user($deletedata->get_user()->id, $deletedata->get_context());
$assignmentid = $deletedata->get_assign()->get_instance()->id;
$submissionid = $deletedata->get_pluginobject()->id;
$fs = get_file_storage();
$fs->delete_area_files($deletedata->get_context()->id, 'assignsubmission_dta', ASSIGNSUBMISSION_DTA_FILEAREA_SUBMISSION,
$submissionid);
// Delete records from assignsubmission_dta tables. Also possible with a list as below.
$DB->delete_records('assignsubmission_dta_result', [
'assignmentid' => $assignmentid,
'submissionid' => $submissionid,
]);
$DB->delete_records('assignsubmission_dta_summary', [
'assignmentid' => $assignmentid,
'submissionid' => $submissionid,
]);
$DB->delete_records('assignsubmission_dta_recommendations', [
'assignmentid' => $assignmentid,
'submissionid' => $submissionid,
]);
}
/**
* Deletes all submissions for the submission ids / userids provided in a context.
* assign_plugin_request_data contains:
* - context
* - assign object
* - submission ids (pluginids)
* - user ids
* @param assign_plugin_request_data $deletedata A class that contains the relevant information required for deletion.
*/
public static function delete_submissions(assign_plugin_request_data $deletedata) {
global $DB;
\core_plagiarism\privacy\provider::delete_plagiarism_for_users($deletedata->get_userids(), $deletedata->get_context());
if (empty($deletedata->get_submissionids())) {
return;
}
$fs = get_file_storage();
list($sql, $params) = $DB->get_in_or_equal($deletedata->get_submissionids(), SQL_PARAMS_NAMED);
$fs->delete_area_files_select($deletedata->get_context()->id, 'assignsubmission_file', ASSIGNSUBMISSION_FILE_FILEAREA,
$sql, $params);
$params['assignid'] = $deletedata->get_assignid();
$DB->delete_records_select('assignsubmission_dta_result', "assignmentid = :assignid AND submissionid $sql", $params);
$DB->delete_records_select('assignsubmission_dta_summary', "assignmentid = :assignid AND submissionid $sql", $params);
$DB->delete_records_select('assignsubmission_dta_recommendations', "assignmentid = :assignid AND submissionid $sql", $params);
}
/**
* Produce a list of files suitable for export that represent this feedback or submission
*
* @param stdClass $submission The submission
* @param stdClass $user The user record - unused
* @return array - return an array of files indexed by filename
*/
public function get_files(stdClass $submission, stdClass $user) {
$result = [];
$fs = get_file_storage();
$files = $fs->get_area_files($this->assignment->get_context()->id,
'assignsubmission_file',
ASSIGNSUBMISSION_DTA_FILEAREA_SUBMISSION,
$submission->id,
'timemodified',
false);
foreach ($files as $file) {
// Do we return the full folder path or just the file name?
if (isset($submission->exportfullpath) && $submission->exportfullpath == false) {
$result[$file->get_filename()] = $file;
} else {
$result[$file->get_filepath().$file->get_filename()] = $file;
}
}
return $result;
}
}
dta/classes/dta_backend_utils.php 0 → 100644
+ 167
- 0
  • View file @ cee505a2

  • Edit in single-file editor

  • Open in Web IDE

<?php
// This file is part of Moodle - http://moodle.org/.
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains the backend webservice contact functionality for the DTA plugin.
*
* @package assignsubmission_dta
* @copyright 2023 Your Name
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace assignsubmission_dta;
/**
* Backend webservice contact utility class.
*
* @package assignsubmission_dta
* @copyright 2023 Your Name
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class dta_backend_utils {
/**
* Component name for the plugin.
*/
public const ASSIGNSUBMISSION_DTA_COMPONENT_NAME = 'assignsubmission_dta';
/**
* Returns the base URL of the backend webservice as configured in the administration settings.
*
* @return string Backend host base URL.
*/
private static function assignsubmission_dta_get_backend_baseurl(): string {
$backendaddress = get_config(
self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME,
'backendHost'
);
if (empty($backendaddress)) {
\core\notification::error(
get_string('backendHost_not_set', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
);
}
return $backendaddress;
}
/**
* Sends the configuration text file uploaded by the teacher to the backend.
*
* @param \assign $assignment Assignment this test-config belongs to.
* @param \stored_file $file Uploaded test-config.
* @return bool True if no error occurred.
*/
public static function assignsubmission_dta_send_testconfig_to_backend($assignment, $file): bool {
$backendaddress = self::assignsubmission_dta_get_backend_baseurl();
if (empty($backendaddress)) {
return true;
}
// Set endpoint for test upload.
$url = $backendaddress . '/v1/unittest';
// Prepare params.
$params = [
'unitTestFile' => $file,
'assignmentId' => $assignment->get_instance()->id,
];
// If request returned null, return false to indicate failure.
if (is_null(self::assignsubmission_dta_post($url, $params))) {
return false;
} else {
return true;
}
}
/**
* Sends submission config or archive to backend to be tested.
*
* @param \assign $assignment Assignment for the submission.
* @param int $submissionid Submission ID of the current file.
* @param \stored_file $file Submission config file or archive with submission.
* @return string|null JSON string with test results or null on error.
*/
public static function assignsubmission_dta_send_submission_to_backend(
$assignment,
int $submissionid,
$file
): ?string {
$backendaddress = self::assignsubmission_dta_get_backend_baseurl();
if (empty($backendaddress)) {
return null;
}
// Set endpoint for submission upload.
$url = $backendaddress . '/v1/task/' . $submissionid;
// Prepare params.
$params = [
'taskFile' => $file,
'assignmentId' => $assignment->get_instance()->id,
];
return self::assignsubmission_dta_post($url, $params);
}
/**
* Posts the given params to the given URL and returns the response as a string.
*
* @param string $url Full URL to request.
* @param array $params Parameters for HTTP request.
* @return string|null Received body on success or null on error.
*/
private static function assignsubmission_dta_post(string $url, array $params): ?string {
if (!isset($url) || !isset($params)) {
return null;
}
$options = ['CURLOPT_RETURNTRANSFER' => true];
$curl = new \curl();
$response = $curl->post($url, $params, $options);
// Check state of request, if response code is 2xx, return the answer.
$info = $curl->get_info();
if ($info['http_code'] >= 200 && $info['http_code'] < 300) {
return $response;
}
// Something went wrong, return null and display an error message.
$msg = self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME
. ': Post file to server was not successful. HTTP code='
. $info['http_code'];
debugging($msg);
if ($info['http_code'] >= 400 && $info['http_code'] < 500) {
\core\notification::error(
get_string('http_client_error_msg', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
);
return null;
} else if ($info['http_code'] >= 500 && $info['http_code'] < 600) {
\core\notification::error(
get_string('http_server_error_msg', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
);
return null;
} else {
$unknownmsg = get_string('http_unknown_error_msg', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
. $info['http_code'] . ' ' . $response;
\core\notification::error($unknownmsg);
return null;
}
}
}
dta/classes/dta_db_utils.php 0 → 100644
+ 325
- 0
  • View file @ cee505a2

  • Edit in single-file editor

  • Open in Web IDE

<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace assignsubmission_dta;
use assignsubmission_dta\dta_backend_utils;
use assignsubmission_dta\dta_view_submission_utils;
use assignsubmission_dta\models\dta_result;
use assignsubmission_dta\models\dta_result_summary;
use assignsubmission_dta\models\dta_recommendation;
/**
* Class dta_db_utils
*
* Persistence layer utility class for storing and retrieving
* DTA plugin data (results, summaries, recommendations).
*
* @package assignsubmission_dta
* @copyright 2023 Gero Lueckemeyer
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class dta_db_utils {
/**
* Summary database table name.
*/
private const ASSIGNSUBMISSION_DTA_TABLE_SUMMARY = 'assignsubmission_dta_summary';
/**
* Result database table name.
*/
private const ASSIGNSUBMISSION_DTA_TABLE_RESULT = 'assignsubmission_dta_result';
/**
* Recommendations database table name.
*/
private const ASSIGNSUBMISSION_DTA_TABLE_RECOMMENDATIONS = 'assignsubmission_dta_recommendations';
/**
* Returns an array of recommendations from the database.
*
* @param int $assignmentid The assignment ID.
* @param int $submissionid The submission ID.
* @return array An array of recommendation records.
*/
public static function assignsubmission_dta_get_recommendations_from_database(
int $assignmentid,
int $submissionid
): array {
global $DB, $USER;
$userid = $USER->id;
// Step 1: Retrieve all recommendations.
$records = $DB->get_records(
self::ASSIGNSUBMISSION_DTA_TABLE_RECOMMENDATIONS,
[
'assignment_id' => $assignmentid,
'submission_id' => $submissionid,
]
);
// Step 2: Retrieve module ID for 'assign'.
$module = $DB->get_record('modules', ['name' => 'assign'], 'id');
if (!$module) {
// Handle error case if the module is not found.
return $records;
}
$moduleid = $module->id;
// Step 3: Check each record.
foreach ($records as $key => $record) {
// Get the name of the exercise from the record.
$exercisename = $record->exercise_name;
// Find the assignment with this name.
$assign = $DB->get_record('assign', ['name' => $exercisename], 'id');
if ($assign) {
// Get the course module ID for this assignment.
$cm = $DB->get_record(
'course_modules',
[
'module' => $moduleid,
'instance' => $assign->id,
],
'id'
);
if ($cm) {
// Check the completion status for this course module and user.
$completion = $DB->get_record(
'course_modules_completion',
[
'coursemoduleid' => $cm->id,
'userid' => $userid,
],
'completionstate'
);
// If the completion state is 1, remove the record from $records.
if ($completion && (int)$completion->completionstate === 1) {
unset($records[$key]);
}
}
}
}
// Return the filtered records.
return $records;
}
/**
* Gets a summary with all corresponding result entries.
*
* @param int $assignmentid Assignment ID to search for.
* @param int $submissionid Submission ID to search for.
* @return dta_result_summary Summary representing the submission.
*/
public static function assignsubmission_dta_get_result_summary_from_database(
int $assignmentid,
int $submissionid
): dta_result_summary {
global $DB;
// Fetch data from database.
$summaryrecord = $DB->get_record(
self::ASSIGNSUBMISSION_DTA_TABLE_SUMMARY,
[
'assignment_id' => $assignmentid,
'submission_id' => $submissionid,
]
);
$resultsarray = $DB->get_records(
self::ASSIGNSUBMISSION_DTA_TABLE_RESULT,
[
'assignment_id' => $assignmentid,
'submission_id' => $submissionid,
]
);
// Create a summary instance.
$summary = new dta_result_summary();
$summary->timestamp = $summaryrecord->timestamp;
$summary->globalstacktrace = $summaryrecord->global_stacktrace;
$summary->successfultestcompetencies = $summaryrecord->successful_competencies;
$summary->overalltestcompetencies = $summaryrecord->tested_competencies;
$summary->results = [];
// Create result instances and add to array of summary instance.
foreach ($resultsarray as $rr) {
$result = new dta_result();
$result->packagename = $rr->package_name;
$result->classname = $rr->class_name;
$result->name = $rr->name;
$result->state = $rr->state;
$result->failuretype = $rr->failure_type;
$result->failurereason = $rr->failure_reason;
$result->stacktrace = $rr->stacktrace;
$result->columnnumber = $rr->column_number;
$result->linenumber = $rr->line_number;
$result->position = $rr->position;
$summary->results[] = $result;
}
return $summary;
}
/**
* Stores an array of recommendations in the database.
*
* @param int $assignmentid The assignment ID.
* @param int $submissionid The submission ID.
* @param array $recommendations An array of dta_recommendation objects.
*/
public static function assignsubmission_dta_store_recommendations_to_database(
int $assignmentid,
int $submissionid,
array $recommendations
): void {
global $DB;
// Debug output (you can remove or adapt this if unneeded).
debugging('Recommendations array: ' . json_encode($recommendations));
// If recommendations already exist, delete old values beforehand.
$existingrecords = $DB->get_records(
'assignsubmission_dta_recommendations',
[
'assignment_id' => $assignmentid,
'submission_id' => $submissionid,
]
);
if ($existingrecords) {
$DB->delete_records(
'assignsubmission_dta_recommendations',
[
'assignment_id' => $assignmentid,
'submission_id' => $submissionid,
]
);
}
// Create new recommendation entries.
foreach ($recommendations as $recommendation) {
// Check if $recommendation is an instance of dta_recommendation.
if ($recommendation instanceof dta_recommendation) {
// Add assignment and submission IDs to the recommendation object.
$recommendation->assignment_id = $assignmentid;
$recommendation->submission_id = $submissionid;
debugging('Inserting new recommendation record: ' . json_encode($recommendation));
// Insert the recommendation into the database.
$DB->insert_record('assignsubmission_dta_recommendations', $recommendation);
} else {
// Handle the case where $recommendation is not a dta_recommendation instance.
debugging('Invalid recommendation object encountered.');
}
}
}
/**
* Saves the given result summary and single results to the database
* under the specified assignment and submission ID.
*
* @param int $assignmentid Assignment this submission is linked to.
* @param int $submissionid Submission ID for these results.
* @param dta_result_summary $summary Summary instance to persist.
*/
public static function assignsubmission_dta_store_result_summary_to_database(
int $assignmentid,
int $submissionid,
dta_result_summary $summary
): void {
global $DB;
// Prepare new database entries.
$summaryrecord = new dta_result_summary();
$summaryrecord->assignment_id = $assignmentid;
$summaryrecord->submission_id = $submissionid;
$summaryrecord->timestamp = $summary->timestamp;
$summaryrecord->global_stacktrace = $summary->globalstacktrace;
$summaryrecord->successful_competencies = $summary->successfultestcompetencies;
$summaryrecord->tested_competencies = $summary->overalltestcompetencies;
// Prepare results to persist.
$resultrecords = [];
foreach ($summary->results as $r) {
$record = new dta_result();
$record->assignment_id = $assignmentid;
$record->submission_id = $submissionid;
$record->package_name = $r->packagename;
$record->class_name = $r->classname;
$record->name = $r->name;
$record->state = $r->state;
$record->failure_type = $r->failuretype;
$record->failure_reason = $r->failurereason;
$record->stacktrace = $r->stacktrace;
$record->column_number = $r->columnnumber;
$record->line_number = $r->linenumber;
$record->position = $r->position;
$resultrecords[] = $record;
}
// If results already exist, delete old values beforehand.
$submission = $DB->get_record(
self::ASSIGNSUBMISSION_DTA_TABLE_SUMMARY,
[
'assignment_id' => $assignmentid,
'submission_id' => $submissionid,
]
);
if ($submission) {
$DB->delete_records(
self::ASSIGNSUBMISSION_DTA_TABLE_RESULT,
[
'assignment_id' => $assignmentid,
'submission_id' => $submissionid,
]
);
$DB->delete_records(
self::ASSIGNSUBMISSION_DTA_TABLE_SUMMARY,
[
'assignment_id' => $assignmentid,
'submission_id' => $submissionid,
]
);
}
// Create summary and single result entries.
$DB->insert_record(self::ASSIGNSUBMISSION_DTA_TABLE_SUMMARY, $summaryrecord);
foreach ($resultrecords as $rr) {
$DB->insert_record(self::ASSIGNSUBMISSION_DTA_TABLE_RESULT, $rr);
}
}
/**
* Cleans up database if plugin is uninstalled.
*/
public static function assignsubmission_dta_uninstall_plugin_cleaup(): void {
global $DB;
$DB->delete_records(self::ASSIGNSUBMISSION_DTA_TABLE_RESULT, null);
$DB->delete_records(self::ASSIGNSUBMISSION_DTA_TABLE_SUMMARY, null);
$DB->delete_records(self::ASSIGNSUBMISSION_DTA_TABLE_RECOMMENDATIONS, null);
}
}
Assignee
mamunozgil's avatar
mamunozgil
Assign to
2 Reviewers
Khalani's avatar
Khalani
Kurzenberger's avatar
Kurzenberger
Request review from
Labels
0
None
0
None
    Assign labels
  • Manage project labels

Milestone
No milestone
None
None
Time tracking
No estimate or time spent
Lock merge request
Unlocked
3
3 participants
Khalani
Kurzenberger
mamunozgil
Reference: cota/moodle-assignsubmission_dta!1
Source branch: niklas-dev-recommendation

Menu

Explore Projects Groups Snippets

Dies ist die Gitlab-Instanz des Transferportals der Hochschule für Technik Stuttgart. Hier geht es zurück zum Portal