Skip to content

Commit 91a4426

Browse files
alphagoccclaude
andcommitted
refactor(exttestcase): improve code quality and maintainability
- Extract remapTestCaseDeps() helper to deduplicate subtask dependency remapping logic (was duplicated across moveUp/moveDown/remove) - Rename cryptic variables: hav→selectedSubtasks, res→partialSelections, dlt→selectionDelta, ban1/ban2→skipSub1/skipSub2, mi/mx→minRow/maxRow, xlen→fileCount, gar→baseCaseCount - Replace int sentinel 1e9 with std::numeric_limits<int>::max() - Eliminate comma operator abuse in ExtTestCaseUpdaterDialog constructor - Extract chooseFile() to deduplicate input/output file chooser dialogs - Add comment explaining score distribution in splitSelected() Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> (cherry picked from commit c642e1d)
1 parent 2b0b674 commit 91a4426

4 files changed

Lines changed: 169 additions & 177 deletions

File tree

src/exttestcasemodifier.cpp

Lines changed: 113 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,27 @@
1212
#include "core/testcase.h"
1313
#include "exttestcaseupdaterdialog.h"
1414
//
15+
#include <functional>
1516
#include <memory>
17+
#include <optional>
18+
19+
// Remap a single test case's subtask dependencies using a mapping function.
20+
// The mapper receives 0-indexed dependency indices and returns:
21+
// - a mapped 0-indexed index, or
22+
// - std::nullopt to remove that dependency.
23+
static void remapTestCaseDeps(TestCase *testCase, const std::function<std::optional<int>(int)> &mapper) {
24+
const auto &currentDeps = testCase->getDependenceSubtask();
25+
QSet<int> remappedDeps;
26+
27+
for (int dep : currentDeps) {
28+
auto mapped = mapper(dep - 1);
29+
30+
if (mapped.has_value())
31+
remappedDeps.insert(mapped.value() + 1);
32+
}
33+
34+
testCase->setDependenceSubtask(remappedDeps);
35+
}
1636

1737
ExtTestCaseModifier::ExtTestCaseModifier(QWidget *parent) : QWidget(parent), ui(new Ui::ExtTestCaseModifier) {
1838
ui->setupUi(this);
@@ -58,11 +78,11 @@ void ExtTestCaseModifier::whenTestCaseSelectionChanged() {
5878
}
5979

6080
void ExtTestCaseModifier::modifySelected() {
61-
auto hav = ui->testCaseTable->getSelectedHaveSub();
62-
auto res = ui->testCaseTable->getSelectedResSub();
81+
auto selectedSubtasks = ui->testCaseTable->getSelectedHaveSub();
82+
auto partialSelections = ui->testCaseTable->getSelectedResSub();
6383

64-
if (res.empty()) {
65-
int l = hav.front(), r = hav.back();
84+
if (partialSelections.empty()) {
85+
int l = selectedSubtasks.front(), r = selectedSubtasks.back();
6686

6787
if (l != r) {
6888
auto dialog = std::make_unique<ExtTestCaseUpdaterDialog>(
@@ -98,7 +118,7 @@ void ExtTestCaseModifier::modifySelected() {
98118
}
99119
}
100120
} else {
101-
int who = res.front().first, loc = res.front().second.first;
121+
int who = partialSelections.front().first, loc = partialSelections.front().second.first;
102122

103123
auto dialog = std::make_unique<ExtTestCaseUpdaterDialog>(this, editTask, editSettings, -1, NO_EDIT, 1,
104124
NO_EDIT, NO_EDIT, NO_EDIT);
@@ -113,200 +133,167 @@ void ExtTestCaseModifier::modifySelected() {
113133
}
114134

115135
void ExtTestCaseModifier::moveUpSelected() {
116-
auto hav = ui->testCaseTable->getSelectedHaveSub();
117-
auto res = ui->testCaseTable->getSelectedResSub();
136+
auto selectedSubtasks = ui->testCaseTable->getSelectedHaveSub();
137+
auto partialSelections = ui->testCaseTable->getSelectedResSub();
118138

119-
auto temp = ui->testCaseTable->getSelectRange();
120-
int dlt = 0;
139+
auto selectRange = ui->testCaseTable->getSelectRange();
140+
int selectionDelta = 0;
121141

122-
if (! res.empty()) {
123-
int l = res[0].second.first, r = res[0].second.second;
124-
dlt = -1;
142+
if (! partialSelections.empty()) {
143+
int l = partialSelections[0].second.first, r = partialSelections[0].second.second;
144+
selectionDelta = -1;
125145

126146
for (int i = l; i <= r; i++)
127-
editTask->getTestCaseList()[res[0].first]->swapFiles(i - 1, i);
147+
editTask->getTestCaseList()[partialSelections[0].first]->swapFiles(i - 1, i);
128148
} else {
129-
int l = hav.front(), r = hav.back();
130-
dlt = -editTask->getTestCase(l - 1)->getInputFiles().size();
149+
int l = selectedSubtasks.front(), r = selectedSubtasks.back();
150+
selectionDelta = -editTask->getTestCase(l - 1)->getInputFiles().size();
131151

132152
for (int i = l; i <= r; i++)
133153
editTask->swapTestCase(i - 1, i);
134154

135155
for (int i = l - 1; i <= r - 1; i++) {
136-
auto nowd = editTask->getTestCase(i)->getDependenceSubtask();
137-
QSet<int> havd;
138-
139-
for (auto a_ : nowd) {
140-
int a = a_ - 1;
141-
156+
remapTestCaseDeps(editTask->getTestCase(i), [l, r](int a) -> std::optional<int> {
142157
if (a == l - 1)
143-
continue;
158+
return std::nullopt;
144159

145160
if (l <= a && a <= r)
146-
a--;
161+
return a - 1;
147162

148-
havd.insert(a + 1);
149-
}
150-
151-
editTask->getTestCase(i)->setDependenceSubtask(havd);
163+
return a;
164+
});
152165
}
153166

154-
for (int i = r + 1, ii = editTask->getTestCaseList().size(); i < ii; i++) {
155-
auto nowd = editTask->getTestCase(i)->getDependenceSubtask();
156-
QSet<int> havd;
157-
158-
for (auto a_ : nowd) {
159-
int a = a_ - 1;
167+
int totalCases = editTask->getTestCaseList().size();
160168

169+
for (int i = r + 1; i < totalCases; i++) {
170+
remapTestCaseDeps(editTask->getTestCase(i), [l, r](int a) -> std::optional<int> {
161171
if (l <= a && a <= r)
162-
a--;
163-
else if (a == l - 1)
164-
a = r;
172+
return a - 1;
165173

166-
havd.insert(a + 1);
167-
}
174+
if (a == l - 1)
175+
return r;
168176

169-
editTask->getTestCase(i)->setDependenceSubtask(havd);
177+
return a;
178+
});
170179
}
171180
}
172181

173182
refresh();
174183

175-
ui->testCaseTable->modifySelected(temp.first + dlt, temp.second + dlt);
184+
ui->testCaseTable->modifySelected(selectRange.first + selectionDelta,
185+
selectRange.second + selectionDelta);
176186
}
177187

178188
void ExtTestCaseModifier::moveDownSelected() {
179-
auto hav = ui->testCaseTable->getSelectedHaveSub();
180-
auto res = ui->testCaseTable->getSelectedResSub();
189+
auto selectedSubtasks = ui->testCaseTable->getSelectedHaveSub();
190+
auto partialSelections = ui->testCaseTable->getSelectedResSub();
181191

182-
auto temp = ui->testCaseTable->getSelectRange();
183-
int dlt = 0;
192+
auto selectRange = ui->testCaseTable->getSelectRange();
193+
int selectionDelta = 0;
184194

185-
if (! res.empty()) {
186-
int l = res[0].second.first, r = res[0].second.second;
187-
dlt = 1;
195+
if (! partialSelections.empty()) {
196+
int l = partialSelections[0].second.first, r = partialSelections[0].second.second;
197+
selectionDelta = 1;
188198

189199
for (int i = r; i >= l; i--)
190-
editTask->getTestCaseList()[res[0].first]->swapFiles(i, i + 1);
200+
editTask->getTestCaseList()[partialSelections[0].first]->swapFiles(i, i + 1);
191201
} else {
192-
int l = hav.front(), r = hav.back();
193-
dlt = editTask->getTestCase(r + 1)->getInputFiles().size();
202+
int l = selectedSubtasks.front(), r = selectedSubtasks.back();
203+
selectionDelta = editTask->getTestCase(r + 1)->getInputFiles().size();
194204

195205
for (int i = r; i >= l; i--)
196206
editTask->swapTestCase(i, i + 1);
197207

198-
{
199-
auto nowd = editTask->getTestCase(l)->getDependenceSubtask();
200-
QSet<int> havd;
201-
202-
for (auto a_ : nowd) {
203-
int a = a_ - 1;
204-
205-
if (l <= a && a <= r)
206-
continue;
207-
208-
havd.insert(a + 1);
209-
}
208+
remapTestCaseDeps(editTask->getTestCase(l), [l, r](int a) -> std::optional<int> {
209+
if (l <= a && a <= r)
210+
return std::nullopt;
210211

211-
editTask->getTestCase(l)->setDependenceSubtask(havd);
212-
}
212+
return a;
213+
});
213214

214215
for (int i = l + 1; i <= r + 1; i++) {
215-
auto nowd = editTask->getTestCase(i)->getDependenceSubtask();
216-
QSet<int> havd;
217-
218-
for (auto a_ : nowd) {
219-
int a = a_ - 1;
220-
216+
remapTestCaseDeps(editTask->getTestCase(i), [l, r](int a) -> std::optional<int> {
221217
if (l <= a && a <= r)
222-
a++;
218+
return a + 1;
223219

224-
havd.insert(a + 1);
225-
}
226-
227-
editTask->getTestCase(i)->setDependenceSubtask(havd);
220+
return a;
221+
});
228222
}
229223

230-
for (int i = r + 1, ii = editTask->getTestCaseList().size(); i < ii; i++) {
231-
auto nowd = editTask->getTestCase(i)->getDependenceSubtask();
232-
QSet<int> havd;
233-
234-
for (auto a_ : nowd) {
235-
int a = a_ - 1;
224+
int totalCases = editTask->getTestCaseList().size();
236225

226+
for (int i = r + 1; i < totalCases; i++) {
227+
remapTestCaseDeps(editTask->getTestCase(i), [l, r](int a) -> std::optional<int> {
237228
if (l <= a && a <= r)
238-
a++;
239-
else if (a == r + 1)
240-
a = l;
229+
return a + 1;
241230

242-
havd.insert(a + 1);
243-
}
231+
if (a == r + 1)
232+
return l;
244233

245-
editTask->getTestCase(i)->setDependenceSubtask(havd);
234+
return a;
235+
});
246236
}
247237
}
248238

249239
refresh();
250240

251-
ui->testCaseTable->modifySelected(temp.first + dlt, temp.second + dlt);
241+
ui->testCaseTable->modifySelected(selectRange.first + selectionDelta,
242+
selectRange.second + selectionDelta);
252243
}
253244

254245
void ExtTestCaseModifier::removeSelected() {
255-
auto hav = ui->testCaseTable->getSelectedHaveSub();
256-
auto res = ui->testCaseTable->getSelectedResSub();
246+
auto selectedSubtasks = ui->testCaseTable->getSelectedHaveSub();
247+
auto partialSelections = ui->testCaseTable->getSelectedResSub();
257248

258-
int ban1 = -1, ban2 = -1;
249+
int skipSub1 = -1, skipSub2 = -1;
259250

260-
for (auto i : std::as_const(res)) {
261-
if (ban1 < 0)
262-
ban1 = i.first;
251+
for (auto i : std::as_const(partialSelections)) {
252+
if (skipSub1 < 0)
253+
skipSub1 = i.first;
263254
else
264-
ban2 = i.first;
255+
skipSub2 = i.first;
265256

266257
int l = i.second.first, r = i.second.second;
267258

268259
for (int j = l; j <= r; j++)
269260
editTask->getTestCaseList()[i.first]->deleteSingleCase(l);
270261
}
271262

272-
int l = hav.front(), r = hav.back();
263+
int l = selectedSubtasks.front(), r = selectedSubtasks.back();
273264

274-
while (l == ban1 || l == ban2)
265+
while (l == skipSub1 || l == skipSub2)
275266
l++;
276267

277-
while (r == ban1 || r == ban2)
268+
while (r == skipSub1 || r == skipSub2)
278269
r--;
279270

280271
for (int i = l; i <= r; i++)
281272
editTask->deleteTestCase(l);
282273

283-
for (int i = l + 1, ii = editTask->getTestCaseList().size(); i < ii; i++) {
284-
auto nowd = editTask->getTestCase(i)->getDependenceSubtask();
285-
QSet<int> havd;
286-
287-
for (auto a_ : nowd) {
288-
int a = a_ - 1;
274+
int totalCases = editTask->getTestCaseList().size();
289275

276+
for (int i = l + 1; i < totalCases; i++) {
277+
remapTestCaseDeps(editTask->getTestCase(i), [l, r](int a) -> std::optional<int> {
290278
if (l <= a && a <= r)
291-
continue;
292-
else if (a > r)
293-
a -= r - l;
279+
return std::nullopt;
294280

295-
havd.insert(a + 1);
296-
}
281+
if (a > r)
282+
return a - (r - l);
297283

298-
editTask->getTestCase(i)->setDependenceSubtask(havd);
284+
return a;
285+
});
299286
}
300287

301288
refresh();
302289
}
303290

304291
void ExtTestCaseModifier::mergeSelected() {
305-
auto hav = ui->testCaseTable->getSelectedHaveSub();
292+
auto selectedSubtasks = ui->testCaseTable->getSelectedHaveSub();
306293

307-
auto temp = ui->testCaseTable->getSelectRange();
294+
auto selectRange = ui->testCaseTable->getSelectRange();
308295

309-
int l = hav.front(), r = hav.back();
296+
int l = selectedSubtasks.front(), r = selectedSubtasks.back();
310297

311298
auto ans = *editTask->getTestCase(l);
312299

@@ -326,32 +313,35 @@ void ExtTestCaseModifier::mergeSelected() {
326313

327314
refresh();
328315

329-
ui->testCaseTable->modifySelected(temp.first, temp.second);
316+
ui->testCaseTable->modifySelected(selectRange.first, selectRange.second);
330317
}
331318

332319
void ExtTestCaseModifier::splitSelected() {
333-
auto hav = ui->testCaseTable->getSelectedHaveSub();
320+
auto selectedSubtasks = ui->testCaseTable->getSelectedHaveSub();
334321

335-
auto temp = ui->testCaseTable->getSelectRange();
322+
auto selectRange = ui->testCaseTable->getSelectRange();
336323

337324
QList<TestCase *> ans;
338325

339-
int l = hav.front(), r = hav.back();
326+
int l = selectedSubtasks.front(), r = selectedSubtasks.back();
340327

341328
for (int i = l; i <= r; i++) {
342329
TestCase *now = editTask->getTestCase(i);
343330
auto in = now->getInputFiles();
344331
auto out = now->getOutputFiles();
345-
int allScore = now->getFullScore(), gar = 0;
332+
int allScore = now->getFullScore();
333+
334+
// Distribute the total score evenly across test cases.
335+
// The first baseCaseCount cases get floor(allScore / n),
336+
// the remaining cases get ceil(allScore / n).
337+
int baseCaseCount = 0;
346338

347339
if (! in.empty())
348-
gar = in.size() - allScore % in.size();
349-
else
350-
gar = 0;
340+
baseCaseCount = in.size() - allScore % in.size();
351341

352342
for (int j = 0; j < in.size(); j++) {
353343
auto *app = new TestCase;
354-
app->setFullScore((allScore / in.size()) + (j >= gar));
344+
app->setFullScore((allScore / in.size()) + (j >= baseCaseCount));
355345
app->setTimeLimit(now->getTimeLimit());
356346
app->setMemoryLimit(now->getMemoryLimit());
357347
app->setDependenceSubtask(now->getDependenceSubtask());
@@ -369,7 +359,7 @@ void ExtTestCaseModifier::splitSelected() {
369359

370360
refresh();
371361

372-
ui->testCaseTable->modifySelected(temp.first, temp.second);
362+
ui->testCaseTable->modifySelected(selectRange.first, selectRange.second);
373363
}
374364

375365
void ExtTestCaseModifier::appendNewSub() {

0 commit comments

Comments
 (0)