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

Commit

Permalink
fix: ルール変更に対応 (#21)
Browse files Browse the repository at this point in the history
* feat(service): 予選対戦表でずらす数を変更

* feat: オープン部門のトーナメントを生成できるように
  • Loading branch information
laminne authored Dec 31, 2023
1 parent 7e878df commit 313c6c0
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 21 deletions.
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

0 comments on commit 313c6c0

Please sign in to comment.