view.php 17.8 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

17
18
19
20
21
22
23
24
25
/**
 * utility class for DTA submission plugin result display
 *
 * @package assignsubmission_dta
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 * @copyright Gero Lueckemeyer and student project teams
 */
namespace assignsubmission_dta\util

Lückemeyer's avatar
Lückemeyer committed
26
27
28
29
30
31
32
33
34
/**
 * utility class for DTA submission plugin result display
 *
 * @package assignsubmission_dta
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 * @copyright Gero Lueckemeyer and student project teams
 */
class view_submission_utils {

Lückemeyer's avatar
Lückemeyer committed
35
    /**
Lückemeyer's avatar
Lückemeyer committed
36
37
     * Broadly used in logic, parametrized for easier change.
     */
38
39
    const COMPONENT_NAME = "assignsubmission_dta";

40
41
42
    /**
     * generates a short summary html
     *
43
44
     * @param int $assignmentid id of the assignment to show
     * @param int $submissionid id of the submission for which to create a report
45
46
     * @return string html
     */
47
    public static function generatesummaryhtml(
48
49
        int $assignmentid,
        int $submissionid
50
51
    ): string {

52
        // Fetch data.
53
        $summary = DbUtils::getResultSummaryFromDatabase($assignmentid, $submissionid);
54
55
        $html = "";

56
        // Calculate success rate, if no unknown result states or compilation errors.
57
        $successrate = "?";
58
        if ($summary->unknownCount() == 0 && $summary->compilationErrorCount() == 0) {
59
            $successrate = round(($summary->successfulCount() / $summary->resultCount()) * 100, 2 );
60
61
        }

62
        // Generate html.
63
64
        $html .= $summary->successfulCount() . "/";
        $html .= ($summary->compilationErrorCount() == 0 && $summary->unknownCount() == 0)
65
            ? $summary->resultCount() . " (" . $successrate . "%)"
66
                : "?";
Lückemeyer's avatar
Lückemeyer committed
67
        $html .= get_string("tests_successful", self::COMPONENT_NAME) . "<br />";
68
69

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

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

Lückemeyer's avatar
Lückemeyer committed
77
78
        $showncompetencies = explode(";", $summary->successfultestcompetencies);
        $overallcompetencies = explode(";", $summary->overalltestcompetencies);
Lückemeyer's avatar
Lückemeyer committed
79

Lückemeyer's avatar
Lückemeyer committed
80
        $tmp = "";
Lückemeyer's avatar
Lückemeyer committed
81
82
83
        for ($index = 0, $size = count($showncompetencies); $index < $size; $index++) {
            $shown = $showncompetencies[$index];
            $comp = $overallcompetencies[$index];
Lückemeyer's avatar
Lückemeyer committed
84
            // If the competency was actually assessed by the assignment and tests, add a summary entry.
Lückemeyer's avatar
Lückemeyer committed
85
            if ($shown != "0") {
Lückemeyer's avatar
Lückemeyer committed
86
                $tmp .= get_string("comp" . $index, self::COMPONENT_NAME) .
Lückemeyer's avatar
Lückemeyer committed
87
                " " . 100 * floatval($shown) / floatval($comp) . "% " . "<br />";
Lückemeyer's avatar
Lückemeyer committed
88
89
            }
        }
Lückemeyer's avatar
Lückemeyer committed
90

Lückemeyer's avatar
Lückemeyer committed
91
        $html .= get_string("success_competencies", self::COMPONENT_NAME) . "<br />" . $tmp . "<br />";
92
93
94
95
96
97
98

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

    /**
     * generates detailed view html
     *
99
100
     * @param int $assignmentid id of the assignment to show
     * @param int $submissionid id of the submission for which to create a report
101
     */
102
    public static function generatedetailhtml(
103
104
        int $assignmentid,
        int $submissionid
105
106
    ): string {

107
        // Fetch data.
108
        $summary = DbUtils::getResultSummaryFromDatabase($assignmentid, $submissionid);
109
110
        $html = "";

111
        // Define a few css classes and prepare html attribute arrays to beautify the output.
112
113
        $tableheaderrowattributes = ["class" => "dtaTableHeaderRow"];
        $tablerowattributes = ["class" => "dtaTableRow"];
114
115
116
117
118
        $resultrowattributes = $tablerowattributes;
        $unknownattributes = 'dtaResultUnknown';
        $successattributes = 'dtaResultSuccess';
        $failureattributes = 'dtaResultFailure';
        $compilationerrorattributes = 'dtaResultCompilationError';
119

120
        // Summary table.
121
        $tmp = "";
122
        $tmp .= html_writer::tag("th", get_string("summary", self::COMPONENT_NAME), ["class" => "dtaTableHeader"]);
123
        $tmp .= html_writer::empty_tag("th", ["class" => "dtaTableHeader"]);
124
        $header = html_writer::tag("tr", $tmp, $tableheaderrowattributes);
125
126
127
128
        $header = html_writer::tag("thead", $header);

        $body = "";
        $tmp = "";
129
        $attributes = ["class" => "dtaTableData"];
130
131
        $tmp .= html_writer::tag(
            "td",
132
            get_string("total_items", self::COMPONENT_NAME),
133
134
135
136
137
138
139
            $attributes);

        $tmp .= html_writer::tag(
            "td",
            $summary->resultCount(),
            $attributes);

140
141
        $resultrowattributes = $tablerowattributes;
        $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $unknownattributes;
142

143
        $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
144
145

        $tmp = "";
146
        $tmp .= html_writer::tag("td", get_string("tests_successful", self::COMPONENT_NAME), $attributes);
147
148
        $tmp .= html_writer::tag( "td", $summary->successfulCount(), $attributes);

149
        $resultrowattributes = $tablerowattributes;
150
        $successrate = "?";
151
152

        if ($summary->unknownCount() > 0 || $summary->compilationErrorCount() > 0) {
153
            $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $unknownattributes;
154
        } else {
155
156
            $successrate = round(($summary->successfulCount() / $summary->resultCount()) * 100, 2 );
            if ($successrate < 50) {
157
                $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $compilationerrorattributes;
158
            } else if ($successrate < 75) {
159
                $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $failureattributes;
160
            } else {
161
                $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $successattributes;
162
163
            }
        }
164
        $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
165
166

        $tmp = "";
167
        $tmp .= html_writer::tag("td", get_string("failures", self::COMPONENT_NAME), $attributes);
168
169
        $tmp .= html_writer::tag("td", $summary->failedCount(), $attributes);

170
        $resultrowattributes = $tablerowattributes;
171
        if ($summary->failedCount() > 0) {
172
            $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $failureattributes;
173
        } else {
174
            $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $successattributes;
175
        }
176
        $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
177
178

        $tmp = "";
179
        $tmp .= html_writer::tag("td", get_string("compilation_errors", self::COMPONENT_NAME), $attributes);
180
181
        $tmp .= html_writer::tag("td", $summary->compilationErrorCount(), $attributes);

182
        $resultrowattributes = $tablerowattributes;
183
        if ($summary->compilationErrorCount() > 0) {
184
            $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $compilationerrorattributes;
185
        } else {
186
            $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $successattributes;
187
        }
188
        $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
189
190

        $tmp = "";
191
        $tmp .= html_writer::tag("td", get_string("unknown_state", self::COMPONENT_NAME), $attributes);
192
193
        $tmp .= html_writer::tag("td", $summary->unknownCount(), $attributes);

194
        $resultrowattributes = $tablerowattributes;
195
        if ($summary->unknownCount() > 0) {
196
            $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $unknownattributes;
197
        } else {
198
            $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $successattributes;
199
        }
200
        $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
201
202

        $tmp = "";
203
        $tmp .= html_writer::tag("td", html_writer::tag("b", get_string("success_rate", self::COMPONENT_NAME)), $attributes);
204
205
206
207
        $tmp .= html_writer::tag(
            "td",
            html_writer::tag("b", $summary->successfulCount()
                . "/" . (($summary->compilationErrorCount() == 0 && $summary->unknownCount() == 0) ? $summary->resultCount()
208
                . " (" . $successrate . "%)"
209
210
211
                    : "?")),
            $attributes);

212
        $resultrowattributes = $tablerowattributes;
213
        if ($summary->unknownCount() > 0 || $summary->compilationErrorCount() > 0) {
214
            $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $unknownattributes;
215
        } else {
216
            if ($successrate < 50) {
217
                $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $compilationerrorattributes;
218
            } else if ($successrate < 75) {
219
                $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $failureattributes;
220
            } else {
221
                $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $successattributes;
222
223
            }
        }
224
        $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
225
226

        $body = html_writer::tag("tbody", $body);
227
        $table = html_writer::tag("table", $header . $body, ["class" => "dtaTable"]);
228
229
230

        $html .= $table;

231
232
        // Add empty div for spacing between summary and compentency table.
        $html .= html_writer::empty_tag("div", ["class" => "dtaSpacer"]);
Lückemeyer's avatar
Lückemeyer committed
233

Lückemeyer's avatar
Lückemeyer committed
234
        // Competency assessment table.
235
        $body = "";
236
237
238
239
240
        $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);
Lückemeyer's avatar
Lückemeyer committed
241

242
243
        $showncompetencies = explode(";", $summary->successfultestcompetencies);
        $overallcompetencies = explode(";", $summary->overalltestcompetencies);
Lückemeyer's avatar
Lückemeyer committed
244

Lückemeyer's avatar
Lückemeyer committed
245
246
247
        for ($index = 0, $size = count($overallcompetencies); $index < $size; $index++) {
            $comp = $overallcompetencies[$index];
            $shown = $showncompetencies[$index];
248
            // If the competency was actually assessed by the assignment and tests, add a row in the table.
Lückemeyer's avatar
Lückemeyer committed
249
            if ($comp != "0") {
250
251
252
                // New copy of base attributes array.
                $resultrowattributes = $tablerowattributes;
                $tmp = "";
253
                $tmp .= html_writer::tag("td", get_string("comp" . $index, self::COMPONENT_NAME), $resultrowattributes);
Lückemeyer's avatar
Lückemeyer committed
254
                $tmp .= html_writer::tag("td", 100 * floatval($shown) / floatval($comp) . "% " .
255
                    "(" . $shown . " / " . $comp . ")", $resultrowattributes);
Lückemeyer's avatar
Lückemeyer committed
256
257
                $tmp .= html_writer::tag("td", get_string("comp_expl" . $index, self::COMPONENT_NAME), $resultrowattributes);

258
                $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
259
            }
260
261
262
263
264
        }
        $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.
265
        $html .= html_writer::empty_tag("div", ["class" => "dtaSpacer"]);
266

267
        // Details table.
268
        $tmp = "";
269
        $tmp .= html_writer::tag("th", get_string("details", self::COMPONENT_NAME), ["class" => "dtaTableHeader"]);
270
        $tmp .= html_writer::empty_tag("th", ["class" => "dtaTableHeader"]);
271
        $header = html_writer::tag("tr", $tmp, $tableheaderrowattributes);
272
273
274
        $header = html_writer::tag("thead", $header);

        $body = "";
275
        $spacerrow = null;
276
        foreach ($summary->results as $r) {
277
            // Add spacer first if not null.
278
279
            if (!is_null($spacerrow)) {
                $body .= $spacerrow;
280
281
            }

282
283
            // New copy of base attributes array.
            $resultrowattributes = $tablerowattributes;
284

285
            // Check which css class to add for the colored left-border according to resuls state.
286
            if ($r->state == 0) {
287
                $resultrowattributes['class'] = $resultrowattributes['class'] . ' dtaResultUnknown';
288
            } else if ($r->state == 1) {
289
                $resultrowattributes['class'] = $resultrowattributes['class'] . ' dtaResultSuccess';
290
            } else if ($r->state == 2) {
291
                $resultrowattributes['class'] = $resultrowattributes['class'] . ' dtaResultFailure';
292
            } else if ($r->state == 3) {
293
                $resultrowattributes['class'] = $resultrowattributes['class'] . ' dtaResultCompilationError';
294
295
296
297
298
            }

            $tmp = "";
            $tmp .= html_writer::tag(
                "td",
299
300
                get_string("package_name", self::COMPONENT_NAME),
                $attributes);
Lückemeyer's avatar
Lückemeyer committed
301

302
303
304
305
306
307
308
309
310
            $tmp .= html_writer::tag(
                "td",
                $r->packagename,
                $attributes);

            $tmp .= html_writer::tag(
                "td",
                get_string("unit_name", self::COMPONENT_NAME),
                $attributes);
Lückemeyer's avatar
Lückemeyer committed
311

312
313
314
315
316
317
318
319
            $tmp .= html_writer::tag(
                "td",
                $r->classname,
                $attributes);

            $tmp .= html_writer::tag(
                "td",
                get_string("test_name", self::COMPONENT_NAME),
320
                $attributes);
321

322
323
324
325
            $tmp .= html_writer::tag(
                "td",
                $r->name,
                $attributes);
326
            $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
327
328
329
330

            $tmp = "";
            $tmp .= html_writer::tag(
                "td",
331
                get_string("status", self::COMPONENT_NAME),
332
333
334
335
336
337
                $attributes);

            $tmp .= html_writer::tag(
                "td",
                DtaResult::getStateName($r->state),
                $attributes);
338
            $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
339

340
            // If state is something different than successful, show additional rows.
341
342
343
344
            if ($r->state != 1) {
                $tmp = "";
                $tmp .= html_writer::tag(
                    "td",
345
                    get_string("failure_type", self::COMPONENT_NAME),
346
                    $attributes);
347

348
349
350
351
                $tmp .= html_writer::tag(
                    "td",
                    $r->failureType,
                    $attributes);
352
                $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
353

354
355
356
                $tmp = "";
                $tmp .= html_writer::tag(
                    "td",
357
                    get_string("failure_reason", self::COMPONENT_NAME),
358
                    $attributes);
359

360
361
362
363
                $tmp .= html_writer::tag(
                    "td",
                    $r->failureReason,
                    $attributes);
364
                $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
365

366
                // Only show line, column and position if they have useful values.
367
368
369
370
                if (!is_null($r->lineNumber) && $r->lineNumber > 0) {
                    $tmp = "";
                    $tmp .= html_writer::tag(
                        "td",
Lückemeyer's avatar
Lückemeyer committed
371
                        get_string("line_no", self::COMPONENT_NAME),
372
373
374
375
376
377
                        $attributes);

                    $tmp .= html_writer::tag(
                        "td",
                        $r->lineNumber,
                        $attributes);
378
                    $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
379
380
381
                }

                if (!is_null($r->columnNumber) && $r->columnNumber > 0) {
382
383
384
                    $tmp = "";
                    $tmp .= html_writer::tag(
                        "td",
385
                        get_string("col_no", self::COMPONENT_NAME),
386
                        $attributes);
387

388
389
390
391
392
                    $tmp .= html_writer::tag(
                        "td",
                        $r->columnNumber,
                        $attributes);
                    $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
393
394
395
                }

                if (!is_null($r->position) && $r->position > 0) {
396
397
398
                    $tmp = "";
                    $tmp .= html_writer::tag(
                        "td",
399
                        get_string("pos", self::COMPONENT_NAME),
400
                        $attributes);
401

402
403
404
405
406
                    $tmp .= html_writer::tag(
                        "td",
                        $r->position,
                        $attributes);
                    $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
407
408
409
410
411
                }

                $tmp = "";
                $tmp .= html_writer::tag(
                    "td",
412
                    get_string("stacktrace", self::COMPONENT_NAME),
413
414
415
416
                    $attributes);

                $tmp .= html_writer::tag(
                    "td",
417
                    html_writer::tag("details", $r->stacktrace, ["class" => "dtaStacktraceDetails"]),
418
                    $attributes);
419
                $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
420
421
            }

422
            // Set spacerrow value if null for next round separation.
423
            if (is_null($spacerrow)) {
424
                $spacerrow = html_writer::empty_tag("tr", ["class" => "dtaTableSpacer"]);
425
426
            }
        }
427
        $html .= html_writer::tag("table", $header . $body, ["class" => "dtaTable"]);
428

429
        // Wrap generated html into final div.
430
431
432
433
434
435
        $html = html_writer::div($html, "dtaSubmissionDetails");

        return $html;
    }

}