Skip to content
This repository has been archived by the owner on Aug 7, 2024. It is now read-only.

fix: ルール変更に対応 #21

Merged
merged 2 commits into from
Dec 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions src/match/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@ export class MatchController {
}

async getMatchByType(matchType: string) {
if (matchType !== "primary") {
return Result.err(new Error("not implemented"));
}
const res = await this.getService.findByType(matchType);
if (Result.isErr(res)) {
return Result.err(res[1]);
Expand Down
12 changes: 7 additions & 5 deletions src/match/service/generate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,21 @@ const generateDummyData = (n: number): Entry[] => {
return res;
};

describe("予選の対戦表を正しく生成できる", () => {
describe("予選の対戦表を正しく生成できる", async () => {
const repository = new DummyRepository();
const matchRepository = new DummyMatchRepository();
const service = new GenerateMatchService(repository, matchRepository);
const dummyData = generateDummyData(8);
const dummyData = generateDummyData(10);
console.log(dummyData.length);
dummyData.map((v) => repository.create(v));

it("初期状態の対戦表を生成できる", async () => {
const res = await service.generatePrimaryMatch();
expect(Result.isErr(res)).toStrictEqual(false);
if (Result.isErr(res)) {
return;
for (const v of Result.unwrap(res)) {
for (const j of v) {
expect(j.teams.Left!.id).not.toBe(j.teams.Right!.id);
}
}
});
});
Expand Down Expand Up @@ -87,6 +89,6 @@ describe("本選の対戦表を正しく生成できる", async () => {
});

it("本選の対戦表を正しく生成できる", async () => {
await service.generateFinalMatch("open");
await service.generateFinalMatch("elementary");
});
});
59 changes: 46 additions & 13 deletions src/match/service/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type Tuple<T, L extends number> = BaseTuple<T, L>;

export class GenerateMatchService {
private readonly COURSE_COUNT = 3;
private readonly FINAL_TOURNAMENT_COUNT = 8;
private readonly entryRepository: EntryRepository;
private readonly matchRepository: MatchRepository;

Expand Down Expand Up @@ -65,8 +66,10 @@ export class GenerateMatchService {
for (let i = 0; i < courses.length; i++) {
const courseMatches: Match[] = [];
for (let k = 0; k < courses[i].length; k++) {
// 対戦相手のインデックス
const opponentIndex = k + 1 >= courses[i].length ? 0 : k + 1;
const courseLength = courses[i].length;
const gap = Math.floor(courseLength / 2);
const opponentIndex =
k + gap >= courseLength ? k + gap - courseLength : k + gap;
const match = Match.new({
id: crypto.randomUUID(),
matchType: "primary",
Expand All @@ -87,7 +90,6 @@ export class GenerateMatchService {
return Result.ok(tmpMatches);
}

// ToDo: 本選トーナメント対戦表の生成
async generateFinalMatch(
category: "elementary" | "open",
): Promise<Result.Result<Error, Match[]>> {
Expand All @@ -96,10 +98,14 @@ export class GenerateMatchService {
1 vs 8, 4 vs 5, 2 vs 7, 3 vs 6 (数字は順位)
*/

const [elementaryRank, openRank] = await this.generateRanking();
const [elementaryRank] = await this.generateRanking();
const openRank = await this.generateOpenTournament();
const [elementaryTournament, openTournament] = [
this.generateTournamentPair(this.generateTournament(elementaryRank)),
this.generateTournamentPair(this.generateTournament(openRank)),
// fixme: unwrapやめる
this.generateTournamentPair(
this.generateTournament(Result.unwrap(openRank)),
),
];

const matches: Match[] = [];
Expand All @@ -116,12 +122,15 @@ export class GenerateMatchService {
}
} else {
for (const v of openTournament) {
Match.new({
id: crypto.randomUUID(),
matchType: "final",
teams: { Left: v[0].entry, Right: v[1].entry },
courseIndex: 0,
});
console.log(v[0].entry.id, v[1].entry.id);
matches.push(
Match.new({
id: crypto.randomUUID(),
matchType: "final",
teams: { Left: v[0].entry, Right: v[1].entry },
courseIndex: 0,
}),
);
}
}

Expand All @@ -134,7 +143,6 @@ export class GenerateMatchService {

// ToDo: 本戦の順位を計算できるようにする
// - ToDo: (予選)タイムと得点が同じ場合だったときの順位決定処理
// - ToDo: 部門ごとにランキングを生成できるように -> OK
async generateRanking(): Promise<TournamentRank[][]> {
const res = await this.matchRepository.findAll();
if (Result.isErr(res)) {
Expand Down Expand Up @@ -214,11 +222,36 @@ export class GenerateMatchService {
return v;
});
};

return [sortAndRanking(categoryRank[0]), sortAndRanking(categoryRank[1])];
}

// generateOpenTournament オープン部門は予選を行わないのでランキング(?)を無理やり作る
private async generateOpenTournament(): Promise<
Result.Result<Error, TournamentRank[]>
> {
const res = await this.entryRepository.findAll();
if (Result.isErr(res)) {
return Result.err(res[1]);
}

return Result.ok(
res[1]
.filter((v) => v.category === "Open")
.map((v, i): TournamentRank => {
return {
rank: i,
points: 0,
time: 0,
entry: v,
};
}),
);
}

private generateTournament(ranks: TournamentRank[]): TournamentPermutation {
// ランキング上位8チームを取得
ranks = ranks.slice(0, this.FINAL_TOURNAMENT_COUNT);

const genTournament = (
ids: TournamentRank[] | Tournament[] | Tournament,
): TournamentPermutation => {
Expand Down