From 544f40fa6362f585ba7d28f32b653cd323decb66 Mon Sep 17 00:00:00 2001 From: Evan Burkey Date: Mon, 10 Mar 2025 08:21:59 -0700 Subject: [PATCH] init --- .gitignore | 2 + go.mod | 3 ++ main.go | 35 +++++++++++++ parser.go | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 183 insertions(+) create mode 100644 .gitignore create mode 100644 go.mod create mode 100644 main.go create mode 100644 parser.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c7042f8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +WoWChatLog.txt +.idea \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..0605659 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module gamboupload + +go 1.24 diff --git a/main.go b/main.go new file mode 100644 index 0000000..35f3417 --- /dev/null +++ b/main.go @@ -0,0 +1,35 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "log" + "os" + "strings" +) + +func main() { + b, err := os.ReadFile("WoWChatLog.txt") + if err != nil { + log.Fatal(err) + } + + // Strip carriage returns because Windows is retarded + b = bytes.ReplaceAll(b, []byte("\r"), []byte("")) + + lines := strings.Split(string(b), "\n") + + games, err := parseGames(lines) + if err != nil { + log.Fatal(err) + } + + for _, game := range games { + j, err := json.Marshal(game) + if err != nil { + log.Fatal(err) + } + fmt.Println(string(j)) + } +} diff --git a/parser.go b/parser.go new file mode 100644 index 0000000..ceae200 --- /dev/null +++ b/parser.go @@ -0,0 +1,143 @@ +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"` +} + +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) + 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] + + return g, i, nil +}