view.php 9.28 KB
Newer Older
1
<?php
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 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/>.
16

Lückemeyer's avatar
Lückemeyer committed
17
18
19
20
21
22
23
24
/**
 * utility class for DTA submission plugin result display
 *
 * @package assignsubmission_dta
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
class view_submission_utils {

Lückemeyer's avatar
Lückemeyer committed
25
    /**
Lückemeyer's avatar
Lückemeyer committed
26
27
     * Broadly used in logic, parametrized for easier change.
     */
28
29
    const COMPONENT_NAME = "assignsubmission_dta";

30
31
32
    /**
     * generates a short summary html
     *
Lückemeyer's avatar
Lückemeyer committed
33
34
     * @param int $assignmentid assignment
     * @param int $submissionid submission to create a report for
35
36
     * @return string html
     */
37
    public static function generatesummaryhtml(
38
39
        int $assignmentid,
        int $submissionid
40
41
    ): string {

42
        // Fetch data.
43
        $summary = DbUtils::getResultSummaryFromDatabase($assignmentid, $submissionid);
44
45
        $html = "";

46
        // Calculate success rate, if no unknown result states or compilation errors.
47
        $successrate = "?";
48
        if ($summary->unknownCount() == 0 && $summary->compilationErrorCount() == 0) {
49
            $successrate = round(($summary->successfulCount() / $summary->resultCount()) * 100, 2 );
50
51
        }

52
        // Generate html.
53
54
        $html .= $summary->successfulCount() . "/";
        $html .= ($summary->compilationErrorCount() == 0 && $summary->unknownCount() == 0)
55
            ? $summary->resultCount() . " (" . $successrate . "%)"
56
                : "?";
Lückemeyer's avatar
Lückemeyer committed
57
        $html .= get_string("tests_successful", self::COMPONENT_NAME) . "<br />";
58
59

        if ($summary->compilationErrorCount() > 0) {
Lückemeyer's avatar
Lückemeyer committed
60
            $html .= $summary->compilationErrorCount() . get_string("compilation_errors", self::COMPONENT_NAME) . "<br />";
61
62
63
        }

        if ($summary->unknownCount() > 0) {
Lückemeyer's avatar
Lückemeyer committed
64
            $html .= $summary->unknownCount() . get_string("unknown_state", self::COMPONENT_NAME) . "<br />";
65
        }
66

Lückemeyer's avatar
Lückemeyer committed
67
68
        $showncompetencies = explode(";", $summary->successfultestcompetencies);
        $overallcompetencies = explode(";", $summary->overalltestcompetencies);
Lückemeyer's avatar
Lückemeyer committed
69

Lückemeyer's avatar
Lückemeyer committed
70
        $tmp = "";
Lückemeyer's avatar
Lückemeyer committed
71
72
73
        for ($index = 0, $size = count($showncompetencies); $index < $size; $index++) {
            $shown = $showncompetencies[$index];
            $comp = $overallcompetencies[$index];
Lückemeyer's avatar
Lückemeyer committed
74
            // If the competency was actually assessed by the assignment and tests, add a summary entry.
Lückemeyer's avatar
Lückemeyer committed
75
            if ($shown != "0") {
Lückemeyer's avatar
Lückemeyer committed
76
                $tmp .= get_string("comp" . $index, self::COMPONENT_NAME) .
Lückemeyer's avatar
Lückemeyer committed
77
                " " . 100 * floatval($shown) / floatval($comp) . "% " . "<br />";
Lückemeyer's avatar
Lückemeyer committed
78
79
            }
        }
Lückemeyer's avatar
Lückemeyer committed
80

Lückemeyer's avatar
Lückemeyer committed
81
        $html .= get_string("success_competencies", self::COMPONENT_NAME) . "<br />" . $tmp . "<br />";
82
83
84
85

        return html_writer::div($html, "dtaSubmissionSummary");
    }

86
 /**
Kurzenberger's avatar
Kurzenberger committed
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
 * Generiert die detaillierte HTML-Ansicht, einschließlich Zusammenfassung, Kompetenzen, Details und Empfehlungen.
 *
 * @param int $assignmentid Assignment-ID
 * @param int $submissionid Submission-ID, für die der Bericht erstellt wird
 * @return string HTML-Code
 */
public static function generatedetailhtml(
    int $assignmentid,
    int $submissionid
): string {

    // HTML-Inhalt initialisieren
    $html = "";

    // Daten abrufen
    $summary = DbUtils::getResultSummaryFromDatabase($assignmentid, $submissionid);

    // CSS-Klassen und HTML-Attributarrays definieren
    $tableheaderrowattributes = ["class" => "dtaTableHeaderRow"];
    $tablerowattributes = ["class" => "dtaTableRow"];
    $attributes = ["class" => "dtaTableData"];
    $unknownattributes = 'dtaResultUnknown';
    $successattributes = 'dtaResultSuccess';
    $failureattributes = 'dtaResultFailure';
    $compilationerrorattributes = 'dtaResultCompilationError';

    // **Zusammenfassungstabelle erstellen**
114
    // (Ihr bisheriger Code bleibt unverändert)
115

Kurzenberger's avatar
Kurzenberger committed
116
117
    // **Abstand zwischen Tabellen**
    $html .= html_writer::empty_tag("div", ["class" => "dtaSpacer"]);
118

119
120
121
    // **Empfehlungstabelle hinzufügen**
    // Empfehlungen für die Submission abrufen
    $recommendations = DbUtils::get_recommendations_from_database($assignmentid, $submissionid);
Kurzenberger's avatar
Kurzenberger committed
122

123
124
125
126
    if (!empty($recommendations)) {
        // **Sortierparameter abrufen**
        $allowed_sort_fields = ['topic', 'exercise_name', 'difficulty', 'score'];
        $allowed_sort_dirs = ['asc', 'desc'];
Kurzenberger's avatar
Kurzenberger committed
127

128
129
130
        // Sortierparameter aus POST-Daten abrufen
        $sortby = isset($_POST['sortby']) ? $_POST['sortby'] : 'score';
        $sortdir = isset($_POST['sortdir']) ? $_POST['sortdir'] : 'asc';
131

132
133
134
135
136
137
        // Sortierparameter validieren
        if (!in_array($sortby, $allowed_sort_fields)) {
            $sortby = 'score';
        }
        if (!in_array($sortdir, $allowed_sort_dirs)) {
            $sortdir = 'asc';
138
139
        }

140
141
142
143
        // Empfehlungen sortieren
        usort($recommendations, function($a, $b) use ($sortby, $sortdir) {
            $valueA = $a->{$sortby};
            $valueB = $b->{$sortby};
144

145
146
147
148
            if (is_numeric($valueA) && is_numeric($valueB)) {
                $comparison = $valueA - $valueB;
            } else {
                $comparison = strnatcasecmp($valueA, $valueB);
Kurzenberger's avatar
Kurzenberger committed
149
            }
150

151
152
            if ($comparison == 0) {
                return 0;
Kurzenberger's avatar
Kurzenberger committed
153
            }
154

155
156
157
158
            if ($sortdir == 'asc') {
                return ($comparison < 0) ? -1 : 1;
            } else {
                return ($comparison < 0) ? 1 : -1;
159
            }
160
        });
161

Kurzenberger's avatar
Kurzenberger committed
162
163
164
        // Überschrift für Empfehlungen
        $html .= html_writer::tag('h3', get_string('recommendations', self::COMPONENT_NAME));

165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
        // Helper-Funktion zum Generieren von sortierbaren Headern
        $generate_sortable_header = function($column_name, $display_name) use ($sortby, $sortdir) {
            $new_sortdir = ($sortby == $column_name && $sortdir == 'asc') ? 'desc' : 'asc';
            $class = 'dtaTableHeader';
            if ($sortby == $column_name) {
                $class .= ' sorted ' . $sortdir;
            }

            // Button erstellen
            $button = html_writer::empty_tag('input', [
                'type' => 'submit',
                'name' => 'sortbutton',
                'value' => ($new_sortdir == 'asc' ? '↑' : '↓'),
                'class' => 'sort-button'
            ]);

            // Hidden Inputs für Sortierparameter
            $hidden_inputs = html_writer::empty_tag('input', [
                'type' => 'hidden',
                'name' => 'sortby',
                'value' => $column_name
            ]);
            $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 .= $hidden_inputs;
            $form .= $display_name . ' ' . $button;
            $form .= html_writer::end_tag('form');

            return html_writer::tag("th", $form, ["class" => $class]);
        };

Kurzenberger's avatar
Kurzenberger committed
202
203
        // Tabellenkopf für Empfehlungen
        $tableheader = "";
204
205
        $tableheader .= $generate_sortable_header('topic', get_string("topic", self::COMPONENT_NAME));
        $tableheader .= $generate_sortable_header('exercise_name', get_string("exercise_name", self::COMPONENT_NAME));
Kurzenberger's avatar
Kurzenberger committed
206
        $tableheader .= html_writer::tag("th", get_string("url", self::COMPONENT_NAME), ["class" => "dtaTableHeader"]);
207
208
        $tableheader .= $generate_sortable_header('difficulty', get_string("difficulty", self::COMPONENT_NAME));
        $tableheader .= $generate_sortable_header('score', get_string("score", self::COMPONENT_NAME));
Kurzenberger's avatar
Kurzenberger committed
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225

        $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);

            $tablebody .= html_writer::tag("tr", $tablerow, $tablerowattributes);
        }
        $tablebody = html_writer::tag("tbody", $tablebody);
226

Kurzenberger's avatar
Kurzenberger committed
227
228
        // Empfehlungstabelle zusammenstellen
        $html .= html_writer::tag("table", $tableheader . $tablebody, ["class" => "dtaTable"]);
229
230
    }

Kurzenberger's avatar
Kurzenberger committed
231
232
233
234
235
236
237
    // Abschließendes Div für die gesamte HTML-Ausgabe
    $html = html_writer::div($html, "dtaSubmissionDetails");

    return $html;
}


238
239


240
}