best and worst stats
This commit is contained in:
@@ -24,8 +24,6 @@ struct StatsController: RouteCollection {
|
|||||||
statsRoute.post("logMatch", use: logMatch)
|
statsRoute.post("logMatch", use: logMatch)
|
||||||
statsRoute.get("history","page",":page", use: history)
|
statsRoute.get("history","page",":page", use: history)
|
||||||
statsRoute.get("history", use: history)
|
statsRoute.get("history", use: history)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -82,10 +80,9 @@ struct StatsController: RouteCollection {
|
|||||||
let winCount = totals[0]
|
let winCount = totals[0]
|
||||||
let lossCount = totals[1]
|
let lossCount = totals[1]
|
||||||
|
|
||||||
let ratio = self.getRatio(num: Double(winCount), den: Double(lossCount))
|
return Stats( totalWins: Int(winCount), totalLosses: Int(lossCount))
|
||||||
return Stats(winLoss: ratio, totalWins: Int(winCount), totalLosses: Int(lossCount))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStatsWithMostRecentDailyRecord(matches:[Match], game:String? = nil) -> StatsWithMostRecentDailyRecord {
|
func getStatsWithMostRecentDailyRecord(matches:[Match], game:String? = nil) -> StatsWithMostRecentDailyRecord {
|
||||||
|
|
||||||
let stats = getStats(matches: matches)
|
let stats = getStats(matches: matches)
|
||||||
@@ -95,7 +92,7 @@ struct StatsController: RouteCollection {
|
|||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func mostRecentDailyStats (matches:[Match], game:String? = nil) -> Stats{
|
func mostRecentDailyStats (matches:[Match], game:String? = nil) -> Stats{
|
||||||
|
|
||||||
let daysPlayed = getDaysPlayed(matches: matches)
|
let daysPlayed = getDaysPlayed(matches: matches)
|
||||||
@@ -109,15 +106,15 @@ struct StatsController: RouteCollection {
|
|||||||
self.shouldCountMatch(match: match)
|
self.shouldCountMatch(match: match)
|
||||||
|
|
||||||
if let game = game {
|
if let game = game {
|
||||||
// if game == "mw" {
|
// if game == "mw" {
|
||||||
// shouldInclude = shouldInclude && match.codGame == "mw"
|
// shouldInclude = shouldInclude && match.codGame == "mw"
|
||||||
// }
|
// }
|
||||||
// else if game == "bocw" {
|
// else if game == "bocw" {
|
||||||
// shouldInclude = shouldInclude && match.codGame == "bocw"
|
// shouldInclude = shouldInclude && match.codGame == "bocw"
|
||||||
//
|
//
|
||||||
// }else {
|
// }else {
|
||||||
//
|
//
|
||||||
// }
|
// }
|
||||||
|
|
||||||
shouldInclude = shouldInclude && match.codGame == game
|
shouldInclude = shouldInclude && match.codGame == game
|
||||||
}
|
}
|
||||||
@@ -246,7 +243,7 @@ struct StatsController: RouteCollection {
|
|||||||
}))
|
}))
|
||||||
// print ( Date().timeIntervalSince(startTime))
|
// print ( Date().timeIntervalSince(startTime))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let mostRecentDailyStats = self.mostRecentDailyStats(matches: matches)
|
let mostRecentDailyStats = self.mostRecentDailyStats(matches: matches)
|
||||||
|
|
||||||
@@ -260,16 +257,16 @@ struct StatsController: RouteCollection {
|
|||||||
// print ( Date().timeIntervalSince(startTime))
|
// print ( Date().timeIntervalSince(startTime))
|
||||||
|
|
||||||
|
|
||||||
// let cumulativeWinLossRatios = self.getCumulativeWinLossRatios(matches: matches)
|
// let cumulativeWinLossRatios = self.getCumulativeWinLossRatios(matches: matches)
|
||||||
|
|
||||||
// print ( Date().timeIntervalSince(startTime))
|
// print ( Date().timeIntervalSince(startTime))
|
||||||
|
|
||||||
// let highestWinLossRatio = cumulativeWinLossRatios.reduce("0") { (highestRatio, dataPoint) -> String in
|
// let highestWinLossRatio = cumulativeWinLossRatios.reduce("0") { (highestRatio, dataPoint) -> String in
|
||||||
// if dataPoint.y > Double(highestRatio)!{
|
// if dataPoint.y > Double(highestRatio)!{
|
||||||
// return String(dataPoint.y)
|
// return String(dataPoint.y)
|
||||||
// }
|
// }
|
||||||
// return highestRatio
|
// return highestRatio
|
||||||
// }
|
// }
|
||||||
// print ( Date().timeIntervalSince(startTime))
|
// print ( Date().timeIntervalSince(startTime))
|
||||||
|
|
||||||
|
|
||||||
@@ -356,8 +353,7 @@ struct StatsController: RouteCollection {
|
|||||||
let combined = winCount.and(lossCount)
|
let combined = winCount.and(lossCount)
|
||||||
|
|
||||||
return combined.map { (winCount, lossCount) -> (Stats) in
|
return combined.map { (winCount, lossCount) -> (Stats) in
|
||||||
let ratio:Double = (Double(winCount) / Double(lossCount)).truncate(places: 2)
|
return Stats.init( totalWins: winCount, totalLosses: lossCount)
|
||||||
return Stats.init(winLoss: String(ratio), totalWins: winCount, totalLosses: lossCount)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,7 +376,7 @@ struct StatsController: RouteCollection {
|
|||||||
|
|
||||||
return combined.map { (winCount, lossCount) -> (Stats) in
|
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)
|
let combined = winCount.and(lossCount)
|
||||||
|
|
||||||
return combined.map { (winCount, lossCount) -> (Stats) in
|
return combined.map { (winCount, lossCount) -> (Stats) in
|
||||||
let ratio:Double = (Double(winCount) / Double(lossCount)).truncate(places: 2)
|
return Stats.init(totalWins: winCount, totalLosses: lossCount)
|
||||||
return Stats.init(winLoss: String(ratio), totalWins: winCount, totalLosses: lossCount)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,17 +542,17 @@ struct StatsController: RouteCollection {
|
|||||||
|
|
||||||
func overall(req: Request) throws -> EventLoopFuture<OverallStats> {
|
func overall(req: Request) throws -> EventLoopFuture<OverallStats> {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let statsWithHyder = statsWithPlayer(req: req, playerId: 5)
|
let statsWithHyder = statsWithPlayer(req: req, playerId: 5)
|
||||||
|
|
||||||
let statsWithoutHyder = statsWithoutPlayer(req: req, playerId: 5)
|
let statsWithoutHyder = statsWithoutPlayer(req: req, playerId: 5)
|
||||||
|
|
||||||
let hyderFuture = statsWithHyder.and(statsWithoutHyder)
|
let hyderFuture = statsWithHyder.and(statsWithoutHyder)
|
||||||
|
|
||||||
let hyderStats = hyderFuture.map { (withHyder, withoutHyder) -> [Stats] in
|
let hyderStats = hyderFuture.map { (withHyder, withoutHyder) -> [Stats] in
|
||||||
return [withHyder, withoutHyder]
|
return [withHyder, withoutHyder]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let matches = Match.query(on: req.db).all()
|
let matches = Match.query(on: req.db).all()
|
||||||
@@ -571,22 +566,22 @@ struct StatsController: RouteCollection {
|
|||||||
var mwStats:StatsWithMostRecentDailyRecord?
|
var mwStats:StatsWithMostRecentDailyRecord?
|
||||||
var bocwStats:StatsWithMostRecentDailyRecord?
|
var bocwStats:StatsWithMostRecentDailyRecord?
|
||||||
var mostRecentStats:Stats?
|
var mostRecentStats:Stats?
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
queue.async {
|
queue.async {
|
||||||
overallStats = self.getStatsWithMostRecentDailyRecord(matches: matches)
|
overallStats = self.getStatsWithMostRecentDailyRecord(matches: matches)
|
||||||
group.leave()
|
group.leave()
|
||||||
}
|
}
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
queue.async {
|
queue.async {
|
||||||
mwStats = self.getStatsWithMostRecentDailyRecord(matches: matches.filter({ (match) -> Bool in
|
mwStats = self.getStatsWithMostRecentDailyRecord(matches: matches.filter({ (match) -> Bool in
|
||||||
return match.codGame == "mw" && self.shouldCountMatch(match: match )
|
return match.codGame == "mw" && self.shouldCountMatch(match: match )
|
||||||
}))
|
}))
|
||||||
group.leave()
|
group.leave()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
queue.async {
|
queue.async {
|
||||||
@@ -594,33 +589,86 @@ struct StatsController: RouteCollection {
|
|||||||
return match.codGame == "bocw" && self.shouldCountMatch(match: match )
|
return match.codGame == "bocw" && self.shouldCountMatch(match: match )
|
||||||
}))
|
}))
|
||||||
group.leave()
|
group.leave()
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
group.enter()
|
|
||||||
queue.async {
|
|
||||||
mostRecentStats = self.mostRecentDailyStats(matches: matches)
|
|
||||||
group.leave()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// group.enter()
|
||||||
|
// queue.async {
|
||||||
|
// mostRecentStats = self.mostRecentDailyStats(matches: matches)
|
||||||
|
// group.leave()
|
||||||
|
// }
|
||||||
|
|
||||||
group.wait()
|
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: "Temporarily Unavailable", statsWithHyder:hyderStats[0], statsWithoutHyder: hyderStats[1], dashboardItems:dashboardItems)
|
||||||
return OverallStats(overall: overallStats!, mwStats: mwStats!, bocwStats: bocwStats!, mostRecentRecord: "\(mostRecentStats!.totalWins) - \(mostRecentStats!.totalLosses)", statsWithHyder:hyderStats[0], statsWithoutHyder: hyderStats[1])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 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> {
|
func statsWithPlayer(req: Request, playerId:Int) -> EventLoopFuture<Stats> {
|
||||||
return Match.query(on: req.db)
|
return Match.query(on: req.db)
|
||||||
@@ -629,7 +677,7 @@ struct StatsController: RouteCollection {
|
|||||||
return self.getStats(matches: matches)
|
return self.getStats(matches: matches)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func statsWithoutPlayer (req: Request, playerId:Int) -> EventLoopFuture<Stats> {
|
func statsWithoutPlayer (req: Request, playerId:Int) -> EventLoopFuture<Stats> {
|
||||||
return Match.query(on: req.db)
|
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]> {
|
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]> {
|
func getCumulativeWinLossRatios(req:Request) -> EventLoopFuture<[DataPoint]> {
|
||||||
|
|
||||||
|
|||||||
69
Sources/App/Data/MapData.swift
Normal file
69
Sources/App/Data/MapData.swift
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -50,8 +50,9 @@ final class OverallStats: Content {
|
|||||||
var statsWithHyder:Stats
|
var statsWithHyder:Stats
|
||||||
var statsWithoutHyder: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.overall = overall
|
||||||
self.mwStats = mwStats;
|
self.mwStats = mwStats;
|
||||||
@@ -60,6 +61,8 @@ final class OverallStats: Content {
|
|||||||
|
|
||||||
self.statsWithHyder = statsWithHyder
|
self.statsWithHyder = statsWithHyder
|
||||||
self.statsWithoutHyder = statsWithoutHyder
|
self.statsWithoutHyder = statsWithoutHyder
|
||||||
|
|
||||||
|
self.dashboardItems = dashboardItems
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -81,15 +84,39 @@ final class MonthStats: Content {
|
|||||||
|
|
||||||
|
|
||||||
final class Stats: Content {
|
final class Stats: Content {
|
||||||
var winLossRatio:String
|
|
||||||
|
var winLossRatio:String {
|
||||||
|
get {
|
||||||
|
return getRatio()
|
||||||
|
}
|
||||||
|
}
|
||||||
var totalWins:Int
|
var totalWins:Int
|
||||||
var totalLosses:Int
|
var totalLosses:Int
|
||||||
|
|
||||||
init( winLoss:String, totalWins:Int, totalLosses:Int) {
|
init( totalWins:Int, totalLosses:Int) {
|
||||||
self.winLossRatio = winLoss
|
|
||||||
self.totalWins = totalWins
|
self.totalWins = totalWins
|
||||||
self.totalLosses = totalLosses
|
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 {
|
final class StatsWithMostRecentDailyRecord: Content {
|
||||||
@@ -104,6 +131,10 @@ final class StatsWithMostRecentDailyRecord: Content {
|
|||||||
self.totalLosses = totalLosses
|
self.totalLosses = totalLosses
|
||||||
self.mostRecentRecord = mostRecentRecord
|
self.mostRecentRecord = mostRecentRecord
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var record:String {
|
||||||
|
return "\(totalWins)-\(totalLosses)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
19
Sources/App/Models/DashboardItem.swift
Normal file
19
Sources/App/Models/DashboardItem.swift
Normal 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
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
16
Sources/App/Models/Map.swift
Normal file
16
Sources/App/Models/Map.swift
Normal 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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user