added some initial routes, ways to show overall stats, matches
This commit is contained in:
117
Sources/App/Controllers/StatsAPIController.swift
Normal file
117
Sources/App/Controllers/StatsAPIController.swift
Normal file
@@ -0,0 +1,117 @@
|
||||
////
|
||||
//// StatsAPIController.swift
|
||||
//// App
|
||||
////
|
||||
//// Created by Michael Simard on 5/29/20.
|
||||
////
|
||||
//
|
||||
//import Fluent
|
||||
//import Vapor
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//protocol ContentController {
|
||||
// associatedtype Model: Fluent.Model
|
||||
//}
|
||||
//
|
||||
//protocol StatsContentRepresentable {
|
||||
// associatedtype StatsItem: Content
|
||||
// var statsContent : StatsItem { get }
|
||||
//}
|
||||
//
|
||||
//
|
||||
//protocol StatsContentController: ContentController where Model: StatsContentRepresentable {
|
||||
//
|
||||
// func stats (_:Request) throws -> EventLoopFuture<Page<Model.StatsItem>>
|
||||
// func setupStatsRoute( routes: RoutesBuilder)
|
||||
//}
|
||||
//
|
||||
//extension StatsContentController {
|
||||
//
|
||||
//
|
||||
// func stats (req:Request) throws -> EventLoopFuture<Page<Model.StatsItem>> {
|
||||
// return Model.query(on: req.db).paginate(for: req).map { $0.map(\.statsContent)}
|
||||
//
|
||||
// }
|
||||
//
|
||||
// func setupStatsRoute( routes: RoutesBuilder)
|
||||
// {
|
||||
// routes.get(use: self.stats)
|
||||
// }
|
||||
//
|
||||
//}
|
||||
//
|
||||
//
|
||||
//
|
||||
////***********
|
||||
//
|
||||
//final class StatsModel: Model, Content {
|
||||
// typealias IDValue = <#type#>
|
||||
//
|
||||
// static var schema: String
|
||||
//
|
||||
// init() {
|
||||
// <#code#>
|
||||
// }
|
||||
//
|
||||
// var winLoss:String
|
||||
// var totalWins:Int
|
||||
// var totalLosses:Int
|
||||
// init( winLoss:String, totalWins:Int, totalLosses:Int) {
|
||||
//
|
||||
// self.winLoss = winLoss
|
||||
// self.totalWins = totalWins
|
||||
// self.totalLosses = totalLosses
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//extension StatsModel: StatsContentRepresentable {
|
||||
//
|
||||
// struct StatsItem: Content {
|
||||
//
|
||||
// var winLoss:String
|
||||
// var totalWins:Int
|
||||
// var totalLosses:Int
|
||||
//
|
||||
// init(model:StatsModel) {
|
||||
//
|
||||
// self.winLoss = model.winLoss
|
||||
// self.totalWins = model.totalWins
|
||||
// self.totalLosses = model.totalLosses
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// var statsContent: StatsItem { .init(model:self) }
|
||||
//}
|
||||
//
|
||||
//
|
||||
////***********
|
||||
//
|
||||
//
|
||||
//struct StatsAPIController: StatsContentController {
|
||||
//
|
||||
// typealias Model = StatsModel
|
||||
//
|
||||
//
|
||||
//}
|
||||
//
|
||||
//struct StatsRouter: RouteCollection {
|
||||
//
|
||||
// func boot(routes: RoutesBuilder) throws {
|
||||
// let statsRoute = routes.grouped("api", "stats")
|
||||
//
|
||||
// StatsAPIController().setupStatsRoute(routes: statsRoute)
|
||||
//
|
||||
//// statsRoute.get("allMatches", use: index)
|
||||
//// statsRoute.get("totalWins", use: totalWins)
|
||||
//// statsRoute.get("totalLosses", use: totalLosses)
|
||||
// //statsRoute.get("overall", use: totalLosses)
|
||||
//
|
||||
// //beaconsRoute.get("overallStats", use: index)
|
||||
// //beaconsRoute.post("", use: create)
|
||||
// // beaconsRoute.delete(":beaconID", use: delete)
|
||||
//
|
||||
// }
|
||||
//}
|
||||
86
Sources/App/Controllers/StatsController.swift
Normal file
86
Sources/App/Controllers/StatsController.swift
Normal file
@@ -0,0 +1,86 @@
|
||||
import Fluent
|
||||
import Vapor
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct StatsController: RouteCollection {
|
||||
func boot(routes: RoutesBuilder) throws {
|
||||
let statsRoute = routes.grouped("api", "stats")
|
||||
|
||||
statsRoute.get("allMatches", use: index)
|
||||
statsRoute.get("totalWins", use: totalWins)
|
||||
statsRoute.get("totalLosses", use: totalLosses)
|
||||
statsRoute.get("overall", use: overall)
|
||||
|
||||
//beaconsRoute.get("overallStats", use: index)
|
||||
//beaconsRoute.post("", use: create)
|
||||
// beaconsRoute.delete(":beaconID", use: delete)
|
||||
|
||||
}
|
||||
|
||||
func index(req: Request) throws -> EventLoopFuture<[Match]> {
|
||||
return Match.query(on: req.db).all()
|
||||
}
|
||||
|
||||
|
||||
func totalWins(req: Request) throws -> EventLoopFuture<Int> {
|
||||
return Match.query(on: req.db)
|
||||
.filter(\.$win == true)
|
||||
.count()
|
||||
}
|
||||
|
||||
func totalLosses(req: Request) throws -> EventLoopFuture<Int> {
|
||||
return Match.query(on: req.db)
|
||||
.filter(\.$win == false)
|
||||
.count()
|
||||
}
|
||||
|
||||
|
||||
func overall(req: Request) throws -> EventLoopFuture<Stats> {
|
||||
let lossCount = Match.query(on: req.db)
|
||||
.filter(\.$win == false)
|
||||
.count()
|
||||
|
||||
|
||||
let winCount = Match.query(on: req.db)
|
||||
.filter(\.$win == true )
|
||||
.count()
|
||||
|
||||
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
//
|
||||
|
||||
// func create(req: Request) throws -> EventLoopFuture<Beacon> {
|
||||
// let newBeacon = try req.content.decode(Beacon.Create.self)
|
||||
// let beacon = Beacon(id: UUID(), ownerId: nil)
|
||||
// return beacon.save(on: req.db).map { beacon }
|
||||
// }
|
||||
//
|
||||
// func delete(req: Request) throws -> EventLoopFuture<HTTPStatus> {
|
||||
// return Beacon.find(req.parameters.get("beaconID"), on: req.db)
|
||||
// .unwrap(or: Abort(.notFound))
|
||||
// .flatMap { $0.delete(on: req.db) }
|
||||
// .transform(to: .ok)
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
extension Double
|
||||
{
|
||||
func truncate(places : Int)-> Double
|
||||
{
|
||||
return Double(floor(pow(10.0, Double(places)) * self)/pow(10.0, Double(places)))
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import Fluent
|
||||
import Vapor
|
||||
|
||||
struct TodoController: RouteCollection {
|
||||
func boot(routes: RoutesBuilder) throws {
|
||||
let todos = routes.grouped("match")
|
||||
todos.get(use: index)
|
||||
todos.post(use: create)
|
||||
todos.group(":matchID") { todo in
|
||||
todo.delete(use: delete)
|
||||
}
|
||||
}
|
||||
|
||||
func index(req: Request) throws -> EventLoopFuture<[Todo]> {
|
||||
return Todo.query(on: req.db).all()
|
||||
}
|
||||
|
||||
func create(req: Request) throws -> EventLoopFuture<Todo> {
|
||||
let todo = try req.content.decode(Todo.self)
|
||||
return todo.save(on: req.db).map { todo }
|
||||
}
|
||||
|
||||
func delete(req: Request) throws -> EventLoopFuture<HTTPStatus> {
|
||||
return Todo.find(req.parameters.get("matchID"), on: req.db)
|
||||
.unwrap(or: Abort(.notFound))
|
||||
.flatMap { $0.delete(on: req.db) }
|
||||
.transform(to: .ok)
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ struct CreateMatch: Migration {
|
||||
.id()
|
||||
.field("map", .string)
|
||||
.field("win", .bool)
|
||||
.field("date", .bool)
|
||||
.field("date", .date)
|
||||
.field("roundsWon", .int)
|
||||
.field("roundsLost", .int)
|
||||
|
||||
|
||||
43
Sources/App/Models/Match.swift
Normal file
43
Sources/App/Models/Match.swift
Normal file
@@ -0,0 +1,43 @@
|
||||
import Fluent
|
||||
import Vapor
|
||||
|
||||
final class Match: Model, Content {
|
||||
static let schema = "match"
|
||||
|
||||
@ID(key: .id)
|
||||
var id: UUID?
|
||||
|
||||
@Field(key: "map")
|
||||
var map: String?
|
||||
|
||||
@Field(key: "win")
|
||||
var win: Bool
|
||||
|
||||
@Field(key: "date")
|
||||
var date: Date
|
||||
|
||||
@Field(key: "roundsWon")
|
||||
var roundsWon: Int?
|
||||
|
||||
@Field(key: "roundsLost")
|
||||
var roundsLost: Int?
|
||||
|
||||
|
||||
init() { }
|
||||
|
||||
init(id: UUID? = nil, map:String?, win:Bool, date:Date, roundsWon:Int?, roundsLost:Int?) {
|
||||
self.id = id
|
||||
self.map = map
|
||||
self.win = win
|
||||
self.date = date
|
||||
self.roundsWon = roundsWon
|
||||
self.roundsLost = roundsLost
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension Match {
|
||||
struct Create: Content {
|
||||
}
|
||||
}
|
||||
|
||||
24
Sources/App/Models/Stats.swift
Normal file
24
Sources/App/Models/Stats.swift
Normal file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Stats.swift
|
||||
// App
|
||||
//
|
||||
// Created by Michael Simard on 5/29/20.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
import Fluent
|
||||
import Vapor
|
||||
|
||||
final class Stats: Content {
|
||||
var winLossRatio:String
|
||||
var totalWins:Int
|
||||
var totalLosses:Int
|
||||
|
||||
init( winLoss:String, totalWins:Int, totalLosses:Int) {
|
||||
self.winLossRatio = winLoss
|
||||
self.totalWins = totalWins
|
||||
self.totalLosses = totalLosses
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import Fluent
|
||||
import Vapor
|
||||
|
||||
final class Todo: Model, Content {
|
||||
static let schema = "todos"
|
||||
|
||||
@ID(key: .id)
|
||||
var id: UUID?
|
||||
|
||||
@Field(key: "title")
|
||||
var title: String
|
||||
|
||||
init() { }
|
||||
|
||||
init(id: UUID? = nil, title: String) {
|
||||
self.id = id
|
||||
self.title = title
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,10 @@ public func configure(_ app: Application) throws {
|
||||
// app.middleware.use(FileMiddleware(publicDirectory: app.directory.publicDirectory))
|
||||
|
||||
app.databases.use(.postgres(
|
||||
hostname: Environment.get("DATABASE_HOST") ?? "localhost",
|
||||
username: Environment.get("DATABASE_USERNAME") ?? "fanosphere",
|
||||
password: Environment.get("DATABASE_PASSWORD") ?? "pw4fanosphere",
|
||||
database: Environment.get("DATABASE_NAME") ?? "codmw"
|
||||
hostname: Environment.get("DATABASE_HOST") ?? "sledsoft.com",
|
||||
username: Environment.get("DATABASE_USERNAME") ?? "cod",
|
||||
password: Environment.get("DATABASE_PASSWORD") ?? "pw4cod",
|
||||
database: Environment.get("DATABASE_NAME") ?? "cod_db"
|
||||
), as: .psql)
|
||||
|
||||
app.migrations.add(CreateMatch())
|
||||
|
||||
@@ -10,5 +10,5 @@ func routes(_ app: Application) throws {
|
||||
return "Hello, world!"
|
||||
}
|
||||
|
||||
try app.register(collection: TodoController())
|
||||
try app.register(collection: StatsController())
|
||||
}
|
||||
Reference in New Issue
Block a user