Skip to content

Commit

Permalink
Count badges for all leg types
Browse files Browse the repository at this point in the history
  • Loading branch information
thordy committed Mar 28, 2024
1 parent 759ba1e commit 409e4f8
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- New game type `170`
- Endpoint for getting badge statistics
- Added Darts Per Leg `DPL` metric to tournament
- Count badges for all leg types
- Lots of new badges

#### Changed
Expand Down
5 changes: 4 additions & 1 deletion data/badge.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ func GetBadges() ([]*models.Badge, error) {
b.name,
b.description,
b.filename,
b.secret,
b.hidden,
b.levels
FROM badge b`)
if err != nil {
Expand All @@ -27,7 +29,7 @@ func GetBadges() ([]*models.Badge, error) {
badges := make([]*models.Badge, 0)
for rows.Next() {
badge := new(models.Badge)
err := rows.Scan(&badge.ID, &badge.Name, &badge.Description, &badge.Filename, &badge.Levels)
err := rows.Scan(&badge.ID, &badge.Name, &badge.Description, &badge.Filename, &badge.Secret, &badge.Hidden, &badge.Levels)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -239,6 +241,7 @@ func CheckLegForBadges(leg *models.Leg, statistics map[int]*models.PlayerBadgeSt
}
}
}

for _, badge := range models.VisitBadges {
for _, playerID := range leg.Players {
valid, visitID := badge.Validate(playerID, leg.Visits)
Expand Down
2 changes: 1 addition & 1 deletion data/leg.go
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,7 @@ func GetBadgeLegsToRecalculate() ([]int, error) {
SELECT l.id
FROM leg l
JOIN matches m on m.id = l.match_id
WHERE l.has_scores = 1 AND COALESCE(l.leg_type_id, m.match_type_id) = 1 -- X01
WHERE l.has_scores = 1
AND m.is_abandoned = 0 AND m.is_bye = 0 AND m.is_walkover = 0
AND l.is_finished = 1
GROUP BY l.id
Expand Down
2 changes: 0 additions & 2 deletions data/statistics_x01.go
Original file line number Diff line number Diff line change
Expand Up @@ -933,7 +933,6 @@ func GetPlayerBadgeStatistics(ids []int, legID *int) (map[int]*models.PlayerBadg
LEFT JOIN matches m ON l.match_id = m.id
WHERE player_id IN (?)
AND l.is_finished = 1 AND m.is_abandoned = 0 AND m.is_walkover = 0
AND COALESCE(l.leg_type_id, m.match_type_id) = 1 -- X01
AND m.is_bye = 0 AND m.is_walkover = 0 AND leg_id <= COALESCE(?, ~0) -- BIGINT hack
GROUP BY player_id
ORDER BY player_id DESC`, ids, legID)
Expand Down Expand Up @@ -979,7 +978,6 @@ func GetPlayerBadgeStatistics(ids []int, legID *int) (map[int]*models.PlayerBadg
or (first_dart_multiplier = 2 and second_dart_multiplier = 1 and third_dart_multiplier = 3))
AND is_bust = 0 AND s.player_id IN (?) AND leg_id <= COALESCE(?, ~0) -- BIGINT hack
AND l.is_finished = 1 AND m.is_abandoned = 0 AND m.is_walkover = 0
AND COALESCE(l.leg_type_id, m.match_type_id) = 1 -- X01
AND m.is_bye = 0 AND m.is_walkover = 0
GROUP BY first_dart, player_id`, ids, legID)
if err != nil {
Expand Down
119 changes: 109 additions & 10 deletions models/badge.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package models

import (
"encoding/json"
"log"
"sort"
"time"

Expand Down Expand Up @@ -216,6 +217,9 @@ func (b BadgeJustAQuickie) GetID() int {
return b.ID
}
func (b BadgeJustAQuickie) Validate(match *Match) (bool, []int) {
if !match.IsX01() {
return false, nil
}
if len(match.Legs) == 3 && len(match.Players) > 1 {
first := match.Legs[0]
second := match.Legs[1]
Expand All @@ -226,13 +230,18 @@ func (b BadgeJustAQuickie) Validate(match *Match) (bool, []int) {
return true, []int{int(match.WinnerID.Int64)}
}
}

return false, nil
}

func (b BadgeAroundTheWorld) GetID() int {
return b.ID
}
func (b BadgeAroundTheWorld) Validate(match *Match) (bool, []int) {
if !match.IsX01() {
return false, nil
}

playerHits := make(map[int][]int)
for playerID := range match.Players {
playerHits[playerID] = make([]int, 0)
Expand Down Expand Up @@ -308,6 +317,7 @@ var LegBadges = []LegBadge{
BadgeChampagneShot{ID: 42},
BadgeYin{ID: 44},
BadgeYang{ID: 45},
BadgeZebra{ID: 47},
}

type LegBadge interface {
Expand Down Expand Up @@ -335,11 +345,15 @@ type BadgePerfection struct{ ID int }
type BadgeChampagneShot struct{ ID int }
type BadgeYin struct{ ID int }
type BadgeYang struct{ ID int }
type BadgeZebra struct{ ID int }

func (b BadgeDoubleDouble) GetID() int {
return b.ID
}
func (b BadgeDoubleDouble) Validate(leg *Leg) (bool, *int, *int) {
if !leg.IsX01() {
return false, nil, nil
}
visit := leg.GetLastVisit()
doubles := 0
if visit.ThirdDart.IsDouble() {
Expand All @@ -358,6 +372,9 @@ func (b BadgeTripleDouble) GetID() int {
return b.ID
}
func (b BadgeTripleDouble) Validate(leg *Leg) (bool, *int, *int) {
if !leg.IsX01() {
return false, nil, nil
}
visit := leg.GetLastVisit()
return visit.FirstDart.IsDouble() && visit.SecondDart.IsDouble() && visit.ThirdDart.IsDouble(), &visit.PlayerID, &visit.ID
}
Expand All @@ -366,6 +383,9 @@ func (b BadgeMadHouse) GetID() int {
return b.ID
}
func (b BadgeMadHouse) Validate(leg *Leg) (bool, *int, *int) {
if !leg.IsX01() {
return false, nil, nil
}
visit := leg.GetLastVisit()
last := visit.GetLastDart()
return last.IsDouble() && last.ValueRaw() == 1, &visit.PlayerID, &visit.ID
Expand Down Expand Up @@ -408,6 +428,9 @@ func (b BadgeBullseye) GetID() int {
return b.ID
}
func (b BadgeBullseye) Validate(leg *Leg) (bool, *int, *int) {
if !leg.IsX01() {
return false, nil, nil
}
visit := leg.GetLastVisit()
last := visit.GetLastDart()
return last.ValueRaw() == BULLSEYE && last.Multiplier == DOUBLE, &visit.PlayerID, &visit.ID
Expand All @@ -417,6 +440,9 @@ func (b BadgeEasyAs123) GetID() int {
return b.ID
}
func (b BadgeEasyAs123) Validate(leg *Leg) (bool, *int, *int) {
if !leg.IsX01() {
return false, nil, nil
}
visit := leg.GetLastVisit()
last := visit.GetLastDart()
return visit.GetScore() == 123 && last.IsDouble(), &visit.PlayerID, &visit.ID
Expand All @@ -426,6 +452,9 @@ func (b BadgeCloseToPerfect) GetID() int {
return b.ID
}
func (b BadgeCloseToPerfect) Validate(leg *Leg) (bool, *int, *int) {
if !leg.IsX01() {
return false, nil, nil
}
visit := leg.GetLastVisit()
return leg.StartingScore == 501 && visit.DartsThrown < 15 && visit.DartsThrown > 9, &visit.PlayerID, nil
}
Expand All @@ -445,6 +474,9 @@ func (b BadgeShanghaiCheckout) GetID() int {
return b.ID
}
func (b BadgeShanghaiCheckout) Validate(leg *Leg) (bool, *int, *int) {
if !leg.IsX01() {
return false, nil, nil
}
visit := leg.GetLastVisit()
return visit.IsShanghai(), &visit.PlayerID, &visit.ID
}
Expand All @@ -453,8 +485,11 @@ func (b BadgeTripleTrouble) GetID() int {
return b.ID
}
func (b BadgeTripleTrouble) Validate(leg *Leg) (bool, *int, *int) {
visit := leg.GetLastVisit()
if !leg.IsX01() {
return false, nil, nil
}

visit := leg.GetLastVisit()
if visit.FirstDart.IsDouble() && visit.SecondDart.IsDouble() && visit.ThirdDart.IsDouble() &&
visit.FirstDart.ValueRaw() == visit.SecondDart.ValueRaw() && visit.FirstDart.ValueRaw() == visit.ThirdDart.ValueRaw() {
return true, &visit.PlayerID, &visit.ID
Expand All @@ -467,6 +502,10 @@ func (b BadgePerfection) GetID() int {
return b.ID
}
func (b BadgePerfection) Validate(leg *Leg) (bool, *int, *int) {
if !leg.IsX01() {
return false, nil, nil
}

visit := leg.GetLastVisit()
if leg.StartingScore == 501 && visit.DartsThrown == 9 {
return true, &visit.PlayerID, nil
Expand All @@ -478,6 +517,10 @@ func (b BadgeChampagneShot) GetID() int {
return b.ID
}
func (b BadgeChampagneShot) Validate(leg *Leg) (bool, *int, *int) {
if !leg.IsX01() {
return false, nil, nil
}

visit := leg.GetLastVisit()

if visit.FirstDart.IsBull() && visit.FirstDart.IsDouble() &&
Expand All @@ -493,17 +536,19 @@ func (b BadgeYin) GetID() int {
return b.ID
}
func (b BadgeYin) Validate(leg *Leg) (bool, *int, *int) {
black := []int{0, 20, 18, 13, 10, 2, 3, 7, 8, 14, 12}
if !leg.IsX01() {
return false, nil, nil
}

completed := true
winner := leg.GetLastVisit().PlayerID
for _, visit := range leg.Visits {
if visit.PlayerID != winner {
continue
}
if !containsInt(black, visit.FirstDart.ValueRaw()) ||
!containsInt(black, visit.SecondDart.ValueRaw()) ||
!containsInt(black, visit.ThirdDart.ValueRaw()) {
if !containsInt(NUMS_BLACK, visit.FirstDart.ValueRaw()) ||
!containsInt(NUMS_BLACK, visit.SecondDart.ValueRaw()) ||
!containsInt(NUMS_BLACK, visit.ThirdDart.ValueRaw()) {
completed = false
break

Expand All @@ -519,16 +564,19 @@ func (b BadgeYang) GetID() int {
return b.ID
}
func (b BadgeYang) Validate(leg *Leg) (bool, *int, *int) {
white := []int{0, 1, 4, 6, 15, 17, 19, 16, 11, 9, 5}
if !leg.IsX01() {
return false, nil, nil
}

completed := true
winner := leg.GetLastVisit().PlayerID
for _, visit := range leg.Visits {
if visit.PlayerID != winner {
continue
}
if !containsInt(white, visit.FirstDart.ValueRaw()) ||
!containsInt(white, visit.SecondDart.ValueRaw()) ||
!containsInt(white, visit.ThirdDart.ValueRaw()) {
if !containsInt(NUMS_WHITE, visit.FirstDart.ValueRaw()) ||
!containsInt(NUMS_WHITE, visit.SecondDart.ValueRaw()) ||
!containsInt(NUMS_WHITE, visit.ThirdDart.ValueRaw()) {
completed = false
break

Expand All @@ -540,6 +588,57 @@ func (b BadgeYang) Validate(leg *Leg) (bool, *int, *int) {
return false, nil, nil
}

func (b BadgeZebra) GetID() int {
return b.ID
}
func (b BadgeZebra) Validate(leg *Leg) (bool, *int, *int) {
if !leg.IsX01() {
return false, nil, nil
}
winner := leg.GetLastVisit().PlayerID

COLORS := map[int][]int{
0: NUMS_BLACK,
1: NUMS_WHITE,
}
completed := true

first := leg.GetFirstHitDart(winner)
var color int
if containsInt(COLORS[0], first.ValueRaw()) {
color = 0
} else {
color = 1
}
for _, visit := range leg.Visits {
if visit.PlayerID != winner {
continue
}

for _, dart := range visit.GetDarts() {
if dart.IsMiss() {
log.Printf("Skipping Missed dart")
continue
}
colors := COLORS[color%2]
log.Printf("Checking if %d is %d in %v", dart.ValueRaw(), color, colors)
if !containsInt(colors, dart.ValueRaw()) {
completed = false
break
}
color++
}

if !completed {
break
}
}
if completed {
return true, &winner, nil
}
return false, nil, nil
}

var LegPlayerBadges = []LegPlayerBadge{
BadgeImpersonator{ID: 21},
BadgeBotBeaterEasy{ID: 22},
Expand Down Expand Up @@ -838,7 +937,7 @@ func (b BadgeSoClose) Validate(playerID int, visits []*Visit) (bool, *int) {
func GetLevel(value int, levels []int) int {
level := 1
for i, treshold := range levels {
if value > treshold {
if value >= treshold {
level = i + 1
}
}
Expand Down
20 changes: 20 additions & 0 deletions models/leg.go
Original file line number Diff line number Diff line change
Expand Up @@ -411,3 +411,23 @@ func DecorateVisitsScam(players map[int]*Player2Leg, visits []*Visit) {
func (leg Leg) GetLastVisit() *Visit {
return leg.Visits[len(leg.Visits)-1]
}

// IsX01 returns true if this leg is a X01 leg
func (leg Leg) IsX01() bool {
return leg.LegType.ID == X01
}

// GetFirstHitDart will return the first (non-Miss) dart for the given player
func (leg Leg) GetFirstHitDart(playerID int) *Dart {
for _, visit := range leg.Visits {
if visit.PlayerID != playerID {
continue
}
for _, dart := range visit.GetDarts() {
if !dart.IsMiss() {
return &dart
}
}
}
return nil
}
5 changes: 5 additions & 0 deletions models/match.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,3 +329,8 @@ type MatchConfigError struct {
func (e *MatchConfigError) Error() string {
return e.Err.Error()
}

// IsX01 returns true if this match is a X01 match
func (m Match) IsX01() bool {
return m.MatchType.ID == X01
}
3 changes: 3 additions & 0 deletions models/visit.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import (
"github.com/guregu/null"
)

var NUMS_WHITE = []int{0, 1, 4, 6, 15, 17, 19, 16, 11, 9, 5}
var NUMS_BLACK = []int{0, 20, 18, 13, 10, 2, 3, 7, 8, 14, 12}

// Visit struct used for storing legs
type Visit struct {
ID int `json:"id"`
Expand Down

0 comments on commit 409e4f8

Please sign in to comment.