Skip to content

Commit aa39a7f

Browse files
authored
Merge pull request #3012 from AtCoder-NoviSteps/#3000
breaking: Remove ABC latest 20 rounds from contest table (#3000)
2 parents c780af0 + fc48d8a commit aa39a7f

File tree

6 files changed

+163
-167
lines changed

6 files changed

+163
-167
lines changed

docs/dev-notes/2025-11-01/add_and_refactoring_tests_for_contest_table_provider/plan.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,6 @@ describe.each([
513513

514514
**ターゲット**:
515515

516-
- `ABCLatest20RoundsProvider` テストの `generateTable` 検証を追加
517516
- `ABC319Onwards``ABC212to318` のテストもTypical90 同等レベルに
518517

519518
**期間**: 2-3 日
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# **ABCLatest20RoundsProvider の削除計画**
2+
3+
## **目的**
4+
5+
`ABCLatest20RoundsProvider` を削除し、関連するコードやテストを整理することで、コードベースの簡素化とメンテナンス性の向上を図る。
6+
7+
## ** 理由**
8+
9+
- ABC 319 〜 に完全に包含されている
10+
- X 公式アカウントでのアンケートで、「ABC 最新 20 回」を日常的に使っているユーザは投票数の約1/4程度
11+
- 当初の目的であった初回表示の負荷軽減対策には、「ABS」をデフォルトで表示することで対応
12+
13+
---
14+
15+
## **削除対象**
16+
17+
### 1. `src/lib/utils/contest_table_provider.ts`
18+
19+
- **行167**: `export class ABCLatest20RoundsProvider extends ContestTableProviderBase {` を削除。
20+
- **行1086**: `.addProvider(new ABCLatest20RoundsProvider(ContestType.ABC)),` を削除。
21+
- **行1244**: `abcLatest20Rounds: prepareContestProviderPresets().ABCLatest20Rounds(),` を削除。
22+
23+
### 2. `src/test/lib/utils/contest_table_provider.test.ts`
24+
25+
- **`describe('ABC providers', () => {` 内の以下を削除**:
26+
```typescript
27+
{
28+
providerClass: ABCLatest20RoundsProvider,
29+
label: 'Latest 20 rounds',
30+
displayConfig: {
31+
roundLabelWidth: 'xl:w-16',
32+
tableBodyCellsWidth: 'w-1/2 xs:w-1/3 sm:w-1/4 md:w-1/5 lg:w-1/6 px-1 py-1',
33+
},
34+
},
35+
```
36+
- **`describe('ABC Latest 20 Rounds', () => {` のテスト全体を削除**
37+
- **行349, 357, 374, 382**: `ABCLatest20RoundsProvider` に関連するテストを削除。
38+
- **行2425, 2437, 2466, 2512, 2526, 2604**: `ABCLatest20RoundsProvider``ABSProvider` に置き換え。
39+
40+
### 3. `src/lib/stores/active_contest_type.svelte.ts`
41+
42+
- **行16**: コメント内の `'abcLatest20Rounds'``'abs'` に変更。
43+
- **行21**: `'abcLatest20Rounds'``'abs'` に変更。
44+
- **行28**: コメント内の `'abcLatest20Rounds'``'abs'` に変更。
45+
- **行30**: コンストラクタのデフォルト値 `'abcLatest20Rounds'``'abs'` に変更。
46+
- **行79**: コメント内の `'abcLatest20Rounds'``'abs'` に変更。
47+
- **行82**: `this.storage.value = 'abcLatest20Rounds';``this.storage.value = 'abs';` に変更。
48+
49+
### 4. `src/test/lib/stores/active_contest_type.svelte.test.ts`
50+
51+
- **行44**: `expect(store.get()).toBe('abcLatest20Rounds');``expect(store.get()).toBe('abs');` に変更。
52+
- **行48**: 同上。
53+
- **行64**: `expect(store.isSame('abcLatest20Rounds' as ContestTableProviderGroups)).toBe(true);``expect(store.isSame('abs' as ContestTableProviderGroups)).toBe(true);` に変更。
54+
- **行70**: 同上。
55+
- **行75**: 同上。
56+
- **行86**: `expect(store.get()).toBe('abcLatest20Rounds');``expect(store.get()).toBe('abs');` に変更。
57+
- **行93**: 同上。
58+
- **行101**: `expect(newStore.get()).toBe('abcLatest20Rounds');``expect(newStore.get()).toBe('abs');` に変更。
59+
- **行108**: 同上。
60+
- **行115**: `'abcLatest20Rounds' as ContestTableProviderGroups``'abs' as ContestTableProviderGroups` に変更。
61+
- **行138**: `expect(activeContestTypeStore.get()).toBe('abcLatest20Rounds');``expect(activeContestTypeStore.get()).toBe('abs');` に変更。
62+
63+
### 5. ドキュメントの更新
64+
65+
- **`/usr/src/app/docs/dev-notes/2025-11-01/add_and_refactoring_tests_for_contest_table_provider/plan.md`**
66+
- **行516**: `- ABCLatest20RoundsProvider テストの generateTable 検証を追加` を削除。
67+
68+
---
69+
70+
## **影響範囲**
71+
72+
1. **`src/lib/utils/contest_table_provider.ts`**
73+
- 他のプロバイダーやロジックに影響を与えないか確認済み。
74+
75+
2. **`src/test/lib/utils/contest_table_provider.test.ts`**
76+
- 削除対象のテストが他のテストケースに依存していないことを確認済み。
77+
78+
3. **テストカバレッジ**
79+
- 削除前後でテストカバレッジを比較し、削除が他のテストに影響を与えないことを確認済み。
80+
81+
4. **ドキュメント**
82+
- 関連するドキュメントを特定し、更新箇所を明確化。
83+
84+
---
85+
86+
## **次のステップ**
87+
88+
1. **コードの修正**
89+
- 上記の削除対象箇所を修正。
90+
91+
2. **テストの実行**
92+
- 修正後にテストを再実行し、他の箇所に影響がないことを確認。
93+
94+
3. **ドキュメントの更新**
95+
- 削除に伴う変更をドキュメントに反映。
96+
97+
## 教訓
98+
99+
1. **削除対象の影響範囲を明確化する**
100+
- 削除対象が他のコードやテストに与える影響を事前に洗い出し、計画に反映する。
101+
102+
2. **テストカバレッジの維持**
103+
- 削除後もテストカバレッジが低下しないよう、必要に応じて代替テストを追加する。
104+
105+
3. **ドキュメントの更新を徹底する**
106+
- 削除に伴う変更をドキュメントに反映し、後続の開発者が変更内容を正確に把握できるようにする。

src/lib/stores/active_contest_type.svelte.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,18 @@ import {
1313
*
1414
* The store uses the ContestTableProviderGroups type which represents
1515
* different contest table configurations or data providers,
16-
* with a default value of 'abcLatest20Rounds'.
16+
* with a default value of 'abs'.
1717
*/
1818
export class ActiveContestTypeStore {
19-
private storage = useLocalStorage<ContestTableProviderGroups>(
20-
'contest_table_providers',
21-
'abcLatest20Rounds',
22-
);
19+
private storage = useLocalStorage<ContestTableProviderGroups>('contest_table_providers', 'abs');
2320

2421
/**
2522
* Creates an instance with the specified contest type.
2623
*
2724
* @param defaultContestType - The default contest type to initialize.
28-
* Defaults to 'abcLatest20Rounds'.
25+
* Defaults to 'abs'.
2926
*/
30-
constructor(defaultContestType: ContestTableProviderGroups = 'abcLatest20Rounds') {
27+
constructor(defaultContestType: ContestTableProviderGroups = 'abs') {
3128
if (!this.isValidContestType(this.storage.value)) {
3229
this.storage.value = defaultContestType;
3330
}
@@ -76,10 +73,10 @@ export class ActiveContestTypeStore {
7673

7774
/**
7875
* Resets the active contest type to the default value.
79-
* Sets the internal value to 'abcLatest20Rounds'.
76+
* Sets the internal value to 'abs'.
8077
*/
8178
reset(): void {
82-
this.storage.value = 'abcLatest20Rounds';
79+
this.storage.value = 'abs';
8380
}
8481
}
8582

src/lib/utils/contest_table_provider.ts

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -164,41 +164,6 @@ export class ABSProvider extends ContestTableProviderBase {
164164
}
165165
}
166166

167-
export class ABCLatest20RoundsProvider extends ContestTableProviderBase {
168-
filter(taskResults: TaskResults): TaskResults {
169-
const taskResultsOnlyABC = taskResults.filter(this.setFilterCondition());
170-
171-
const CONTEST_ROUND_COUNT = 20;
172-
const latest20ContestIds = Array.from(
173-
new Set(taskResultsOnlyABC.map((taskResult: TaskResult) => taskResult.contest_id)),
174-
)
175-
.sort()
176-
.reverse()
177-
.slice(0, CONTEST_ROUND_COUNT);
178-
179-
return taskResultsOnlyABC.filter((task: TaskResult) =>
180-
latest20ContestIds.includes(task.contest_id),
181-
);
182-
}
183-
184-
protected setFilterCondition(): (taskResult: TaskResult) => boolean {
185-
// Note: Narrow down taskResults in advance to reduce time to display.
186-
return (task: TaskResult) => classifyContest(task.contest_id) === ContestType.ABC;
187-
}
188-
189-
getMetadata(): ContestTableMetaData {
190-
return {
191-
title: 'AtCoder Beginner Contest 最新 20 回',
192-
abbreviationName: 'abcLatest20Rounds',
193-
};
194-
}
195-
196-
getContestRoundLabel(contestId: string): string {
197-
const contestNameLabel = getContestNameLabel(contestId);
198-
return contestNameLabel.replace('ABC ', '');
199-
}
200-
}
201-
202167
// ABC319 〜 (2023/09/09 〜 )
203168
// 7 tasks per contest
204169
export class ABC319OnwardsProvider extends ContestTableProviderBase {
@@ -1076,15 +1041,6 @@ export const prepareContestProviderPresets = () => {
10761041
ariaLabel: 'Filter AtCoder Beginners Selection',
10771042
}).addProvider(new ABSProvider(ContestType.ABS)),
10781043

1079-
/**
1080-
* Single group for ABC latest 20 rounds
1081-
*/
1082-
ABCLatest20Rounds: () =>
1083-
new ContestTableProviderGroup(`ABC Latest 20 Rounds`, {
1084-
buttonLabel: 'ABC 最新 20 回',
1085-
ariaLabel: 'Filter ABC latest 20 rounds',
1086-
}).addProvider(new ABCLatest20RoundsProvider(ContestType.ABC)),
1087-
10881044
/**
10891045
* Single group for ABC 319 onwards
10901046
*/
@@ -1241,7 +1197,6 @@ export const prepareContestProviderPresets = () => {
12411197

12421198
export const contestTableProviderGroups = {
12431199
abs: prepareContestProviderPresets().ABS(),
1244-
abcLatest20Rounds: prepareContestProviderPresets().ABCLatest20Rounds(),
12451200
abc319Onwards: prepareContestProviderPresets().ABC319Onwards(),
12461201
fromAbc212ToAbc318: prepareContestProviderPresets().ABC212ToABC318(),
12471202
fromAbc126ToAbc211: prepareContestProviderPresets().ABC126ToABC211(),

src/test/lib/stores/active_contest_type.svelte.test.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@ describe('ActiveContestTypeStore', () => {
4141
});
4242

4343
test('expects to initialize with default value', () => {
44-
expect(store.get()).toBe('abcLatest20Rounds');
44+
expect(store.get()).toBe('abs');
4545
});
4646

4747
test('expects to return the current value when calling get()', () => {
48-
expect(store.get()).toBe('abcLatest20Rounds');
48+
expect(store.get()).toBe('abs');
4949

5050
// Change the value and verify get() returns the new value
5151
store.set('abc319Onwards' as ContestTableProviderGroups);
@@ -61,18 +61,18 @@ describe('ActiveContestTypeStore', () => {
6161
});
6262

6363
test('expects to correctly determine if contest type is the same with isSame()', () => {
64-
expect(store.isSame('abcLatest20Rounds' as ContestTableProviderGroups)).toBe(true);
64+
expect(store.isSame('abs' as ContestTableProviderGroups)).toBe(true);
6565
expect(store.isSame('abc319Onwards' as ContestTableProviderGroups)).toBe(false);
6666
expect(store.isSame('fromAbc212ToAbc318' as ContestTableProviderGroups)).toBe(false);
6767

6868
store.set('abc319Onwards' as ContestTableProviderGroups);
6969
expect(store.isSame('abc319Onwards' as ContestTableProviderGroups)).toBe(true);
70-
expect(store.isSame('abcLatest20Rounds' as ContestTableProviderGroups)).toBe(false);
70+
expect(store.isSame('abs' as ContestTableProviderGroups)).toBe(false);
7171
expect(store.isSame('fromAbc212ToAbc318' as ContestTableProviderGroups)).toBe(false);
7272

7373
store.set('fromAbc212ToAbc318' as ContestTableProviderGroups);
7474
expect(store.isSame('fromAbc212ToAbc318' as ContestTableProviderGroups)).toBe(true);
75-
expect(store.isSame('abcLatest20Rounds' as ContestTableProviderGroups)).toBe(false);
75+
expect(store.isSame('abs' as ContestTableProviderGroups)).toBe(false);
7676
expect(store.isSame('abc319Onwards' as ContestTableProviderGroups)).toBe(false);
7777
});
7878

@@ -83,36 +83,36 @@ describe('ActiveContestTypeStore', () => {
8383

8484
// Call reset and verify it goes back to default
8585
store.reset();
86-
expect(store.get()).toBe('abcLatest20Rounds');
86+
expect(store.get()).toBe('abs');
8787

8888
// Change to a different value and reset again to verify consistency
8989
store.set('fromAbc212ToAbc318' as ContestTableProviderGroups);
9090
expect(store.get()).toBe('fromAbc212ToAbc318');
9191

9292
store.reset();
93-
expect(store.get()).toBe('abcLatest20Rounds');
93+
expect(store.get()).toBe('abs');
9494
});
9595

9696
test('expects to reset to default when initialized with invalid localStorage key', () => {
9797
// Simulate invalid key in localStorage
9898
mockStorage['contest_table_providers'] = JSON.stringify('invalidContestType');
9999

100100
const newStore = new ActiveContestTypeStore();
101-
expect(newStore.get()).toBe('abcLatest20Rounds');
101+
expect(newStore.get()).toBe('abs');
102102
});
103103

104104
test('expects to reset to default when initialized with null', () => {
105105
mockStorage['contest_table_providers'] = JSON.stringify(null);
106106

107107
const newStore = new ActiveContestTypeStore();
108-
expect(newStore.get()).toBe('abcLatest20Rounds');
108+
expect(newStore.get()).toBe('abs');
109109
});
110110

111111
test('expects to handle multiple contest type changes', () => {
112112
const types: ContestTableProviderGroups[] = [
113113
'abc319Onwards' as ContestTableProviderGroups,
114114
'fromAbc212ToAbc318' as ContestTableProviderGroups,
115-
'abcLatest20Rounds' as ContestTableProviderGroups,
115+
'abs' as ContestTableProviderGroups,
116116
];
117117

118118
types.forEach((type) => {
@@ -135,6 +135,6 @@ describe('Active contest type store in SSR', () => {
135135
});
136136

137137
test('handles SSR gracefully', () => {
138-
expect(activeContestTypeStore.get()).toBe('abcLatest20Rounds');
138+
expect(activeContestTypeStore.get()).toBe('abs');
139139
});
140140
});

0 commit comments

Comments
 (0)