view.php 17.5 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
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
 */
class view_submission_utils {

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

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

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

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

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

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

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

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

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

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

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

    /**
     * generates detailed view html
     *
Lückemeyer's avatar
Lückemeyer committed
90
91
     * @param int $assignmentid assignment
     * @param int $submissionid submission to create a report for
92
     */
93
    public static function generatedetailhtml(
94
95
        int $assignmentid,
        int $submissionid
96
97
    ): string {

98
        // Fetch data.
99
        $summary = DbUtils::getResultSummaryFromDatabase($assignmentid, $submissionid);
100
101
        $html = "";

102
        // Define a few css classes and prepare html attribute arrays to beautify the output.
103
104
        $tableheaderrowattributes = ["class" => "dtaTableHeaderRow"];
        $tablerowattributes = ["class" => "dtaTableRow"];
105
106
107
108
109
        $resultrowattributes = $tablerowattributes;
        $unknownattributes = 'dtaResultUnknown';
        $successattributes = 'dtaResultSuccess';
        $failureattributes = 'dtaResultFailure';
        $compilationerrorattributes = 'dtaResultCompilationError';
110

111
        // Summary table.
112
        $tmp = "";
113
        $tmp .= html_writer::tag("th", get_string("summary", self::COMPONENT_NAME), ["class" => "dtaTableHeader"]);
114
        $tmp .= html_writer::empty_tag("th", ["class" => "dtaTableHeader"]);
115
        $header = html_writer::tag("tr", $tmp, $tableheaderrowattributes);
116
117
118
119
        $header = html_writer::tag("thead", $header);

        $body = "";
        $tmp = "";
120
        $attributes = ["class" => "dtaTableData"];
121
122
        $tmp .= html_writer::tag(
            "td",
123
            get_string("total_items", self::COMPONENT_NAME),
124
125
126
127
128
129
130
            $attributes);

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

131
132
        $resultrowattributes = $tablerowattributes;
        $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $unknownattributes;
133

134
        $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
135
136

        $tmp = "";
137
        $tmp .= html_writer::tag("td", get_string("tests_successful", self::COMPONENT_NAME), $attributes);
138
139
        $tmp .= html_writer::tag( "td", $summary->successfulCount(), $attributes);

140
        $resultrowattributes = $tablerowattributes;
141
        $successrate = "?";
142
143

        if ($summary->unknownCount() > 0 || $summary->compilationErrorCount() > 0) {
144
            $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $unknownattributes;
145
        } else {
146
147
            $successrate = round(($summary->successfulCount() / $summary->resultCount()) * 100, 2 );
            if ($successrate < 50) {
148
                $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $compilationerrorattributes;
149
            } else if ($successrate < 75) {
150
                $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $failureattributes;
151
            } else {
152
                $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $successattributes;
153
154
            }
        }
155
        $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
156
157

        $tmp = "";
158
        $tmp .= html_writer::tag("td", get_string("failures", self::COMPONENT_NAME), $attributes);
159
160
        $tmp .= html_writer::tag("td", $summary->failedCount(), $attributes);

161
        $resultrowattributes = $tablerowattributes;
162
        if ($summary->failedCount() > 0) {
163
            $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $failureattributes;
164
        } else {
165
            $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $successattributes;
166
        }
167
        $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
168
169

        $tmp = "";
170
        $tmp .= html_writer::tag("td", get_string("compilation_errors", self::COMPONENT_NAME), $attributes);
171
172
        $tmp .= html_writer::tag("td", $summary->compilationErrorCount(), $attributes);

173
        $resultrowattributes = $tablerowattributes;
174
        if ($summary->compilationErrorCount() > 0) {
175
            $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $compilationerrorattributes;
176
        } else {
177
            $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $successattributes;
178
        }
179
        $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
180
181

        $tmp = "";
182
        $tmp .= html_writer::tag("td", get_string("unknown_state", self::COMPONENT_NAME), $attributes);
183
184
        $tmp .= html_writer::tag("td", $summary->unknownCount(), $attributes);

185
        $resultrowattributes = $tablerowattributes;
186
        if ($summary->unknownCount() > 0) {
187
            $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $unknownattributes;
188
        } else {
189
            $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $successattributes;
190
        }
191
        $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
192
193

        $tmp = "";
194
        $tmp .= html_writer::tag("td", html_writer::tag("b", get_string("success_rate", self::COMPONENT_NAME)), $attributes);
195
196
197
198
        $tmp .= html_writer::tag(
            "td",
            html_writer::tag("b", $summary->successfulCount()
                . "/" . (($summary->compilationErrorCount() == 0 && $summary->unknownCount() == 0) ? $summary->resultCount()
199
                . " (" . $successrate . "%)"
200
201
202
                    : "?")),
            $attributes);

203
        $resultrowattributes = $tablerowattributes;
204
        if ($summary->unknownCount() > 0 || $summary->compilationErrorCount() > 0) {
205
            $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $unknownattributes;
206
        } else {
207
            if ($successrate < 50) {
208
                $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $compilationerrorattributes;
209
            } else if ($successrate < 75) {
210
                $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $failureattributes;
211
            } else {
212
                $resultrowattributes['class'] = $resultrowattributes['class'] . " " . $successattributes;
213
214
            }
        }
215
        $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
216
217

        $body = html_writer::tag("tbody", $body);
218
        $table = html_writer::tag("table", $header . $body, ["class" => "dtaTable"]);
219
220
221

        $html .= $table;

222
223
        // 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
224

Lückemeyer's avatar
Lückemeyer committed
225
        // Competency assessment table.
226
        $body = "";
227
228
229
230
231
        $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
232

233
234
        $showncompetencies = explode(";", $summary->successfultestcompetencies);
        $overallcompetencies = explode(";", $summary->overalltestcompetencies);
Lückemeyer's avatar
Lückemeyer committed
235

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

249
                $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
250
            }
251
252
253
254
255
        }
        $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.
256
        $html .= html_writer::empty_tag("div", ["class" => "dtaSpacer"]);
257

258
        // Details table.
259
        $tmp = "";
260
        $tmp .= html_writer::tag("th", get_string("details", self::COMPONENT_NAME), ["class" => "dtaTableHeader"]);
261
        $tmp .= html_writer::empty_tag("th", ["class" => "dtaTableHeader"]);
262
        $header = html_writer::tag("tr", $tmp, $tableheaderrowattributes);
263
264
265
        $header = html_writer::tag("thead", $header);

        $body = "";
266
        $spacerrow = null;
267
        foreach ($summary->results as $r) {
268
            // Add spacer first if not null.
269
270
            if (!is_null($spacerrow)) {
                $body .= $spacerrow;
271
272
            }

273
274
            // New copy of base attributes array.
            $resultrowattributes = $tablerowattributes;
275

276
            // Check which css class to add for the colored left-border according to resuls state.
277
            if ($r->state == 0) {
278
                $resultrowattributes['class'] = $resultrowattributes['class'] . ' dtaResultUnknown';
279
            } else if ($r->state == 1) {
280
                $resultrowattributes['class'] = $resultrowattributes['class'] . ' dtaResultSuccess';
281
            } else if ($r->state == 2) {
282
                $resultrowattributes['class'] = $resultrowattributes['class'] . ' dtaResultFailure';
283
            } else if ($r->state == 3) {
284
                $resultrowattributes['class'] = $resultrowattributes['class'] . ' dtaResultCompilationError';
285
286
287
288
289
            }

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

293
294
295
296
297
298
299
300
301
            $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
302

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

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

313
314
315
316
            $tmp .= html_writer::tag(
                "td",
                $r->name,
                $attributes);
317
            $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
318
319
320
321

            $tmp = "";
            $tmp .= html_writer::tag(
                "td",
322
                get_string("status", self::COMPONENT_NAME),
323
324
325
326
327
328
                $attributes);

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

331
            // If state is something different than successful, show additional rows.
332
333
334
335
            if ($r->state != 1) {
                $tmp = "";
                $tmp .= html_writer::tag(
                    "td",
336
                    get_string("failure_type", self::COMPONENT_NAME),
337
                    $attributes);
338

339
340
341
342
                $tmp .= html_writer::tag(
                    "td",
                    $r->failureType,
                    $attributes);
343
                $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
344

345
346
347
                $tmp = "";
                $tmp .= html_writer::tag(
                    "td",
348
                    get_string("failure_reason", self::COMPONENT_NAME),
349
                    $attributes);
350

351
352
353
354
                $tmp .= html_writer::tag(
                    "td",
                    $r->failureReason,
                    $attributes);
355
                $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
356

357
                // Only show line, column and position if they have useful values.
358
359
360
361
                if (!is_null($r->lineNumber) && $r->lineNumber > 0) {
                    $tmp = "";
                    $tmp .= html_writer::tag(
                        "td",
Lückemeyer's avatar
Lückemeyer committed
362
                        get_string("line_no", self::COMPONENT_NAME),
363
364
365
366
367
368
                        $attributes);

                    $tmp .= html_writer::tag(
                        "td",
                        $r->lineNumber,
                        $attributes);
369
                    $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
370
371
372
                }

                if (!is_null($r->columnNumber) && $r->columnNumber > 0) {
373
374
375
                    $tmp = "";
                    $tmp .= html_writer::tag(
                        "td",
376
                        get_string("col_no", self::COMPONENT_NAME),
377
                        $attributes);
378

379
380
381
382
383
                    $tmp .= html_writer::tag(
                        "td",
                        $r->columnNumber,
                        $attributes);
                    $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
384
385
386
                }

                if (!is_null($r->position) && $r->position > 0) {
387
388
389
                    $tmp = "";
                    $tmp .= html_writer::tag(
                        "td",
390
                        get_string("pos", self::COMPONENT_NAME),
391
                        $attributes);
392

393
394
395
396
397
                    $tmp .= html_writer::tag(
                        "td",
                        $r->position,
                        $attributes);
                    $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
398
399
400
401
402
                }

                $tmp = "";
                $tmp .= html_writer::tag(
                    "td",
403
                    get_string("stacktrace", self::COMPONENT_NAME),
404
405
406
407
                    $attributes);

                $tmp .= html_writer::tag(
                    "td",
408
                    html_writer::tag("details", $r->stacktrace, ["class" => "dtaStacktraceDetails"]),
409
                    $attributes);
410
                $body .= html_writer::tag("tr", $tmp, $resultrowattributes);
411
412
            }

413
            // Set spacerrow value if null for next round separation.
414
            if (is_null($spacerrow)) {
415
                $spacerrow = html_writer::empty_tag("tr", ["class" => "dtaTableSpacer"]);
416
417
            }
        }
418
        $html .= html_writer::tag("table", $header . $body, ["class" => "dtaTable"]);
419

420
        // Wrap generated html into final div.
421
422
423
424
425
426
        $html = html_writer::div($html, "dtaSubmissionDetails");

        return $html;
    }

}