|
13 | 13 |
|
14 | 14 | <h1>Judging verifier</h1> |
15 | 15 |
|
16 | | - <p> |
17 | | - {{ numChecked }} submissions checked: |
18 | | - {{ unexpected | length }} unexpected results, |
19 | | - {% if verifyMultiple %} |
20 | | - {{ multiple | length }} automatically verified (multiple outcomes), |
21 | | - {% else %} |
22 | | - {{ multiple | length }} to check manually, |
23 | | - {% endif %} |
24 | | - {{ verified | length }} automatically verified |
25 | | - <br> |
26 | | - {{ numUnchecked }} submissions not checked: |
27 | | - {{ earlier | length }} verified earlier, |
28 | | - {{ nomatch | length }} without magic string |
29 | | - </p> |
30 | | - |
31 | | - {% macro verifyResults(id, header, results, collapse) %} |
32 | | - {% if results is not empty %} |
33 | | - <h2><a class="collapse-link" href="javascript:collapse('#detail{{ id }}')">{{ header }}</a></h2> |
34 | | - <table id="detail{{ id }}" class="{% if collapse | default(false) %}d-none{% endif %} data-table table table-hover table-striped table-sm submissions-table table-full-clickable-cell"> |
| 16 | + {% macro resultTable(results, hasExpectedScore) %} |
| 17 | + <table class="data-table table table-hover table-striped table-sm submissions-table table-full-clickable-cell mb-0"> |
| 18 | + <thead> |
35 | 19 | <tr> |
36 | | - <th></th><th>problem</th><th>file(s)</th> |
37 | | - <th>actual</th> |
38 | | - <th>expected (one of)</th> |
39 | | - <th>actual score</th> |
40 | | - <th>expected score</th> |
| 20 | + <th scope="col">ID</th> |
| 21 | + <th scope="col">problem</th> |
| 22 | + <th scope="col">file(s)</th> |
| 23 | + <th scope="col">actual</th> |
| 24 | + <th scope="col">expected (one of)</th> |
| 25 | + {% if hasExpectedScore %} |
| 26 | + <th scope="col">actual score</th> |
| 27 | + <th scope="col">expected score</th> |
| 28 | + {% endif %} |
41 | 29 | </tr> |
| 30 | + </thead> |
| 31 | + <tbody> |
42 | 32 | {% for submitId,result in results %} |
43 | 33 | {% set link = path('jury_submission', {'contestId': result.contest.externalid, 'submitId': submitId}) %} |
44 | 34 | <tr> |
|
61 | 51 | </td> |
62 | 52 | <td> |
63 | 53 | <a href="{{ link }}"> |
64 | | - {% if result is defined and result.actual is defined %} |
65 | | - {{ result.actual | printResult }} |
66 | | - {% endif %} |
| 54 | + {{ result.actual | printResult }} |
67 | 55 | </a> |
68 | 56 | </td> |
69 | 57 | <td> |
70 | 58 | <a href="{{ link }}"> |
71 | | - {% if result is defined and result.expected is defined and result.expected is not empty %} |
| 59 | + {% if result.expected is defined and result.expected is not empty %} |
72 | 60 | {% for r in result.expected %} |
73 | 61 | {{ r | printResult }} |
74 | 62 | {% if not loop.last %}, {% endif %} |
|
78 | 66 | {% endif %} |
79 | 67 | </a> |
80 | 68 | </td> |
81 | | - <td> |
82 | | - <a href="{{ link }}"> |
83 | | - {% if result is defined and result.expectedScore is defined and result.expectedScore is not null %} |
84 | | - {{ result.actualScore | number_format(2) }} |
85 | | - {% else %} |
86 | | - - |
87 | | - {% endif %} |
88 | | - </a> |
89 | | - </td> |
90 | | - <td> |
91 | | - <a href="{{ link }}"> |
92 | | - {% if result is defined and result.expectedScore is defined and result.expectedScore is not null %} |
93 | | - {{ result.expectedScore | number_format(2) }} |
94 | | - {% else %} |
95 | | - - |
96 | | - {% endif %} |
97 | | - </a> |
98 | | - </td> |
| 69 | + {% if hasExpectedScore %} |
| 70 | + <td> |
| 71 | + <a href="{{ link }}"> |
| 72 | + {% if result.expectedScore is defined and result.expectedScore is not null %} |
| 73 | + {{ result.actualScore | number_format(2) }} |
| 74 | + {% else %} |
| 75 | + - |
| 76 | + {% endif %} |
| 77 | + </a> |
| 78 | + </td> |
| 79 | + <td> |
| 80 | + <a href="{{ link }}"> |
| 81 | + {% if result.expectedScore is defined and result.expectedScore is not null %} |
| 82 | + {{ result.expectedScore | number_format(2) }} |
| 83 | + {% else %} |
| 84 | + - |
| 85 | + {% endif %} |
| 86 | + </a> |
| 87 | + </td> |
| 88 | + {% endif %} |
99 | 89 | </tr> |
100 | 90 | {% endfor %} |
101 | | - </table> |
102 | | - {% endif %} |
| 91 | + </tbody> |
| 92 | + </table> |
103 | 93 | {% endmacro %} |
104 | 94 |
|
105 | | - {{ checkJudgings.verifyResults('unexpected', 'Unexpected results', unexpected) }} |
106 | | - {% if verifyMultiple %} |
107 | | - {{ checkJudgings.verifyResults('multiple', 'Automatically verified (multiple outcomes)', multiple, true) }} |
| 95 | + {% if contestId is null %} |
| 96 | + <div class="alert alert-warning">No active contest selected.</div> |
| 97 | + {% elseif numChecked == 0 and numUnchecked == 0 %} |
| 98 | + <div class="alert alert-info">No judged submissions found.</div> |
108 | 99 | {% else %} |
109 | | - {{ checkJudgings.verifyResults('multiple', 'Check manually', multiple) }} |
| 100 | + <div class="mb-4 d-flex flex-wrap gap-2 align-items-center"> |
| 101 | + <span class="badge text-bg-info">{{ numChecked + numUnchecked }} total</span> |
| 102 | + {% if unexpected|length > 0 %} |
| 103 | + <a href="#detailunexpected"><span class="badge text-bg-danger">{{ unexpected|length }} unexpected</span></a> |
| 104 | + {% endif %} |
| 105 | + {% if multiple|length > 0 %} |
| 106 | + {% if verifyMultiple %} |
| 107 | + <a href="#detailmultiple"><span class="badge text-bg-warning">{{ multiple|length }} auto-verified (multiple)</span></a> |
| 108 | + {% else %} |
| 109 | + <a href="#detailmultiple"><span class="badge text-bg-warning">{{ multiple|length }} check manually</span></a> |
| 110 | + {% endif %} |
| 111 | + {% endif %} |
| 112 | + {% if verified|length > 0 %} |
| 113 | + <a href="#detailverified"><span class="badge text-bg-success">{{ verified|length }} verified</span></a> |
| 114 | + {% endif %} |
| 115 | + {% if earlier|length > 0 %} |
| 116 | + <a href="#detailearlier"><span class="badge text-bg-secondary">{{ earlier|length }} verified earlier</span></a> |
| 117 | + {% endif %} |
| 118 | + {% if nomatch|length > 0 %} |
| 119 | + <a href="#detailnomatch"><span class="badge text-bg-secondary">{{ nomatch|length }} without magic string</span></a> |
| 120 | + {% endif %} |
| 121 | + </div> |
| 122 | + |
| 123 | + {% if unexpected is not empty %} |
| 124 | + <div class="card mb-3" id="detailunexpected"> |
| 125 | + <div class="card-header d-flex justify-content-between align-items-center"> |
| 126 | + <span class="text-danger fw-bold"> |
| 127 | + <i class="fas fa-exclamation-triangle me-1"></i> |
| 128 | + Unexpected results |
| 129 | + </span> |
| 130 | + <span class="badge text-bg-danger">{{ unexpected|length }}</span> |
| 131 | + </div> |
| 132 | + <div> |
| 133 | + {{ checkJudgings.resultTable(unexpected, hasExpectedScore) }} |
| 134 | + </div> |
| 135 | + </div> |
| 136 | + {% endif %} |
| 137 | + |
110 | 138 | {% if multiple is not empty %} |
111 | | - <form action="{{ path('jury_judging_verifier') }}" method="post"> |
112 | | - <input type="hidden" name="verify_multiple" value="1"> |
113 | | - <p> |
114 | | - Verify all multiple outcome submissions: |
115 | | - <button type="submit" class="btn btn-primary"><i class="fas fa-check"></i> Verify</button> |
116 | | - </p> |
117 | | - </form> |
| 139 | + <div class="card mb-3" id="detailmultiple"> |
| 140 | + <div class="card-header d-flex justify-content-between align-items-center"> |
| 141 | + <a class="collapse-link text-decoration-none text-dark fw-bold" href="javascript:collapse('#detailmultiple-body')"> |
| 142 | + <i class="fas fa-question-circle me-1 text-warning"></i> |
| 143 | + {% if verifyMultiple %} |
| 144 | + Automatically verified (multiple outcomes) |
| 145 | + {% else %} |
| 146 | + Check manually |
| 147 | + {% endif %} |
| 148 | + <i class="fas fa-chevron-down ms-1 small"></i> |
| 149 | + </a> |
| 150 | + <div class="d-flex align-items-center gap-2"> |
| 151 | + {% if not verifyMultiple %} |
| 152 | + <form action="{{ path('jury_judging_verifier') }}" method="post"> |
| 153 | + <input type="hidden" name="verify_multiple" value="1"> |
| 154 | + <button type="submit" class="btn btn-primary btn-sm"> |
| 155 | + <i class="fas fa-check"></i> Verify all |
| 156 | + </button> |
| 157 | + </form> |
| 158 | + {% endif %} |
| 159 | + <span class="badge text-bg-warning">{{ multiple|length }}</span> |
| 160 | + </div> |
| 161 | + </div> |
| 162 | + <div id="detailmultiple-body"{% if verifyMultiple %} class="d-none"{% endif %}> |
| 163 | + {{ checkJudgings.resultTable(multiple, hasExpectedScore) }} |
| 164 | + </div> |
| 165 | + </div> |
118 | 166 | {% endif %} |
119 | | - {% endif %} |
120 | | - {{ checkJudgings.verifyResults('verified', 'Automatically verified', verified, true) }} |
121 | | - {{ checkJudgings.verifyResults('earlier', 'Verified earlier', earlier, true) }} |
122 | | - {{ checkJudgings.verifyResults('nomatch', 'Without magic string', nomatch, true) }} |
123 | 167 |
|
124 | | - {% if problems != [] %} |
125 | | - <h2>Problem runtime analytics</h2> |
126 | | - You probably want to <a href="{{ path('jury_contest', {'contestId': contestId }) }}">rejudge</a> |
127 | | - all submissions with a reasonable overshoot and |
128 | | - {%- if not is_granted('ROLE_ADMIN') %} let an admin {% endif %} |
129 | | - judge the |
130 | | - {%- if is_granted('ROLE_ADMIN') %}<a href="{{ path('jury_contest_request_remaining', {'contestId': contestId}) }}">{% endif %} |
131 | | - remaining testcases |
132 | | - {%- if is_granted('ROLE_ADMIN') %}</a>{% endif %}. |
133 | | - After this compare the maximum runtime for <code>Accepted</code> |
134 | | - solutions and tune those against expected <code>Time Limit Exceeded</code> solutions.<br> |
135 | | - {% for p in problems %} |
136 | | - {% set link = path('analysis_problem', {'probid': p.externalId, 'view': 'hidden'}) %} |
137 | | - <a href="{{ link }}">{{ p | problemBadge }}</a> |
138 | | - {% endfor %} |
| 168 | + {% if verified is not empty %} |
| 169 | + <div class="card mb-3" id="detailverified"> |
| 170 | + <div class="card-header d-flex justify-content-between align-items-center"> |
| 171 | + <a class="collapse-link text-decoration-none text-dark fw-bold" href="javascript:collapse('#detailverified-body')"> |
| 172 | + <i class="fas fa-check-circle me-1 text-success"></i> |
| 173 | + Automatically verified |
| 174 | + <i class="fas fa-chevron-down ms-1 small"></i> |
| 175 | + </a> |
| 176 | + <span class="badge text-bg-success">{{ verified|length }}</span> |
| 177 | + </div> |
| 178 | + <div id="detailverified-body" class="d-none"> |
| 179 | + {{ checkJudgings.resultTable(verified, hasExpectedScore) }} |
| 180 | + </div> |
| 181 | + </div> |
| 182 | + {% endif %} |
| 183 | + |
| 184 | + {% if earlier is not empty %} |
| 185 | + <div class="card mb-3" id="detailearlier"> |
| 186 | + <div class="card-header d-flex justify-content-between align-items-center"> |
| 187 | + <a class="collapse-link text-decoration-none text-dark fw-bold" href="javascript:collapse('#detailearlier-body')"> |
| 188 | + Verified earlier |
| 189 | + <i class="fas fa-chevron-down ms-1 small"></i> |
| 190 | + </a> |
| 191 | + <span class="badge text-bg-secondary">{{ earlier|length }}</span> |
| 192 | + </div> |
| 193 | + <div id="detailearlier-body" class="d-none"> |
| 194 | + {{ checkJudgings.resultTable(earlier, hasExpectedScore) }} |
| 195 | + </div> |
| 196 | + </div> |
| 197 | + {% endif %} |
| 198 | + |
| 199 | + {% if nomatch is not empty %} |
| 200 | + <div class="card mb-3" id="detailnomatch"> |
| 201 | + <div class="card-header d-flex justify-content-between align-items-center"> |
| 202 | + <a class="collapse-link text-decoration-none text-dark fw-bold" href="javascript:collapse('#detailnomatch-body')"> |
| 203 | + Without magic string |
| 204 | + <i class="fas fa-chevron-down ms-1 small"></i> |
| 205 | + </a> |
| 206 | + <span class="badge text-bg-secondary">{{ nomatch|length }}</span> |
| 207 | + </div> |
| 208 | + <div id="detailnomatch-body" class="d-none"> |
| 209 | + {{ checkJudgings.resultTable(nomatch, hasExpectedScore) }} |
| 210 | + </div> |
| 211 | + </div> |
| 212 | + {% endif %} |
| 213 | + |
| 214 | + {% if problems != [] %} |
| 215 | + <div class="card mb-3"> |
| 216 | + <div class="card-header"> |
| 217 | + <strong>Problem runtime analytics</strong> |
| 218 | + </div> |
| 219 | + <div class="card-body"> |
| 220 | + <p class="mb-2"> |
| 221 | + You probably want to <a href="{{ path('jury_contest', {'contestId': contestId }) }}">rejudge</a> |
| 222 | + all submissions with a reasonable overshoot and |
| 223 | + {%- if not is_granted('ROLE_ADMIN') %} let an admin {% endif %} |
| 224 | + judge the |
| 225 | + {%- if is_granted('ROLE_ADMIN') %}<a href="{{ path('jury_contest_request_remaining', {'contestId': contestId}) }}">{% endif %} |
| 226 | + remaining testcases |
| 227 | + {%- if is_granted('ROLE_ADMIN') %}</a>{% endif %}. |
| 228 | + After this compare the maximum runtime for <code>Accepted</code> |
| 229 | + solutions and tune those against expected <code>Time Limit Exceeded</code> solutions. |
| 230 | + </p> |
| 231 | + <div class="d-flex flex-wrap gap-1"> |
| 232 | + {% for p in problems %} |
| 233 | + {% set link = path('analysis_problem', {'probid': p.externalId, 'view': 'hidden'}) %} |
| 234 | + <a href="{{ link }}">{{ p | problemBadge }}</a> |
| 235 | + {% endfor %} |
| 236 | + </div> |
| 237 | + </div> |
| 238 | + </div> |
| 239 | + {% endif %} |
139 | 240 | {% endif %} |
140 | 241 |
|
141 | 242 | {% endblock %} |
0 commit comments