Skip to content

Commit 2b630b7

Browse files
authored
Merge pull request #1877 from AtCoder-NoviSteps/#1631
🎨 Improve grade colors (#1631)
2 parents 1bf71b0 + 1cc7f2d commit 2b630b7

File tree

6 files changed

+163
-45
lines changed

6 files changed

+163
-45
lines changed

src/lib/components/GradeLabel.svelte

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,35 @@
11
<script lang="ts">
22
import { TaskGrade } from '$lib/types/task';
3-
import { getTaskGradeColor, getTaskGradeLabel, toWhiteTextIfNeeds } from '$lib/utils/task';
3+
import {
4+
getTaskGradeColor,
5+
getTaskGradeLabel,
6+
toChangeTextColorIfNeeds,
7+
toChangeBorderColorIfNeeds,
8+
} from '$lib/utils/task';
49
510
interface Props {
611
taskGrade: TaskGrade | string;
712
defaultPadding?: number;
813
defaultWidth?: number;
914
reducedWidth?: number;
15+
defaultTextSize?: string;
1016
}
1117
12-
let { taskGrade, defaultPadding = 1, defaultWidth = 10, reducedWidth = 8 }: Props = $props();
18+
let {
19+
taskGrade,
20+
defaultPadding = 1,
21+
defaultWidth = 10,
22+
reducedWidth = 8,
23+
defaultTextSize = 'md',
24+
}: Props = $props();
1325
1426
let grade = $derived(getTaskGradeLabel(taskGrade));
1527
let gradeColor = $derived(getTaskGradeColor(taskGrade));
1628
</script>
1729

18-
<div class="rounded-lg border-2 border-white">
30+
<div class="rounded-lg border-2 {toChangeBorderColorIfNeeds(grade)}">
1931
<div
20-
class="p-{defaultPadding} w-{reducedWidth} xs:w-{defaultWidth} text-sm xs:text-md text-center rounded-md {toWhiteTextIfNeeds(
32+
class="p-{defaultPadding} w-{reducedWidth} xs:w-{defaultWidth} text-sm xs:text-{defaultTextSize} text-center rounded-md {toChangeTextColorIfNeeds(
2133
grade,
2234
)} {gradeColor}"
2335
>

src/lib/components/TaskGradeList.svelte

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
44
import TaskList from '$lib/components/TaskList.svelte';
55
6-
import { getTaskGradeColor, getTaskGradeLabel } from '$lib/utils/task';
7-
86
import type { TaskResults, TaskResult } from '$lib/types/task';
97
import { TaskGrade, taskGradeValues } from '$lib/types/task';
108
@@ -53,8 +51,7 @@
5351
<!-- HACK: Svelteでcontinueに相当する構文は確認できず(2024年1月時点)。 -->
5452
{#if countTasks(taskGrade) && isShowTaskList(isAdmin, taskGrade)}
5553
<TaskList
56-
grade={getTaskGradeLabel(taskGrade)}
57-
gradeColor={getTaskGradeColor(taskGrade)}
54+
grade={taskGrade}
5855
taskResults={taskResultsForEachGrade.get(taskGrade)}
5956
{isAdmin}
6057
{isLoggedIn}

src/lib/components/TaskList.svelte

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010
TableHeadCell,
1111
} from 'svelte-5-ui-lib';
1212
13-
import { type TaskResult, type TaskResults, TaskGrade } from '$lib/types/task';
13+
import { type TaskResult, type TaskResults } from '$lib/types/task';
1414
15+
import GradeLabel from '$lib/components/GradeLabel.svelte';
1516
import ThermometerProgressBar from '$lib/components/ThermometerProgressBar.svelte';
1617
import UpdatingModal from '$lib/components/SubmissionStatus/UpdatingModal.svelte';
1718
import SubmissionStatusImage from '$lib/components/SubmissionStatus/SubmissionStatusImage.svelte';
@@ -21,17 +22,16 @@
2122
import { getBackgroundColorFrom } from '$lib/services/submission_status';
2223
2324
import { addContestNameToTaskIndex } from '$lib/utils/contest';
24-
import { toWhiteTextIfNeeds, getTaskUrl, removeTaskIndexFromTitle } from '$lib/utils/task';
25+
import { getTaskUrl, removeTaskIndexFromTitle } from '$lib/utils/task';
2526
2627
interface Props {
2728
grade: string;
28-
gradeColor: string;
2929
taskResults: TaskResults;
3030
isAdmin: boolean;
3131
isLoggedIn: boolean;
3232
}
3333
34-
let { grade, gradeColor, taskResults, isAdmin, isLoggedIn }: Props = $props();
34+
let { grade, taskResults, isAdmin, isLoggedIn }: Props = $props();
3535
3636
// TODO: 他のコンポーネントでも利用できるようにする。
3737
let updatingModal: UpdatingModal | null = null;
@@ -49,17 +49,13 @@
4949
<AccordionItem>
5050
{#snippet header()}
5151
<span class="flex justify-around w-full place-items-center">
52-
<div
53-
class="text-sm xs:text-xl w-9 xs:w-12 p-0.5 text-center rounded-lg {toWhiteTextIfNeeds(
54-
grade,
55-
)} {gradeColor}"
56-
>
57-
{#if grade !== TaskGrade.PENDING}
58-
{grade}
59-
{:else}
60-
??
61-
{/if}
62-
</div>
52+
<GradeLabel
53+
taskGrade={grade}
54+
defaultPadding={0.25}
55+
defaultWidth={12}
56+
reducedWidth={9}
57+
defaultTextSize="xl"
58+
/>
6359

6460
<ThermometerProgressBar {taskResults} />
6561
<AcceptedCounter {taskResults} />

src/lib/utils/task.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,20 +263,28 @@ export const getTaskGradeLabel = (taskGrade: TaskGrade | string) => {
263263

264264
// See:
265265
// https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
266-
export const toWhiteTextIfNeeds = (grade: string) => {
266+
export const toChangeTextColorIfNeeds = (grade: string): string => {
267267
const gradeToWhiteText = [
268-
`${getTaskGradeLabel(TaskGrade.Q3)}`,
269-
`${getTaskGradeLabel(TaskGrade.Q2)}`,
270268
`${getTaskGradeLabel(TaskGrade.D1)}`,
271269
`${getTaskGradeLabel(TaskGrade.D2)}`,
270+
`${getTaskGradeLabel(TaskGrade.D3)}`,
272271
`${getTaskGradeLabel(TaskGrade.D4)}`,
273272
`${getTaskGradeLabel(TaskGrade.D5)}`,
274-
`${getTaskGradeLabel(TaskGrade.D6)}`,
275273
];
276274

277275
if (gradeToWhiteText.includes(grade)) {
278276
return 'text-white';
277+
} else if (getTaskGradeLabel(grade) === TaskGrade.D6) {
278+
return 'text-atcoder-bronze';
279279
} else {
280280
return 'text-black';
281281
}
282282
};
283+
284+
export const toChangeBorderColorIfNeeds = (grade: string): string => {
285+
if (getTaskGradeLabel(grade) === TaskGrade.D6) {
286+
return 'border-atcoder-bronze';
287+
}
288+
289+
return 'border-white';
290+
};

src/test/lib/utils/task_grade.test.ts

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import { expect, test } from 'vitest';
22

3+
import { runTests } from '../common/test_helpers';
34
import {
45
getGradeOrder,
56
taskGradeOrderInfinity,
67
calcGradeMode,
78
getTaskGradeLabel,
9+
toChangeTextColorIfNeeds,
10+
toChangeBorderColorIfNeeds,
811
} from '$lib/utils/task';
912

1013
import { TaskGrade, type TaskGrades } from '$lib/types/task';
@@ -30,6 +33,13 @@ type TestCaseForTaskGradeLabel = {
3033

3134
type TestCasesForTaskGradeLabel = TestCaseForTaskGradeLabel[];
3235

36+
type TestCaseForTaskGrade = {
37+
taskGrade: TaskGrade;
38+
expected: string;
39+
};
40+
41+
type TestCasesForTaskGrade = TestCaseForTaskGrade[];
42+
3343
// See: src/lib/utils/task.ts
3444
//
3545
// Note: We split the test file by task and task grade because there are more test cases.
@@ -463,4 +473,99 @@ describe('Task grade', () => {
463473
test.each(testCases)(`${testName}(taskGrade: $taskGrade)`, testFunction);
464474
}
465475
});
476+
477+
describe('to change text color if needs', () => {
478+
describe('when task grades from 11Q to 1Q are given ', () => {
479+
const testCases: TestCasesForTaskGrade = [
480+
{ taskGrade: TaskGrade.Q11, expected: 'text-black' },
481+
{ taskGrade: TaskGrade.Q10, expected: 'text-black' },
482+
{ taskGrade: TaskGrade.Q6, expected: 'text-black' },
483+
{ taskGrade: TaskGrade.Q5, expected: 'text-black' },
484+
{ taskGrade: TaskGrade.Q2, expected: 'text-black' },
485+
{ taskGrade: TaskGrade.Q1, expected: 'text-black' },
486+
];
487+
488+
runTests(
489+
'toChangeTextColorIfNeeds',
490+
testCases,
491+
({ taskGrade, expected }: TestCaseForTaskGrade) => {
492+
expect(toChangeTextColorIfNeeds(getTaskGradeLabel(taskGrade))).toBe(expected);
493+
},
494+
);
495+
});
496+
497+
describe('when task grades from 1D to 5D are given', () => {
498+
const testCases: TestCasesForTaskGrade = [
499+
{ taskGrade: TaskGrade.D1, expected: 'text-white' },
500+
{ taskGrade: TaskGrade.D2, expected: 'text-white' },
501+
{ taskGrade: TaskGrade.D3, expected: 'text-white' },
502+
{ taskGrade: TaskGrade.D4, expected: 'text-white' },
503+
{ taskGrade: TaskGrade.D5, expected: 'text-white' },
504+
];
505+
506+
runTests(
507+
'toChangeTextColorIfNeeds',
508+
testCases,
509+
({ taskGrade, expected }: TestCaseForTaskGrade) => {
510+
expect(toChangeTextColorIfNeeds(getTaskGradeLabel(taskGrade))).toBe(expected);
511+
},
512+
);
513+
});
514+
515+
describe('when task grades 6D is given', () => {
516+
const testCases: TestCasesForTaskGrade = [
517+
{ taskGrade: TaskGrade.D6, expected: 'text-atcoder-bronze' },
518+
];
519+
520+
runTests(
521+
'toChangeTextColorIfNeeds',
522+
testCases,
523+
({ taskGrade, expected }: TestCaseForTaskGrade) => {
524+
expect(toChangeTextColorIfNeeds(getTaskGradeLabel(taskGrade))).toBe(expected);
525+
},
526+
);
527+
});
528+
});
529+
530+
describe('to change border color if needs', () => {
531+
describe('when task grades from 11Q to 5D are given', () => {
532+
const testCasesForQGrades = [
533+
{ taskGrade: TaskGrade.Q11, expected: 'border-white' },
534+
{ taskGrade: TaskGrade.Q10, expected: 'border-white' },
535+
{ taskGrade: TaskGrade.Q7, expected: 'border-white' },
536+
{ taskGrade: TaskGrade.Q6, expected: 'border-white' },
537+
{ taskGrade: TaskGrade.Q2, expected: 'border-white' },
538+
{ taskGrade: TaskGrade.Q1, expected: 'border-white' },
539+
];
540+
const testCasesForDGrades = [
541+
{ taskGrade: TaskGrade.D1, expected: 'border-white' },
542+
{ taskGrade: TaskGrade.D2, expected: 'border-white' },
543+
{ taskGrade: TaskGrade.D4, expected: 'border-white' },
544+
{ taskGrade: TaskGrade.D5, expected: 'border-white' },
545+
];
546+
const testCases: TestCasesForTaskGrade = [...testCasesForQGrades, ...testCasesForDGrades];
547+
548+
runTests(
549+
'toChangeBorderColorIfNeeds',
550+
testCases,
551+
({ taskGrade, expected }: TestCaseForTaskGrade) => {
552+
expect(toChangeBorderColorIfNeeds(getTaskGradeLabel(taskGrade))).toBe(expected);
553+
},
554+
);
555+
});
556+
557+
describe('when task grade 6D is given ', () => {
558+
const testCases: TestCasesForTaskGrade = [
559+
{ taskGrade: TaskGrade.D6, expected: 'border-atcoder-bronze' },
560+
];
561+
562+
runTests(
563+
'toChangeBorderColorIfNeeds',
564+
testCases,
565+
({ taskGrade, expected }: TestCaseForTaskGrade) => {
566+
expect(toChangeBorderColorIfNeeds(getTaskGradeLabel(taskGrade))).toBe(expected);
567+
},
568+
);
569+
});
570+
});
466571
});

tailwind.config.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,23 @@ const config = {
3333
900: '#159957',
3434
},
3535
atcoder: {
36-
Q11: '#e4e3e3',
37-
Q10: '#e4dfdc',
38-
Q9: '#dde3dc',
39-
Q8: '#dde7e7',
40-
Q7: '#dddceb',
41-
Q6: '#e8e7dc',
42-
Q5: '#ece3dc',
43-
Q4: '#ecdcdc',
44-
Q3: '#741b47',
45-
Q2: '#7f6000',
46-
Q1: '#01fb02',
47-
D1: '#72C6ef',
48-
D2: '#002eff',
49-
D3: '#ffff02',
50-
D4: '#ff9900',
51-
D5: '#ff1000',
52-
D6: '#cc0A00',
36+
Q11: '#e4d3da',
37+
Q10: '#e3cad8',
38+
Q9: '#e4cde0',
39+
Q8: '#e4cbe8',
40+
Q7: '#d0afd6',
41+
Q6: '#d9afe5',
42+
Q5: '#f7cc52',
43+
Q4: '#f1dd72',
44+
Q3: '#c8e389',
45+
Q2: '#97d093',
46+
Q1: '#73d091',
47+
D1: '#1c85b6',
48+
D2: '#7f36be',
49+
D3: '#e68e2e',
50+
D4: '#e36223',
51+
D5: '#e60d00',
52+
D6: '#432414',
5353
gray: '',
5454
brown: '',
5555
green: '',
@@ -58,7 +58,7 @@ const config = {
5858
yellow: '',
5959
orange: '',
6060
red: '',
61-
bronze: '',
61+
bronze: '#e38a66',
6262
silver: '',
6363
gold: '',
6464
ns: '#ffffff',

0 commit comments

Comments
 (0)