best and worst stats

This commit is contained in:
Michael Simard
2021-01-10 09:44:21 -06:00
parent a3977ac3ac
commit f974477106
5 changed files with 252 additions and 67 deletions

View File

@@ -24,8 +24,6 @@ struct StatsController: RouteCollection {
statsRoute.post("logMatch", use: logMatch)
statsRoute.get("history","page",":page", use: history)
statsRoute.get("history", use: history)
}
@@ -82,8 +80,7 @@ struct StatsController: RouteCollection {
let winCount = totals[0]
let lossCount = totals[1]
let ratio = self.getRatio(num: Double(winCount), den: Double(lossCount))
return Stats(winLoss: ratio, totalWins: Int(winCount), totalLosses: Int(lossCount))
return Stats( totalWins: Int(winCount), totalLosses: Int(lossCount))
}
func getStatsWithMostRecentDailyRecord(matches:[Match], game:String? = nil) -> StatsWithMostRecentDailyRecord {
@@ -109,15 +106,15 @@ struct StatsController: RouteCollection {
self.shouldCountMatch(match: match)
if let game = game {
// if game == "mw" {
// shouldInclude = shouldInclude && match.codGame == "mw"
// }
// else if game == "bocw" {
// shouldInclude = shouldInclude && match.codGame == "bocw"
//
// }else {
//
// }
// if game == "mw" {
// shouldInclude = shouldInclude && match.codGame == "mw"
// }
// else if game == "bocw" {
// shouldInclude = shouldInclude && match.codGame == "bocw"
//
// }else {
//
// }
shouldInclude = shouldInclude && match.codGame == game
}
@@ -260,16 +257,16 @@ struct StatsController: RouteCollection {
// print ( Date().timeIntervalSince(startTime))
// let cumulativeWinLossRatios = self.getCumulativeWinLossRatios(matches: matches)
// let cumulativeWinLossRatios = self.getCumulativeWinLossRatios(matches: matches)
// print ( Date().timeIntervalSince(startTime))
// let highestWinLossRatio = cumulativeWinLossRatios.reduce("0") { (highestRatio, dataPoint) -> String in
// if dataPoint.y > Double(highestRatio)!{
// return String(dataPoint.y)
// }
// return highestRatio
// }
// let highestWinLossRatio = cumulativeWinLossRatios.reduce("0") { (highestRatio, dataPoint) -> String in
// if dataPoint.y > Double(highestRatio)!{
// return String(dataPoint.y)
// }
// return highestRatio
// }
// print ( Date().timeIntervalSince(startTime))
@@ -356,8 +353,7 @@ struct StatsController: RouteCollection {
let combined = winCount.and(lossCount)
return combined.map { (winCount, lossCount) -> (Stats) in
let ratio:Double = (Double(winCount) / Double(lossCount)).truncate(places: 2)
return Stats.init(winLoss: String(ratio), totalWins: winCount, totalLosses: lossCount)
return Stats.init( totalWins: winCount, totalLosses: lossCount)
}
}
@@ -380,7 +376,7 @@ struct StatsController: RouteCollection {
return combined.map { (winCount, lossCount) -> (Stats) in
return Stats.init(winLoss: self.getRatio(num: Double(winCount), den: Double(lossCount)), totalWins: winCount, totalLosses: lossCount)
return Stats.init(totalWins: winCount, totalLosses: lossCount)
}
}
@@ -403,8 +399,7 @@ struct StatsController: RouteCollection {
let combined = winCount.and(lossCount)
return combined.map { (winCount, lossCount) -> (Stats) in
let ratio:Double = (Double(winCount) / Double(lossCount)).truncate(places: 2)
return Stats.init(winLoss: String(ratio), totalWins: winCount, totalLosses: lossCount)
return Stats.init(totalWins: winCount, totalLosses: lossCount)
}
}
@@ -557,7 +552,7 @@ struct StatsController: RouteCollection {
let hyderStats = hyderFuture.map { (withHyder, withoutHyder) -> [Stats] in
return [withHyder, withoutHyder]
}
}
let matches = Match.query(on: req.db).all()
@@ -597,30 +592,83 @@ struct StatsController: RouteCollection {
}
group.enter()
queue.async {
mostRecentStats = self.mostRecentDailyStats(matches: matches)
group.leave()
}
// group.enter()
// queue.async {
// mostRecentStats = self.mostRecentDailyStats(matches: matches)
// group.leave()
// }
group.wait()
let mapStats = getMapStats(matches: matches)
let bestMap = getBestMap(records: mapStats)
let worstMap = getWorstMap(records: mapStats)
let dashboardItems = [
DashboardItem(title: "Overall", content: overallStats!.record, title2: "Ratio", content2: overallStats!.winLossRatio),
DashboardItem(title: "MW Overall", content: mwStats!.record, title2: "Ratio", content2: mwStats!.winLossRatio),
DashboardItem(title: "Cold War Overall", content: bocwStats!.record, title2: "Ratio", content2: bocwStats!.winLossRatio),
DashboardItem(title: "With Hyder", content: hyderStats[0].record, title2: "Ratio", content2: hyderStats[0].winLossRatio),
DashboardItem(title: "No Hyder", content: hyderStats[1].record, title2: "Ratio", content2: hyderStats[1].winLossRatio),
DashboardItem(title: "Best Map", content: MapData.allMaps[bestMap]?.name ?? "error", title2: "Ratio", content2: "\(mapStats[bestMap]!.winLossRatio) \(mapStats[bestMap]!.record)"),
DashboardItem(title: "Worst Map", content: MapData.allMaps[worstMap]?.name ?? "error", title2: "Ratio", content2: "\(mapStats[worstMap]!.winLossRatio) \(mapStats[worstMap]!.record)"),
]
return OverallStats(overall: overallStats!, mwStats: mwStats!, bocwStats: bocwStats!, mostRecentRecord: "\(mostRecentStats!.totalWins) - \(mostRecentStats!.totalLosses)", statsWithHyder:hyderStats[0], statsWithoutHyder: hyderStats[1])
return OverallStats(overall: overallStats!, mwStats: mwStats!, bocwStats: bocwStats!, mostRecentRecord: "Temporarily Unavailable", statsWithHyder:hyderStats[0], statsWithoutHyder: hyderStats[1], dashboardItems:dashboardItems)
}
// return Match.query(on: req.db).all().map { (matches) -> OverallStats in
//
//
// }
// return Match.query(on: req.db).all().map { (matches) -> OverallStats in
//
//
// }
}
func getBestMap (records :[ Int:Stats] ) -> Int {
let maps = records.keys.sorted { (map1, map2) -> Bool in
return records[map1]?.getRatioDouble() ?? 0.0 < records[map2]?.getRatioDouble() ?? 0.0
}
return maps.last ?? -1
}
func getWorstMap (records :[ Int:Stats] ) -> Int {
let maps = records.keys.sorted { (map1, map2) -> Bool in
return records[map1]?.getRatioDouble() ?? 0.0 < records[map2]?.getRatioDouble() ?? 0.0
}
return maps.first ?? -1
}
func getMapStats(matches:[Match]) -> [Int:Stats] {
var mapStats:[Int:Stats] = [Int:Stats]()
for match in matches {
if match.codGame == "mw" {
if let map = match.map, let mapInt = Int(map) {
if mapStats[mapInt] == nil {
mapStats[mapInt] = Stats(totalWins: 0, totalLosses: 0)
}
if match.win {
mapStats[mapInt]?.totalWins += 1
}
else{
mapStats[mapInt]?.totalLosses += 1
}
}
}
}
return mapStats
}
func statsWithPlayer(req: Request, playerId:Int) -> EventLoopFuture<Stats> {
return Match.query(on: req.db)
@@ -629,7 +677,7 @@ struct StatsController: RouteCollection {
return self.getStats(matches: matches)
}
}
}
func statsWithoutPlayer (req: Request, playerId:Int) -> EventLoopFuture<Stats> {
return Match.query(on: req.db)
@@ -640,19 +688,7 @@ struct StatsController: RouteCollection {
}
private func getRatio( num:Double, den:Double) -> String {
var returnString = ""
let deno = (den != 0) ? den : 1
returnString = String((Double(num) / Double(deno)).truncate(places: 2))
if den == 0 {
returnString = returnString + "+"
}
return returnString
}
private func getDaysPlayed(req:Request) -> EventLoopFuture<[CODDate]> {
@@ -722,6 +758,20 @@ struct StatsController: RouteCollection {
}
}
private func getRatio( num:Double, den:Double) -> String {
var returnString = ""
let deno = (den != 0) ? den : 1
returnString = String((Double(num) / Double(deno)).truncate(places: 2))
if den == 0 {
returnString = returnString + "+"
}
return returnString
}
func getCumulativeWinLossRatios(req:Request) -> EventLoopFuture<[DataPoint]> {

View File

@@ -0,0 +1,69 @@
//
// MapData.swift
// App
//
// Created by Michael Simard on 1/10/21.
//
import Foundation
class MapData {
static let allMaps:[Int:Map] = [
0: Map(id: 0, name: "Satellite", imageName: "bocw_satellite"),
1: Map(id: 1, name: "Armada", imageName: "bocw_armada"),
2: Map(id: 2, name: "Nuketown", imageName: "bocw_nuketown"),
3: Map(id: 3, name: "Cartel", imageName: "bocw_cartel"),
4: Map(id: 4, name: "Garrison", imageName: "bocw_garrison"),
5: Map(id: 5, name: "Miami", imageName: "bocw_miami"),
6: Map(id: 6, name: "Moscow", imageName: "bocw_moscow"),
7: Map(id: 7, name: "Crossroads", imageName: "bocw_crossroads"),
8: Map(id: 8, name: "Checkmate", imageName: "bocw_checkmate"),
9: Map(id: 9, name: "Arklov Peak", imageName: "mw_arklov"),
10: Map(id: 10, name: "Atlas Superstore", imageName: "mw_atlas"),
11: Map(id: 11, name: "Talsik Backlot", imageName: "mw_backlot"),
12: Map(id: 12, name: "Broadcast", imageName: "mw_broadcast"),
13: Map(id: 13, name: "Azhir Cave", imageName: "mw_caves"),
14: Map(id: 14, name: "Chesire Park", imageName: "mw_chesire"),
15: Map(id: 15, name: "Crash", imageName: "mw_crash"),
28: Map(id: 28, name: "Gun Runner", imageName: "mw_gunrunner"),
16: Map(id: 16, name: "Hackney Yard", imageName: "mw_hackney"),
17: Map(id: 17, name: "Suldal Harbor", imageName: "mw_harbor"),
18: Map(id: 18, name: "Hardhat", imageName: "mw_hardhat"),
19: Map(id: 19, name: "Hovec Sawmill", imageName: "mw_hovec"),
20: Map(id: 20, name: "Khandor Hideout", imageName: "mw_khandor"),
21: Map(id: 21, name: "Petrov Oil Rig", imageName: "mw_oil"),
22: Map(id: 22, name: "St. Petrograd", imageName: "mw_petrograd"),
23: Map(id: 23, name: "Rammaza", imageName: "mw_rammaza"),
24: Map(id: 24, name: "Scrapyard", imageName: "mw_scrapyard"),
25: Map(id: 25, name: "Shoot House", imageName: "mw_shoothouse"),
26: Map(id: 26, name: "Mialstor Tank Factory", imageName: "mw_tank"),
27: Map(id: 27, name: "Vacant", imageName: "mw_vacant"),
31: Map(id: 31, name: "The Pines", imageName: "bocw_pines"),
29: Map(id: 29, name: "Nuketown Holiday", imageName: "bocw_nuketown_holiday"),
30: Map(id: 30, name: "Raid", imageName: "bocw_raid"),
32: Map(id: 32, name: "Piccadilly", imageName: "mw_piccadilly"),
33: Map(id: 33, name: "Grazna Raid", imageName: "mw_grazna")
]
static let bocwMaps = {
return [1,3,8,7,4,2,29,31,5,6,30,0].compactMap {
return allMaps[$0];
}
.sorted { (m1, m2) -> Bool in
return m1.name < m2.name
}
}
static let mwMaps = {
return [9,10,11,12,13,14,15,28,16,17,18,19,20,21,22,23,24,25,26,27,32,33].compactMap {
return allMaps[$0];
}.sorted { (m1, m2) -> Bool in
return m1.name < m2.name
}
}
}

View File

@@ -50,8 +50,9 @@ final class OverallStats: Content {
var statsWithHyder:Stats
var statsWithoutHyder:Stats
var dashboardItems:[DashboardItem] = []
init( overall:StatsWithMostRecentDailyRecord, mwStats:StatsWithMostRecentDailyRecord, bocwStats:StatsWithMostRecentDailyRecord, mostRecentRecord:String, statsWithHyder:Stats, statsWithoutHyder:Stats){
init( overall:StatsWithMostRecentDailyRecord, mwStats:StatsWithMostRecentDailyRecord, bocwStats:StatsWithMostRecentDailyRecord, mostRecentRecord:String, statsWithHyder:Stats, statsWithoutHyder:Stats, dashboardItems:[DashboardItem]){
self.overall = overall
self.mwStats = mwStats;
@@ -60,6 +61,8 @@ final class OverallStats: Content {
self.statsWithHyder = statsWithHyder
self.statsWithoutHyder = statsWithoutHyder
self.dashboardItems = dashboardItems
}
}
@@ -81,15 +84,39 @@ final class MonthStats: Content {
final class Stats: Content {
var winLossRatio:String
var winLossRatio:String {
get {
return getRatio()
}
}
var totalWins:Int
var totalLosses:Int
init( winLoss:String, totalWins:Int, totalLosses:Int) {
self.winLossRatio = winLoss
init( totalWins:Int, totalLosses:Int) {
self.totalWins = totalWins
self.totalLosses = totalLosses
}
var record:String {
return "\(totalWins)-\(totalLosses)"
}
private func getRatio() -> String {
var returnString = ""
let deno = (totalLosses != 0) ? totalLosses : 1
returnString = String(getRatioDouble())
if deno == 0 {
returnString = returnString + "+"
}
return returnString
}
func getRatioDouble() -> Double {
let deno = (totalLosses != 0) ? totalLosses : 1
return (Double(totalWins) / Double(deno)).truncate(places: 3)
}
}
final class StatsWithMostRecentDailyRecord: Content {
@@ -104,6 +131,10 @@ final class StatsWithMostRecentDailyRecord: Content {
self.totalLosses = totalLosses
self.mostRecentRecord = mostRecentRecord
}
var record:String {
return "\(totalWins)-\(totalLosses)"
}
}

View File

@@ -0,0 +1,19 @@
//
// DashboardItem.swift
// App
//
// Created by Michael Simard on 1/9/21.
//
import Foundation
import Fluent
import Vapor
struct DashboardItem: Content {
var title:String
var content:String
var title2:String? = nil
var content2:String? = nil
}

View File

@@ -0,0 +1,16 @@
//
// Map.swift
// App
//
// Created by Michael Simard on 1/10/21.
//
import Foundation
struct Map: Hashable {
var id: Int
var name:String
var imageName:String
}