func (v *Visits) Start() { for { in := <-v.events if ev, ok := in.(cod.Join); ok { if exists(v.db, ev.GUID) { // update log.Println("visits: updating total for player", ev.GUID) _, err := v.db.Exec("update visits set total = total + 1 where players_id = ?;", ev.GUID) if err != nil { log.Fatal("visits: fatal error in update:", err) } } else { // insert new log.Println("visits: inserting player", ev.GUID, "into database") _, err := v.db.Exec("insert into visits(players_id) values(?);", ev.GUID) if err != nil { log.Fatal("visits: fatal error in insert:", err) } } var total int err := v.db.QueryRow("select total from visits where players_id = ?", ev.GUID).Scan(&total) if err != nil { total = 1 } var msg string if total != 1 { msg = fmt.Sprintf(v.cfg.Message, ev.Name, total) } else { msg = fmt.Sprintf(v.cfg.FirstMessage, ev.Name) } if num, ok := integrated.Num(ev.GUID); ok { log.Println("visits: welcoming player with guid", ev.GUID, "and num", num) v.requests <- rcon.RCONQuery{Command: "tell " + strconv.Itoa(num) + " " + v.cfg.Prefix + msg, Response: nil} } else { log.Println("visits: could not resolve num for player", ev.GUID) } } } }
func (s *Stats) Start() { currentStats := make(map[string]*playerStats) currentStartedAt := time.Now().Unix() var currentMap string for { ev := <-s.events switch ev := ev.(type) { case cod.InitGame: currentStats = make(map[string]*playerStats) currentStartedAt = ev.Unix currentMap = "mp_backlot" // TODO extract from initgame case cod.ExitLevel: if len(currentStats) > 0 { // write to db log.Println("stats: inserting game", currentStartedAt, "into database") _, err := s.db.Exec("insert into games(started_at, ended_at, mapname) values (?, ?, ?);", currentStartedAt, ev.Unix, currentMap) if err != nil { log.Fatal("stats: failed to insert games", err) } for k, v := range currentStats { log.Println("stats: inserting stats for player", k, "into database") _, err = s.db.Exec("insert into stats(games_started_at, players_id, kills, deaths, assists) values(?, ?, ?, ?, ?);", currentStartedAt, k, v.Kills, v.Deaths, v.Assists) if err != nil { log.Fatal("stats: failed to insert stats for player", k, err) } } } case cod.ShutdownGame: // shutdowngame vs exitlevel? case cod.Kill: // TODO suicide if ev.GUIDA == ev.GUIDB { if ev.DamageDealt == 100000 && ev.MOD == "MOD_SUICIDE" { // team switch break } // suicide } if s, ok := currentStats[ev.GUIDA]; ok { s.Deaths = s.Deaths + 1 } else { s = &playerStats{Kills: 0, Deaths: 1, Assists: 0} currentStats[ev.GUIDA] = s } if r, ok := currentStats[ev.GUIDB]; ok { r.Kills = r.Kills + 1 } else { r := &playerStats{Kills: 1, Deaths: 0, Assists: 0} currentStats[ev.GUIDB] = r } case cod.Damage: // not yet implemented (used for assists) case cod.Say: if strings.HasPrefix(ev.Message, "!stats") || strings.HasPrefix(ev.Message[1:], "!stats") { var kills int var deaths int var assists int log.Println("stats: calculating stats for player", ev.GUID) err := s.db.QueryRow("select sum(s.kills), sum(s.deaths), sum(s.assists) "+ "from stats s where s.players_id = ?", ev.GUID).Scan(&kills, &deaths, &assists) if err != nil { log.Println("stats: could not sum up stats for player", ev.GUID) } if num, ok := integrated.Num(ev.GUID); ok { log.Println("stats: showing stats to player with guid", ev.GUID, "and num", num) s.requests <- rcon.RCONQuery{Command: "tell " + strconv.Itoa(num) + " " + s.cfg.Prefix + fmt.Sprintf("Kills: %d Deaths: %d Assists: %d", kills, deaths, assists), Response: nil} } else { log.Println("stats: could not resolve num for player", ev.GUID) } } } } }