init
This commit is contained in:
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
WoWChatLog.txt
 | 
			
		||||
.idea
 | 
			
		||||
							
								
								
									
										35
									
								
								main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								main.go
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										143
									
								
								parser.go
									
									
									
									
									
										Normal 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
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user