Skip to content

Commit

Permalink
map vote stats added, more detailed map stats in UI
Browse files Browse the repository at this point in the history
  • Loading branch information
Harrison-Miller committed May 24, 2020
1 parent 78c0a3c commit 44ac2f2
Show file tree
Hide file tree
Showing 12 changed files with 163 additions and 31 deletions.
9 changes: 8 additions & 1 deletion api/maps.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import (
type MapBasics struct {
MapName string `json:"mapName" db:"mapName"`
Average float32 `json:"average"`
Stddev float32 `json:"stddev" db:"stddev"`
Matches int64 `json:"matches"`
Ballots int64 `json:"ballots"`
Votes int64 `json:"votes"`
Wins int64 `json:"wins"`
}

func MapsRoutes(r *mux.Router) {
Expand All @@ -19,7 +23,10 @@ func MapsRoutes(r *mux.Router) {

func getMaps(w http.ResponseWriter, r *http.Request) {
var m []MapBasics
err := db.Select(&m, `SELECT mapName, ROUND((AVG(ticks)/30)/60) AS average, COUNT(mapName) AS matches FROM map_stats group by mapName`)
err := db.Select(&m, `SELECT map_stats.mapName, average, stddev, matches, ballots, votes, wins
FROM (SELECT mapName, ROUND((AVG(ticks)/30)/60) AS average, ROUND(STDDEV((ticks/30)/60)) AS stddev, COUNT(mapName) AS matches
FROM map_stats GROUP BY mapName) as map_stats JOIN map_vote_stats ON map_stats.mapName=map_vote_stats.mapName;
`)
if err != nil {
http.Error(w, fmt.Sprintf("could not get basic map stats: %v", err), http.StatusInternalServerError)
return
Expand Down
11 changes: 11 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,17 @@ services:
links:
- mysql
restart: always
mapvotes-indexer:
build:
context: .
dockerfile: Dockerfile-indexer
args:
indexer: mapvotes
VERSION: ${TAG:-latest}
image: gcr.io/kagstats/mapvotes-indexer:${TAG:-latest}
links:
- mysql
restart: always
apicache:
build:
context: .
Expand Down
6 changes: 3 additions & 3 deletions indexer/basic/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ func (i *BasicIndexer) Index(kill Kill) []Index {
if kill.KillerID != kill.VictimID {
if kill.TeamKill {
indices = append(indices, Index{
Keys: []int{int(kill.KillerID)},
Keys: []interface{}{int(kill.KillerID)},
Counters: map[string]int{"teamkills": 1},
})
} else {
indices = append(indices, Index{
Keys: []int{int(kill.KillerID)},
Keys: []interface{}{int(kill.KillerID)},
Counters: map[string]int{
"archer_kills": OneIfEqual(kill.KillerClass, "archer"),
"builder_kills": OneIfEqual(kill.KillerClass, "builder"),
Expand All @@ -84,7 +84,7 @@ func (i *BasicIndexer) Index(kill Kill) []Index {

if !kill.TeamKill {
indices = append(indices, Index{
Keys: []int{int(kill.VictimID)},
Keys: []interface{}{int(kill.VictimID)},
Counters: map[string]int{
"suicides": ToInt(kill.KillerID == kill.VictimID),
"archer_deaths": OneIfEqual(kill.VictimClass, "archer"),
Expand Down
5 changes: 1 addition & 4 deletions indexer/harness.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,7 @@ func Run(indexer Indexer) error {
var processed int
var err error

switch indexer.(type) {
case KillsIndexer:
processed, err = Process(indexer.(KillsIndexer), config.Indexer.BatchSize, db)
}
processed, err = Process(indexer, config.Indexer.BatchSize, db)

if err != nil {
log.Println(err)
Expand Down
2 changes: 1 addition & 1 deletion indexer/hitters/hitters.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (i *HittersIndexer) Index(kill Kill) []Index {
}

indices = append(indices, Index{
Keys: []int{int(kill.KillerID), int(kill.Hitter)},
Keys: []interface{}{int(kill.KillerID), int(kill.Hitter)},
Counters: map[string]int{"kills": 1},
})
}
Expand Down
68 changes: 53 additions & 15 deletions indexer/indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ type IndexKey struct {
Name string
Table string
Column string
Type string
}

type Index struct {
Keys []int
Keys []interface{}
Counters map[string]int
}

func Equal(a []int, b []int) bool {
func Equal(a []interface{}, b []interface{}) bool {
if len(a) != len(b) {
return false
}
Expand Down Expand Up @@ -60,6 +61,21 @@ type KillsIndexer interface {
Index(kill Kill) []Index
}

type MapVotesIndexer interface {
Indexer
Index(votes MapVotes) []Index
}

func GetIndexedTable(indexer Indexer) string {
if _, ok := indexer.(KillsIndexer); ok {
return "kills"
} else if _, ok := indexer.(MapVotesIndexer); ok {
return "map_votes"
}

return "kills"
}

func BuildTable(indexer Indexer) string {
keys := indexer.Keys()
var keyNames []string
Expand All @@ -68,7 +84,11 @@ func BuildTable(indexer Indexer) string {
fmt.Fprintf(&b, "CREATE TABLE IF NOT EXISTS %s (", indexer.Name())

for _, k := range keys {
fmt.Fprintf(&b, "%s INT NOT NULL,", k.Name)
t := "INT"
if k.Type != "" {
t = k.Type
}
fmt.Fprintf(&b, "%s %s NOT NULL,", k.Name, t)
if k.Table != "" && k.Column != "" {
fmt.Fprintf(&b, "FOREIGN KEY(%s) REFERENCES %s(%s) ON DELETE CASCADE,", k.Name, k.Table, k.Column)
}
Expand Down Expand Up @@ -147,8 +167,10 @@ func UnprocessedRows(indexer Indexer, batchSize int, tx *sql.Tx) (int64, *sql.Ro
return 0, nil, err
}

indexedTable := GetIndexedTable(indexer)

upperBound := currentIndex + int64(batchSize) + 1
rows, err := tx.Query("SELECT * from kills WHERE ID>? AND ID<?", currentIndex, upperBound)
rows, err := tx.Query("SELECT * from "+indexedTable+" WHERE ID>? AND ID<?", currentIndex, upperBound)
return currentIndex, rows, err
}

Expand Down Expand Up @@ -211,7 +233,7 @@ func SkipKill(kill models.Kill, db *sqlx.DB) bool {
return false
}

func Process(indexer KillsIndexer, batchSize int, db *sqlx.DB) (int, error) {
func Process(indexer Indexer, batchSize int, db *sqlx.DB) (int, error) {
tx, err := db.Begin()
defer tx.Rollback()
if err != nil {
Expand All @@ -227,17 +249,33 @@ func Process(indexer KillsIndexer, batchSize int, db *sqlx.DB) (int, error) {
newIndex := currentIndex
updates := make(map[string]Index)
for rows.Next() {
var kill Kill
if err := rows.Scan(&kill.ID, &kill.KillerID, &kill.VictimID, &kill.KillerClass,
&kill.VictimClass, &kill.Hitter, &kill.Time, &kill.ServerID, &kill.TeamKill); err != nil {
return 0, err
}
nextIndex := newIndex
var indices []Index

if killsIndexer, ok := indexer.(KillsIndexer); ok {
var kill Kill
if err := rows.Scan(&kill.ID, &kill.KillerID, &kill.VictimID, &kill.KillerClass,
&kill.VictimClass, &kill.Hitter, &kill.Time, &kill.ServerID, &kill.TeamKill); err != nil {
return 0, err
}

if SkipKill(kill, db) {
continue
}

indices = killsIndexer.Index(kill)
nextIndex = kill.ID
} else if mapVotesIndexer, ok := indexer.(MapVotesIndexer); ok {
var votes MapVotes
if err := rows.Scan(&votes.ID, &votes.Map1Name, &votes.Map1Votes, &votes.Map2Name,
&votes.Map2Votes, &votes.RandomVotes); err != nil {
return 0, err
}

if SkipKill(kill, db) {
continue
indices = mapVotesIndexer.Index(votes)
nextIndex = votes.ID
}

indices := indexer.Index(kill)
for _, index := range indices {
if len(index.Keys) != len(indexer.Keys()) {
return 0, fmt.Errorf("Indexer failed to return the correct number of keys\n\texpected: %d got %d", len(indexer.Keys()), len(index.Keys))
Expand All @@ -255,8 +293,8 @@ func Process(indexer KillsIndexer, batchSize int, db *sqlx.DB) (int, error) {
updates[mapKey] = index
}

if kill.ID > newIndex {
newIndex = kill.ID
if nextIndex > newIndex {
newIndex = nextIndex
}

}
Expand Down
68 changes: 68 additions & 0 deletions indexer/mapvotes/mapvotes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package main

import (
"log"

. "github.com/Harrison-Miller/kagstats/common/models"
. "github.com/Harrison-Miller/kagstats/indexer"
)

type MapVoteStatsIndexer struct {
}

func (i *MapVoteStatsIndexer) Name() string {
return "map_vote_stats"
}

func (i *MapVoteStatsIndexer) Version() int {
return 1
}

func (i *MapVoteStatsIndexer) Keys() []IndexKey {
var keys []IndexKey
keys = append(keys, IndexKey{
Name: "mapName",
Type: "varchar(255)",
})
return keys
}

func (i *MapVoteStatsIndexer) Counters() []string {
return []string{"ballots", "votes", "wins"}
}

func OneIfGreater(a int64, b int64, c int64) int {
if a > b && a > c {
return 1
}

return 0
}

func (i *MapVoteStatsIndexer) Index(votes MapVotes) []Index {
var indices []Index

indices = append(indices, Index{
Keys: []interface{}{votes.Map1Name},
Counters: map[string]int{"ballots": 1,
"votes": int(votes.Map1Votes),
"wins": OneIfGreater(votes.Map1Votes, votes.Map2Votes, votes.RandomVotes)},
})

indices = append(indices, Index{
Keys: []interface{}{votes.Map2Name},
Counters: map[string]int{"ballots": 1,
"votes": int(votes.Map2Votes),
"wins": OneIfGreater(votes.Map2Votes, votes.Map1Votes, votes.RandomVotes)},
})

return indices
}

func main() {
indexer := MapVoteStatsIndexer{}
err := Run(&indexer)
if err != nil {
log.Fatal(err)
}
}
6 changes: 3 additions & 3 deletions indexer/monthly/monthly.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,12 @@ func (i *MonthlyIndexer) Index(kill Kill) []Index {
if kill.KillerID != kill.VictimID {
if kill.TeamKill {
indices = append(indices, Index{
Keys: []int{int(kill.KillerID), year, int(month)},
Keys: []interface{}{int(kill.KillerID), year, int(month)},
Counters: map[string]int{"teamkills": 1},
})
} else {
indices = append(indices, Index{
Keys: []int{int(kill.KillerID), year, int(month)},
Keys: []interface{}{int(kill.KillerID), year, int(month)},
Counters: map[string]int{
"archer_kills": OneIfEqual(kill.KillerClass, "archer"),
"builder_kills": OneIfEqual(kill.KillerClass, "builder"),
Expand All @@ -93,7 +93,7 @@ func (i *MonthlyIndexer) Index(kill Kill) []Index {

if !kill.TeamKill {
indices = append(indices, Index{
Keys: []int{int(kill.VictimID), year, int(month)},
Keys: []interface{}{int(kill.VictimID), year, int(month)},
Counters: map[string]int{
"suicides": ToInt(kill.KillerID == kill.VictimID),
"archer_deaths": OneIfEqual(kill.VictimClass, "archer"),
Expand Down
2 changes: 1 addition & 1 deletion indexer/nemesis/nemesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func (i *NemesisIndexer) Index(kill Kill) []Index {

if kill.KillerID != kill.VictimID && !kill.TeamKill {
indices = append(indices, Index{
Keys: []int{int(kill.VictimID), int(kill.KillerID)},
Keys: []interface{}{int(kill.VictimID), int(kill.KillerID)},
Counters: map[string]int{"deaths": 1},
})
}
Expand Down
7 changes: 7 additions & 0 deletions ui/src/app/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,15 @@ export interface PagedResult<T> {
export interface MapBasics {
mapName: string;
average: number;
stddev: number;
matches: number;
ballots: number;
votes: number;
wins: number;

// used for UI only
image: string;
percent: number;
}

export interface GithubTreeEntry {
Expand Down
4 changes: 3 additions & 1 deletion ui/src/app/pages/maps/maps.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ <h2>Maps</h2>
{{map.mapName}}
</div>
<div class="card-body card-overflow">
<div>Average Match Duration: {{map.average}} minutes</div>
<div>Match Duration: {{map.average}} &#177; {{map.stddev}} minutes</div>
<div>Total Matches: {{map.matches}}</div>
<div>Vote Win Percent: {{map.percent}}%</div>
<div>Votes Appeared In: {{map.ballots}}</div>
<div>
<img class="minimap" src="{{map.image}}" onError="this.src='/assets/unkownmap.png'">
</div>
Expand Down
6 changes: 4 additions & 2 deletions ui/src/app/pages/maps/maps.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@ export class MapsComponent implements OnInit {
maps => {
this.maps = maps;
this.maps.sort((a,b) => {
return b.matches - a.matches;
a.percent = Math.floor(a.wins / a.ballots * 100)
b.percent = Math.floor(b.wins / b.ballots * 100)
return b.percent - a.percent;
});
this.mapsService.getMapPaths().subscribe(
paths => {
this.paths = paths;
for(var map of maps) {
for(var p of this.paths.tree) {
if(p.path.endsWith(map.mapName + ".png")) {
if(p.path.toLowerCase().endsWith(map.mapName.toLowerCase() + ".png")) {
map.image = "https://raw.githubusercontent.com/transhumandesign/kag-base/master/" + p.path;
}
}
Expand Down

0 comments on commit 44ac2f2

Please sign in to comment.