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)
			}
		}
	}
}
Exemple #2
0
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)
				}

			}
		}
	}
}