Skip to content

Commit

Permalink
Merge pull request #114 from isucon/billing-breakdown
Browse files Browse the repository at this point in the history
billingに内訳を記載する
  • Loading branch information
fujiwara authored Jun 29, 2022
2 parents 2c87f53 + 384e128 commit 94af90f
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 23 deletions.
17 changes: 14 additions & 3 deletions bench/scenario_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -455,11 +455,22 @@ func (sc *Scenario) ValidationScenario(ctx context.Context, step *isucandar.Benc
return fmt.Errorf("対象の大会のIDが違います (want: %s, got: %s)", competitionID, r.Data.Reports[0].CompetitionID)
}
// score登録者 rankingアクセスあり: 100 yen x 1 player
// score登録者 rankingアクセスなし: 50 yen x (playerNum - 2) player
// score未登録者 rankingアクセスあり: 10 yen x 1 player
billingYen := int64((100 * 1) + (50 * (playerNum - 2)) + (10 * 1))
if r.Data.Reports[0].PlayerCount != 1 {
return fmt.Errorf("大会の参加者数が違います competitionID: %s (want: %d, got: %d)", competitionID, 1, r.Data.Reports[0].PlayerCount)
}
if r.Data.Reports[0].VisitorCount != 1 {
return fmt.Errorf("大会の閲覧者数が違います competitionID: %s (want: %d, got: %d)", competitionID, 1, r.Data.Reports[0].VisitorCount)
}
if r.Data.Reports[0].BillingPlayerYen != 100 {
return fmt.Errorf("大会の請求金額内訳(参加者分)が違います competitionID: %s (want: %d, got: %d)", competitionID, 100, r.Data.Reports[0].BillingPlayerYen)
}
if r.Data.Reports[0].BillingVisitorYen != 10 {
return fmt.Errorf("大会の請求金額内訳(閲覧者)が違います competitionID: %s (want: %d, got: %d)", competitionID, 10, r.Data.Reports[0].BillingVisitorYen)
}
billingYen := int64((100 * 1) + (10 * 1))
if billingYen != r.Data.Reports[0].BillingYen {
return fmt.Errorf("大会の請求金額が違います competitionID: %s (want: %d, got: %d)", competitionID, billingYen, r.Data.Reports[0].BillingYen)
return fmt.Errorf("大会の請求金額合計が違います competitionID: %s (want: %d, got: %d)", competitionID, billingYen, r.Data.Reports[0].BillingYen)
}

return nil
Expand Down
50 changes: 30 additions & 20 deletions webapp/go/isuports.go
Original file line number Diff line number Diff line change
Expand Up @@ -529,10 +529,13 @@ func validateTenantName(name string) error {
}

type BillingReport struct {
CompetitionID string `json:"competition_id"`
CompetitionTitle string `json:"competition_title"`
PlayerCount int64 `json:"player_count"`
BillingYen int64 `json:"billing_yen"`
CompetitionID string `json:"competition_id"`
CompetitionTitle string `json:"competition_title"`
PlayerCount int64 `json:"player_count"` // スコアを登録した参加者数
VisitorCount int64 `json:"visitor_count"` // ランキングを閲覧だけした(スコアを登録していない)参加者数
BillingPlayerYen int64 `json:"billing_player_yen"` // 請求金額 スコアを登録した参加者分
BillingVisitorYen int64 `json:"billing_visitor_yen"` // 請求金額 ランキングを閲覧だけした(スコアを登録していない)参加者分
BillingYen int64 `json:"billing_yen"` // 合計請求金額
}

type VisitHistoryRow struct {
Expand All @@ -555,6 +558,7 @@ func billingReportByCompetition(ctx context.Context, tenantDB dbOrTx, tenantID i
return nil, fmt.Errorf("error retrieveCompetition: %w", err)
}

// ランキングにアクセスした参加者のIDを取得する
vhs := []VisitHistorySummaryRow{}
if err := adminDB.SelectContext(
ctx,
Expand All @@ -565,14 +569,13 @@ func billingReportByCompetition(ctx context.Context, tenantDB dbOrTx, tenantID i
); err != nil && err != sql.ErrNoRows {
return nil, fmt.Errorf("error Select visit_history: tenantID=%d, competitionID=%s, %w", tenantID, comp.ID, err)
}
billingMap := map[string]int64{}
billingMap := map[string]string{}
for _, vh := range vhs {
// competition.finished_atよりもあとの場合は、終了後に訪問したとみなして大会開催内アクセス済みとみなさない
if comp.FinishedAt.Valid && comp.FinishedAt.Int64 < vh.MinCreatedAt {
continue
}
// scoreに登録されていないplayerでアクセスした人 * 10
billingMap[vh.PlayerID] = 10
billingMap[vh.PlayerID] = "visitor"
}

// player_scoreを読んでいるときに更新が走ると不整合が起こるのでロックを取得する
Expand All @@ -581,6 +584,8 @@ func billingReportByCompetition(ctx context.Context, tenantDB dbOrTx, tenantID i
return nil, fmt.Errorf("error flockByTenantID: %w", err)
}
defer fl.Close()

// スコアを登録した参加者のIDを取得する
scoredPlayerIDs := []string{}
if err := tenantDB.SelectContext(
ctx,
Expand All @@ -592,26 +597,31 @@ func billingReportByCompetition(ctx context.Context, tenantDB dbOrTx, tenantID i
}
for _, pid := range scoredPlayerIDs {
if _, ok := billingMap[pid]; ok {
// scoreに登録されているplayerでアクセスした人 * 100
billingMap[pid] = 100
} else {
// scoreに登録されているplayerでアクセスしていない人 * 50
billingMap[pid] = 50
// スコアが登録されている参加者
billingMap[pid] = "player"
}
}

var billingYen int64
// 大会が終了している場合は課金を計算する(開催中の場合は常に 0)
// 大会が終了している場合のみ請求金額が確定するので計算する
var playerCount, visitorCount int64
if comp.FinishedAt.Valid {
for _, v := range billingMap {
billingYen += v
for _, category := range billingMap {
switch category {
case "player":
playerCount++
case "visitor":
visitorCount++
}
}
}
return &BillingReport{
CompetitionID: comp.ID,
CompetitionTitle: comp.Title,
PlayerCount: int64(len(scoredPlayerIDs)),
BillingYen: billingYen,
CompetitionID: comp.ID,
CompetitionTitle: comp.Title,
PlayerCount: playerCount,
VisitorCount: visitorCount,
BillingPlayerYen: 100 * playerCount, // スコアを登録した参加者は100円
BillingVisitorYen: 10 * visitorCount, // ランキングを閲覧だけした(スコアを登録していない)参加者は10円
BillingYen: 100*playerCount + 10*visitorCount,
}, nil
}

Expand Down

0 comments on commit 94af90f

Please sign in to comment.