From 64a66e28b8e94c8701b45ca8278b3f034810b43f Mon Sep 17 00:00:00 2001 From: Michael Simard Date: Sun, 31 Oct 2021 00:01:27 -0500 Subject: [PATCH] map, player, game, gamemode data now database driven --- .../App/Content/Config/Configuration.swift | 31 +++ Sources/App/Content/Config/GameConfig.swift | 22 ++ .../App/Content/Config/GameModeConfig.swift | 18 ++ .../Content/Config/GameModeGroupConfig.swift | 19 ++ .../Content/Config/LossReasonsConfig.swift | 15 ++ Sources/App/Content/Config/MapConfig.swift | 19 ++ Sources/App/Content/Config/PlayerConfig.swift | 15 ++ Sources/App/Content/MapRecord.swift | 2 +- .../App/Content/{Map.swift => OldMap.swift} | 2 +- .../App/Controllers/AppDataController.swift | 66 ++++++ Sources/App/Controllers/MapsController.swift | 35 +++ Sources/App/Controllers/StatsController.swift | 95 ++++++-- Sources/App/Data/MapData.swift | 224 +++++++++--------- Sources/App/Models/Game.swift | 53 +++++ Sources/App/Models/GameMode.swift | 51 ++++ Sources/App/Models/GameModeGroup.swift | 45 ++++ Sources/App/Models/LossReason.swift | 43 ++++ Sources/App/Models/Map.swift | 48 ++++ Sources/App/Models/Match.swift | 8 +- Sources/App/Models/Player.swift | 40 ++++ Sources/App/Models/Statistics.swift | 1 + Sources/App/routes.swift | 2 + 22 files changed, 711 insertions(+), 143 deletions(-) create mode 100644 Sources/App/Content/Config/Configuration.swift create mode 100644 Sources/App/Content/Config/GameConfig.swift create mode 100644 Sources/App/Content/Config/GameModeConfig.swift create mode 100644 Sources/App/Content/Config/GameModeGroupConfig.swift create mode 100644 Sources/App/Content/Config/LossReasonsConfig.swift create mode 100644 Sources/App/Content/Config/MapConfig.swift create mode 100644 Sources/App/Content/Config/PlayerConfig.swift rename Sources/App/Content/{Map.swift => OldMap.swift} (81%) create mode 100644 Sources/App/Controllers/AppDataController.swift create mode 100644 Sources/App/Controllers/MapsController.swift create mode 100644 Sources/App/Models/Game.swift create mode 100644 Sources/App/Models/GameMode.swift create mode 100644 Sources/App/Models/GameModeGroup.swift create mode 100644 Sources/App/Models/LossReason.swift create mode 100644 Sources/App/Models/Map.swift create mode 100644 Sources/App/Models/Player.swift diff --git a/Sources/App/Content/Config/Configuration.swift b/Sources/App/Content/Config/Configuration.swift new file mode 100644 index 0000000..ba80d51 --- /dev/null +++ b/Sources/App/Content/Config/Configuration.swift @@ -0,0 +1,31 @@ +// +// Configuration.swift +// App +// +// Created by Michael Simard on 10/29/21. +// + +import Foundation +import Fluent +import Vapor + + + +struct Configuration : Content { + + var games:[GameConfig] + var gameModes:[GameModeConfig] + var gameModeGroups:[GameModeGroupConfig] + var players:[PlayerConfig] + var lossReasons:[LossReasonConfig] + + + init (games:[GameConfig], gameModes:[GameModeConfig], gameModeGroups:[GameModeGroupConfig], players:[PlayerConfig], lossReasons:[LossReasonConfig]){ + self.games = games + self.gameModes = gameModes + self.gameModeGroups = gameModeGroups + self.players = players + self.lossReasons = lossReasons + } + +} diff --git a/Sources/App/Content/Config/GameConfig.swift b/Sources/App/Content/Config/GameConfig.swift new file mode 100644 index 0000000..25bf2c1 --- /dev/null +++ b/Sources/App/Content/Config/GameConfig.swift @@ -0,0 +1,22 @@ +// +// GameConfig.swift +// App +// +// Created by Michael Simard on 10/29/21. +// + +import Foundation + + +import Fluent +import Vapor + +struct GameConfig: Content { + + var gameId: String + var name: String + var maps: [MapConfig] + var enabled:Bool + + +} diff --git a/Sources/App/Content/Config/GameModeConfig.swift b/Sources/App/Content/Config/GameModeConfig.swift new file mode 100644 index 0000000..6f24d58 --- /dev/null +++ b/Sources/App/Content/Config/GameModeConfig.swift @@ -0,0 +1,18 @@ +// +// GameModeConfig.swift +// App +// +// Created by Michael Simard on 10/29/21. +// + +import Foundation +import Fluent +import Vapor + +struct GameModeConfig:Content { + + var gameModeId:Int + var name:String + var competitive:Bool + +} diff --git a/Sources/App/Content/Config/GameModeGroupConfig.swift b/Sources/App/Content/Config/GameModeGroupConfig.swift new file mode 100644 index 0000000..e34a251 --- /dev/null +++ b/Sources/App/Content/Config/GameModeGroupConfig.swift @@ -0,0 +1,19 @@ +// +// GameModeGroupConfig.swift +// App +// +// Created by Michael Simard on 10/29/21. +// + +import Foundation +import Fluent +import Vapor + + +struct GameModeGroupConfig: Content { + + var gameModeIds: String + var gameModeGroupId: String + var name: String + +} diff --git a/Sources/App/Content/Config/LossReasonsConfig.swift b/Sources/App/Content/Config/LossReasonsConfig.swift new file mode 100644 index 0000000..29af0ff --- /dev/null +++ b/Sources/App/Content/Config/LossReasonsConfig.swift @@ -0,0 +1,15 @@ +// +// LossReasonsConfig.swift +// App +// +// Created by Michael Simard on 10/30/21. +// + +import Foundation +import Fluent +import Vapor + +struct LossReasonConfig: Content { + var reasonId: Int + var name: String +} diff --git a/Sources/App/Content/Config/MapConfig.swift b/Sources/App/Content/Config/MapConfig.swift new file mode 100644 index 0000000..bb93161 --- /dev/null +++ b/Sources/App/Content/Config/MapConfig.swift @@ -0,0 +1,19 @@ +// +// MapConfig.swift +// App +// +// Created by Michael Simard on 10/29/21. +// + +import Foundation +import Fluent +import Vapor + +struct MapConfig:Content, Hashable{ + + var mapId:Int + var name:String + var imageName:String + var gameModeGroupIds:[String] + +} diff --git a/Sources/App/Content/Config/PlayerConfig.swift b/Sources/App/Content/Config/PlayerConfig.swift new file mode 100644 index 0000000..12f53d2 --- /dev/null +++ b/Sources/App/Content/Config/PlayerConfig.swift @@ -0,0 +1,15 @@ +// +// PlayerConfig.swift +// App +// +// Created by Michael Simard on 10/30/21. +// + +import Foundation +import Fluent +import Vapor + +struct PlayerConfig: Content { + var playerId: Int + var name: String +} diff --git a/Sources/App/Content/MapRecord.swift b/Sources/App/Content/MapRecord.swift index fbfd4cb..41fff54 100644 --- a/Sources/App/Content/MapRecord.swift +++ b/Sources/App/Content/MapRecord.swift @@ -10,7 +10,7 @@ import Vapor import Fluent struct MapRecord: Content { - var map:Map + var map:MapConfig var stats:Stats var ratio:String } diff --git a/Sources/App/Content/Map.swift b/Sources/App/Content/OldMap.swift similarity index 81% rename from Sources/App/Content/Map.swift rename to Sources/App/Content/OldMap.swift index 5a7796f..2b1e79f 100644 --- a/Sources/App/Content/Map.swift +++ b/Sources/App/Content/OldMap.swift @@ -7,7 +7,7 @@ import Foundation -struct Map: Hashable, Codable { +struct OldMap: Hashable, Codable { var id: Int var name:String var imageName:String diff --git a/Sources/App/Controllers/AppDataController.swift b/Sources/App/Controllers/AppDataController.swift new file mode 100644 index 0000000..2284937 --- /dev/null +++ b/Sources/App/Controllers/AppDataController.swift @@ -0,0 +1,66 @@ +// +// AppDataController.swift +// App +// +// Created by Michael Simard on 10/29/21. +// + + // +import Fluent +import Vapor + +import Foundation + +struct AppDataController: RouteCollection { + + func boot(routes: RoutesBuilder) throws { + let matchRoute = routes.grouped("cod-tracker","api") + matchRoute.get("config", use: config) + } + + func config(req:Request) -> EventLoopFuture{ + + let gameModeConfigs = GameMode.query(on: req.db).all().map { gameMode in + return gameMode.map { gm in + return gm.gameModeConfig + } + } + + let gameModeGroupConfigs = GameModeGroup.query(on: req.db).all().map { gameModeGroup in + return gameModeGroup.map { gmg in + return gmg.gameModeGroupConfig + } + } + + let games = Game.query(on: req.db).all() + let maps = Map.query(on: req.db).all() + + let playerConfigs = Player.query(on: req.db).all().map { player in + return player.map { p in + return p.playerConfig + } + } + + let lossReasonConfigs = LossReason.query(on: req.db).all().map { lossReason in + return lossReason.map { lr in + return lr.lossReasonConfig + } + } + + return (gameModeConfigs.and(gameModeGroupConfigs).and(games).and(maps).and(playerConfigs).and(lossReasonConfigs)).map { arg -> (Configuration) in + + let (((((( gameModeConfigs), gameModeGroupConfigs),games),maps),playerConfigs), lossReasonConfigs) = arg + + var gameConfigs:[GameConfig] = [] + gameConfigs = games.map({ game in + let mapConfigs = game.mapIds.compactMap { mapId in + return maps.first { m in + m.mapId == mapId + }?.mapConfig + } + return GameConfig(gameId: game.gameId, name: game.name, maps: mapConfigs, enabled: game.enabled) + }) + return Configuration(games:gameConfigs, gameModes: gameModeConfigs, gameModeGroups: gameModeGroupConfigs, players: playerConfigs, lossReasons: lossReasonConfigs) + } + } +} diff --git a/Sources/App/Controllers/MapsController.swift b/Sources/App/Controllers/MapsController.swift new file mode 100644 index 0000000..38fe839 --- /dev/null +++ b/Sources/App/Controllers/MapsController.swift @@ -0,0 +1,35 @@ +// +// MapsController.swift +// App +// +// Created by Michael Simard on 10/29/21. +// +import Fluent +import Vapor + +import Foundation + +struct MapsController: RouteCollection { + func boot(routes: RoutesBuilder) throws { + let matchRoute = routes.grouped("cod-tracker","api", "maps") + matchRoute.get("all", use: maps) + matchRoute.get("game-modes", use: gameModes) + matchRoute.get("game-mode-groups", use: gameModeGroups) + + } + + + func maps(req:Request) -> EventLoopFuture<[Map]>{ + return Map.query(on: req.db).all() + + } + + func gameModes(req:Request) -> EventLoopFuture<[GameMode]>{ + return GameMode.query(on: req.db).all() + + } + + func gameModeGroups(req:Request) -> EventLoopFuture<[GameModeGroup]>{ + return GameModeGroup.query(on: req.db).all() + } +} diff --git a/Sources/App/Controllers/StatsController.swift b/Sources/App/Controllers/StatsController.swift index bbf3ab1..23cb4a8 100644 --- a/Sources/App/Controllers/StatsController.swift +++ b/Sources/App/Controllers/StatsController.swift @@ -28,7 +28,6 @@ struct StatsController: RouteCollection { statsRoute.get("maps","game",":game","competitive",":competitive", "gamemode", ":gamemode",use: mapRecords) statsRoute.get("dashboard", use: dashboard) statsRoute.get("recalculate", use: recalc) - statsRoute.get("stats","q",":query", use: history) } @@ -236,11 +235,7 @@ struct StatsController: RouteCollection { } func getStatsWithMostRecentDailyRecord(sortedMatches:[Match], game:String? = nil) -> StatsWithMostRecentDailyRecord { - - - let startTime = Date() - //print ("MRR START \(Date().timeIntervalSince(startTime))") - + let stats = getCountedMatches(matches: sortedMatches) //print ("MRR STATS \(Date().timeIntervalSince(startTime))") @@ -256,9 +251,7 @@ struct StatsController: RouteCollection { func mostRecentDailyStats (matches:[Match], game:String? = nil) -> Stats{ - - let startTime = Date() - + let daysPlayed = getDaysPlayed(sortedMatches: matches) let lastDayPlayed = daysPlayed.last @@ -359,10 +352,7 @@ struct StatsController: RouteCollection { private func getDaysPlayed(sortedMatches:[Match]) -> [CODDate] { - let startTime = 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) } @@ -618,11 +608,7 @@ struct StatsController: RouteCollection { return self.getStatsForDay(year: days.first?.year ?? 0, month: days.first?.month ?? 0, day: days.first?.day ?? 0, req: req) } } - -// func cachedStats(db: Database) -> EventLoopFuture<[String:Stats]> { -// -// } - + func recalc(req:Request) -> EventLoopFuture<[String:Stats]> { return forceCalculatedStats(db: req.db) } @@ -754,9 +740,12 @@ struct StatsController: RouteCollection { let matches = Match.query(on: db).sort( \.$date).all() - return matches.and(dashboardStats).map { arg -> (OverallStats) in + let mapConfigs = mapConfigs(db: db) + + + return matches.and(dashboardStats).and(mapConfigs).map { arg -> (OverallStats) in - let (matches, dashboardStats) = arg + let ((matches, dashboardStats),mapConfigs) = arg let queue = DispatchQueue(label: "com.sledsoft.cod-tracker.queue", attributes: .concurrent) @@ -797,8 +786,8 @@ struct StatsController: RouteCollection { (dashboardStats.dashboardItems + [ - DashboardItem(codTrackerId:"best_map_overall", title: "Best Map", content: MapData.allMaps[bestMap!]?.name ?? "error", title2: "Ratio", content2: "\(mapStats![bestMap!]!.winLossRatio) \(mapStats![bestMap!]!.record)", sortOrder: 12), - DashboardItem(codTrackerId:"worst_map_overall", title: "Worst Map", content: MapData.allMaps[worstMap!]?.name ?? "error", title2: "Ratio", content2: "\(mapStats![worstMap!]!.winLossRatio) \(mapStats![worstMap!]!.record)",sortOrder: 13), + DashboardItem(codTrackerId:"best_map_overall", title: "Best Map", content: mapConfigs.first{$0.mapId == bestMap}?.name ?? "error", title2: "Ratio", content2: "\(mapStats![bestMap!]!.winLossRatio) \(mapStats![bestMap!]!.record)", sortOrder: 12), + DashboardItem(codTrackerId:"worst_map_overall", title: "Worst Map", content: mapConfigs.first{$0.mapId == worstMap}?.name ?? "error", title2: "Ratio", content2: "\(mapStats![worstMap!]!.winLossRatio) \(mapStats![worstMap!]!.record)",sortOrder: 13), ]).sorted{ $0.sortOrder < $1.sortOrder @@ -815,11 +804,25 @@ struct StatsController: RouteCollection { } + func mapConfigs(db: Database) -> EventLoopFuture<[MapConfig]> { + + return Map.query(on: db).all().map { map in + return map.map { m in + return m.mapConfig + } + } + } + func mapRecords(req: Request) throws -> EventLoopFuture<[MapRecord]> { - return Match.query(on: req.db).all().map { (matches) -> [MapRecord] in + + let matches = Match.query(on: req.db).all() + let mapConfigs = mapConfigs(db: req.db) + + return matches.and(mapConfigs).map { matches, mapConfigs in + let mapStats:[Int:Stats] if let game = req.parameters.get("game", as: String.self), @@ -833,10 +836,11 @@ struct StatsController: RouteCollection { mapStats = self.getMapStats(matches: matches,game: "mw", competitive: true) } - let sortedMaps = self.mapsSortedByBest(records: mapStats) + + let sortedMaps = self.mapsSortedByBest(records: mapStats) let records = sortedMaps.map { (mapId) -> MapRecord in - return MapRecord(map: MapData.allMaps[mapId]!, stats: mapStats[mapId]!, ratio:mapStats[mapId]!.winLossRatio) + return MapRecord(map: mapConfigs.first{$0.mapId == mapId}!, stats: mapStats[mapId]!, ratio:mapStats[mapId]!.winLossRatio) } var wins:Double = 0 @@ -849,7 +853,48 @@ struct StatsController: RouteCollection { } return records + } + + + + +// +// return Match.query(on: req.db).all().map { (matches) -> [MapRecord] in +// +// +// +// let mapStats:[Int:Stats] +// +// if let game = req.parameters.get("game", as: String.self), +// let competitive = req.parameters.get("competitive", as:Bool.self) { +// +// let gameMode = req.parameters.get("gamemode", as:Int.self) ?? -2 +// mapStats = self.getMapStats(matches: matches,game: game, competitive: competitive, gameMode: gameMode) +// +// } +// else { +// mapStats = self.getMapStats(matches: matches,game: "mw", competitive: true) +// } +// +// +// let sortedMaps = self.mapsSortedByBest(records: mapStats) +// +// let records = sortedMaps.map { (mapId) -> MapRecord in +// return MapRecord(map: MapData.allMaps[mapId]!, stats: mapStats[mapId]!, ratio:mapStats[mapId]!.winLossRatio) +// } +// +// var wins:Double = 0 +// var loss:Double = 0 +// +// for record in records { +// //print("\(record.map.name) \(record.stats.record) \(record.ratio)") +// wins = wins + Double(record.stats.totalWins) +// loss = loss + Double(record.stats.totalLosses) +// +// } +// return records +// } } func mapsSortedByBest (records :[ Int:Stats] ) -> [ Int ] { diff --git a/Sources/App/Data/MapData.swift b/Sources/App/Data/MapData.swift index 47cc220..d40efd8 100644 --- a/Sources/App/Data/MapData.swift +++ b/Sources/App/Data/MapData.swift @@ -7,119 +7,115 @@ 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"), - 34: Map(id: 34, name: "Express", imageName: "bocw_express"), - 35: Map(id: 35, name: "Apocalypse", imageName: "bocw_apocalypse"), - 36: Map(id: 36, name: "Killhouse", imageName: "mw_killhouse"), - 37: Map(id: 37, name: "Al-Raab Airbase", imageName: "mw_airbase"), - 38: Map(id: 38, name: "Yamantau", imageName: "bocw_yamantau"), - 39: Map(id: 39, name: "Standoff", imageName: "bocw_standoff"), - 40: Map(id: 40, name: "Rush", imageName: "bocw_rush"), - 41: Map(id: 41, name: "Collateral", imageName: "bocw_collateral"), - 42: Map(id: 42, name: "Diesel", imageName: "bocw_diesel"), - 43: Map(id: 43, name: "Miami Strike", imageName: "bocw_miamistrike"), - - 44: Map(id: 44, name: "Amsterdam", imageName: "bocw_amsterdam"), - 45: Map(id: 45, name: "Game Show", imageName: "bocw_gameshow"), - 46: Map(id: 46, name: "ICBM", imageName: "bocw_icbm"), - 47: Map(id: 47, name: "KGB", imageName: "bocw_kgb"), - 48: Map(id: 48, name: "Mansion", imageName: "bocw_mansion"), - 49: Map(id: 49, name: "U-Bahn", imageName: "bocw_ubahn"), - - 50: Map(id: 50, name: "Alpine", imageName: "bocw_alpine"), - 51: Map(id: 51, name: "Duga", imageName: "bocw_duga"), - 52: Map(id: 52, name: "Golova", imageName: "bocw_golova"), - 53: Map(id: 53, name: "Ruka", imageName: "bocw_ruka"), - 54: Map(id: 54, name: "Sanatorium", imageName: "bocw_sanatorium"), - 55: Map(id: 55, name: "Hijacked", imageName: "bocw_hijacked"), - - 56: Map(id: 56, name: "Echelon", imageName: "bocw_echelon"), - 57: Map(id: 57, name: "Slums", imageName: "bocw_slums"), - 58: Map(id: 58, name: "Showroom", imageName: "bocw_showroom"), - 59: Map(id: 59, name: "Drive-In", imageName: "bocw_drive-in"), - 60: Map(id: 60, name: "Zoo", imageName: "bocw_zoo"), +//class MapData { +// static let allMaps:[Int:OldMap] = [ +// 0: OldMap(id: 0, name: "Satellite", imageName: "bocw_satellite"), +// 1: OldMap(id: 1, name: "Armada", imageName: "bocw_armada"), +// 2: OldMap(id: 2, name: "Nuketown", imageName: "bocw_nuketown"), +// 3: OldMap(id: 3, name: "Cartel", imageName: "bocw_cartel"), +// 4: OldMap(id: 4, name: "Garrison", imageName: "bocw_garrison"), +// 5: OldMap(id: 5, name: "Miami", imageName: "bocw_miami"), +// 6: OldMap(id: 6, name: "Moscow", imageName: "bocw_moscow"), +// 7: OldMap(id: 7, name: "Crossroads", imageName: "bocw_crossroads"), +// 8: OldMap(id: 8, name: "Checkmate", imageName: "bocw_checkmate"), +// 9: OldMap(id: 9, name: "Arklov Peak", imageName: "mw_arklov"), +// 10: OldMap(id: 10, name: "Atlas Superstore", imageName: "mw_atlas"), +// 11: OldMap(id: 11, name: "Talsik Backlot", imageName: "mw_backlot"), +// 12: OldMap(id: 12, name: "Broadcast", imageName: "mw_broadcast"), +// 13: OldMap(id: 13, name: "Azhir Cave", imageName: "mw_caves"), +// 14: OldMap(id: 14, name: "Chesire Park", imageName: "mw_chesire"), +// 15: OldMap(id: 15, name: "Crash", imageName: "mw_crash"), +// 28: OldMap(id: 28, name: "Gun Runner", imageName: "mw_gunrunner"), +// 16: OldMap(id: 16, name: "Hackney Yard", imageName: "mw_hackney"), +// 17: OldMap(id: 17, name: "Suldal Harbor", imageName: "mw_harbor"), +// 18: OldMap(id: 18, name: "Hardhat", imageName: "mw_hardhat"), +// 19: OldMap(id: 19, name: "Hovec Sawmill", imageName: "mw_hovec"), +// 20: OldMap(id: 20, name: "Khandor Hideout", imageName: "mw_khandor"), +// 21: OldMap(id: 21, name: "Petrov Oil Rig", imageName: "mw_oil"), +// 22: OldMap(id: 22, name: "St. Petrograd", imageName: "mw_petrograd"), +// 23: OldMap(id: 23, name: "Rammaza", imageName: "mw_rammaza"), +// 24: OldMap(id: 24, name: "Scrapyard", imageName: "mw_scrapyard"), +// 25: OldMap(id: 25, name: "Shoot House", imageName: "mw_shoothouse"), +// 26: OldMap(id: 26, name: "Mialstor Tank Factory", imageName: "mw_tank"), +// 27: OldMap(id: 27, name: "Vacant", imageName: "mw_vacant"), +// 31: OldMap(id: 31, name: "The Pines", imageName: "bocw_pines"), +// 29: OldMap(id: 29, name: "Nuketown Holiday", imageName: "bocw_nuketown_holiday"), +// 30: OldMap(id: 30, name: "Raid", imageName: "bocw_raid"), +// 32: OldMap(id: 32, name: "Piccadilly", imageName: "mw_piccadilly"), +// 33: OldMap(id: 33, name: "Grazna Raid", imageName: "mw_grazna"), +// 34: OldMap(id: 34, name: "Express", imageName: "bocw_express"), +// 35: OldMap(id: 35, name: "Apocalypse", imageName: "bocw_apocalypse"), +// 36: OldMap(id: 36, name: "Killhouse", imageName: "mw_killhouse"), +// 37: OldMap(id: 37, name: "Al-Raab Airbase", imageName: "mw_airbase"), +// 38: OldMap(id: 38, name: "Yamantau", imageName: "bocw_yamantau"), +// 39: OldMap(id: 39, name: "Standoff", imageName: "bocw_standoff"), +// 40: OldMap(id: 40, name: "Rush", imageName: "bocw_rush"), +// 41: OldMap(id: 41, name: "Collateral", imageName: "bocw_collateral"), +// 42: OldMap(id: 42, name: "Diesel", imageName: "bocw_diesel"), +// 43: OldMap(id: 43, name: "Miami Strike", imageName: "bocw_miamistrike"), +// +// 44: OldMap(id: 44, name: "Amsterdam", imageName: "bocw_amsterdam"), +// 45: OldMap(id: 45, name: "Game Show", imageName: "bocw_gameshow"), +// 46: OldMap(id: 46, name: "ICBM", imageName: "bocw_icbm"), +// 47: OldMap(id: 47, name: "KGB", imageName: "bocw_kgb"), +// 48: OldMap(id: 48, name: "Mansion", imageName: "bocw_mansion"), +// 49: OldMap(id: 49, name: "U-Bahn", imageName: "bocw_ubahn"), +// +// 50: OldMap(id: 50, name: "Alpine", imageName: "bocw_alpine"), +// 51: OldMap(id: 51, name: "Duga", imageName: "bocw_duga"), +// 52: OldMap(id: 52, name: "Golova", imageName: "bocw_golova"), +// 53: OldMap(id: 53, name: "Ruka", imageName: "bocw_ruka"), +// 54: OldMap(id: 54, name: "Sanatorium", imageName: "bocw_sanatorium"), +// 55: OldMap(id: 55, name: "Hijacked", imageName: "bocw_hijacked"), +// +// 56: OldMap(id: 56, name: "Echelon", imageName: "bocw_echelon"), +// 57: OldMap(id: 57, name: "Slums", imageName: "bocw_slums"), +// 58: OldMap(id: 58, name: "Showroom", imageName: "bocw_showroom"), +// 59: OldMap(id: 59, name: "Drive-In", imageName: "bocw_drive-in"), +// 60: OldMap(id: 60, name: "Zoo", imageName: "bocw_zoo"), - - - 61: Map(id: 61, name: "Champion Hill", imageName: "vg_championhill"), - 62: Map(id: 62, name: "Hotel Royal", imageName: "vg_hotel"), - 63: Map(id: 63, name: "Red Star", imageName: "vg_redstar"), - 64: Map(id: 64, name: "Gavutu", imageName: "vg_gavutu"), - 65: Map(id: 65, name: "Eagle’s Nest", imageName: "vg_eaglesnest"), - - - - 66: Map(id: 66, name: "Deprogram", imageName: "bocw_deprogram"), - 67: Map(id: 67, name: "Amerika", imageName: "bocw_amerika"), - 68: Map(id: 68, name: "Gluboko", imageName: "bocw_gluboko"), - - 69: Map(id: 69, name: "Nuketown Halloween", imageName: "bocw_nuketown_halloween"), - - - ] - - static let bocwMaps = { - - return [1,3,8,7,4,2,29,31,5,6,30,0,34,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,66,67,68,69].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,36,37].compactMap { - return allMaps[$0] - }.sorted { (m1, m2) -> Bool in - return m1.name < m2.name - } - } - - static let vgMaps = { - return [61,62,63,64,65].compactMap { - return allMaps[$0]; - }.sorted { (m1, m2) -> Bool in - return m1.name < m2.name - } - } - - -} +// 61: OldMap(id: 61, name: "Champion Hill", imageName: "vg_championhill"), +// 62: OldMap(id: 62, name: "Hotel Royal", imageName: "vg_hotel"), +// 63: OldMap(id: 63, name: "Red Star", imageName: "vg_redstar"), +// 64: OldMap(id: 64, name: "Gavutu", imageName: "vg_gavutu"), +// 65: OldMap(id: 65, name: "Eagle’s Nest", imageName: "vg_eaglesnest"), +// +// +// +// 66: OldMap(id: 66, name: "Deprogram", imageName: "bocw_deprogram"), +// 67: OldMap(id: 67, name: "Amerika", imageName: "bocw_amerika"), +// 68: OldMap(id: 68, name: "Gluboko", imageName: "bocw_gluboko"), +// +// 69: OldMap(id: 69, name: "Nuketown Halloween", imageName: "bocw_nuketown_halloween"), +// +// +// ] +// +// static let bocwMaps = { +// +// return [1,3,8,7,4,2,29,31,5,6,30,0,34,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,66,67,68,69].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,36,37].compactMap { +// return allMaps[$0] +// }.sorted { (m1, m2) -> Bool in +// return m1.name < m2.name +// } +// } +// +// static let vgMaps = { +// return [61,62,63,64,65].compactMap { +// return allMaps[$0]; +// }.sorted { (m1, m2) -> Bool in +// return m1.name < m2.name +// } +// } +// +// +//} diff --git a/Sources/App/Models/Game.swift b/Sources/App/Models/Game.swift new file mode 100644 index 0000000..15396f3 --- /dev/null +++ b/Sources/App/Models/Game.swift @@ -0,0 +1,53 @@ +// +// Game.swift +// App +// +// Created by Michael Simard on 10/29/21. +// + +import Foundation + + +import Fluent +import Vapor + +final class Game: Model, Content { + // Name of the table or collection. + static let schema = "game" + + @ID(key: .id) + var id: UUID? + + @Field(key: "game_id") + var gameId: String + + @Field(key: "name") + var name: String + + @Field(key: "maps") + var maps: String + + + @Field(key: "enabled") + var enabled: Bool + + + + + // Creates a new, empty . + init() { } + + // Creates a new with all properties set. + init(id: UUID? = nil, gameId: String, name: String, maps:String, enabled:Bool) { + self.id = id + self.gameId = gameId + self.name = name + self.maps = maps + self.enabled = enabled + } + + + var mapIds:[Int] { + maps.components(separatedBy: ",").map{Int($0)!} + } +} diff --git a/Sources/App/Models/GameMode.swift b/Sources/App/Models/GameMode.swift new file mode 100644 index 0000000..82902bf --- /dev/null +++ b/Sources/App/Models/GameMode.swift @@ -0,0 +1,51 @@ +// +// GameModes.swift +// App +// +// Created by Michael Simard on 10/29/21. +// + +import Foundation + +import Fluent +import Vapor + +final class GameMode: Model, Content { + // Name of the table or collection. + static let schema = "game_mode" + + @ID(key: .id) + var id: UUID? + + @Field(key: "game_mode_id") + var gameModeId: Int + + @Field(key: "name") + var name: String + + @Field(key: "competitive") + var competitive: Bool + + + + + // Creates a new, empty . + init() { } + + // Creates a new with all properties set. + init(id: UUID? = nil, gameModeId: Int, name: String, competitive:Bool) { + self.id = id + self.gameModeId = gameModeId + self.name = name + self.competitive = competitive + + } + + + var gameModeConfig:GameModeConfig { + return GameModeConfig(gameModeId: gameModeId, name: name, competitive: competitive) + } + + + +} diff --git a/Sources/App/Models/GameModeGroup.swift b/Sources/App/Models/GameModeGroup.swift new file mode 100644 index 0000000..7e2993d --- /dev/null +++ b/Sources/App/Models/GameModeGroup.swift @@ -0,0 +1,45 @@ +// +// GameModeGroups.swift +// App +// +// Created by Michael Simard on 10/29/21. +// + + import Fluent +import Vapor + +final class GameModeGroup: Model, Content { + // Name of the table or collection. + static let schema = "game_mode_group" + + @ID(key: .id) + var id: UUID? + + @Field(key: "game_mode_ids") + var gameModeIds: String + + @Field(key: "game_mode_group_id") + var gameModeGroupId: String + + @Field(key: "name") + var name: String + + + + + // Creates a new, empty . + init() { } + + // Creates a new with all properties set. + init(id: UUID? = nil, gameModeIds: String, name: String, gameModeGroupId:String) { + self.id = id + self.gameModeIds = gameModeIds + self.name = name + self.gameModeGroupId = gameModeGroupId + } + + + var gameModeGroupConfig: GameModeGroupConfig { + return GameModeGroupConfig(gameModeIds: gameModeIds, gameModeGroupId: gameModeGroupId, name: name) + } +} diff --git a/Sources/App/Models/LossReason.swift b/Sources/App/Models/LossReason.swift new file mode 100644 index 0000000..b3c677e --- /dev/null +++ b/Sources/App/Models/LossReason.swift @@ -0,0 +1,43 @@ +// +// LossReason.swift +// App +// +// Created by Michael Simard on 10/30/21. +// + +import Fluent +import Vapor + +import Fluent +import Vapor + +final class LossReason: Model, Content { + // Name of the table or collection. + static let schema = "loss_reason" + + @ID(key: .id) + var id: UUID? + + @Field(key: "reason_id") + var reasonId: Int + + @Field(key: "name") + var name: String + + // Creates a new, empty . + init() { } + + // Creates a new with all properties set. + init(id: UUID? = nil, lossReasonId: Int, name: String) { + self.id = id + self.reasonId = reasonId + self.name = name + + } + + + var lossReasonConfig: LossReasonConfig { + return LossReasonConfig(reasonId: reasonId, name: name) + + } +} diff --git a/Sources/App/Models/Map.swift b/Sources/App/Models/Map.swift new file mode 100644 index 0000000..b6a7e33 --- /dev/null +++ b/Sources/App/Models/Map.swift @@ -0,0 +1,48 @@ +// +// Map.swift +// App +// +// Created by Michael Simard on 10/29/21. +// + + +import Fluent +import Vapor + +final class Map: Model, Content { + // Name of the table or collection. + static let schema = "map" + + @ID(key: .id) + var id: UUID? + + @Field(key: "name") + var name: String + + @Field(key: "image_name") + var imageName: String + + @Field(key: "game_mode_group_ids") + var gameModeGroupIds: String + + @Field(key: "map_id") + var mapId: Int + + + // Creates a new, empty . + init() { } + + // Creates a new with all properties set. + init(id: UUID? = nil, name: String, imageName: String, gameModeGroupIds: String, mapId:Int) { + self.id = id + self.name = name + self.imageName = imageName + self.gameModeGroupIds = gameModeGroupIds + self.mapId = mapId + + } + + var mapConfig:MapConfig { + return MapConfig(mapId: mapId, name: name, imageName: imageName, gameModeGroupIds: gameModeGroupIds.components(separatedBy: ",")) + } +} diff --git a/Sources/App/Models/Match.swift b/Sources/App/Models/Match.swift index 43a2c15..f615248 100644 --- a/Sources/App/Models/Match.swift +++ b/Sources/App/Models/Match.swift @@ -47,11 +47,14 @@ final class Match: Model, Content { var gameMode: Int + @Field(key: "lossReason") + var lossReason: Int + init() { } - init(id: UUID? = nil, map:String?, win:Bool, date:Date, roundsWon:Int?, roundsLost:Int?, codGame:String?, notes:String?, players:String?, sweaty:Bool?, finalKillRuinedPlayerId:Int?, numberOfFinalKillsRuined:Int?,competitive:Bool, gameMode:Int) { + init(id: UUID? = nil, map:String?, win:Bool, date:Date, roundsWon:Int?, roundsLost:Int?, codGame:String?, notes:String?, players:String?, sweaty:Bool?, finalKillRuinedPlayerId:Int?, numberOfFinalKillsRuined:Int?,competitive:Bool, gameMode:Int, lossReason:Int) { self.id = id self.map = map self.win = win @@ -66,7 +69,7 @@ final class Match: Model, Content { self.numberOfFinalKillsRuined = numberOfFinalKillsRuined self.competitive = competitive self.gameMode = gameMode - + self.lossReason = lossReason } func update( newMatch:Match) { @@ -88,6 +91,7 @@ final class Match: Model, Content { self.numberOfFinalKillsRuined = newMatch.numberOfFinalKillsRuined self.competitive = newMatch.competitive self.gameMode = newMatch.gameMode + self.lossReason = newMatch.lossReason } diff --git a/Sources/App/Models/Player.swift b/Sources/App/Models/Player.swift new file mode 100644 index 0000000..ebae06e --- /dev/null +++ b/Sources/App/Models/Player.swift @@ -0,0 +1,40 @@ +// +// Player.swift +// App +// +// Created by Michael Simard on 10/30/21. +// + +import Fluent +import Vapor + +final class Player: Model, Content { + // Name of the table or collection. + static let schema = "player" + + @ID(key: .id) + var id: UUID? + + @Field(key: "player_id") + var playerId: Int + + @Field(key: "name") + var name: String + + // Creates a new, empty . + init() { } + + // Creates a new with all properties set. + init(id: UUID? = nil, playerId: Int, name: String) { + self.id = id + self.playerId = playerId + self.name = name + + } + + + var playerConfig: PlayerConfig { + return PlayerConfig(playerId: playerId, name: name) + + } +} diff --git a/Sources/App/Models/Statistics.swift b/Sources/App/Models/Statistics.swift index 6e9eef0..079acba 100644 --- a/Sources/App/Models/Statistics.swift +++ b/Sources/App/Models/Statistics.swift @@ -55,6 +55,7 @@ final class WinLossRecords: Model, Content { self.wins = statistics.wins self.losses = statistics.losses self.codTrackerId = statistics.codTrackerId + } diff --git a/Sources/App/routes.swift b/Sources/App/routes.swift index c2b800a..c538d1e 100644 --- a/Sources/App/routes.swift +++ b/Sources/App/routes.swift @@ -12,5 +12,7 @@ func routes(_ app: Application) throws { try app.register(collection: StatsController()) try app.register(collection: MatchController()) + try app.register(collection: MapsController()) + try app.register(collection: AppDataController()) }