11 "github.com/jmoiron/sqlx"
15 const DefaultStartGameID = 0
16 const DefaultEndGameID = -1
17 const DefaultRankingWindowDays = 7
20 // database connection string
23 // the starting game_id in the games table
26 // the ending game_id in the games table
29 // the number of days constituting the ranking window
33 func loadConfig(path string) (*Config, error) {
37 config.ConnStr = "user=xonstat host=localhost dbname=xonstatdb sslmode=disable"
38 config.StartGameID = DefaultStartGameID
39 config.EndGameID = DefaultEndGameID
40 config.RankingWindowDays = DefaultRankingWindowDays
42 file, err := os.Open(path)
44 fmt.Println("Failed opening the file.")
48 decoder := json.NewDecoder(file)
50 // overwrite in-mem config with new values
51 err = decoder.Decode(config)
53 fmt.Println("Failed to decode the JSON.")
61 GameID int `db:"game_id"`
62 GameType string `db:"game_type_cd"`
63 ServerID int `db:"server_id"`
64 Duration int `db:"duration"`
65 CreateDt time.Time `db:"create_dt"`
68 type PlayerGameStat struct {
69 PlayerGameStatID int `db:"player_game_stat_id"`
70 PlayerID int `db:"player_id"`
71 GameID int `db:"game_id"`
72 Nick string `db:"stripped_nick"`
73 AliveTime int `db:"alivetime"`
74 Score int `db:"score"`
77 type GameProcessor struct {
82 func NewGameProcessor(config *Config) *GameProcessor {
83 processor := new(GameProcessor)
85 processor.config = config
87 db, err := sqlx.Connect("postgres", config.ConnStr)
96 func (gp *GameProcessor) GamesInRange() []Game {
99 sql := `select game_id, game_type_cd, server_id, EXTRACT(EPOCH FROM duration) duration,
100 create_dt from games where game_id between $1 and $2 order by game_id`
102 err := gp.db.Select(&games, sql, gp.config.StartGameID, gp.config.EndGameID)
104 log.Fatalf("Unable to select games: %s.\n", err)
110 func (gp *GameProcessor) PlayerGameStats(gameID int) []PlayerGameStat {
111 pgstats := []PlayerGameStat{}
113 sql := `select player_game_stat_id, player_id, game_id, stripped_nick,
114 EXTRACT(EPOCH from alivetime) alivetime, score from player_game_stats
115 where game_id = $1 and player_id > 2 order by player_game_stat_id`
117 err := gp.db.Select(&pgstats, sql, gameID)
119 log.Fatalf("Unable to select player_game_stats for game %d: %s.\n", gameID, err)
126 path := flag.String("config", "xs_glicko.json", "configuration file path")
127 start := flag.Int("start", DefaultStartGameID, "starting game_id")
128 end := flag.Int("end", DefaultEndGameID, "ending game_id")
129 days := flag.Int("days", DefaultRankingWindowDays, "number of days in the ranking window")
132 config, err := loadConfig(*path)
134 log.Fatalf("Unable to load config file: %s.\n", err)
137 if *start != DefaultStartGameID {
138 config.StartGameID = *start
141 if *end != DefaultEndGameID {
142 config.EndGameID = *end
145 if *days != DefaultRankingWindowDays {
146 config.RankingWindowDays = *days
149 processor := NewGameProcessor(config)
150 for _, game := range processor.GamesInRange() {
151 pgstats := processor.PlayerGameStats(game.GameID)