This commit is contained in:
Evan Burkey 2025-03-10 08:21:59 -07:00
commit 544f40fa63
4 changed files with 183 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
WoWChatLog.txt
.idea

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module gamboupload
go 1.24

35
main.go Normal file
View File

@ -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))
}
}

143
parser.go Normal file
View File

@ -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
}