From c2c2729ed626a18a29b032cfdfecef50ae2f8689 Mon Sep 17 00:00:00 2001
From: Gero Lueckemeyer <gero.lueckemeyer@hft-stuttgart.de>
Date: Sat, 4 Nov 2023 20:51:57 +0100
Subject: [PATCH] added competency table to detail result view

---
 dta.zip                              | Bin 17620 -> 19042 bytes
 dta/lang/en/assignsubmission_dta.php |  95 +++++++++++++++++++++++--
 dta/locallib.php                     |   1 +
 dta/utils/view.php                   | 100 +++++++++++++++++++++------
 4 files changed, 168 insertions(+), 28 deletions(-)

diff --git a/dta.zip b/dta.zip
index d3e484ac961939f713024dc0926cbc3c944d6663..9caa7a91d4ad5759ff5316b9a412dea62e82a8ba 100644
GIT binary patch
delta 7248
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
RQ&O;KIeC=Nvi~6f{{?B`*Z}|l

delta 5836
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

diff --git a/dta/lang/en/assignsubmission_dta.php b/dta/lang/en/assignsubmission_dta.php
index dced807..5b41546 100644
--- a/dta/lang/en/assignsubmission_dta.php
+++ b/dta/lang/en/assignsubmission_dta.php
@@ -21,22 +21,105 @@
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-$string["pluginname"] = "Dockerized Testing Agent";
+// General.
+$string["pluginname"] = "Dockerized Testing Agent (DTA)";
+$string["enabled"] = $string["pluginname"];
+
+// Dialog field labels.
 $string["submission_label"] = "DTA submission configuration or zip-packed project";
 $string["submission_label_help"] = "Either upload a single textfile containing one DTA URI pointing to the repository with your submission or pack your project as zip and upload it directly. Using the textfile you can additionally add as many unified-ticketing URI (one per line) as you wish for feedback into one or more ticketsystems.";
 $string["submission_settings_label"] = "DTA test configuration";
 $string["submission_settings_label_help"] = "single text file with  DTA test URI";
-$string["backendHost_help"] = "Address/Name and Port of backend server";
-$string["backendHost_not_set"] = "The Dockerized Testing Agent backend URL is not configured";
-$string["enabled"] = $string["pluginname"];
 $string["enabled_help"] = "If enabled, you will have to upload a textfile containing a valid DTA URI pointing to the repository with your test logic and defining a docker image on dockerhub used as testrunner. Your students will have to either upload their code in a zip archive resembling the expected repository structure or as well by providing a textifle with a valid DTA URI pointing to the repository with their submission logic";
-$string["no_submissionfile_warning"] = "Submission type is \"Dockerized Testing Agent\" but no configuration file or submission archive uploaded";
+
+// Content.
+$string["tests_successful"] = " tests successful";
+$string["failures"] = " failures";
+$string["compilation_errors"] = " compilation error(s)";
+$string["unknown_state"] = " test(s) with unknown state";
+$string["sucess_competencies"] = "Successfully tested competency profile";
+$string["summary"] = "Summary";
+$string["total_items"] = "Total items";
+$string["success_rate"] = "Success rate";
+$string["details"] = "Details";
+$string["competencies"] = "Competencies";
+$string["package_name"] = "Package Name";
+$string["unit_name"] = "Unit Name";
+$string["test_name"] = "Test Name";
+$string["status"] = "Status";
+$string["failure_type"] = "Failure Type";
+$string["failure_reason"] = "Failure Reason";
+$string["line_no"] = "Line Number";
+$string["col_no"] = "Column Number";
+$string["pos"] = "Position";
+$string["stacktrace"] = "Stack Trace";
+
+// Comeptencies.
+$string["comp_statement"] = "Statement";
+$string["comp_block"] = "Block";
+$string["comp_flow"] = "Flow of Control";
+$string["comp_loop"] = "Repetition";
+$string["comp_const"] = "Constant";
+$string["comp_var"] = "Variable";
+$string["comp_type"] = "Type";
+$string["comp_datastructure"] = "Data Structure";
+$string["comp_interface"] = "Interface";
+$string["comp_unit"] = "Unit of Code";
+$string["comp_proc_usage"] = "Procedure Usage";
+$string["comp_proc_sign"] = "Procedure Signature";
+$string["comp_library"] = "Library Usage";
+$string["comp_ext_api"] = "External API Usage";
+$string["comp_simple"] = "Simplicity";
+$stirng["comp_abstraction"] = "Abstraction";
+
+// Competencies for index calculation.
+$string["comp1"] = $string["comp_statement"];
+$string["comp2"] = $string["comp_block"];
+$string["comp3"] = $string["comp_flow"];
+$string["comp4"] = $string["comp_loop"];
+$string["comp5"] = $string["comp_const"];
+$string["comp6"] = $string["comp_var"];
+$string["comp7"] = $string["comp_type"];
+$string["comp8"] = $string["comp_datastructure"];
+$string["comp9"] = $string["comp_interface"];
+$string["comp10"] = $string["comp_unit"];
+$string["comp11"] = $string["comp_proc_usage"];
+$string["comp12"] = $string["comp_proc_sign"];
+$string["comp13"] = $string["comp_library"];
+$string["comp14"] = $string["comp_ext_api"];
+$string["comp15"] = $string["comp_simple"];
+$string["comp16"] = $stirng["comp_abstraction"];
+
+// Competency explanations.
+$string["comp_statement_expl"] = "formulate a syntactically correct statement that contributes to the solution of the given problem.";
+$string["comp_block_expl"] = "structure code into syntactically correct small unnamed units that contribute to the solution of the given problem.";
+$string["comp_flow_expl"] = "formulate syntax elements guiding the control flow such that it contributes to the solution of the given problem.";
+$string["comp_loop_expl"] = "use syntax elements repeating statements such that it contributes to the solution of the given problem.";
+$string["comp_const_expl"] = "identify and syntactically correctly define constants that contribute to the understanding and solution of the given problem.";
+$string["comp_var_expl"] = "identify and syntactically correctly define variables that contribute to the solution of the given problem.";
+$string["comp_type_expl"] = "define and/or choose appropriate data types for data elements such that they contribute to the solution of the given problem.";
+$string["comp_datastructure_expl"] = "define and/or choose appropriate data structures for data elements such that they contribute to the solution of the given problem.";
+$string["comp_interface_expl"] = "define and use interfaces for larger units of code such that it contributes to the solution of the given problem.";
+$string["comp_unit_expl"] = "define and larger units of code such that it contributes to the solution of the given problem.";
+$string["comp_proc_usage_expl"] = "use existing named structure blocks with a pre-defined behavior and signature such that it contributes to the solution of the given problem.";
+$string["comp_proc_sign_expl"] = "define named structure blocks with a pre-defined behavior and signature such that it contributes to the solution of the given problem.";
+$string["comp_library_expl"] = "use existing larger collections of named structure blocks with a pre-defined behavior and signature such that it contributes to the solution of the given problem.";
+$string["comp_ext_api_expl"] = "use standardized existing external collections of named structure blocks with a pre-defined behavior and signature such that it contributes to the solution of the given problem.";
+$string["comp_simple_expl"] = "create a simple solution of the given problem.";
+$string["comp_abstraction_expl"] = "create a sufficiently abstract solution for the given problem.";
+
+// Warnings.
 $string["no_testfile_warning"] = "Submission type is \"Dockerized Testing Agent\" but no configuration file uploaded";
+
+// Error messages.
+$string["backendHost_not_set"] = "The Dockerized Testing Agent backend URL is not configured";
+$string["no_submissionfile_warning"] = "Submission type is \"Dockerized Testing Agent\" but no configuration file or submission archive uploaded";
 $string["http_client_error_msg"] = "A client error occured (HTTP 4xx)";
 $string["http_server_error_msg"] = "A server error occured (HTTP 5xx)";
 $string["http_unknown_error_msg"] = "An unknown HTTP error occured on backend transfer";
 
-// Admin Settings.
+// Admin settings.
 $string["default"] = "Enabled by default";
 $string["default_help"] = "If set, this submission method will be enabled by default for all new assignments.";
 $string["backendHost"] = "Backend Server Address";
+$string["backendHost_help"] = "Address/Name and Port of backend server";
diff --git a/dta/locallib.php b/dta/locallib.php
index 5ff5bcd..1e77341 100644
--- a/dta/locallib.php
+++ b/dta/locallib.php
@@ -67,6 +67,7 @@ class assign_submission_dta extends assign_submission_plugin {
         $mform->addHelpButton(
             // Form-unique element id to which to add button.
             self::ASSIGNSUBMISSION_DTA_DRAFT_FILEAREA_TEST,
+            // Key.
             "submission_settings_label",
             // Language file to use.
             self::COMPONENT_NAME
diff --git a/dta/utils/view.php b/dta/utils/view.php
index 4ac060f..63f4327 100644
--- a/dta/utils/view.php
+++ b/dta/utils/view.php
@@ -16,6 +16,9 @@
 
 class ViewSubmissionUtils {
 
+    // Broadly used in logic, parametrized for easier change.
+    const COMPONENT_NAME = "assignsubmission_dta";
+
     /**
      * generates a short summary html
      *
@@ -43,17 +46,17 @@ class ViewSubmissionUtils {
         $html .= ($summary->compilationErrorCount() == 0 && $summary->unknownCount() == 0)
             ? $summary->resultCount() . " (" . $successrate . "%)"
                 : "?";
-        $html .= " tests successful<br>";
+        $html .= get_string("tests_successful", self::COMPONENT_NAME) . "<br>";
 
         if ($summary->compilationErrorCount() > 0) {
-            $html .= $summary->compilationErrorCount() . " compilation error(s)<br>";
+            $html .= $summary->compilationErrorCount() . get_string("compilation_errors", self::COMPONENT_NAME) . "<br>";
         }
 
         if ($summary->unknownCount() > 0) {
-            $html .= $summary->unknownCount() . " test(s) with unknown state<br>";
+            $html .= $summary->unknownCount() . get_string("unknown_state", self::COMPONENT_NAME) . "<br>";
         }
 
-        $html .= $summary->successfulTestCompetencyProfile . " successfully tested competency profile<br>";
+        $html .= $summary->successfulTestCompetencyProfile . get_string("success_competencies", self::COMPONENT_NAME) . "<br>";
 
         return html_writer::div($html, "dtaSubmissionSummary");
     }
@@ -84,7 +87,7 @@ class ViewSubmissionUtils {
 
         // Summary table.
         $tmp = "";
-        $tmp .= html_writer::tag("th", "Summary", ["class" => "dtaTableHeader"]);
+        $tmp .= html_writer::tag("th", get_string("summary", self::COMPONENT_NAME), ["class" => "dtaTableHeader"]);
         $tmp .= html_writer::empty_tag("th", ["class" => "dtaTableHeader"]);
         $header = html_writer::tag("tr", $tmp, $tableheaderrowattributes);
         $header = html_writer::tag("thead", $header);
@@ -94,7 +97,7 @@ class ViewSubmissionUtils {
         $attributes = ["class" => "dtaTableData"];
         $tmp .= html_writer::tag(
             "td",
-            "result items in sum",
+            get_string("total_items", self::COMPONENT_NAME),
             $attributes);
 
         $tmp .= html_writer::tag(
@@ -108,7 +111,7 @@ class ViewSubmissionUtils {
         $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
 
         $tmp = "";
-        $tmp .= html_writer::tag("td", "successes", $attributes);
+        $tmp .= html_writer::tag("td", get_string("tests_successful", self::COMPONENT_NAME), $attributes);
         $tmp .= html_writer::tag( "td", $summary->successfulCount(), $attributes);
 
         $resultrowattributes = $tablerowattributes;
@@ -129,7 +132,7 @@ class ViewSubmissionUtils {
         $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
 
         $tmp = "";
-        $tmp .= html_writer::tag("td", "failures", $attributes);
+        $tmp .= html_writer::tag("td", get_string("failures", self::COMPONENT_NAME), $attributes);
         $tmp .= html_writer::tag("td", $summary->failedCount(), $attributes);
 
         $resultrowattributes = $tablerowattributes;
@@ -141,7 +144,7 @@ class ViewSubmissionUtils {
         $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
 
         $tmp = "";
-        $tmp .= html_writer::tag("td", "compilation errors", $attributes);
+        $tmp .= html_writer::tag("td", get_string("compilation_errors", self::COMPONENT_NAME), $attributes);
         $tmp .= html_writer::tag("td", $summary->compilationErrorCount(), $attributes);
 
         $resultrowattributes = $tablerowattributes;
@@ -153,7 +156,7 @@ class ViewSubmissionUtils {
         $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
 
         $tmp = "";
-        $tmp .= html_writer::tag("td", "unknown state", $attributes);
+        $tmp .= html_writer::tag("td", get_string("unknown_state", self::COMPONENT_NAME), $attributes);
         $tmp .= html_writer::tag("td", $summary->unknownCount(), $attributes);
 
         $resultrowattributes = $tablerowattributes;
@@ -165,7 +168,7 @@ class ViewSubmissionUtils {
         $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
 
         $tmp = "";
-        $tmp .= html_writer::tag("td", html_writer::tag("b", "success rate"), $attributes);
+        $tmp .= html_writer::tag("td", html_writer::tag("b", get_string("success_rate", self::COMPONENT_NAME)), $attributes);
         $tmp .= html_writer::tag(
             "td",
             html_writer::tag("b", $summary->successfulCount()
@@ -193,12 +196,45 @@ class ViewSubmissionUtils {
 
         $html .= $table;
 
-        // Add empty div for spacing between summary and details table.
+        // Add empty div for spacing between summary and compentency table.
+        $html .= html_writer::empty_tag("div", ["class" => "dtaSpacer"]);
+
+        $tmp = "";
+        $tmp .= html_writer::tag("th", get_string("competencies", self::COMPONENT_NAME), ["class" => "dtaTableHeader"]);
+        $tmp .= html_writer::empty_tag("th", ["class" => "dtaTableHeader"]);
+        $header = html_writer::tag("tr", $tmp, $tableheaderrowattributes);
+        $header = html_writer::tag("thead", $header);
+        
+        $showncompetencies = explode(";", $summary->successfultestcompetencies);
+        $overallcompetencies = explode(";", $summary->overalltestcompetencies);
+        $index=1;
+        foreach ($overallcompetencies as $comp) {
+            // If the competency was actually assessed by the assignment and tests, add a row in the table.
+            if($comp!="0") {
+                // New copy of base attributes array.
+                $resultrowattributes = $tablerowattributes;
+                $tmp = "";
+                $tmp .= html_writer::tag("td", get_string("comp" . $index, self::COMPONENT_NAME), $resultrowattributes);
+                
+                $tmp = "";
+                $tmp .= html_writer::tag("td", 
+                    floatval($showncompetencies[index])/floatval ($comp) . "% 
+                    (" . $showncompetencies[index] . " / " . $comp . ")",
+                    $resultrowattributes);
+                
+                $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
+            }
+            $index = $index + 1;
+        }
+        $body = html_writer::tag("tbody", $body);
+        $html .= html_writer::tag("table", $header . $body, ["class" => "dtaTable"]);
+
+        // Add empty div for spacing between competency and details table.
         $html .= html_writer::empty_tag("div", ["class" => "dtaSpacer"]);
 
         // Details table.
         $tmp = "";
-        $tmp .= html_writer::tag("th", "Details", ["class" => "dtaTableHeader"]);
+        $tmp .= html_writer::tag("th", get_string("details", self::COMPONENT_NAME), ["class" => "dtaTableHeader"]);
         $tmp .= html_writer::empty_tag("th", ["class" => "dtaTableHeader"]);
         $header = html_writer::tag("tr", $tmp, $tableheaderrowattributes);
         $header = html_writer::tag("thead", $header);
@@ -228,7 +264,27 @@ class ViewSubmissionUtils {
             $tmp = "";
             $tmp .= html_writer::tag(
                 "td",
-                "name",
+                get_string("package_name", self::COMPONENT_NAME),
+                $attributes);
+                
+            $tmp .= html_writer::tag(
+                "td",
+                $r->packagename,
+                $attributes);
+
+            $tmp .= html_writer::tag(
+                "td",
+                get_string("unit_name", self::COMPONENT_NAME),
+                $attributes);
+                
+            $tmp .= html_writer::tag(
+                "td",
+                $r->classname,
+                $attributes);
+
+            $tmp .= html_writer::tag(
+                "td",
+                get_string("test_name", self::COMPONENT_NAME),
                 $attributes);
 
             $tmp .= html_writer::tag(
@@ -240,7 +296,7 @@ class ViewSubmissionUtils {
             $tmp = "";
             $tmp .= html_writer::tag(
                 "td",
-                "state",
+                get_string("status", self::COMPONENT_NAME),
                 $attributes);
 
             $tmp .= html_writer::tag(
@@ -254,7 +310,7 @@ class ViewSubmissionUtils {
                 $tmp = "";
                 $tmp .= html_writer::tag(
                     "td",
-                    "failure type",
+                    get_string("failure_type", self::COMPONENT_NAME),
                     $attributes);
 
                 $tmp .= html_writer::tag(
@@ -266,7 +322,7 @@ class ViewSubmissionUtils {
                 $tmp = "";
                 $tmp .= html_writer::tag(
                     "td",
-                    "failure reason",
+                    get_string("failure_reason", self::COMPONENT_NAME),
                     $attributes);
 
                 $tmp .= html_writer::tag(
@@ -280,7 +336,7 @@ class ViewSubmissionUtils {
                     $tmp = "";
                     $tmp .= html_writer::tag(
                         "td",
-                        "line number",
+                        get_string("line_no", self::COMPONENT_NAME)"line number",
                         $attributes);
 
                     $tmp .= html_writer::tag(
@@ -294,7 +350,7 @@ class ViewSubmissionUtils {
                     $tmp = "";
                     $tmp .= html_writer::tag(
                         "td",
-                        "column number",
+                        get_string("col_no", self::COMPONENT_NAME),
                         $attributes);
 
                     $tmp .= html_writer::tag(
@@ -308,7 +364,7 @@ class ViewSubmissionUtils {
                     $tmp = "";
                     $tmp .= html_writer::tag(
                         "td",
-                        "position",
+                        get_string("pos", self::COMPONENT_NAME),
                         $attributes);
 
                     $tmp .= html_writer::tag(
@@ -321,7 +377,7 @@ class ViewSubmissionUtils {
                 $tmp = "";
                 $tmp .= html_writer::tag(
                     "td",
-                    "stacktrace",
+                    get_string("stacktrace", self::COMPONENT_NAME),
                     $attributes);
 
                 $tmp .= html_writer::tag(
@@ -331,7 +387,7 @@ class ViewSubmissionUtils {
                 $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
             }
 
-            // Set spacerrow value if null for next rount separation.
+            // Set spacerrow value if null for next round separation.
             if (is_null($spacerrow)) {
                 $spacerrow = html_writer::empty_tag("tr", ["class" => "dtaTableSpacer"]);
             }
-- 
GitLab