diff --git a/typing-server/api/repository/score.go b/typing-server/api/repository/score.go index aa6ff5a..417449c 100644 --- a/typing-server/api/repository/score.go +++ b/typing-server/api/repository/score.go @@ -90,10 +90,20 @@ func GetScoresRanking(ctx context.Context, client *ent.Client, sortBy string, st return rankings, nil } - func CreateScore(ctx context.Context, client *ent.Client, userID uuid.UUID, keystrokes int, accuracy float64) error { - // Create a new score - createdScore, err := client.Score.Create(). + // トランザクションを開始 + tx, err := client.Tx(ctx) + if err != nil { + return err + } + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + + // 新しいスコアを作成 + createdScore, err := tx.Score.Create(). SetKeystrokes(keystrokes). SetAccuracy(accuracy). SetUserID(userID). @@ -102,46 +112,70 @@ func CreateScore(ctx context.Context, client *ent.Client, userID uuid.UUID, keys return err } + // キーストロークと精度のチェック if keystrokes < 120 || accuracy < 0.95 { - return nil + return tx.Commit() + } + + // ユーザーを取得 + user, err := tx.User.Query().Where(user.ID(userID)).Only(ctx) + if err != nil { + return err + } + + // 最大キーストロークと最大精度のスコアを取得 + maxKeystrokeScore, maxAccuracyScore, err := getMaxScores(ctx, user) + if err != nil { + return err } - // Get the user - user, err := client.User.Query().Where(user.ID(userID)).Only(ctx) + // 以前の最大スコアのフラグを更新 + err = updateMaxScoreFlags(ctx, maxKeystrokeScore, maxAccuracyScore, createdScore) if err != nil { return err } - // Check if the new score has the maximum keystrokes + // トランザクションをコミット + return tx.Commit() +} + +func getMaxScores(ctx context.Context, user *ent.User) (*ent.Score, *ent.Score, error) { + // 最大キーストロークのスコアを取得 maxKeystrokeScore, err := user.QueryScores().Where(score.IsMaxKeystrokes(true)).Only(ctx) if err != nil && !ent.IsNotFound(err) { - return err + return nil, nil, err } - isMaxKeystrokes := maxKeystrokeScore == nil || createdScore.Keystrokes >= maxKeystrokeScore.Keystrokes - // Check if the new score has the maximum accuracy + // 最大精度のスコアを取得 maxAccuracyScore, err := user.QueryScores().Where(score.IsMaxAccuracy(true)).Only(ctx) if err != nil && !ent.IsNotFound(err) { - return err + return nil, nil, err } + + return maxKeystrokeScore, maxAccuracyScore, nil +} + +func updateMaxScoreFlags(ctx context.Context, maxKeystrokeScore, maxAccuracyScore, createdScore *ent.Score) error { + isMaxKeystrokes := maxKeystrokeScore == nil || createdScore.Keystrokes >= maxKeystrokeScore.Keystrokes isMaxAccuracy := maxAccuracyScore == nil || createdScore.Accuracy >= maxAccuracyScore.Accuracy - // Update the flags of the previous maximum scores - if maxKeystrokeScore != nil && !isMaxKeystrokes { - err = maxKeystrokeScore.Update().SetIsMaxKeystrokes(false).Exec(ctx) + // 以前の最大スコアのフラグを更新 + if maxKeystrokeScore != nil && isMaxKeystrokes { + err := maxKeystrokeScore.Update().SetIsMaxKeystrokes(false).Exec(ctx) if err != nil { return err } } - if maxAccuracyScore != nil && !isMaxAccuracy { - err = maxAccuracyScore.Update().SetIsMaxAccuracy(false).Exec(ctx) + + if maxAccuracyScore != nil && isMaxAccuracy { + err := maxAccuracyScore.Update().SetIsMaxAccuracy(false).Exec(ctx) if err != nil { return err } } - // Update the score with the maximum flags - err = createdScore.Update(). + // 作成したスコアの最大フラグを更新 + err := createdScore.Update(). SetIsMaxKeystrokes(isMaxKeystrokes). SetIsMaxAccuracy(isMaxAccuracy). Exec(ctx)