-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
210 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import { describe, expect, it } from 'vitest'; | ||
import { PreMatch, PreMatchID } from './pre.js'; | ||
import { EntryID } from '../../entry/entry.js'; | ||
import { RunResult, RunResultID } from './runResult.js'; | ||
|
||
describe('PreMatch', () => { | ||
it('正しく初期化できる', () => { | ||
const args = { | ||
id: '1' as PreMatchID, | ||
courseIndex: 1, | ||
matchIndex: 1, | ||
teamId1: '2' as EntryID, | ||
teamId2: '3' as EntryID, | ||
runResults: [], | ||
}; | ||
const res = PreMatch.new(args); | ||
|
||
expect(res.getId()).toBe(args.id); | ||
expect(res.getCourseIndex()).toBe(args.courseIndex); | ||
expect(res.getMatchIndex()).toBe(args.matchIndex); | ||
expect(res.getTeamId1()).toBe(args.teamId1); | ||
expect(res.getTeamId2()).toBe(args.teamId2); | ||
expect(res.getRunResults()).toBe(args.runResults); | ||
}); | ||
|
||
it('走行結果を追加できる', () => { | ||
const args = { | ||
id: '1' as PreMatchID, | ||
courseIndex: 1, | ||
matchIndex: 1, | ||
teamId1: '2' as EntryID, | ||
teamId2: '3' as EntryID, | ||
runResults: [...Array(2)].map((_, i) => | ||
RunResult.new({ | ||
id: String(i) as RunResultID, | ||
goalTimeSeconds: i * 10, | ||
points: 10 + i, | ||
teamId: i % 2 == 0 ? ('2' as EntryID) : ('3' as EntryID), | ||
finishState: 'FINISHED', | ||
}) | ||
), | ||
}; | ||
const res = PreMatch.new(args); | ||
|
||
expect(res.getRunResults().length).toBe(2); | ||
}); | ||
|
||
it('走行結果は0,1,2個になる', () => { | ||
for (let i = 0; i < 100; i++) { | ||
const args = { | ||
id: '1' as PreMatchID, | ||
courseIndex: 1, | ||
matchIndex: 1, | ||
teamId1: '2' as EntryID, | ||
teamId2: '3' as EntryID, | ||
runResults: [], | ||
}; | ||
|
||
for (let i = 1; i < 100; i++) { | ||
const mainMatch = PreMatch.new(args); | ||
// 0,1,2以外は足せない | ||
if (i == 0 || i == 1 || i == 2) { | ||
expect(() => { | ||
mainMatch.appendRunResults( | ||
[...Array(i)].map((_, i) => { | ||
return RunResult.new({ | ||
id: String(i) as RunResultID, | ||
goalTimeSeconds: i * 10, | ||
points: 10 + i, | ||
teamId: i % 2 == 0 ? args.teamId1 : args.teamId2, | ||
finishState: 'FINISHED', | ||
}); | ||
}) | ||
); | ||
}).not.toThrow(new Error('RunResult length must be 1 or 2')); | ||
continue; | ||
} | ||
expect(() => { | ||
mainMatch.appendRunResults( | ||
[...Array(i)].map((_, i) => { | ||
return RunResult.new({ | ||
id: String(i) as RunResultID, | ||
goalTimeSeconds: i * 10, | ||
points: 10 + i, | ||
teamId: i % 2 == 0 ? args.teamId1 : args.teamId2, | ||
finishState: 'FINISHED', | ||
}); | ||
}) | ||
); | ||
}).toThrow(new Error('RunResult length must be 1 or 2')); | ||
} | ||
} | ||
}); | ||
|
||
it('走行結果はチーム1またはチーム2のもの', () => { | ||
const args = { | ||
id: '1' as PreMatchID, | ||
courseIndex: 1, | ||
matchIndex: 1, | ||
teamId1: '2' as EntryID, | ||
teamId2: '3' as EntryID, | ||
runResults: [], | ||
}; | ||
const res = PreMatch.new(args); | ||
|
||
expect(() => | ||
res.appendRunResults( | ||
[...Array(2)].map((_, i) => { | ||
return RunResult.new({ | ||
id: String(i) as RunResultID, | ||
goalTimeSeconds: i * 10, | ||
points: 10 + i, | ||
teamId: i % 2 == 0 ? args.teamId1 : ('999' as EntryID), | ||
finishState: 'FINISHED', | ||
}); | ||
}) | ||
) | ||
).toThrowError(new Error('RunResult teamId must be teamId1 or teamId2')); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// 予選試合 | ||
|
||
import { SnowflakeID } from '../../id/main.js'; | ||
import { RunResult } from './runResult.js'; | ||
import { EntryID } from '../../entry/entry.js'; | ||
|
||
export type PreMatchID = SnowflakeID<PreMatch>; | ||
|
||
export interface CreatePreMatchArgs { | ||
id: PreMatchID; | ||
courseIndex: number; | ||
matchIndex: number; | ||
teamId1: EntryID; | ||
teamId2?: EntryID; | ||
runResults: RunResult[]; | ||
} | ||
|
||
export class PreMatch { | ||
private readonly id: PreMatchID; | ||
private readonly courseIndex: number; | ||
private readonly matchIndex: number; | ||
private readonly teamId1: EntryID; | ||
// NOTE: 予選参加者は奇数になる可能性があるので2チーム目はいないことがある | ||
private readonly teamId2?: EntryID; | ||
private runResults: RunResult[]; | ||
|
||
private constructor(args: CreatePreMatchArgs) { | ||
this.id = args.id; | ||
this.courseIndex = args.courseIndex; | ||
this.matchIndex = args.matchIndex; | ||
this.teamId1 = args.teamId1; | ||
this.teamId2 = args.teamId2; | ||
this.runResults = args.runResults; | ||
} | ||
|
||
public static new(args: CreatePreMatchArgs) { | ||
return new PreMatch(args); | ||
} | ||
|
||
getId(): PreMatchID { | ||
return this.id; | ||
} | ||
|
||
getCourseIndex(): number { | ||
return this.courseIndex; | ||
} | ||
|
||
getMatchIndex(): number { | ||
return this.matchIndex; | ||
} | ||
|
||
getTeamId1(): EntryID { | ||
return this.teamId1; | ||
} | ||
|
||
getTeamId2(): EntryID | undefined { | ||
return this.teamId2; | ||
} | ||
|
||
getRunResults(): RunResult[] { | ||
return this.runResults; | ||
} | ||
|
||
appendRunResults(runResults: RunResult[]) { | ||
// 1チーム1つずつ結果を持つので,1 or 2個 | ||
if (runResults.length !== 1 && runResults.length !== 2) { | ||
throw new Error('RunResult length must be 1 or 2'); | ||
} | ||
if ( | ||
runResults.some((result) => result.getTeamId() !== this.teamId1) || | ||
(this.teamId2 && runResults.some((result) => result.getTeamId() !== this.teamId2)) | ||
) { | ||
throw new Error('RunResult teamId must be teamId1 or teamId2'); | ||
} | ||
this.runResults.concat(runResults); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters