151 lines
3.0 KiB
Go
151 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
gameTypeUnknown = iota
|
|
gameTypeClassic
|
|
)
|
|
|
|
type Game struct {
|
|
Timestamp time.Time `json:"timestamp"`
|
|
GameType int `json:"game_type"`
|
|
Wager int `json:"wager"`
|
|
Winner string `json:"winner"`
|
|
Loser string `json:"loser"`
|
|
HighRoll int `json:"high_roll"`
|
|
LowRoll int `json:"low_roll"`
|
|
Payout int `json:"payout"`
|
|
Players []string `json:"players"`
|
|
}
|
|
|
|
var (
|
|
reTimeStamp = regexp.MustCompile(`(\d/\d \d+:\d+:\d+.\d+)`)
|
|
reGameStart = regexp.MustCompile(`WoWGoldGambler: A new game has been started`)
|
|
reWager = regexp.MustCompile(`Game Mode - ([A-Z]+) - Wager - ([\d,]+)g$`)
|
|
reSignup = regexp.MustCompile(`([\p{L}']+)-[\p{L}'0-9]+: (1|-1)`)
|
|
reRoll = regexp.MustCompile(`([\p{L}']+) rolls (\d+) \(1-(\d+)\)$`)
|
|
reEnd = regexp.MustCompile(`([\p{L}']+) owes ([\p{L}']+) ([\d,]+) gold!`)
|
|
)
|
|
|
|
func parseGames(lines []string) ([]Game, error) {
|
|
games := make([]Game, 0)
|
|
var err error
|
|
|
|
i := 0
|
|
for i < len(lines) {
|
|
if reGameStart.MatchString(lines[i]) {
|
|
var game Game
|
|
game, i, err = parse(lines, i)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
games = append(games, game)
|
|
}
|
|
i++
|
|
}
|
|
|
|
return games, nil
|
|
}
|
|
|
|
func parse(lines []string, i int) (Game, int, error) {
|
|
var (
|
|
g Game
|
|
err error
|
|
)
|
|
|
|
// Timestamp
|
|
ts := reTimeStamp.FindString(lines[i])
|
|
if ts == "" {
|
|
return g, i, fmt.Errorf("failed to extract timestamp from %s", lines[i])
|
|
}
|
|
g.Timestamp, err = time.Parse("1/2 15:04:05.000", ts)
|
|
g.Timestamp = time.Date(time.Now().Year(), g.Timestamp.Month(), g.Timestamp.Day(), g.Timestamp.Hour(), g.Timestamp.Minute(), g.Timestamp.Second(), 0, time.UTC)
|
|
if err != nil {
|
|
return g, i, err
|
|
}
|
|
|
|
// Wager
|
|
i++
|
|
matches := reWager.FindStringSubmatch(lines[i])
|
|
switch matches[1] {
|
|
case "CLASSIC":
|
|
g.GameType = gameTypeClassic
|
|
default:
|
|
g.GameType = gameTypeUnknown
|
|
}
|
|
g.Wager, err = strconv.Atoi(strings.ReplaceAll(matches[2], ",", ""))
|
|
if err != nil {
|
|
return g, i, err
|
|
}
|
|
|
|
// Registration
|
|
for {
|
|
if strings.Contains(lines[i], "Registration has ended") {
|
|
break
|
|
}
|
|
i++
|
|
}
|
|
|
|
// Capture Rolls
|
|
rolls := make(map[string]int)
|
|
for {
|
|
if reEnd.MatchString(lines[i]) {
|
|
break
|
|
}
|
|
|
|
rollMatches := reRoll.FindStringSubmatch(lines[i])
|
|
if rollMatches == nil {
|
|
i++
|
|
continue
|
|
}
|
|
|
|
v, err := strconv.Atoi(rollMatches[3])
|
|
if err != nil {
|
|
return g, i, err
|
|
}
|
|
if v != g.Wager {
|
|
i++
|
|
continue
|
|
}
|
|
|
|
// Ignore extra rolls
|
|
if _, ok := rolls[rollMatches[1]]; !ok {
|
|
val, err := strconv.Atoi(rollMatches[2])
|
|
if err != nil {
|
|
return g, i, err
|
|
}
|
|
rolls[rollMatches[1]] = val
|
|
}
|
|
|
|
i++
|
|
}
|
|
|
|
endMatches := reEnd.FindStringSubmatch(lines[i])
|
|
p := strings.ReplaceAll(endMatches[3], ",", "")
|
|
payout, err := strconv.Atoi(p)
|
|
if err != nil {
|
|
return g, i, err
|
|
}
|
|
g.Payout = payout
|
|
|
|
g.Winner = endMatches[2]
|
|
g.HighRoll = rolls[g.Winner]
|
|
|
|
g.Loser = endMatches[1]
|
|
g.LowRoll = rolls[g.Loser]
|
|
|
|
g.Players = make([]string, 0)
|
|
for pl, _ := range rolls {
|
|
g.Players = append(g.Players, pl)
|
|
}
|
|
|
|
return g, i, nil
|
|
}
|