optimzations for dashbaord
This commit is contained in:
@@ -18,9 +18,7 @@ struct StatsController: RouteCollection {
|
|||||||
statsRoute.get("totalWins", use: totalWins)
|
statsRoute.get("totalWins", use: totalWins)
|
||||||
statsRoute.get("totalLosses", use: totalLosses)
|
statsRoute.get("totalLosses", use: totalLosses)
|
||||||
statsRoute.get("overall", use: overall)
|
statsRoute.get("overall", use: overall)
|
||||||
statsRoute.get("all", use: test)
|
|
||||||
statsRoute.get("allDaily", use: allDaily)
|
statsRoute.get("allDaily", use: allDaily)
|
||||||
statsRoute.get("test", use: test)
|
|
||||||
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)
|
||||||
@@ -85,10 +83,17 @@ struct StatsController: RouteCollection {
|
|||||||
return Stats( totalWins: Int(winCount), totalLosses: Int(lossCount))
|
return Stats( totalWins: Int(winCount), totalLosses: Int(lossCount))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStatsWithMostRecentDailyRecord(matches:[Match], game:String? = nil) -> StatsWithMostRecentDailyRecord {
|
func getStatsWithMostRecentDailyRecord(sortedMatches:[Match], game:String? = nil) -> StatsWithMostRecentDailyRecord {
|
||||||
|
|
||||||
let stats = getStats(matches: matches)
|
|
||||||
let mostRecentDailyStats = self.mostRecentDailyStats(matches: matches, game: game)
|
let startTime = Date()
|
||||||
|
//print ("MRR START \(Date().timeIntervalSince(startTime))")
|
||||||
|
|
||||||
|
let stats = getStats(matches: sortedMatches)
|
||||||
|
//print ("MRR STATS \(Date().timeIntervalSince(startTime))")
|
||||||
|
|
||||||
|
let mostRecentDailyStats = self.mostRecentDailyStats(matches: sortedMatches, game: game)
|
||||||
|
//print ("MRR DAILY \(Date().timeIntervalSince(startTime))")
|
||||||
|
|
||||||
let ret = StatsWithMostRecentDailyRecord(winLoss: stats.winLossRatio, totalWins: stats.totalWins, totalLosses: stats.totalLosses, mostRecentRecord:"\(mostRecentDailyStats.totalWins)-\(mostRecentDailyStats.totalLosses)")
|
let ret = StatsWithMostRecentDailyRecord(winLoss: stats.winLossRatio, totalWins: stats.totalWins, totalLosses: stats.totalLosses, mostRecentRecord:"\(mostRecentDailyStats.totalWins)-\(mostRecentDailyStats.totalLosses)")
|
||||||
|
|
||||||
@@ -97,9 +102,15 @@ struct StatsController: RouteCollection {
|
|||||||
|
|
||||||
func mostRecentDailyStats (matches:[Match], game:String? = nil) -> Stats{
|
func mostRecentDailyStats (matches:[Match], game:String? = nil) -> Stats{
|
||||||
|
|
||||||
let daysPlayed = getDaysPlayed(matches: matches)
|
|
||||||
|
let startTime = Date()
|
||||||
|
|
||||||
|
let daysPlayed = getDaysPlayed(sortedMatches: matches)
|
||||||
let lastDayPlayed = daysPlayed.last
|
let lastDayPlayed = daysPlayed.last
|
||||||
|
|
||||||
|
|
||||||
|
//print ("MDD days played \(Date().timeIntervalSince(startTime))")
|
||||||
|
|
||||||
return getStats(matches: matches.filter({ (match) -> Bool in
|
return getStats(matches: matches.filter({ (match) -> Bool in
|
||||||
var shouldInclude =
|
var shouldInclude =
|
||||||
match.date.day == lastDayPlayed?.day &&
|
match.date.day == lastDayPlayed?.day &&
|
||||||
@@ -108,20 +119,8 @@ struct StatsController: RouteCollection {
|
|||||||
self.shouldCountMatch(match: match)
|
self.shouldCountMatch(match: match)
|
||||||
|
|
||||||
if let game = game {
|
if let game = game {
|
||||||
// if game == "mw" {
|
|
||||||
// shouldInclude = shouldInclude && match.codGame == "mw"
|
|
||||||
// }
|
|
||||||
// else if game == "bocw" {
|
|
||||||
// shouldInclude = shouldInclude && match.codGame == "bocw"
|
|
||||||
//
|
|
||||||
// }else {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
shouldInclude = shouldInclude && match.codGame == game
|
shouldInclude = shouldInclude && match.codGame == game
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return shouldInclude
|
return shouldInclude
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@@ -141,16 +140,20 @@ struct StatsController: RouteCollection {
|
|||||||
return match.players?.components(separatedBy: ",").count ?? 0
|
return match.players?.components(separatedBy: ",").count ?? 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private func getDaysPlayed(matches:[Match]) -> [CODDate] {
|
private func getDaysPlayed(sortedMatches:[Match]) -> [CODDate] {
|
||||||
|
|
||||||
var sortedMatches = matches
|
let startTime = Date()
|
||||||
sortedMatches.sort { (match1, match2) -> Bool in
|
|
||||||
return match1.date < match2.date
|
//print ("MDP Sort \(Date().timeIntervalSince(startTime))")
|
||||||
|
|
||||||
|
let dates = sortedMatches.suffix(30).map { (match) -> CODDate in
|
||||||
|
return CODDate(month: match.date.month, year: match.date.year, day: match.date.day, hour: match.date.hour, minute: match.date.minute)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sortedMatches.map { (match) -> CODDate in
|
//print ("MDP to dates \(Date().timeIntervalSince(startTime))")
|
||||||
return CODDate(month: match.date.month, year: match.date.year, day: match.date.day, hour: match.date.hour, minute: match.date.minute)
|
|
||||||
}.reduce([CODDate]()) { (datesPlayed, codDate) -> [CODDate] in
|
|
||||||
|
return dates.reduce([CODDate]()) { (datesPlayed, codDate) -> [CODDate] in
|
||||||
|
|
||||||
if datesPlayed.contains(where: { (existingDate) -> Bool in
|
if datesPlayed.contains(where: { (existingDate) -> Bool in
|
||||||
if codDate.month == existingDate.month && codDate.year == existingDate.year && existingDate.day == codDate.day{
|
if codDate.month == existingDate.month && codDate.year == existingDate.year && existingDate.day == codDate.day{
|
||||||
@@ -170,7 +173,7 @@ struct StatsController: RouteCollection {
|
|||||||
|
|
||||||
func getCumulativeWinLossRatios(matches:[Match]) -> [DataPoint] {
|
func getCumulativeWinLossRatios(matches:[Match]) -> [DataPoint] {
|
||||||
|
|
||||||
let daysPlayed = getDaysPlayed(matches: matches)
|
let daysPlayed = getDaysPlayed(sortedMatches: matches)
|
||||||
|
|
||||||
var cumulativeRatios : [DataPoint] = []
|
var cumulativeRatios : [DataPoint] = []
|
||||||
var cumulativeWins:Int = 0
|
var cumulativeWins:Int = 0
|
||||||
@@ -215,106 +218,6 @@ struct StatsController: RouteCollection {
|
|||||||
return cumulativeRatios
|
return cumulativeRatios
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func test(req: Request) throws -> EventLoopFuture<AllStats> {
|
|
||||||
|
|
||||||
let startTime = Date()
|
|
||||||
|
|
||||||
var date = getStartDate()
|
|
||||||
var previousMonths:[CODDate] = []
|
|
||||||
|
|
||||||
repeat {
|
|
||||||
//let stats = getStatsByMonth(year: date.year, month: date.month, req: req) //returns eventloopfuture<Stats>
|
|
||||||
previousMonths.append(CODDate(month: date.month, year: date.year, day: 15, hour:6, minute: 0))
|
|
||||||
date = Calendar.current.date(byAdding: .month, value: 1, to: date)!
|
|
||||||
} while ( date < Calendar.current.date(byAdding: .month, value: 1, to: Date())!)
|
|
||||||
|
|
||||||
// print (date - Date().timeIntervalSince(startTime))
|
|
||||||
|
|
||||||
return Match.query(on: req.db).all().map { (matches) -> AllStats in
|
|
||||||
let overallStats = self.getStatsWithMostRecentDailyRecord(matches: matches)
|
|
||||||
// print ( Date().timeIntervalSince(startTime))
|
|
||||||
|
|
||||||
let mwStats = self.getStatsWithMostRecentDailyRecord(matches: matches.filter({ (match) -> Bool in
|
|
||||||
return match.codGame == "mw"
|
|
||||||
}))
|
|
||||||
// print ( Date().timeIntervalSince(startTime))
|
|
||||||
|
|
||||||
let bocwStats = self.getStatsWithMostRecentDailyRecord(matches: matches.filter({ (match) -> Bool in
|
|
||||||
return match.codGame == "bocw"
|
|
||||||
}))
|
|
||||||
// print ( Date().timeIntervalSince(startTime))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let mostRecentDailyStats = self.mostRecentDailyStats(matches: matches)
|
|
||||||
|
|
||||||
|
|
||||||
let monthlyStats = previousMonths.reversed().map { (codDate) -> MonthStats in
|
|
||||||
let relevantMatches = matches.filter { (match) -> Bool in
|
|
||||||
return match.date.month == codDate.month
|
|
||||||
}
|
|
||||||
return MonthStats(month: codDate.month, year: codDate.year, stats: self.getStats(matches: relevantMatches ))
|
|
||||||
}
|
|
||||||
// print ( Date().timeIntervalSince(startTime))
|
|
||||||
|
|
||||||
|
|
||||||
// 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
|
|
||||||
// }
|
|
||||||
// print ( Date().timeIntervalSince(startTime))
|
|
||||||
|
|
||||||
|
|
||||||
return AllStats.init(overall: overallStats,mwStats: mwStats, bocwStats: bocwStats, byMonth: monthlyStats, mostRecentRecord: "\(mostRecentDailyStats.totalWins) - \(mostRecentDailyStats.totalLosses)")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// func getMonthStats (_ remaining: ArraySlice<CODDate>, allMonthlyStats: inout [MonthStats], eventLoop: EventLoop) -> EventLoopFuture<[MonthStats]> {
|
|
||||||
// var remaining = remaining
|
|
||||||
// if let first = remaining.popLast() {
|
|
||||||
//
|
|
||||||
// return getstatsForMonth(year: first.year, month: first.month, req: req).flatMap { [remaining, allMonthlyStats] (stats) -> EventLoopFuture<[MonthStats]> in
|
|
||||||
// var allMonthlyStats = allMonthlyStats
|
|
||||||
// allMonthlyStats.append(MonthStats(month: first.month, year: first.year, stats:stats ))
|
|
||||||
// return getMonthStats(remaining, allMonthlyStats:&allMonthlyStats, eventLoop: eventLoop)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
// return req.eventLoop.makeSucceededFuture(allMonthlyStats)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var stats:[MonthStats] = []
|
|
||||||
// let monthstats = getMonthStats(previousMonths[0..<previousMonths.count], allMonthlyStats:&stats, eventLoop: req.eventLoop)
|
|
||||||
// let cumulativeRatios = getCumulativeWinLossRatios(req: req)
|
|
||||||
// let mostRecentDayStats = mostRecentDailyStats(req: req)
|
|
||||||
//
|
|
||||||
// return try overall(req: req).and(monthstats).and(cumulativeRatios).and(mostRecentDayStats).map { arg -> AllStats in
|
|
||||||
//
|
|
||||||
// let (((overall, monthlyStats), cumulativeRatios), mostRecentDayStats) = arg
|
|
||||||
// let highestWinLossRatio = cumulativeRatios.reduce("0") { (highestRatio, dataPoint) -> String in
|
|
||||||
// if dataPoint.y > Double(highestRatio)!{
|
|
||||||
// return String(dataPoint.y)
|
|
||||||
// }
|
|
||||||
// return highestRatio
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return AllStats.init(overall: overall,mwStats: overall, bocwStats: overall, byMonth: monthlyStats, highestWinLossRatio: highestWinLossRatio, dataPoints: cumulativeRatios, mostRecentRecord: "\(mostRecentDayStats.totalWins) - \(mostRecentDayStats.totalLosses)")
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func index(req: Request) throws -> EventLoopFuture<[Match]> {
|
func index(req: Request) throws -> EventLoopFuture<[Match]> {
|
||||||
return Match.query(on: req.db).sort(\.$date).all()
|
return Match.query(on: req.db).sort(\.$date).all()
|
||||||
}
|
}
|
||||||
@@ -490,62 +393,12 @@ struct StatsController: RouteCollection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// func all(req: Request) throws -> EventLoopFuture<AllStats> {
|
|
||||||
//
|
|
||||||
// var date = getStartDate()
|
|
||||||
// var previousMonths:[CODDate] = []
|
|
||||||
//
|
|
||||||
// repeat {
|
|
||||||
// //let stats = getStatsByMonth(year: date.year, month: date.month, req: req) //returns eventloopfuture<Stats>
|
|
||||||
// previousMonths.append(CODDate(month: date.month, year: date.year, day: 15, hour:6, minute: 0))
|
|
||||||
// date = Calendar.current.date(byAdding: .month, value: 1, to: date)!
|
|
||||||
// }while ( date < Calendar.current.date(byAdding: .month, value: 1, to: Date())!)
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// func getMonthStats (_ remaining: ArraySlice<CODDate>, allMonthlyStats: inout [MonthStats], eventLoop: EventLoop) -> EventLoopFuture<[MonthStats]> {
|
|
||||||
// var remaining = remaining
|
|
||||||
// if let first = remaining.popLast() {
|
|
||||||
//
|
|
||||||
// return getstatsForMonth(year: first.year, month: first.month, req: req).flatMap { [remaining, allMonthlyStats] (stats) -> EventLoopFuture<[MonthStats]> in
|
|
||||||
// var allMonthlyStats = allMonthlyStats
|
|
||||||
// allMonthlyStats.append(MonthStats(month: first.month, year: first.year, stats:stats ))
|
|
||||||
// return getMonthStats(remaining, allMonthlyStats:&allMonthlyStats, eventLoop: eventLoop)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
// return req.eventLoop.makeSucceededFuture(allMonthlyStats)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var stats:[MonthStats] = []
|
|
||||||
// let monthstats = getMonthStats(previousMonths[0..<previousMonths.count], allMonthlyStats:&stats, eventLoop: req.eventLoop)
|
|
||||||
// let cumulativeRatios = getCumulativeWinLossRatios(req: req)
|
|
||||||
// let mostRecentDayStats = mostRecentDailyStats(req: req)
|
|
||||||
//
|
|
||||||
// return try overall(req: req).and(monthstats).and(cumulativeRatios).and(mostRecentDayStats).map { arg -> AllStats in
|
|
||||||
//
|
|
||||||
// let (((overall, monthlyStats), cumulativeRatios), mostRecentDayStats) = arg
|
|
||||||
// let highestWinLossRatio = cumulativeRatios.reduce("0") { (highestRatio, dataPoint) -> String in
|
|
||||||
// if dataPoint.y > Double(highestRatio)!{
|
|
||||||
// return String(dataPoint.y)
|
|
||||||
// }
|
|
||||||
// return highestRatio
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// return AllStats.init(overall: overall,mwStats: overall, bocwStats: overall, byMonth: monthlyStats, highestWinLossRatio: highestWinLossRatio, dataPoints: cumulativeRatios, mostRecentRecord: "\(mostRecentDayStats.totalWins) - \(mostRecentDayStats.totalLosses)")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
func overall(req: Request) throws -> EventLoopFuture<OverallStats> {
|
func overall(req: Request) throws -> EventLoopFuture<OverallStats> {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let startTime = Date()
|
||||||
|
|
||||||
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)
|
||||||
@@ -554,13 +407,17 @@ struct StatsController: RouteCollection {
|
|||||||
|
|
||||||
let hyderStats = hyderFuture.map { (withHyder, withoutHyder) -> [Stats] in
|
let hyderStats = hyderFuture.map { (withHyder, withoutHyder) -> [Stats] in
|
||||||
return [withHyder, withoutHyder]
|
return [withHyder, withoutHyder]
|
||||||
|
|
||||||
|
//print ("Hyder done \(Date().timeIntervalSince(startTime))")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let matches = Match.query(on: req.db).all()
|
let matches = Match.query(on: req.db).sort( \.$date).all()
|
||||||
|
|
||||||
return matches.and(hyderStats).map { (matches, hyderStats) -> (OverallStats) in
|
return matches.and(hyderStats).map { (matches, hyderStats) -> (OverallStats) in
|
||||||
|
|
||||||
|
//print ("got matches \(Date().timeIntervalSince(startTime))")
|
||||||
|
|
||||||
let queue = DispatchQueue(label: "com.sledsoft.cod-tracker.queue", attributes: .concurrent)
|
let queue = DispatchQueue(label: "com.sledsoft.cod-tracker.queue", attributes: .concurrent)
|
||||||
let group = DispatchGroup()
|
let group = DispatchGroup()
|
||||||
|
|
||||||
@@ -568,18 +425,25 @@ struct StatsController: RouteCollection {
|
|||||||
var mwStats:StatsWithMostRecentDailyRecord?
|
var mwStats:StatsWithMostRecentDailyRecord?
|
||||||
var bocwStats:StatsWithMostRecentDailyRecord?
|
var bocwStats:StatsWithMostRecentDailyRecord?
|
||||||
var mostRecentStats:Stats?
|
var mostRecentStats:Stats?
|
||||||
|
var mapStats:[Int:Stats]?
|
||||||
|
var worstMap:Int?
|
||||||
|
var bestMap:Int?
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
queue.async {
|
queue.async {
|
||||||
overallStats = self.getStatsWithMostRecentDailyRecord(matches: matches)
|
overallStats = self.getStatsWithMostRecentDailyRecord(sortedMatches: matches)
|
||||||
group.leave()
|
group.leave()
|
||||||
|
//print ("all stats done \(Date().timeIntervalSince(startTime))")
|
||||||
}
|
}
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
queue.async {
|
queue.async {
|
||||||
mwStats = self.getStatsWithMostRecentDailyRecord(matches: matches.filter({ (match) -> Bool in
|
mwStats = self.getStatsWithMostRecentDailyRecord(sortedMatches: matches.filter({ (match) -> Bool in
|
||||||
return match.codGame == "mw" && self.shouldCountMatch(match: match )
|
return match.codGame == "mw" && self.shouldCountMatch(match: match )
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
//print ("mw stats done \(Date().timeIntervalSince(startTime))")
|
||||||
|
|
||||||
group.leave()
|
group.leave()
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -587,25 +451,47 @@ struct StatsController: RouteCollection {
|
|||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
queue.async {
|
queue.async {
|
||||||
bocwStats = self.getStatsWithMostRecentDailyRecord(matches: matches.filter({ (match) -> Bool in
|
|
||||||
|
bocwStats = self.getStatsWithMostRecentDailyRecord(sortedMatches: matches.filter({ (match) -> Bool in
|
||||||
return match.codGame == "bocw" && self.shouldCountMatch(match: match )
|
return match.codGame == "bocw" && self.shouldCountMatch(match: match )
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
//print ("cw done \(Date().timeIntervalSince(startTime))")
|
||||||
|
|
||||||
group.leave()
|
group.leave()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// group.enter()
|
group.enter()
|
||||||
// queue.async {
|
queue.async {
|
||||||
// mostRecentStats = self.mostRecentDailyStats(matches: matches)
|
mapStats = self.getMapStats(matches: matches)
|
||||||
// group.leave()
|
//print ("maps done \(Date().timeIntervalSince(startTime))")
|
||||||
// }
|
group.leave()
|
||||||
|
|
||||||
|
}
|
||||||
|
//
|
||||||
|
group.enter()
|
||||||
|
queue.async {
|
||||||
|
let mapStats = self.getMapStats(matches: matches)
|
||||||
|
|
||||||
|
bestMap = self.getBestMap(records: mapStats)
|
||||||
|
//print ("best done \(Date().timeIntervalSince(startTime))")
|
||||||
|
group.leave()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
group.enter()
|
||||||
|
queue.async {
|
||||||
|
let mapStats = self.getMapStats(matches: matches)
|
||||||
|
|
||||||
|
worstMap = self.getWorstMap(records: mapStats)
|
||||||
|
//print ("worst done \(Date().timeIntervalSince(startTime))")
|
||||||
|
group.leave()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
group.wait()
|
group.wait()
|
||||||
|
|
||||||
let mapStats = self.getMapStats(matches: matches)
|
|
||||||
let bestMap = self.getBestMap(records: mapStats)
|
|
||||||
let worstMap = self.getWorstMap(records: mapStats)
|
|
||||||
|
|
||||||
let dashboardItems = [
|
let dashboardItems = [
|
||||||
DashboardItem(title: "Overall", content: overallStats!.record, title2: "Ratio", content2: overallStats!.winLossRatio),
|
DashboardItem(title: "Overall", content: overallStats!.record, title2: "Ratio", content2: overallStats!.winLossRatio),
|
||||||
DashboardItem(title: "Total MW Games", content: "\(mwStats!.totalWins + mwStats!.totalLosses)" , title2:"", content2:""),
|
DashboardItem(title: "Total MW Games", content: "\(mwStats!.totalWins + mwStats!.totalLosses)" , title2:"", content2:""),
|
||||||
@@ -613,21 +499,12 @@ struct StatsController: RouteCollection {
|
|||||||
DashboardItem(title: "Cold War Overall", content: bocwStats!.record, title2: "Ratio", content2: bocwStats!.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: "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: "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: "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)"),
|
DashboardItem(title: "Worst Map", content: MapData.allMaps[worstMap!]?.name ?? "error", title2: "Ratio", content2: "\(mapStats![worstMap!]!.winLossRatio) \(mapStats![worstMap!]!.record)"),
|
||||||
DashboardItem(title: "Final Kills Ruined by Adam", content: "\(matches.filter{$0.finalKillRuinedPlayerId == 6}.count + 7)", title2: "", content2: ""),
|
DashboardItem(title: "Final Kills Ruined by Adam", content: "\(matches.filter{$0.finalKillRuinedPlayerId == 6}.count + 7)", title2: "", content2: ""),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
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: "Temporarily Unavailable", statsWithHyder:hyderStats[0], statsWithoutHyder: hyderStats[1], dashboardItems:dashboardItems)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// return Match.query(on: req.db).all().map { (matches) -> OverallStats in
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -647,7 +524,7 @@ struct StatsController: RouteCollection {
|
|||||||
var loss:Double = 0
|
var loss:Double = 0
|
||||||
|
|
||||||
for record in records {
|
for record in records {
|
||||||
print("\(record.map.name) \(record.stats.record) \(record.ratio)")
|
//print("\(record.map.name) \(record.stats.record) \(record.ratio)")
|
||||||
wins = wins + Double(record.stats.totalWins)
|
wins = wins + Double(record.stats.totalWins)
|
||||||
loss = loss + Double(record.stats.totalLosses)
|
loss = loss + Double(record.stats.totalLosses)
|
||||||
|
|
||||||
@@ -818,13 +695,8 @@ struct StatsController: RouteCollection {
|
|||||||
|
|
||||||
func getCumulativeWinLossRatios(req:Request) -> EventLoopFuture<[DataPoint]> {
|
func getCumulativeWinLossRatios(req:Request) -> EventLoopFuture<[DataPoint]> {
|
||||||
|
|
||||||
// let previousDays = getDaysPlayed().reversed()
|
|
||||||
|
|
||||||
|
|
||||||
return getDaysPlayed(req: req).flatMap { (previousDays) -> (EventLoopFuture<[DataPoint]>) in
|
return getDaysPlayed(req: req).flatMap { (previousDays) -> (EventLoopFuture<[DataPoint]>) in
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func getRatios (_ remaining: ArraySlice<CODDate>, allDailyStats: inout [DailyStats], cumulativeWinLossRatios: inout [DataPoint], eventLoop: EventLoop) -> EventLoopFuture<[DataPoint]> {
|
func getRatios (_ remaining: ArraySlice<CODDate>, allDailyStats: inout [DailyStats], cumulativeWinLossRatios: inout [DataPoint], eventLoop: EventLoop) -> EventLoopFuture<[DataPoint]> {
|
||||||
var remaining = remaining
|
var remaining = remaining
|
||||||
if let first = remaining.popLast() {
|
if let first = remaining.popLast() {
|
||||||
@@ -843,7 +715,7 @@ struct StatsController: RouteCollection {
|
|||||||
if !(stats.totalWins == 0 && stats.totalLosses == 0) {
|
if !(stats.totalWins == 0 && stats.totalLosses == 0) {
|
||||||
|
|
||||||
let date = self.createDate(day: first.day, month: first.month, year: first.year, hour: first.hour + 6, minute:first.minute) // 6 hours to make sure we pick a time that isnt on borders of us time zones
|
let date = self.createDate(day: first.day, month: first.month, year: first.year, hour: first.hour + 6, minute:first.minute) // 6 hours to make sure we pick a time that isnt on borders of us time zones
|
||||||
// print ("p \(date.timeIntervalSince1970)")
|
// //print ("p \(date.timeIntervalSince1970)")
|
||||||
let x = Double(cumulativeWinLossRatios.count)
|
let x = Double(cumulativeWinLossRatios.count)
|
||||||
|
|
||||||
let d = Date(timeIntervalSince1970: date.timeIntervalSince1970)
|
let d = Date(timeIntervalSince1970: date.timeIntervalSince1970)
|
||||||
@@ -868,56 +740,3 @@ struct StatsController: RouteCollection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extension Double
|
|
||||||
{
|
|
||||||
func truncate(places : Int)-> Double
|
|
||||||
{
|
|
||||||
return Double(floor(pow(10.0, Double(places)) * self)/pow(10.0, Double(places)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Date {
|
|
||||||
|
|
||||||
var month:Int {
|
|
||||||
|
|
||||||
var calendar = Calendar.current
|
|
||||||
calendar.timeZone = TimeZone(identifier: "GMT")!
|
|
||||||
let calanderDate = calendar.dateComponents([.minute, .month, .year, .hour, .day], from: self)
|
|
||||||
return calanderDate.month ?? 1
|
|
||||||
}
|
|
||||||
|
|
||||||
var year:Int {
|
|
||||||
|
|
||||||
var calendar = Calendar.current
|
|
||||||
calendar.timeZone = TimeZone(identifier: "GMT")!
|
|
||||||
let calanderDate = calendar.dateComponents([.minute, .month, .year, .hour, .day], from: self)
|
|
||||||
return calanderDate.year ?? 1
|
|
||||||
}
|
|
||||||
|
|
||||||
var day:Int {
|
|
||||||
|
|
||||||
var calendar = Calendar.current
|
|
||||||
calendar.timeZone = TimeZone(identifier: "GMT")!
|
|
||||||
let calanderDate = calendar.dateComponents([.minute, .month, .year, .hour, .day], from: self)
|
|
||||||
return calanderDate.day ?? 1
|
|
||||||
}
|
|
||||||
|
|
||||||
var hour:Int {
|
|
||||||
|
|
||||||
var calendar = Calendar.current
|
|
||||||
calendar.timeZone = TimeZone(identifier: "GMT")!
|
|
||||||
let calanderDate = calendar.dateComponents([.minute, .month, .year, .hour, .day], from: self)
|
|
||||||
return calanderDate.hour ?? 1
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var minute:Int {
|
|
||||||
var calendar = Calendar.current
|
|
||||||
calendar.timeZone = TimeZone(identifier: "GMT")!
|
|
||||||
let calanderDate = calendar.dateComponents([.minute, .month, .year, .hour, .day], from: self)
|
|
||||||
return calanderDate.minute ?? 1
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
55
Sources/App/Data/Extensions/Date+components.swift
Normal file
55
Sources/App/Data/Extensions/Date+components.swift
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// Date+components.swift
|
||||||
|
// App
|
||||||
|
//
|
||||||
|
// Created by Michael Simard on 1/15/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
|
extension Date {
|
||||||
|
|
||||||
|
var month:Int {
|
||||||
|
|
||||||
|
var calendar = Calendar.current
|
||||||
|
calendar.timeZone = TimeZone(identifier: "GMT")!
|
||||||
|
let calanderDate = calendar.dateComponents([.minute, .month, .year, .hour, .day], from: self)
|
||||||
|
return calanderDate.month ?? 1
|
||||||
|
}
|
||||||
|
|
||||||
|
var year:Int {
|
||||||
|
|
||||||
|
var calendar = Calendar.current
|
||||||
|
calendar.timeZone = TimeZone(identifier: "GMT")!
|
||||||
|
let calanderDate = calendar.dateComponents([.minute, .month, .year, .hour, .day], from: self)
|
||||||
|
return calanderDate.year ?? 1
|
||||||
|
}
|
||||||
|
|
||||||
|
var day:Int {
|
||||||
|
|
||||||
|
var calendar = Calendar.current
|
||||||
|
calendar.timeZone = TimeZone(identifier: "GMT")!
|
||||||
|
let calanderDate = calendar.dateComponents([.minute, .month, .year, .hour, .day], from: self)
|
||||||
|
return calanderDate.day ?? 1
|
||||||
|
}
|
||||||
|
|
||||||
|
var hour:Int {
|
||||||
|
|
||||||
|
var calendar = Calendar.current
|
||||||
|
calendar.timeZone = TimeZone(identifier: "GMT")!
|
||||||
|
let calanderDate = calendar.dateComponents([.minute, .month, .year, .hour, .day], from: self)
|
||||||
|
return calanderDate.hour ?? 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var minute:Int {
|
||||||
|
var calendar = Calendar.current
|
||||||
|
calendar.timeZone = TimeZone(identifier: "GMT")!
|
||||||
|
let calanderDate = calendar.dateComponents([.minute, .month, .year, .hour, .day], from: self)
|
||||||
|
return calanderDate.minute ?? 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
16
Sources/App/Data/Extensions/Double+Truncate.swift
Normal file
16
Sources/App/Data/Extensions/Double+Truncate.swift
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// Double+Truncate.swift
|
||||||
|
// App
|
||||||
|
//
|
||||||
|
// Created by Michael Simard on 1/15/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension Double
|
||||||
|
{
|
||||||
|
func truncate(places : Int)-> Double
|
||||||
|
{
|
||||||
|
return Double(floor(pow(10.0, Double(places)) * self)/pow(10.0, Double(places)))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,8 +25,39 @@ x-shared_environment: &shared_environment
|
|||||||
DATABASE_NAME: cod_db
|
DATABASE_NAME: cod_db
|
||||||
DATABASE_USERNAME: cod
|
DATABASE_USERNAME: cod
|
||||||
DATABASE_PASSWORD: pw4cod
|
DATABASE_PASSWORD: pw4cod
|
||||||
|
VIRTUAL_HOST: app.local
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
nginx-proxy:
|
||||||
|
image: jwilder/nginx-proxy:alpine
|
||||||
|
restart: "always" # Always restart container
|
||||||
|
ports:
|
||||||
|
- "80:80" # Port mappings in format host:container
|
||||||
|
- "443:443" # Port mappings in format host:container
|
||||||
|
networks:
|
||||||
|
- nginx-proxy # Name of the etwork these two containers will share
|
||||||
|
labels:
|
||||||
|
- "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy" # Label needed for Let's Encrypt companion container
|
||||||
|
volumes: # Volumes needed for container to configure proixes and access certificates genereated by Let's Encrypt companion container
|
||||||
|
- /var/run/docker.sock:/tmp/docker.sock:ro
|
||||||
|
- "nginx-conf:/etc/nginx/conf.d"
|
||||||
|
- "nginx-vhost:/etc/nginx/vhost.d"
|
||||||
|
- "html:/usr/share/nginx/html"
|
||||||
|
- "certs:/etc/nginx/certs:ro"
|
||||||
|
|
||||||
|
letsencrypt-nginx-proxy-companion:
|
||||||
|
image: jrcs/letsencrypt-nginx-proxy-companion
|
||||||
|
restart: always
|
||||||
|
container_name: letsencrypt-nginx-proxy-companion
|
||||||
|
volumes:
|
||||||
|
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||||
|
- "nginx-conf:/etc/nginx/conf.d"
|
||||||
|
- "nginx-vhost:/etc/nginx/vhost.d"
|
||||||
|
- "html:/usr/share/nginx/html"
|
||||||
|
- "certs:/etc/nginx/certs:rw"
|
||||||
|
depends_on: # Make sure we start nginx proxy container first
|
||||||
|
- app
|
||||||
|
- nginx-proxy
|
||||||
app:
|
app:
|
||||||
image: cod-backend:latest
|
image: cod-backend:latest
|
||||||
build:
|
build:
|
||||||
@@ -72,3 +103,11 @@ services:
|
|||||||
POSTGRES_DB: cod_db
|
POSTGRES_DB: cod_db
|
||||||
ports:
|
ports:
|
||||||
- '5432:5432'
|
- '5432:5432'
|
||||||
|
networks:
|
||||||
|
nginx-proxy: # Name of our shared network that containers will use
|
||||||
|
volumes: # Names of volumes that out containers will share. Those will persist on docker's host machine.
|
||||||
|
nginx-conf:
|
||||||
|
nginx-vhost:
|
||||||
|
html:
|
||||||
|
certs:
|
||||||
|
db_data:
|
||||||
Reference in New Issue
Block a user