From 2a7c45cceec1a1ab3a123d1d6f96b3a18508ade3 Mon Sep 17 00:00:00 2001
From: Kurzenberger <01kuni1bif@hft-stuttgart.de>
Date: Fri, 15 Nov 2024 11:12:17 +0100
Subject: [PATCH] changed to match namespace conventions

---
 dta.zip                                       | Bin 33005 -> 35018 bytes
 dta/classes/backend.php                       | 144 ---------
 dta/classes/{database.php => db_utils.php}    |  73 ++---
 dta/classes/dta_backend_utils.php             | 151 ++++++++++
 dta/classes/models/dta_recommendation.php     |  90 ++++++
 dta/classes/models/dta_result.php             | 114 +++++++
 dta/classes/models/dta_result_summary.php     | 173 +++++++++++
 .../{view.php => view_submission_utils.php}   |  61 ++--
 dta/locallib.php                              | 159 +++++-----
 dta/models/DtaResult.php                      | 277 ------------------
 10 files changed, 675 insertions(+), 567 deletions(-)
 delete mode 100644 dta/classes/backend.php
 rename dta/classes/{database.php => db_utils.php} (82%)
 create mode 100644 dta/classes/dta_backend_utils.php
 create mode 100644 dta/classes/models/dta_recommendation.php
 create mode 100644 dta/classes/models/dta_result.php
 create mode 100644 dta/classes/models/dta_result_summary.php
 rename dta/classes/{view.php => view_submission_utils.php} (75%)
 delete mode 100644 dta/models/DtaResult.php

diff --git a/dta.zip b/dta.zip
index b63cd5fd0c2660cc8626519f46958bd7ae94f5df..7dcd55a2535cd9a81852ca626777d90e7c5afd0e 100644
GIT binary patch
delta 16638
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

delta 14529
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
QV1kT8gMc9U{2A>30}dhNegFUf

diff --git a/dta/classes/backend.php b/dta/classes/backend.php
deleted file mode 100644
index d0bc5bc..0000000
--- a/dta/classes/backend.php
+++ /dev/null
@@ -1,144 +0,0 @@
-<?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
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- * @copyright Gero Lueckemeyer and student project teams
- */
-
-/**
- * backend webservice contact utility class
- *
- * @package assignsubmission_dta
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- * @copyright Gero Lueckemeyer and student project teams
- */
-class DtaBackendUtils {
-
-    /**
-     * Returns the base url of the backend webservice as configured in the administration settings.
-     * @return string backend host base url
-     */
-    private static function getbackendbaseurl(): string {
-        $backendaddress = get_config(assign_submission_dta::COMPONENT_NAME, "backendHost");
-
-        if (empty($backendaddress)) {
-            \core\notification::error(get_string("backendHost_not_set", assign_submission_dta::COMPONENT_NAME));
-        }
-
-        return $backendaddress;
-    }
-
-    /**
-     * Sends the configuration textfile uploaded by prof to the backend.
-     *
-     * @param stdClass $assignment assignment this test-config belongs to
-     * @param stdClass $file uploaded test-config
-     * @return bool true if no error occurred
-     */
-    public static function sendtestconfigtobackend($assignment, $file): bool {
-        $backendaddress = self::getbackendbaseurl();
-        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::post($url, $params))) {
-            return false;
-        } else {
-            return true;
-        }
-    }
-
-    /**
-     * Sends submission config or archive to backend to be tested.
-     *
-     * @param stdClass $assignment assignment for the submission
-     * @param int $submissionid submissionid of the current file
-     * @param stdClass $file submission config file or archive with submission
-     * @return string json string with testresults or null on error
-     */
-    public static function send_submission_to_backend($assignment, $submissionid, $file): ?string {
-        $backendaddress = self::getbackendbaseurl();
-        if (empty($backendaddress)) {
-            return true;
-        }
-
-        // Set endpoint for test upload.
-        $url = $backendaddress . "/v1/task/" . $submissionid;
-
-        // Prepare params.
-        $params = [
-            "taskFile" => $file,
-            "assignmentId" => $assignment->get_instance()->id,
-        ];
-
-        return self::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 to
-     * @param array $params parameters for http-request
-     *
-     * @return string received body on success or null on error
-     */
-    private static function post($url, $params): ?string {
-        if (!isset($url) || !isset($params)) {
-            return false;
-        }
-
-        $options = ["CURLOPT_RETURNTRANSFER" => true];
-
-        $curl = new curl();
-        $response = $curl->post($url, $params, $options);
-
-        // Check state of request, if response code is a 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 give an error message.
-        debugging(assign_submission_dta::COMPONENT_NAME . ": Post file to server was not successful: http_code=" .
-        $info["http_code"]);
-
-        if ($info['http_code'] >= 400 && $info['http_code'] < 500) {
-            \core\notification::error(get_string("http_client_error_msg", assign_submission_dta::COMPONENT_NAME));
-            return null;
-        } else if ($info['http_code'] >= 500 && $info['http_code'] < 600) {
-            \core\notification::error(get_string("http_server_error_msg", assign_submission_dta::COMPONENT_NAME));
-            return null;
-        } else {
-            \core\notification::error(get_string("http_unknown_error_msg", assign_submission_dta::COMPONENT_NAME) .
-            $info["http_code"] . $response);
-            return null;
-        }
-    }
-
-}
diff --git a/dta/classes/database.php b/dta/classes/db_utils.php
similarity index 82%
rename from dta/classes/database.php
rename to dta/classes/db_utils.php
index f93fd06..0dfb452 100644
--- a/dta/classes/database.php
+++ b/dta/classes/db_utils.php
@@ -1,4 +1,5 @@
 <?php
+namespace assignsubmission_dta;
 // This file is part of Moodle - http://moodle.org/
 //
 // Moodle is free software: you can redistribute it and/or modify
@@ -21,7 +22,13 @@
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  * @copyright Gero Lueckemeyer and student project teams
  */
-class DbUtils {
+
+use assignsubmission_dta\dta_backend_utils;
+use assignsubmission_dta\view_submission_utils;
+use assignsubmission_dta\models\dta_result;
+use assignsubmission_dta\models\dta_result_summary;
+use assignsubmission_dta\models\dta_recommendation;
+class db_utils {
 
     /**
      * Summary database table name.
@@ -77,6 +84,7 @@ class DbUtils {
                     // Wenn der Abschlussstatus 1 ist, entferne den Datensatz aus $records
                     if ($completion && $completion->completionstate == 1) {
                         unset($records[$key]);
+                        
                     }
                 }
             }
@@ -94,10 +102,10 @@ class DbUtils {
      * @param int $submissionid submission id to search for
      * @return DttResultSummary representing given submission
      */
-    public static function getresultsummaryfromdatabase(
+    public static function get_result_summary_from_database(
         int $assignmentid,
         int $submissionid
-    ): DtaResultSummary {
+    ): dta_result_summary {
         global $DB;
 
         // Fetch data from database.
@@ -112,7 +120,7 @@ class DbUtils {
         ]);
 
         // Create a summary instance.
-        $summary = new DtaResultSummary();
+        $summary = new dta_result_summary();
         $summary->timestamp = $summaryrecord->timestamp;
         $summary->globalstacktrace = $summaryrecord->global_stacktrace;
         $summary->successfultestcompetencies = $summaryrecord->successful_competencies;
@@ -121,7 +129,7 @@ class DbUtils {
 
         // Create result instances and add to array of summary instance.
         foreach ($resultsarray as $rr) {
-            $result = new DtaResult();
+            $result = new dta_result();
             $result->packagename = $rr->package_name;
             $result->classname = $rr->class_name;
             $result->name = $rr->name;
@@ -138,33 +146,16 @@ class DbUtils {
 
         return $summary;
     }
-    public static function storeRecommendationstoDatabase(
+    public static function store_recommendations_to_database(
         int $assignmentid,
         int $submissionid,
         array $recommendations
     ): void {
         global $DB;
-        error_log(print_r($recommendations,true));
-    
-        // Prepare recommendations to persist to array.
-        $recommendationrecords = [];
-        foreach ($recommendations as $recommendation) {
-            $record = new stdClass();
-            $record->assignment_id = $assignmentid;
-            $record->submission_id = $submissionid;
-            $record->topic = $recommendation['topic'];
-            $record->url = $recommendation['url'];
-            $record->exercise_name = $recommendation['exercise_name'];
-            $record->difficulty = $recommendation['difficulty'];
-            $record->score = $recommendation['score'];
-            $recommendationrecords[] = $record;
-        }
-    
-        error_log("Das sind die Recommendationrecords.");
-        error_log(print_r($recommendationrecords,true));
+        error_log(print_r($recommendations, true));
     
         // If recommendations already exist, delete old values beforehand.
-        $existingrecords = $DB->get_record('assignsubmission_dta_recommendations', [
+        $existingrecords = $DB->get_records('assignsubmission_dta_recommendations', [
             'assignment_id' => $assignmentid,
             'submission_id' => $submissionid,
         ]);
@@ -177,10 +168,22 @@ class DbUtils {
         }
     
         // Create new recommendation entries.
-        foreach ($recommendationrecords as $rec) {
-            error_log("Insert record");
-            error_log(print_r($rec,true));
-            $DB->insert_record('assignsubmission_dta_recommendations', $rec);
+        foreach ($recommendations as $recommendation) {
+            // Ensure $recommendation is an instance of DtaRecommendation
+            if ($recommendation instanceof dta_recommendation) {
+                // Add assignment and submission IDs to the recommendation object
+                $recommendation->assignment_id = $assignmentid;
+                $recommendation->submission_id = $submissionid;
+    
+                error_log("Insert record");
+                error_log(print_r($recommendation, true));
+    
+                // Insert the recommendation into the database
+                $DB->insert_record('assignsubmission_dta_recommendations', $recommendation);
+            } else {
+                // Handle the case where $recommendation is not a DtaRecommendation instance
+                error_log("Invalid recommendation object");
+            }
         }
     }
     
@@ -191,17 +194,17 @@ class DbUtils {
      *
      * @param int $assignmentid assigment this is submission is linked to
      * @param int $submissionid submission of this result
-     * @param DtaResultSummary $summary instance to persist
+     * @param dta_result_summary $summary instance to persist
      */
-    public static function storeresultsummarytodatabase(
+    public static function store_result_summary_to_database(
         int $assignmentid,
         int $submissionid,
-        DtaResultSummary $summary
+        dta_result_summary $summary
     ): void {
         global $DB;
 
         // Prepare new database entries.
-        $summaryrecord = new stdClass();
+        $summaryrecord = new dta_result_summary();
         $summaryrecord->assignment_id = $assignmentid;
         $summaryrecord->submission_id = $submissionid;
         $summaryrecord->timestamp = $summary->timestamp;
@@ -212,7 +215,7 @@ class DbUtils {
         // Prepare results to persist to array.
         $resultrecords = [];
         foreach ($summary->results as $r) {
-            $record = new stdClass();
+            $record = new dta_result();
             $record->assignment_id = $assignmentid;
             $record->submission_id = $submissionid;
             $record->package_name = $r->packagename;
@@ -256,7 +259,7 @@ class DbUtils {
     /**
      * cleans up database if plugin is uninstalled
      */
-    public static function uninstallplugincleaup(): void {
+    public static function uninstall_plugin_cleaup(): void {
         global $DB;
 
         $DB->delete_records(self::TABLE_RESULT, null);
diff --git a/dta/classes/dta_backend_utils.php b/dta/classes/dta_backend_utils.php
new file mode 100644
index 0000000..cfe0ac9
--- /dev/null
+++ b/dta/classes/dta_backend_utils.php
@@ -0,0 +1,151 @@
+<?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
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+
+
+/**
+ * Backend webservice contact utility class
+ *
+ * @package    assignsubmission_dta
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace assignsubmission_dta;
+
+defined('MOODLE_INTERNAL') || die();
+
+class dta_backend_utils {
+
+    /**
+     * Component name for the plugin.
+     */
+    const 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 get_backend_baseurl(): string {
+        $backendaddress = get_config(self::COMPONENT_NAME, 'backendHost');
+
+        if (empty($backendaddress)) {
+            \core\notification::error(get_string('backendHost_not_set', self::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 send_testconfig_to_backend($assignment, $file): bool {
+        $backendaddress = self::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::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 send_submission_to_backend($assignment, $submissionid, $file): ?string {
+        $backendaddress = self::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::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 to
+     * @param array $params Parameters for HTTP request
+     *
+     * @return string|null Received body on success or null on error
+     */
+    private static function post($url, $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 a 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 give an error message.
+        debugging(self::COMPONENT_NAME . ': Post file to server was not successful: http_code=' . $info['http_code']);
+
+        if ($info['http_code'] >= 400 && $info['http_code'] < 500) {
+            \core\notification::error(get_string('http_client_error_msg', self::COMPONENT_NAME));
+            return null;
+        } else if ($info['http_code'] >= 500 && $info['http_code'] < 600) {
+            \core\notification::error(get_string('http_server_error_msg', self::COMPONENT_NAME));
+            return null;
+        } else {
+            \core\notification::error(get_string('http_unknown_error_msg', self::COMPONENT_NAME) . $info['http_code'] . $response);
+            return null;
+        }
+    }
+}
diff --git a/dta/classes/models/dta_recommendation.php b/dta/classes/models/dta_recommendation.php
new file mode 100644
index 0000000..19a1cae
--- /dev/null
+++ b/dta/classes/models/dta_recommendation.php
@@ -0,0 +1,90 @@
+<?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;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * 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 $exercise_name Name of the exercise.
+     */
+    public $exercise_name;
+
+    /**
+     * @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 DtaRecommendation objects.
+     *
+     * @param string $jsonstring JSON string containing recommendations
+     * @return array Array of DtaRecommendation objects
+     */
+    public static function decode_json_recommendations(string $jsonstring): array {
+        $response = json_decode($jsonstring);
+
+        $recommendations = [];
+
+        // Prüfe, ob Empfehlungen vorhanden sind
+        if (!empty($response->recommendations)) {
+            foreach ($response->recommendations as $recommendation) {
+                $rec = new dta_recommendation();
+                $rec->topic = $recommendation->topic ?? null;
+                $rec->exercise_name = $recommendation->url ?? null;
+                $rec->url = $recommendation->exerciseName ?? null;
+                $rec->difficulty = $recommendation->difficulty ?? null;
+                $rec->score = $recommendation->score ?? null;
+
+                $recommendations[] = $rec;
+            }
+        }
+
+        return $recommendations;
+    }
+}
diff --git a/dta/classes/models/dta_result.php b/dta/classes/models/dta_result.php
new file mode 100644
index 0000000..d1650ee
--- /dev/null
+++ b/dta/classes/models/dta_result.php
@@ -0,0 +1,114 @@
+<?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;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * 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.
+     */
+    const 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 getstatename(int $state): string {
+        if ($state == 1) {
+            return get_string('tests_successful', self::COMPONENT_NAME);
+        } else if ($state == 2) {
+            return get_string('failures', self::COMPONENT_NAME);
+        } else if ($state == 3) {
+            return get_string('compilation_errors', self::COMPONENT_NAME);
+        } else {
+            return get_string('unknown_state', self::COMPONENT_NAME);
+        }
+    }
+}
diff --git a/dta/classes/models/dta_result_summary.php b/dta/classes/models/dta_result_summary.php
new file mode 100644
index 0000000..56ed33e
--- /dev/null
+++ b/dta/classes/models/dta_result_summary.php
@@ -0,0 +1,173 @@
+<?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 summary
+ *
+ * @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;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Entity class for DTA submission plugin result summary
+ *
+ * @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_summary {
+
+    /**
+     * @var int $timestamp Result timestamp for chronological ordering and deletion of previous results.
+     */
+    public $timestamp;
+
+    /**
+     * @var string $globalstacktrace Global stack trace if applicable, empty string otherwise.
+     */
+    public $globalstacktrace;
+
+    /**
+     * @var string $successfultestcompetencies Successfully tested competencies according to tests and weights, empty string otherwise.
+     */
+    public $successfultestcompetencies;
+
+    /**
+     * @var string $overalltestcompetencies Overall tested competencies according to tests and weights, empty string otherwise.
+     */
+    public $overalltestcompetencies;
+
+    /**
+     * @var array $results List of detail results.
+     */
+    public $results;
+
+    /**
+     * Decodes the JSON result summary returned by the backend service call into the plugin PHP data structure.
+     *
+     * @param string $jsonstring JSON string containing DtaResultSummary
+     * @return DtaResultSummary The result summary
+     */
+    public static function decode_json(string $jsonstring): dta_result_summary {
+        $response = json_decode($jsonstring);
+
+        $summary = new dta_result_summary();
+        $summary->timestamp = $response->timestamp;
+        $summary->globalstacktrace = $response->globalstacktrace;
+
+        $summary->successfultestcompetencies = $response->successfulTestCompetencyProfile ?? '';
+        $summary->overalltestcompetencies = $response->overallTestCompetencyProfile ?? '';
+
+        $summary->results = self::decode_json_result_array($response->results);
+
+        return $summary;
+    }
+
+    /**
+     * Decodes the array of JSON detail results returned by the backend service call into the plugin PHP data structure.
+     *
+     * @param array $jsonarray Decoded JSON array of results
+     * @return array Array of DtaResult
+     */
+    private static function 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 ?? '';
+            $value->linenumber = $entry->lineNumber ?? '';
+            $value->position = $entry->position ?? '';
+
+            $ret[] = $value;
+        }
+        return $ret;
+    }
+
+    /**
+     * Returns the number of detail results attached to the summary.
+     *
+     * @return int Count of occurrences
+     */
+    public function result_count(): int {
+        return count($this->results);
+    }
+
+    /**
+     * Returns the number of detail results with the given state attached to the summary.
+     *
+     * @param int $state State ordinal number
+     * @return int Count of occurrences for the provided state
+     */
+    public function state_occurence_count(int $state): int {
+        $num = 0;
+        foreach ($this->results as $r) {
+            if ($r->state == $state) {
+                $num++;
+            }
+        }
+        return $num;
+    }
+
+    /**
+     * Returns the number of detail results with compilation errors attached to the summary.
+     *
+     * @return int Count of occurrences
+     */
+    public function compilationerrorcount(): int {
+        return $this->state_occurence_count(3);
+    }
+
+    /**
+     * Returns the number of detail results with test failures attached to the summary.
+     *
+     * @return int Count of occurrences
+     */
+    public function failedcount(): int {
+        return $this->state_occurence_count(2);
+    }
+
+    /**
+     * Returns the number of detail results with successful tests attached to the summary.
+     *
+     * @return int Count of occurrences
+     */
+    public function successfulcount(): int {
+        return $this->state_occurence_count(1);
+    }
+
+    /**
+     * Returns the number of detail results with an unknown result attached to the summary.
+     *
+     * @return int Count of occurrences
+     */
+    public function unknowncount(): int {
+        return $this->state_occurence_count(0);
+    }
+}
diff --git a/dta/classes/view.php b/dta/classes/view_submission_utils.php
similarity index 75%
rename from dta/classes/view.php
rename to dta/classes/view_submission_utils.php
index d6258cd..fed291a 100644
--- a/dta/classes/view.php
+++ b/dta/classes/view_submission_utils.php
@@ -1,4 +1,5 @@
 <?php
+namespace assignsubmission_dta;
 // This file is part of Moodle - http://moodle.org/
 //
 // Moodle is free software: you can redistribute it and/or modify
@@ -20,6 +21,12 @@
  * @package assignsubmission_dta
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
+use assignsubmission_dta\db_utils;
+use assignsubmission_dta\dta_backend_utils;
+use assignsubmission_dta\models\dta_result;
+use assignsubmission_dta\models\dta_result_summary;
+use assignsubmission_dta\models\dta_recommendation;
+
 class view_submission_utils {
 
     /**
@@ -34,13 +41,13 @@ class view_submission_utils {
      * @param int $submissionid submission to create a report for
      * @return string html
      */
-    public static function generatesummaryhtml(
+    public static function generate_summary_html(
         int $assignmentid,
         int $submissionid
     ): string {
 
         // Fetch data.
-        $summary = DbUtils::getResultSummaryFromDatabase($assignmentid, $submissionid);
+        $summary = db_utils::get_Result_Summary_From_Database($assignmentid, $submissionid);
         $html = "";
 
         // Calculate success rate, if no unknown result states or compilation errors.
@@ -52,7 +59,7 @@ class view_submission_utils {
         // Generate html.
         $html .= $summary->successfulCount() . "/";
         $html .= ($summary->compilationErrorCount() == 0 && $summary->unknownCount() == 0)
-            ? $summary->resultCount() . " (" . $successrate . "%)"
+            ? $summary->result_Count() . " (" . $successrate . "%)"
                 : "?";
         $html .= get_string("tests_successful", self::COMPONENT_NAME) . "<br />";
 
@@ -80,7 +87,7 @@ class view_submission_utils {
 
         $html .= get_string("success_competencies", self::COMPONENT_NAME) . "<br />" . $tmp . "<br />";
 
-        return html_writer::div($html, "dtaSubmissionSummary");
+        return \html_writer::div($html, "dtaSubmissionSummary");
     }
 
  /**
@@ -90,7 +97,7 @@ class view_submission_utils {
  * @param int $submissionid Submission-ID, für die der Bericht erstellt wird
  * @return string HTML-Code
  */
-public static function generatedetailhtml(
+public static function generate_detail_html(
     int $assignmentid,
     int $submissionid
 ): string {
@@ -99,7 +106,7 @@ public static function generatedetailhtml(
     $html = "";
 
     // Daten abrufen
-    $summary = DbUtils::getResultSummaryFromDatabase($assignmentid, $submissionid);
+    $summary = db_utils::get_Result_Summary_From_Database($assignmentid, $submissionid);
 
     // CSS-Klassen und HTML-Attributarrays definieren
     $tableheaderrowattributes = ["class" => "dtaTableHeaderRow"];
@@ -114,11 +121,11 @@ public static function generatedetailhtml(
     // (Ihr bisheriger Code bleibt unverändert)
 
     // **Abstand zwischen Tabellen**
-    $html .= html_writer::empty_tag("div", ["class" => "dtaSpacer"]);
+    $html .= \html_writer::empty_tag("div", ["class" => "dtaSpacer"]);
 
     // **Empfehlungstabelle hinzufügen**
     // Empfehlungen für die Submission abrufen
-    $recommendations = DbUtils::get_recommendations_from_database($assignmentid, $submissionid);
+    $recommendations = db_utils::get_recommendations_from_database($assignmentid, $submissionid);
 
     if (!empty($recommendations)) {
         // **Sortierparameter abrufen**
@@ -160,7 +167,7 @@ public static function generatedetailhtml(
         });
 
         // Überschrift für Empfehlungen
-        $html .= html_writer::tag('h3', get_string('recommendations', self::COMPONENT_NAME));
+        $html .= \html_writer::tag('h3', get_string('recommendations', self::COMPONENT_NAME));
 
         // Helper-Funktion zum Generieren von sortierbaren Headern
         $generate_sortable_header = function($column_name, $display_name) use ($sortby, $sortdir) {
@@ -171,7 +178,7 @@ public static function generatedetailhtml(
             }
 
             // Button erstellen
-            $button = html_writer::empty_tag('input', [
+            $button = \html_writer::empty_tag('input', [
                 'type' => 'submit',
                 'name' => 'sortbutton',
                 'value' => ($new_sortdir == 'asc' ? '↑' : '↓'),
@@ -179,57 +186,57 @@ public static function generatedetailhtml(
             ]);
 
             // Hidden Inputs für Sortierparameter
-            $hidden_inputs = html_writer::empty_tag('input', [
+            $hidden_inputs = \html_writer::empty_tag('input', [
                 'type' => 'hidden',
                 'name' => 'sortby',
                 'value' => $column_name
             ]);
-            $hidden_inputs .= html_writer::empty_tag('input', [
+            $hidden_inputs .= \html_writer::empty_tag('input', [
                 'type' => 'hidden',
                 'name' => 'sortdir',
                 'value' => $new_sortdir
             ]);
 
             // Formular für den Button erstellen
-            $form = html_writer::start_tag('form', ['method' => 'post', 'style' => 'display:inline']);
+            $form = \html_writer::start_tag('form', ['method' => 'post', 'style' => 'display:inline']);
             $form .= $hidden_inputs;
             $form .= $display_name . ' ' . $button;
-            $form .= html_writer::end_tag('form');
+            $form .= \html_writer::end_tag('form');
 
-            return html_writer::tag("th", $form, ["class" => $class]);
+            return \html_writer::tag("th", $form, ["class" => $class]);
         };
 
         // Tabellenkopf für Empfehlungen
         $tableheader = "";
         $tableheader .= $generate_sortable_header('topic', get_string("topic", self::COMPONENT_NAME));
         $tableheader .= $generate_sortable_header('exercise_name', get_string("exercise_name", self::COMPONENT_NAME));
-        $tableheader .= html_writer::tag("th", get_string("url", self::COMPONENT_NAME), ["class" => "dtaTableHeader"]);
+        $tableheader .= \html_writer::tag("th", get_string("url", self::COMPONENT_NAME), ["class" => "dtaTableHeader"]);
         $tableheader .= $generate_sortable_header('difficulty', get_string("difficulty", self::COMPONENT_NAME));
         $tableheader .= $generate_sortable_header('score', get_string("score", self::COMPONENT_NAME));
 
-        $tableheader = html_writer::tag("tr", $tableheader, ["class" => "dtaTableHeaderRow"]);
-        $tableheader = html_writer::tag("thead", $tableheader);
+        $tableheader = \html_writer::tag("tr", $tableheader, ["class" => "dtaTableHeaderRow"]);
+        $tableheader = \html_writer::tag("thead", $tableheader);
 
         // Tabellenkörper für Empfehlungen
         $tablebody = "";
         foreach ($recommendations as $recommendation) {
             $tablerow = "";
-            $tablerow .= html_writer::tag("td", $recommendation->topic, $attributes);
-            $tablerow .= html_writer::tag("td", $recommendation->exercise_name, $attributes);
-            $tablerow .= html_writer::tag("td", html_writer::link($recommendation->url, $recommendation->url), $attributes);
-            $tablerow .= html_writer::tag("td", $recommendation->difficulty, $attributes);
-            $tablerow .= html_writer::tag("td", $recommendation->score, $attributes);
+            $tablerow .= \html_writer::tag("td", $recommendation->topic, $attributes);
+            $tablerow .= \html_writer::tag("td", $recommendation->exercise_name, $attributes);
+            $tablerow .= \html_writer::tag("td", \html_writer::link($recommendation->url, $recommendation->url), $attributes);
+            $tablerow .= \html_writer::tag("td", $recommendation->difficulty, $attributes);
+            $tablerow .= \html_writer::tag("td", $recommendation->score, $attributes);
 
-            $tablebody .= html_writer::tag("tr", $tablerow, $tablerowattributes);
+            $tablebody .= \html_writer::tag("tr", $tablerow, $tablerowattributes);
         }
-        $tablebody = html_writer::tag("tbody", $tablebody);
+        $tablebody = \html_writer::tag("tbody", $tablebody);
 
         // Empfehlungstabelle zusammenstellen
-        $html .= html_writer::tag("table", $tableheader . $tablebody, ["class" => "dtaTable"]);
+        $html .= \html_writer::tag("table", $tableheader . $tablebody, ["class" => "dtaTable"]);
     }
 
     // Abschließendes Div für die gesamte HTML-Ausgabe
-    $html = html_writer::div($html, "dtaSubmissionDetails");
+    $html = \html_writer::div($html, "dtaSubmissionDetails");
 
     return $html;
 }
diff --git a/dta/locallib.php b/dta/locallib.php
index 28ea9be..cbea769 100644
--- a/dta/locallib.php
+++ b/dta/locallib.php
@@ -16,14 +16,15 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-// Import various entity and application logic files.
-require_once($CFG->dirroot . '/mod/assign/submission/dta/models/DtaResult.php');
-require_once($CFG->dirroot . '/mod/assign/submission/dta/classes/database.php');
-require_once($CFG->dirroot . '/mod/assign/submission/dta/classes/backend.php');
-require_once($CFG->dirroot . '/mod/assign/submission/dta/classes/view.php');
+use assignsubmission_dta\db_utils;
+use assignsubmission_dta\dta_backend_utils;
+use assignsubmission_dta\view_submission_utils;
+use assignsubmission_dta\models\dta_result;
+use assignsubmission_dta\models\dta_result_summary;
+use assignsubmission_dta\models\dta_recommendation;
 
 /**
- * library class for DTA submission plugin extending assign submission plugin base class
+ * Library class for DTA submission plugin extending assign submission plugin base class
  *
  * @package assignsubmission_dta
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@@ -35,20 +36,20 @@ class assign_submission_dta extends assign_submission_plugin {
      */
     const COMPONENT_NAME = "assignsubmission_dta";
     /**
-     * Draft file area for dta tests to be uploaded by the teacher.
+     * Draft file area for DTA tests to be uploaded by the teacher.
      */
     const ASSIGNSUBMISSION_DTA_DRAFT_FILEAREA_TEST = "tests_draft_dta";
     /**
-     * File area for dta tests to be uploaded by the teacher.
+     * File area for DTA tests to be uploaded by the teacher.
      */
     const ASSIGNSUBMISSION_DTA_FILEAREA_TEST = "tests_dta";
     /**
-     * File area for dta submission assignment.
+     * File area for DTA submission assignment.
      */
     const ASSIGNSUBMISSION_DTA_FILEAREA_SUBMISSION = "submissions_dta";
 
     /**
-     * get plugin name
+     * Get plugin name
      * @return string
      */
     public function get_name(): string {
@@ -93,7 +94,7 @@ class assign_submission_dta extends assign_submission_plugin {
     }
 
     /**
-     * Allows the plugin to update the defaultvalues passed in to
+     * Allows the plugin to update the default values passed into
      * the settings form (needed to set up draft areas for editor
      * and filemanager elements)
      * @param array $defaultvalues
@@ -162,7 +163,7 @@ class assign_submission_dta extends assign_submission_plugin {
         $file = reset($files);
 
         // Send file to backend.
-        return DtaBackendUtils::sendtestconfigtobackend($this->assignment, $file);
+        return dta_backend_utils::send_testconfig_to_backend($this->assignment, $file);
     }
 
     /**
@@ -240,86 +241,78 @@ class assign_submission_dta extends assign_submission_plugin {
         return count($files);
     }
 
-   /**
- * Save data to the database
- *
- * @param stdClass $submission
- * @param stdClass $data
- * @return bool
- */
-public function save(stdClass $submission, stdClass $data) {
-    $data = file_postupdate_standard_filemanager(
-        $data,
-        'tasks',
-        $this->get_file_options(false),
-        $this->assignment->get_context(),
-        self::COMPONENT_NAME,
-        self::ASSIGNSUBMISSION_DTA_FILEAREA_SUBMISSION,
-        $submission->id
-    );
-
-    // If submission is empty leave directly.
-    if ($this->is_empty($submission)) {
-        return true;
-    }
-
-    // Get submitted files.
-    $fs = get_file_storage();
-    $files = $fs->get_area_files(
-        // Id of current assignment.
-        $this->assignment->get_context()->id,
-        self::COMPONENT_NAME,
-        self::ASSIGNSUBMISSION_DTA_FILEAREA_SUBMISSION,
-        $submission->id,
-        'id',
-        false
-    );
-
-    // Check if a file is uploaded.
-    if (empty($files)) {
-        \core\notification::error(get_string("no_submissionfile_warning", self::COMPONENT_NAME));
-        return true;
-    }
-
-    // Get the file.
-    $file = reset($files);
+    /**
+     * Save data to the database
+     *
+     * @param stdClass $submission
+     * @param stdClass $data
+     * @return bool
+     */
+    public function save(stdClass $submission, stdClass $data) {
+        $data = file_postupdate_standard_filemanager(
+            $data,
+            'tasks',
+            $this->get_file_options(false),
+            $this->assignment->get_context(),
+            self::COMPONENT_NAME,
+            self::ASSIGNSUBMISSION_DTA_FILEAREA_SUBMISSION,
+            $submission->id
+        );
 
-    // Send file to backend.
-    $response = DtaBackendUtils::send_submission_to_backend($this->assignment, $submission->id, $file);
+        // If submission is empty, leave directly.
+        if ($this->is_empty($submission)) {
+            return true;
+        }
 
-    // With a null response, return an error.
-    if (is_null($response)) {
-        return false;
-    }
+        // Get submitted files.
+        $fs = get_file_storage();
+        $files = $fs->get_area_files(
+            // Id of current assignment.
+            $this->assignment->get_context()->id,
+            self::COMPONENT_NAME,
+            self::ASSIGNSUBMISSION_DTA_FILEAREA_SUBMISSION,
+            $submission->id,
+            'id',
+            false
+        );
 
-    // Convert received json to valid class instances.
-    $resultsummary = DtaResultSummary::decodejson($response);
-    // Log an error message.
-   
-    $recommendations = DtaResultSummary::decodeJsonRecommendation($response);
+        // Check if a file is uploaded.
+        if (empty($files)) {
+            \core\notification::error(get_string("no_submissionfile_warning", self::COMPONENT_NAME));
+            return true;
+        }
 
-    error_log(print_r($recommendations,true));
+        // Get the file.
+        $file = reset($files);
 
+        // Send file to backend.
+        $response = \assignsubmission_dta\dta_backend_utils::send_submission_to_backend($this->assignment, $submission->id, $file);
 
+        // With a null response, return an error.
+        if (is_null($response)) {
+            return false;
+        }
 
-    // Persist new results to database.
-    DbUtils::storeresultsummarytodatabase($this->assignment->get_instance()->id, $submission->id, $resultsummary);
+        // Convert received JSON to valid class instances.
+        $resultsummary = dta_result_summary::decode_json($response);
 
+        // Decode recommendations from response.
+        $recommendations = dta_recommendation::decode_json_recommendations($response);
 
+        error_log(print_r($recommendations, true));
 
-   
-        // Store the array of records in the database.
-    DbUtils::storeRecommendationstoDatabase($this->assignment->get_instance()->id, $submission->id, $recommendations);
-    
-    
+        // Persist new results to database.
+        db_utils::store_result_summary_to_database($this->assignment->get_instance()->id, $submission->id, $resultsummary);
 
-    return true;
-}
+        // Store the array of recommendations in the database.
+        db_utils::store_recommendations_to_database($this->assignment->get_instance()->id, $submission->id, $recommendations);
 
+        return true;
+    }
 
     /**
      * Display a short summary of the test results of the submission
-     * This is diplayed as default view, with the option to expand
+     * This is displayed as default view, with the option to expand
      * to the full detailed results.
      *
      * @param stdClass $submission to show
@@ -329,7 +322,7 @@ public function save(stdClass $submission, stdClass $data) {
     public function view_summary(stdClass $submission, & $showviewlink) {
         $showviewlink = true;
 
-        return view_submission_utils::generatesummaryhtml(
+        return view_submission_utils::generate_summary_html(
             $this->assignment->get_instance()->id,
             $submission->id
         );
@@ -342,16 +335,14 @@ public function save(stdClass $submission, stdClass $data) {
      * @return string detailed results html
      */
     public function view(stdClass $submission) {
-        // Sicherstellen, dass $cmid verfügbar ist
-
-        return view_submission_utils::generatedetailhtml(
+        return view_submission_utils::generate_detail_html(
             $this->assignment->get_instance()->id,
             $submission->id
         );
     }
 
     /**
-     * generate array of allowed filetypes to upload.
+     * Generate array of allowed file types to upload.
      *
      * @param bool $settings switch to define if list for assignment settings
      *      or active submission should be returned
@@ -413,12 +404,12 @@ public function save(stdClass $submission, stdClass $data) {
     }
 
     /**
-     * The plugin is beeing uninstalled - cleanup
+     * The plugin is being uninstalled - cleanup
      *
      * @return bool
      */
     public function delete_instance() {
-        DbUtils::uninstallplugincleanup();
+        db_utils::uninstall_plugin_cleanup();
 
         return true;
     }
diff --git a/dta/models/DtaResult.php b/dta/models/DtaResult.php
deleted file mode 100644
index 867ee81..0000000
--- a/dta/models/DtaResult.php
+++ /dev/null
@@ -1,277 +0,0 @@
-<?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 classes for DTA submission plugin result summary and test results
- *
- * @package assignsubmission_dta
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- * @copyright Gero Lueckemeyer and student project teams
- */
-defined('MOODLE_INTERNAL') || die();
-
-/**
- * entity class for DTA submission plugin result
- *
- * @package assignsubmission_dta
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- * @copyright Gero Lueckemeyer and student project teams
- */
-class DtaResult {
-
-    /**
-     * Broadly used in logic, parametrized for easier change.
-     */
-    const COMPONENT_NAME = "assignsubmission_dta";
-
-    /**
-     * @var $packagename Package name of the test.
-     */
-    public $packagename;
-
-    /**
-     * @var $classname Unit name of the test.
-     */
-    public $classname;
-
-    /**
-     * @var $name Name of the test.
-     */
-    public $name;
-
-    /**
-     * @var $state State is defined like below
-     *
-     *  0 UNKNOWN
-     *  1 SUCCESS
-     *  2 FAILURE
-     *  3 COMPILATIONERROR
-     */
-    public $state;
-
-    /**
-     * @var $failuretype Type of test failure if applicable, "" otherwise.
-     */
-    public $failuretype;
-
-    /**
-     * @var $failurereason Reason of test failure if applicable, "" otherwise.
-     */
-    public $failurereason;
-
-    /**
-     * @var $stacktrace Stack trace of test failure if applicable, "" otherwise.
-     */
-    public $stacktrace;
-
-    /**
-     * @var $columnnumber Column number of compile failure if applicable, "" otherwise.
-     */
-    public $columnnumber;
-    /**
-     * @var $linenumber Line number of compile failure if applicable, "" otherwise.
-     */
-    public $linenumber;
-    /**
-     * @var $position Position of compile failure if applicable, "" otherwise.
-     */
-    public $position;
-
-    /**
-     * Returns the name of a state with the given number of display.
-     * @param int $state number of the state
-     * @return string name of state as defined
-     */
-    public static function getstatename(int $state): string {
-        if ($state == 1) {
-            return get_string("tests_successful", self::COMPONENT_NAME);
-        } else if ($state == 2) {
-            return get_string("failures", self::COMPONENT_NAME);
-        } else if ($state == 3) {
-            return get_string("compilation_errors", self::COMPONENT_NAME);
-        } else {
-            return get_string("unknown_state", self::COMPONENT_NAME);
-        }
-    }
-}
-
-/**
- * entity class for DTA submission plugin result
- *
- * @package assignsubmission_dta
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- * @copyright Gero Lueckemeyer and student project teams
- */
-class DtaResultSummary {
-
-    /**
-     * @var $timestamp Result timestamp for chronological ordering and deletion of previous results.
-     */
-    public $timestamp;
-
-    /**
-     * @var $globalstacktrace Global stack trace if applicable, "" otherwise.
-     */
-    public $globalstacktrace;
-
-    /**
-     * @var $successfultestcompetencies Successfully tested competencies according to tests and weights, "" otherwise.
-     */
-    public $successfultestcompetencies;
-    /**
-     * @var overalltestcompetencies Overall tested competencies according to tests and weights, "" otherwise.
-     */
-    public $overalltestcompetencies;
-    /**
-     * @var results List of detail results.
-     */
-    public $results;
-
-    /**
-     * Decodes the JSON result summary returned by the backend service call into the plugin PHP data structure.
-     * @param string $jsonstring jsonString containing DtaResultSummary
-     * @return DtaResultSummary the result summary
-     */
-    public static function decodejson(string $jsonstring): DtaResultSummary {
-        $response = json_decode($jsonstring);
-        
-
-        $summary = new DtaResultSummary();
-        $summary->timestamp = $response->timestamp;
-        $summary->globalstacktrace = $response->globalstacktrace;
-
-        $summary->successfultestcompetencies = $response->successfulTestCompetencyProfile;
-        $summary->overalltestcompetencies = $response->overallTestCompetencyProfile;
-
-        $summary->results = self::decodejsonresultarray($response->results);
-
-        return $summary;
-    }
-
-    public static function decodeJsonRecommendation(string $jsonstring): array {
-        // Decode the JSON string into a PHP object
-        $response = json_decode($jsonstring);
-        error_log("decodeJsonRecommendation");
-        error_log(print_r($response, true));
-
-        
-        // Initialize an empty array to store recommendations
-        $recommendations = [];
-    
-        // Loop through the recommendations in the response
-        if (!empty($response->recommendations)) {
-            foreach ($response->recommendations as $recommendation) {
-                // For each recommendation, create an associative array with the properties
-                $recommendations[] = [
-                    'topic' => $recommendation->topic ?? null,
-                    'url' => $recommendation->exerciseName ?? null,
-                    'exercise_name' => $recommendation->url ?? null,
-                    'difficulty' => $recommendation->difficulty ?? null,
-                    'score' => $recommendation->score ?? null
-                ];
-            }
-        }
-        error_log(print_r($recommendations,true));
-        // Return the array of recommendations
-        return $recommendations;
-    }
-    
-
-    /**
-     * Decodes the array of JSON detail results returned by the backend service call into the plugin PHP data structure.
-     * @param array $jsonarray decoded json array of results array
-     * @return array of DtaResult
-     */
-    private static function decodejsonresultarray($jsonarray): array {
-        $ret = [];
-        foreach ($jsonarray as $entry) {
-            $value = new DtaResult();
-            $value->packagename = $entry->packageName;
-            $value->classname = $entry->className;
-            $value->name = $entry->name;
-
-            $value->state = $entry->state;
-
-            $value->failuretype = $entry->failureType;
-            $value->failurereason = $entry->failureReason;
-            $value->stacktrace = $entry->stacktrace;
-
-            $value->columnnumber = $entry->columnNumber;
-            $value->linenumber = $entry->lineNumber;
-            $value->position = $entry->position;
-
-            $ret[] = $value;
-        }
-        return $ret;
-    }
-
-
-    /**
-     * Returns the number of detail results attached to the summary.
-     * @return int count of occurences
-     */
-    public function resultcount(): int {
-        return count($this->results);
-    }
-
-    /**
-     * Returns the number of detail results with the given state attached to the summary.
-     * @param int $state state ordinal number
-     * @return int count of occurences provided state has
-     */
-    public function stateoccurencecount(int $state): int {
-        $num = 0;
-        foreach ($this->results as $r) {
-            if ($r->state == $state) {
-                $num++;
-            }
-        }
-        return $num;
-    }
-
-    /**
-     * Returns the number of detail results with compilation errors attached to the summary.
-     * @return int count of occurences
-     */
-    public function compilationerrorcount(): int {
-        return $this->stateoccurencecount(3);
-    }
-
-    /**
-     * Returns the number of detail results with test failures attached to the summary.
-     * @return int count of occurences
-     */
-    public function failedcount(): int {
-        return $this->stateoccurencecount(2);
-    }
-
-    /**
-     * Returns the number of detail results with successful tests attached to the summary.
-     * @return int count of occurences
-     */
-    public function successfulcount(): int {
-        return $this->stateoccurencecount(1);
-    }
-
-    /**
-     * Returns the number of detail results with an unknown result - mostly due to compile errors - attached to the summary.
-     * @return int count of occurences
-     */
-    public function unknowncount(): int {
-        return $this->stateoccurencecount(0);
-    }
-
-}
-- 
GitLab