Skip to content

Commit

Permalink
fix:MainMatchに走行結果を追加できるよう変更 (#573)
Browse files Browse the repository at this point in the history
* fix:追加できるよう変更

* fix:テストの内容を変更

* fix:テスト内容を変更

* feat: 走行結果を正しく保存するように

---------

Co-authored-by: tufusa <me@tufusa.net>
Co-authored-by: tufusa <tufusa74@gmail.com>
  • Loading branch information
3 people authored Oct 24, 2024
1 parent b65e761 commit e400eb6
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 95 deletions.
65 changes: 47 additions & 18 deletions packages/kcms/src/match/adaptor/prisma/mainMatchRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,37 @@ export class PrismaMainMatchRepository implements MainMatchRepository {

async update(match: MainMatch): Promise<Result.Result<Error, void>> {
try {
const currentRunResults = await this.client.runResult.findMany({
where: { mainMatchId: match.getId() },
});
const currentRunResultIDs = new Set<string>(currentRunResults.map((v) => v.id));

// 複数更新と複数作成が同時にできないため、クエリを分ける
const { updatable: updatableRunResults, new: newRunResults } = match
.getRunResults()
.reduce<{ updatable: RunResult[]; new: RunResult[] }>(
(results, runResult) => {
const updateType = currentRunResultIDs.has(runResult.getId()) ? 'updatable' : 'new';
results[updateType].push(runResult);
return results;
},
{ updatable: [], new: [] }
);

await this.client.runResult.createMany({
data: newRunResults.map((v) => ({
id: v.getId(),
teamID: v.getTeamId(),
points: v.getPoints(),
// NOTE: Infinity: 2147483647
goalTimeSeconds: isFinite(v.getGoalTimeSeconds())
? v.getGoalTimeSeconds()
: this.INT32MAX,
mainMatchId: match.getId(),
// NOTE: GOAL: 0 , FINISHED: 1
finishState: v.isGoal() ? 0 : 1,
})),
});
await this.client.mainMatch.update({
where: {
id: match.getId(),
Expand All @@ -128,24 +159,22 @@ export class PrismaMainMatchRepository implements MainMatchRepository {
rightTeamId: match.getTeamId2(),
winnerTeamId: match.getWinnerId(),
runResult: {
updateMany: match.getRunResults().map((v) => {
return {
where: {
id: v.getId(),
},
data: {
id: v.getId(),
teamID: v.getTeamId(),
points: v.getPoints(),
// NOTE: Infinity: 2147483647
goalTimeSeconds: isFinite(v.getGoalTimeSeconds())
? v.getGoalTimeSeconds()
: this.INT32MAX,
// NOTE: GOAL: 0 , FINISHED: 1
finishState: v.isGoal() ? 0 : 1,
},
};
}),
updateMany: updatableRunResults.map((v) => ({
where: {
id: v.getId(),
},
data: {
id: v.getId(),
teamID: v.getTeamId(),
points: v.getPoints(),
// NOTE: Infinity: 2147483647
goalTimeSeconds: isFinite(v.getGoalTimeSeconds())
? v.getGoalTimeSeconds()
: this.INT32MAX,
// NOTE: GOAL: 0 , FINISHED: 1
finishState: v.isGoal() ? 0 : 1,
},
})),
},
},
});
Expand Down
117 changes: 57 additions & 60 deletions packages/kcms/src/match/adaptor/prisma/preMatchRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,72 +115,69 @@ export class PrismaPreMatchRepository implements PreMatchRepository {

async update(match: PreMatch): Promise<Result.Result<Error, void>> {
try {
const runResults = await this.client.runResult.findMany({
const currentRunResults = await this.client.runResult.findMany({
where: {
preMatchId: match.getId(),
},
});
if (runResults.length === 0) {
await this.client.runResult.createMany({
data: match.getRunResults().map((v) => {
return {
id: v.getId(),
teamID: v.getTeamId(),
points: v.getPoints(),
// NOTE: Infinity: 2147483647
goalTimeSeconds: isFinite(v.getGoalTimeSeconds())
? v.getGoalTimeSeconds()
: this.INT32MAX,
preMatchId: match.getId(),
// NOTE: GOAL: 0 , FINISHED: 1
finishState: v.isGoal() ? 0 : 1,
};
}),
});
await this.client.preMatch.update({
where: {
id: match.getId(),
},
data: {
courseIndex: match.getCourseIndex(),
matchIndex: match.getMatchIndex(),
leftTeamID: match.getTeamId1(),
rightTeamID: match.getTeamId2(),
},
});
} else {
await this.client.preMatch.update({
where: {
id: match.getId(),
const currentRunResultIDs = new Set<string>(currentRunResults.map((v) => v.id));

// 複数更新と複数作成が同時にできないため、クエリを分ける
const { updatable: updatableRunResults, new: newRunResults } = match
.getRunResults()
.reduce<{ updatable: RunResult[]; new: RunResult[] }>(
(results, runResult) => {
const updateType = currentRunResultIDs.has(runResult.getId()) ? 'updatable' : 'new';
results[updateType].push(runResult);
return results;
},
data: {
courseIndex: match.getCourseIndex(),
matchIndex: match.getMatchIndex(),
leftTeamID: match.getTeamId1(),
rightTeamID: match.getTeamId2(),
runResult: {
updateMany: match.getRunResults().map((v) => {
return {
where: {
id: v.getId(),
},
data: {
id: v.getId(),
teamID: v.getTeamId(),
points: v.getPoints(),
// NOTE: Infinity: 2147483647
goalTimeSeconds: isFinite(v.getGoalTimeSeconds())
? v.getGoalTimeSeconds()
: this.INT32MAX,
// NOTE: GOAL: 0 , FINISHED: 1
finishState: v.isGoal() ? 0 : 1,
},
};
}),
},
{ updatable: [], new: [] }
);

await this.client.runResult.createMany({
data: newRunResults.map((v) => ({
id: v.getId(),
teamID: v.getTeamId(),
points: v.getPoints(),
// NOTE: Infinity: 2147483647
goalTimeSeconds: isFinite(v.getGoalTimeSeconds())
? v.getGoalTimeSeconds()
: this.INT32MAX,
preMatchId: match.getId(),
// NOTE: GOAL: 0 , FINISHED: 1
finishState: v.isGoal() ? 0 : 1,
})),
});
await this.client.preMatch.update({
where: {
id: match.getId(),
},
data: {
courseIndex: match.getCourseIndex(),
matchIndex: match.getMatchIndex(),
departmentType: match.getDepartmentType(),
leftTeamID: match.getTeamId1(),
rightTeamID: match.getTeamId2(),
runResult: {
updateMany: updatableRunResults.map((v) => ({
where: {
id: v.getId(),
},
data: {
id: v.getId(),
teamID: v.getTeamId(),
points: v.getPoints(),
// NOTE: Infinity: 2147483647
goalTimeSeconds: isFinite(v.getGoalTimeSeconds())
? v.getGoalTimeSeconds()
: this.INT32MAX,
// NOTE: GOAL: 0 , FINISHED: 1
finishState: v.isGoal() ? 0 : 1,
},
})),
},
});
}
},
});
return Result.ok(undefined);
} catch (e) {
return Result.err(e as Error);
Expand Down
76 changes: 61 additions & 15 deletions packages/kcms/src/match/model/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,34 +28,33 @@ describe('MainMatch', () => {
});

it('走行結果は0 or 2 or 4になる', () => {
const args = {
id: '1' as MainMatchID,
courseIndex: 1,
matchIndex: 1,
departmentType: config.departmentTypes[0],
teamId1: '2' as TeamID,
teamId2: '3' as TeamID,
winnerId: '2' as TeamID,
runResults: [],
} satisfies CreateMainMatchArgs;

for (let j = 1; j < 100; j++) {
const mainMatch = MainMatch.new(args);
const mainMatch = MainMatch.new({
id: '1' as MainMatchID,
courseIndex: 1,
matchIndex: 1,
departmentType: config.departmentTypes[0],
teamId1: '2' as TeamID,
teamId2: '3' as TeamID,
winnerId: '2' as TeamID,
runResults: [],
});
// 2か4以外は足せない
if (j == 2 || j == 4) {
if (j == 1 || j == 2 || j == 4) {
expect(() => {
mainMatch.appendRunResults(
[...Array(j)].map((_, i) => {
return RunResult.new({
id: String(i) as RunResultID,
goalTimeSeconds: i * 10,
points: 10 + i,
teamID: i % 2 == 0 ? args.teamId1 : args.teamId2,
teamID: i % 2 == 0 ? ('2' as TeamID) : ('3' as TeamID),
finishState: 'FINISHED',
});
})
);
}).not.toThrow(new Error('RunResult length must be 2 or 4'));
expect(mainMatch.getRunResults().length).toBe(j);
continue;
}
expect(() => {
Expand All @@ -65,12 +64,59 @@ describe('MainMatch', () => {
id: String(i) as RunResultID,
goalTimeSeconds: i * 10,
points: 10 + i,
teamID: i % 2 == 0 ? args.teamId1 : args.teamId2,
teamID: i % 2 == 0 ? ('2' as TeamID) : ('3' as TeamID),
finishState: 'FINISHED',
});
})
);
}).toThrow(new Error('RunResult length must be 2 or 4'));
expect(mainMatch.getRunResults().length).toBe(0);
}
});

it('走行結果を追加できる', () => {
for (let i = 1; i <= 2; i++) {
const mainMatch = MainMatch.new({
id: '1' as MainMatchID,
courseIndex: 1,
matchIndex: 1,
departmentType: config.departmentTypes[0],
teamId1: '2' as TeamID,
teamId2: '3' as TeamID,
winnerId: '2' as TeamID,
runResults: [],
});
for (let j = 1; j < 8; j++) {
if (j === 1 || j == 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 ? ('2' as TeamID) : ('3' as TeamID),
finishState: 'FINISHED',
});
})
);
}).not.toThrow(new Error('RunResult length must be 2 or 4'));
} else {
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 ? ('2' as TeamID) : ('3' as TeamID),
finishState: 'FINISHED',
});
})
);
}).toThrow(new Error('RunResult length must be 2 or 4'));
}
}
}
});

Expand Down
4 changes: 2 additions & 2 deletions packages/kcms/src/match/model/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ export class MainMatch {
appendRunResults(results: RunResult[]) {
// 1チームが2つずつ結果を持つので、2 または 4個
const appendedLength = this.runResults.length + results.length;
if (appendedLength !== 4 && appendedLength !== 2) {
if (appendedLength !== 4 && appendedLength !== 2 && appendedLength !== 1) {
throw new Error('RunResult length must be 2 or 4');
}
this.runResults.concat(results);
this.runResults.push(...results);
}
}

0 comments on commit e400eb6

Please sign in to comment.