Skip to content

Commit 94af90f

Browse files
authored
Merge pull request #114 from isucon/billing-breakdown
billingに内訳を記載する
2 parents 2c87f53 + 384e128 commit 94af90f

File tree

2 files changed

+44
-23
lines changed

2 files changed

+44
-23
lines changed

bench/scenario_validation.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -455,11 +455,22 @@ func (sc *Scenario) ValidationScenario(ctx context.Context, step *isucandar.Benc
455455
return fmt.Errorf("対象の大会のIDが違います (want: %s, got: %s)", competitionID, r.Data.Reports[0].CompetitionID)
456456
}
457457
// score登録者 rankingアクセスあり: 100 yen x 1 player
458-
// score登録者 rankingアクセスなし: 50 yen x (playerNum - 2) player
459458
// score未登録者 rankingアクセスあり: 10 yen x 1 player
460-
billingYen := int64((100 * 1) + (50 * (playerNum - 2)) + (10 * 1))
459+
if r.Data.Reports[0].PlayerCount != 1 {
460+
return fmt.Errorf("大会の参加者数が違います competitionID: %s (want: %d, got: %d)", competitionID, 1, r.Data.Reports[0].PlayerCount)
461+
}
462+
if r.Data.Reports[0].VisitorCount != 1 {
463+
return fmt.Errorf("大会の閲覧者数が違います competitionID: %s (want: %d, got: %d)", competitionID, 1, r.Data.Reports[0].VisitorCount)
464+
}
465+
if r.Data.Reports[0].BillingPlayerYen != 100 {
466+
return fmt.Errorf("大会の請求金額内訳(参加者分)が違います competitionID: %s (want: %d, got: %d)", competitionID, 100, r.Data.Reports[0].BillingPlayerYen)
467+
}
468+
if r.Data.Reports[0].BillingVisitorYen != 10 {
469+
return fmt.Errorf("大会の請求金額内訳(閲覧者)が違います competitionID: %s (want: %d, got: %d)", competitionID, 10, r.Data.Reports[0].BillingVisitorYen)
470+
}
471+
billingYen := int64((100 * 1) + (10 * 1))
461472
if billingYen != r.Data.Reports[0].BillingYen {
462-
return fmt.Errorf("大会の請求金額が違います competitionID: %s (want: %d, got: %d)", competitionID, billingYen, r.Data.Reports[0].BillingYen)
473+
return fmt.Errorf("大会の請求金額合計が違います competitionID: %s (want: %d, got: %d)", competitionID, billingYen, r.Data.Reports[0].BillingYen)
463474
}
464475

465476
return nil

webapp/go/isuports.go

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -529,10 +529,13 @@ func validateTenantName(name string) error {
529529
}
530530

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

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

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

578581
// player_scoreを読んでいるときに更新が走ると不整合が起こるのでロックを取得する
@@ -581,6 +584,8 @@ func billingReportByCompetition(ctx context.Context, tenantDB dbOrTx, tenantID i
581584
return nil, fmt.Errorf("error flockByTenantID: %w", err)
582585
}
583586
defer fl.Close()
587+
588+
// スコアを登録した参加者のIDを取得する
584589
scoredPlayerIDs := []string{}
585590
if err := tenantDB.SelectContext(
586591
ctx,
@@ -592,26 +597,31 @@ func billingReportByCompetition(ctx context.Context, tenantDB dbOrTx, tenantID i
592597
}
593598
for _, pid := range scoredPlayerIDs {
594599
if _, ok := billingMap[pid]; ok {
595-
// scoreに登録されているplayerでアクセスした人 * 100
596-
billingMap[pid] = 100
597-
} else {
598-
// scoreに登録されているplayerでアクセスしていない人 * 50
599-
billingMap[pid] = 50
600+
// スコアが登録されている参加者
601+
billingMap[pid] = "player"
600602
}
601603
}
602604

603-
var billingYen int64
604-
// 大会が終了している場合は課金を計算する(開催中の場合は常に 0)
605+
// 大会が終了している場合のみ請求金額が確定するので計算する
606+
var playerCount, visitorCount int64
605607
if comp.FinishedAt.Valid {
606-
for _, v := range billingMap {
607-
billingYen += v
608+
for _, category := range billingMap {
609+
switch category {
610+
case "player":
611+
playerCount++
612+
case "visitor":
613+
visitorCount++
614+
}
608615
}
609616
}
610617
return &BillingReport{
611-
CompetitionID: comp.ID,
612-
CompetitionTitle: comp.Title,
613-
PlayerCount: int64(len(scoredPlayerIDs)),
614-
BillingYen: billingYen,
618+
CompetitionID: comp.ID,
619+
CompetitionTitle: comp.Title,
620+
PlayerCount: playerCount,
621+
VisitorCount: visitorCount,
622+
BillingPlayerYen: 100 * playerCount, // スコアを登録した参加者は100円
623+
BillingVisitorYen: 10 * visitorCount, // ランキングを閲覧だけした(スコアを登録していない)参加者は10円
624+
BillingYen: 100*playerCount + 10*visitorCount,
615625
}, nil
616626
}
617627

0 commit comments

Comments
 (0)