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 }