Make first check-in for a training event

This commit is contained in:
Raimund Wege
2017-08-29 16:23:40 +02:00
parent 40e68ffb45
commit 26c6ea7ae7
8 changed files with 318 additions and 23 deletions
@@ -348,6 +348,9 @@
C8739E1C1D2D5F1700A89F3C /* LocationData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E1B1D2D5F1700A89F3C /* LocationData.swift */; };
C87A74E11F4EE570003DE396 /* TrainingRequestManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C87A74E01F4EE570003DE396 /* TrainingRequestManager.swift */; };
C87A74E31F4F0E34003DE396 /* TrainingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C87A74E21F4F0E34003DE396 /* TrainingController.swift */; };
C87A74E81F504EBB003DE396 /* CreateEventData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C87A74E71F504EBB003DE396 /* CreateEventData.swift */; };
C87A74EA1F5053AE003DE396 /* CompetitorCreateAndAddData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C87A74E91F5053AE003DE396 /* CompetitorCreateAndAddData.swift */; };
C87A74EC1F5068D0003DE396 /* CreateTrainingData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C87A74EB1F5068D0003DE396 /* CreateTrainingData.swift */; };
C89C5FC51D06A289002AAAD2 /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C5FC41D06A289002AAAD2 /* GradientView.swift */; };
C89C5FCA1D06CECD002AAAD2 /* TrackingViewStatusCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C5FC91D06CECD002AAAD2 /* TrackingViewStatusCell.swift */; };
C89C5FCC1D06CF0C002AAAD2 /* TrackingViewGPSAccuracyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C5FCB1D06CF0C002AAAD2 /* TrackingViewGPSAccuracyCell.swift */; };
@@ -750,6 +753,9 @@
C8739E1B1D2D5F1700A89F3C /* LocationData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationData.swift; sourceTree = "<group>"; };
C87A74E01F4EE570003DE396 /* TrainingRequestManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrainingRequestManager.swift; sourceTree = "<group>"; };
C87A74E21F4F0E34003DE396 /* TrainingController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrainingController.swift; sourceTree = "<group>"; };
C87A74E71F504EBB003DE396 /* CreateEventData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateEventData.swift; sourceTree = "<group>"; };
C87A74E91F5053AE003DE396 /* CompetitorCreateAndAddData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompetitorCreateAndAddData.swift; sourceTree = "<group>"; };
C87A74EB1F5068D0003DE396 /* CreateTrainingData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateTrainingData.swift; sourceTree = "<group>"; };
C89C5FC41D06A289002AAAD2 /* GradientView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = "<group>"; };
C89C5FC91D06CECD002AAAD2 /* TrackingViewStatusCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrackingViewStatusCell.swift; sourceTree = "<group>"; };
C89C5FCB1D06CF0C002AAAD2 /* TrackingViewGPSAccuracyCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrackingViewGPSAccuracyCell.swift; sourceTree = "<group>"; };
@@ -898,14 +904,10 @@
7F06590219F7FEA40077FF95 /* DataController */ = {
isa = PBXGroup;
children = (
7F23F0871A1A3DEF00F03F1C /* CheckInController.swift */,
C843D4871EBCADDC00250F01 /* CompetitorSessionController.swift */,
C84936171D40D295000F30E8 /* GPSFixController.swift */,
C843D4891EBCADF500250F01 /* MarkSessionController.swift */,
C8739E0E1D2BEE7900A89F3C /* SessionController.swift */,
C87A74E61F504CB4003DE396 /* SignUp */,
C87A74E51F504CA7003DE396 /* Regatta */,
C87A74E41F504C97003DE396 /* Training */,
C8739E101D2BF13200A89F3C /* Data */,
C85DB82D1F31D804009559CE /* SignUpController.swift */,
C87A74E21F4F0E34003DE396 /* TrainingController.swift */,
);
name = DataController;
sourceTree = "<group>";
@@ -1337,10 +1339,41 @@
C8739E1B1D2D5F1700A89F3C /* LocationData.swift */,
C8BFCCC31D51C53500FC1A27 /* TeamData.swift */,
C8FF5B7B1EB8CF2C00CF9764 /* MarkData.swift */,
C87A74E71F504EBB003DE396 /* CreateEventData.swift */,
C87A74E91F5053AE003DE396 /* CompetitorCreateAndAddData.swift */,
C87A74EB1F5068D0003DE396 /* CreateTrainingData.swift */,
);
name = Data;
sourceTree = "<group>";
};
C87A74E41F504C97003DE396 /* Training */ = {
isa = PBXGroup;
children = (
C87A74E21F4F0E34003DE396 /* TrainingController.swift */,
);
name = Training;
sourceTree = "<group>";
};
C87A74E51F504CA7003DE396 /* Regatta */ = {
isa = PBXGroup;
children = (
7F23F0871A1A3DEF00F03F1C /* CheckInController.swift */,
C843D4871EBCADDC00250F01 /* CompetitorSessionController.swift */,
C84936171D40D295000F30E8 /* GPSFixController.swift */,
C843D4891EBCADF500250F01 /* MarkSessionController.swift */,
C8739E0E1D2BEE7900A89F3C /* SessionController.swift */,
);
name = Regatta;
sourceTree = "<group>";
};
C87A74E61F504CB4003DE396 /* SignUp */ = {
isa = PBXGroup;
children = (
C85DB82D1F31D804009559CE /* SignUpController.swift */,
);
name = SignUp;
sourceTree = "<group>";
};
C89C5FC31D06A269002AAAD2 /* Views */ = {
isa = PBXGroup;
children = (
@@ -1971,9 +2004,11 @@
C8F71EF31D86A15F00826DE4 /* SMTWiFiStatus.m in Sources */,
7F8CC2081A10D47A00C56D7F /* SettingsViewController.swift in Sources */,
C8739E0D1D2AA2A500A89F3C /* Event.swift in Sources */,
C87A74EC1F5068D0003DE396 /* CreateTrainingData.swift in Sources */,
7F8B8D411A373B0200C34B88 /* SpeedViewController.swift in Sources */,
9E95C3D61C723AB30016632B /* Constants.swift in Sources */,
C8F71EF01D8691F700826DE4 /* UIWebView+AFNetworking.m in Sources */,
C87A74E81F504EBB003DE396 /* CreateEventData.swift in Sources */,
7FD9D3031A1236080058FEAD /* Extensions.swift in Sources */,
C8739E091D2AA2A500A89F3C /* Leaderboard.swift in Sources */,
C8B3B9BC1F39E64400B3B6BA /* Keychain.swift in Sources */,
@@ -2004,6 +2039,7 @@
7F950A911A35E967003C8C5C /* LeaderboardViewController.swift in Sources */,
C8F71EED1D8691F700826DE4 /* UIImageView+AFNetworking.m in Sources */,
C8F71EEB1D8691F700826DE4 /* UIAlertView+AFNetworking.m in Sources */,
C87A74EA1F5053AE003DE396 /* CompetitorCreateAndAddData.swift in Sources */,
C843D48C1EBCB36900250F01 /* SessionViewController.swift in Sources */,
C85DB8281F31AAE0009559CE /* SignUpViewController.swift in Sources */,
C89C5FCE1D06CF26002AAAD2 /* TrackingViewGPSFixesCell.swift in Sources */,
@@ -132,7 +132,19 @@ class CheckInData: NSObject {
return nil
}
}
convenience init?(createTrainingData: CreateTrainingData) {
guard let eventID = createTrainingData.createEventData?.eventID else { return nil }
guard let leaderboardName = createTrainingData.createEventData?.leaderboardName else { return nil }
guard let competitorID = createTrainingData.competitorCreateAndAddData?.competitorID else { return nil }
self.init(
serverURL: createTrainingData.serverURL,
eventID: eventID,
leaderboardName: leaderboardName,
competitorID: competitorID
)
}
// MARK: - Helper
class fileprivate func queryItemValue(queryItems: [URLQueryItem]?, itemName: String) -> String? {
@@ -0,0 +1,19 @@
//
// CompetitorCreateAndAddData.swift
// SAPTracker
//
// Created by Raimund Wege on 25.08.17.
// Copyright © 2017 com.sap.sailing. All rights reserved.
//
import UIKit
class CompetitorCreateAndAddData: BaseData {
fileprivate struct Keys {
static let ID = "id"
}
var competitorID: String { get { return stringValue(forKey: Keys.ID) } }
}
@@ -0,0 +1,31 @@
//
// CreateEventData.swift
// SAPTracker
//
// Created by Raimund Wege on 25.08.17.
// Copyright © 2017 com.sap.sailing. All rights reserved.
//
import UIKit
class CreateEventData: BaseData {
fileprivate struct Keys {
static let EndDate = "eventenddate"
static let ID = "eventid"
static let LeaderboardName = "leaderboard"
static let LeaderboardGroupID = "leaderboardgroupid"
static let Name = "eventname"
static let Regatta = "regatta"
static let StartDate = "eventstartdate"
}
var endDate: Double { get { return doubleValue(forKey: Keys.EndDate) / 1000 } }
var eventID: String { get { return stringValue(forKey: Keys.ID) } }
var name: String { get { return stringValue(forKey: Keys.Name) } }
var leaderboardName: String { get { return stringValue(forKey: Keys.LeaderboardName) } }
var leaderboardGroupID: String { get { return stringValue(forKey: Keys.LeaderboardGroupID) } }
var regatta: String { get { return stringValue(forKey: Keys.Regatta) } }
var startDate: Double { get { return doubleValue(forKey: Keys.StartDate) / 1000 } }
}
@@ -0,0 +1,27 @@
//
// CreateTrainingData.swift
// SAPTracker
//
// Created by Raimund Wege on 25.08.17.
// Copyright © 2017 com.sap.sailing. All rights reserved.
//
import UIKit
class CreateTrainingData: NSObject {
let serverURL: String
let boatClassName: String
let sailID: String = "123"
let nationality: String = "GER"
var createEventData: CreateEventData?
var competitorCreateAndAddData: CompetitorCreateAndAddData?
init(serverURL: String, boatClassName: String) {
self.serverURL = serverURL
self.boatClassName = boatClassName
super.init()
}
}
@@ -42,9 +42,38 @@ class CreateTrainingViewController: UIViewController {
@IBAction func createTrainingButtonTapped(_ sender: Any) {
let boatClassName = BoatClassNames[boatClassPickerView.selectedRow(inComponent: 0)]
trainingController.createEvent(boatClassName: boatClassName)
createTraining(boatClassName: boatClassName)
}
// MARK: - CreateTraining
fileprivate func createTraining(boatClassName: String) {
trainingController.createTraining(forBoatClassName: boatClassName, success: { checkInData in
self.createTrainingSuccess(checkInData: checkInData)
}) { (error) in
self.createTrainingFailure(error: error)
}
}
fileprivate func createTrainingSuccess(checkInData: CheckInData) {
checkInController.checkInWithViewController(self, checkInData: checkInData, success: { checkIn in
// TODO
}) { error in
self.createTrainingFailure(error: error)
}
}
fileprivate func createTrainingFailure(error: Error) {
// TODO
}
// MARK: - Propeties
fileprivate lazy var checkInController: CheckInController = {
let checkInController = CheckInController(coreDataManager: RegattaCoreDataManager.shared)
return checkInController
}()
}
// MARK: - UIPickerViewDataSource
@@ -8,8 +8,13 @@
import UIKit
class TrainingController: NSObject {
enum TrainingControllerError: Error {
case regattaIsMissing
case checkInDataIsIncomplete
}
class TrainingController: NSObject {
let requestManager: TrainingRequestManager
init(baseURLString: String) {
@@ -17,14 +22,108 @@ class TrainingController: NSObject {
super.init()
}
// MARK: - CreateTraining
func createTraining(
forBoatClassName boatClassName: String,
success: @escaping (_ checkInData: CheckInData) -> Void,
failure: @escaping (_ error: Error) -> Void)
{
let collector = CreateTrainingData.init(serverURL: requestManager.baseURLString, boatClassName: boatClassName)
createTraining(collector: collector, success: success, failure: failure)
}
fileprivate func createTraining(
collector: CreateTrainingData,
success: @escaping (_ checkInData: CheckInData) -> Void,
failure: @escaping (_ error: Error) -> Void)
{
createEvent(collector: collector, success: { createTrainingData in
self.createTrainingSuccess(collector: createTrainingData, success: success, failure: failure)
}) { error in
self.createTrainingFailure(error: error, failure: failure)
}
}
fileprivate func createTrainingSuccess(
collector: CreateTrainingData,
success:(_ checkInData: CheckInData) -> Void,
failure: @escaping (_ error: Error) -> Void)
{
if let checkInData = CheckInData.init(createTrainingData: collector) {
success(checkInData)
} else {
failure(TrainingControllerError.checkInDataIsIncomplete)
}
}
fileprivate func createTrainingFailure(error: Error, failure: (_ error: Error) -> Void) {
failure(error)
}
// MARK: - CreateEvent
func createEvent(boatClassName: String) {
requestManager.postCreateEvent(boatClassName: boatClassName, success: {
}, failure: { (error, message) in
})
fileprivate func createEvent(
collector: CreateTrainingData,
success: @escaping (_ createTrainingData: CreateTrainingData) -> Void,
failure: @escaping (_ error: Error) -> Void)
{
requestManager.postCreateEvent(boatClassName: collector.boatClassName, success: { createEventData in
collector.createEventData = createEventData
self.createEventSuccess(collector: collector, success: success, failure: failure)
}) { (error, message) in
self.createEventFailure(error: error, message: message, failure: failure)
}
}
fileprivate func createEventSuccess(
collector: CreateTrainingData,
success: @escaping (_ createTrainingData: CreateTrainingData) -> Void,
failure: @escaping (_ error: Error) -> Void)
{
do {
try competitorCreateAndAdd(collector: collector, success: success, failure: failure)
} catch {
failure(error)
}
}
fileprivate func createEventFailure(error: Error, message: String?, failure: (_ error: Error) -> Void) {
failure(error)
}
// MARK: - CompetitorCreateAndAdd
fileprivate func competitorCreateAndAdd(
collector: CreateTrainingData,
success: @escaping (_ createTrainingData: CreateTrainingData) -> Void,
failure: @escaping (_ error: Error) -> Void) throws
{
guard let regatta = collector.createEventData?.regatta else {
throw TrainingControllerError.regattaIsMissing
}
let boatClassName = collector.boatClassName
let sailID = collector.sailID
let nationality = collector.nationality
requestManager.postCompetitorCreateAndAdd(regatta: regatta, boatClassName: boatClassName, sailID: sailID, nationality: nationality, success: { competitorCreateAndAddData in
collector.competitorCreateAndAddData = competitorCreateAndAddData
self.competitorCreateAndAddSuccess(collector: collector, success: success)
}) { (error, message) in
self.competitorCreateAndAddFailure(error: error, failure: failure)
}
}
fileprivate func competitorCreateAndAddSuccess(
collector: CreateTrainingData,
success: (_ createTrainingData: CreateTrainingData) -> Void)
{
success(collector)
}
fileprivate func competitorCreateAndAddFailure(error: Error, failure: (_ error: Error) -> Void) {
failure(error)
}
}
@@ -10,7 +10,6 @@ import UIKit
enum TrainingRequestManagerError: Error {
case invalidResponse
case postCreateEventFailed
}
class TrainingRequestManager: NSObject {
@@ -35,10 +34,10 @@ class TrainingRequestManager: NSObject {
func postCreateEvent(
boatClassName: String,
success: @escaping () -> Void,
success: @escaping (_ createEventData: CreateEventData) -> Void,
failure: @escaping (_ error: Error, _ message: String?) -> Void)
{
let urlString = "/sailingserver/api/v1/events/createEvent"
let urlString = "\(basePathString)/events/createEvent"
var body = [String: AnyObject]()
// body["eventname"] = "raimund" as AnyObject
// body["eventdescription"] = "raimund" as AnyObject
@@ -64,12 +63,11 @@ class TrainingRequestManager: NSObject {
}
}
fileprivate func postCreateEventSuccess(responseObject: Any?, success: () -> Void, failure: (_ error: Error, _ message: String?) -> Void) {
fileprivate func postCreateEventSuccess(responseObject: Any?, success: (_ createEventData: CreateEventData) -> Void, failure: (_ error: Error, _ message: String?) -> Void) {
if let data = responseObject as? Data {
do {
let jsonObject = try JSONSerialization.jsonObject(with: fixJSON(data: data))
print(jsonObject)
success()
success(CreateEventData(dictionary: jsonObject as? [String: AnyObject]))
} catch {
postCreateEventFailure(error: TrainingRequestManagerError.invalidResponse, failure: failure)
}
@@ -80,7 +78,51 @@ class TrainingRequestManager: NSObject {
fileprivate func postCreateEventFailure(error: Error, failure: (_ error: Error, _ message: String?) -> Void) {
logError(name: "\(#function)", error: error)
failure(TrainingRequestManagerError.postCreateEventFailed, stringForError(error))
failure(error, stringForError(error))
}
// MARK: - CompetitorCreateAndAdd
func postCompetitorCreateAndAdd(
regatta: String,
boatClassName: String,
sailID: String,
nationality: String,
success: @escaping (_ competitorCreateAndAddData: CompetitorCreateAndAddData) -> Void,
failure: @escaping (_ error: Error, _ message: String?) -> Void)
{
let encodedRegatta = regatta.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
let encodedBoatClassName = boatClassName.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
let encodedSailID = sailID.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
let encodedNationality = nationality.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
let urlString = "\(basePathString)/regattas/\(encodedRegatta)/competitors/createandadd?boatclass=\(encodedBoatClassName)&sailid=\(encodedSailID)&nationalityIOC=\(encodedNationality)"
manager.post(urlString, parameters: nil, success: { (requestOperation, responseObject) in
self.postCompetitorCreateAndAddSuccess(responseObject: responseObject, success: success, failure: failure)
}) { (requestOperation, error) in
self.postCompetitorCreateAndAddFailure(error: error, failure: failure)
}
}
fileprivate func postCompetitorCreateAndAddSuccess(
responseObject: Any?,
success: @escaping (_ competitorCreateAndAddData: CompetitorCreateAndAddData) -> Void,
failure: @escaping (_ error: Error, _ message: String?) -> Void)
{
if let data = responseObject as? Data {
do {
let jsonObject = try JSONSerialization.jsonObject(with: data)
success(CompetitorCreateAndAddData(dictionary: jsonObject as? [String: AnyObject]))
} catch {
self.postCompetitorCreateAndAddFailure(error: error, failure: failure)
}
} else {
self.postCompetitorCreateAndAddFailure(error: TrainingRequestManagerError.invalidResponse, failure: failure)
}
}
fileprivate func postCompetitorCreateAndAddFailure(error: Error, failure: @escaping (_ error: Error, _ message: String?) -> Void) {
logError(name: "\(#function)", error: error)
failure(error, stringForError(error))
}
// MARK: - Helper