From 763b0c1e8049b6028f8a77feb40473f8ff1968aa Mon Sep 17 00:00:00 2001 From: Sanjeev Ghimire Date: Thu, 31 May 2018 14:29:55 -0500 Subject: [PATCH 1/4] leaderboard top 10 with user --- .../Application/Model/EntryPersistence.swift | 43 +++++++++++++++++++ .../Model/ScoreEntry+SwiftyJSON.swift | 4 ++ .../Application/Routes/ScoreRoutes.swift | 11 +++++ 3 files changed, 58 insertions(+) diff --git a/Server/Sources/Application/Model/EntryPersistence.swift b/Server/Sources/Application/Model/EntryPersistence.swift index f794403..c44dd94 100644 --- a/Server/Sources/Application/Model/EntryPersistence.swift +++ b/Server/Sources/Application/Model/EntryPersistence.swift @@ -8,6 +8,7 @@ import Foundation import CouchDB import SwiftyJSON +import Dispatch enum RainbowPersistenceError: Error { case noAvatar @@ -124,6 +125,48 @@ extension ScoreEntry { } } + static func getLeaderBoardDataForUser(id: String, from client: CouchDBClient, completion: @escaping (_ entries: [ScoreEntry]?, _ error: Error?) -> Void) { + getDatabase(from: client) { database, error in + guard let database = database else { + return completion(nil, error) + } + + let dispatchGroup = DispatchGroup() + + var entries = [ScoreEntry]() + // give me this user and if the game was completed + // + dispatchGroup.enter(); + database.retrieve(id, callback: { document, error in + if let document = document, let newEntry = ScoreEntry(document: document) { + if newEntry.finishDate != nil { + entries.append(newEntry) + } + } + dispatchGroup.leave() + }) + + dispatchGroup.enter() + database.queryByView("leader-board", ofDesign: "LeaderBoard", usingParameters: [Database.QueryParameters.limit(10) ,Database.QueryParameters.descending(false)], callback: { (documents, error) in + if let documents = documents { + for document in documents["rows"].arrayValue { + if let newEntry = ScoreEntry(document: document["value"]) { + entries.append(newEntry) + } + } + } + dispatchGroup.leave() + }) + dispatchGroup.notify(queue: DispatchQueue.global(qos: .default), execute: { + //entries.sorted(by: { $0.totalTime > $1.totalTime }) + completion(entries, nil) + }) + + + } + } + + static func getScores(from client: CouchDBClient, completion: @escaping (_ entries: [ScoreEntry]?, _ error: Error?) -> Void) { getDatabase(from: client) { database, error in guard let database = database else { diff --git a/Server/Sources/Application/Model/ScoreEntry+SwiftyJSON.swift b/Server/Sources/Application/Model/ScoreEntry+SwiftyJSON.swift index 811003b..a0a5090 100644 --- a/Server/Sources/Application/Model/ScoreEntry+SwiftyJSON.swift +++ b/Server/Sources/Application/Model/ScoreEntry+SwiftyJSON.swift @@ -39,7 +39,11 @@ extension ScoreEntry { startDate = potentialStartDate finishDate = document["finishDate"].dateTime objects = nil + totalTime = nil + if document["finishDate"] != nil { + totalTime = document["finishDate"].doubleValue - document["startDate"].doubleValue + } } mutating func toJSONDocument() -> JSON? { diff --git a/Server/Sources/Application/Routes/ScoreRoutes.swift b/Server/Sources/Application/Routes/ScoreRoutes.swift index 229ca86..641a663 100644 --- a/Server/Sources/Application/Routes/ScoreRoutes.swift +++ b/Server/Sources/Application/Routes/ScoreRoutes.swift @@ -21,6 +21,7 @@ func initializeScoreRoutes(app: App) { app.router.post("watsonml/entries", handler: addNewEntry) app.router.put("/watsonml/entries", handler: updateEntry) app.router.get("/watsonml/leaderboard", handler: getLeaderBoard) + app.router.get("/watsonml/leaderboard", handler: getLeaderBoardForUser) app.router.get("/avatar/leaderboardAvatar/:id", handler: getLeaderboardAvatar) } @@ -87,6 +88,16 @@ func getLeaderBoard(completion: @escaping ([ScoreEntry]?, RequestError?) -> Void } } +func getLeaderBoardForUser(id: String, completion: @escaping ([ScoreEntry]?, RequestError?) -> Void) { + Log.info("Getting leaderboard data") + guard let client = client else { + return completion(nil, .failedDependency) + } + ScoreEntry.Persistence.getLeaderBoardData(from: client) { entries, error in + return completion(entries, error as? RequestError) + } +} + func getLeaderboardAvatar(request: RouterRequest, response: RouterResponse, next: @escaping () -> Void) { guard let requestID = request.parameters["id"] else { response.status(.badRequest).send(json: []) From 4d528bc3a5b5ce92563fa66ee539555ac5fc63f1 Mon Sep 17 00:00:00 2001 From: David Okun Date: Thu, 31 May 2018 18:48:09 -0500 Subject: [PATCH 2/4] New leaderboard call on server, organization on client --- .../Application/Model/EntryPersistence.swift | 21 +++++----- .../Application/Model/ScoreEntry.swift | 10 +++++ .../Application/Routes/ScoreRoutes.swift | 2 +- .../LeaderboardTableViewController.swift | 13 ++++++- iOS/rainbow/Model/ScoreEntry+Client.swift | 38 +++++++++++++++---- iOS/rainbow/Model/ScoreEntry.swift | 10 +++++ 6 files changed, 74 insertions(+), 20 deletions(-) diff --git a/Server/Sources/Application/Model/EntryPersistence.swift b/Server/Sources/Application/Model/EntryPersistence.swift index c44dd94..7f6d368 100644 --- a/Server/Sources/Application/Model/EntryPersistence.swift +++ b/Server/Sources/Application/Model/EntryPersistence.swift @@ -130,13 +130,10 @@ extension ScoreEntry { guard let database = database else { return completion(nil, error) } - let dispatchGroup = DispatchGroup() - var entries = [ScoreEntry]() - // give me this user and if the game was completed - // - dispatchGroup.enter(); + + dispatchGroup.enter() database.retrieve(id, callback: { document, error in if let document = document, let newEntry = ScoreEntry(document: document) { if newEntry.finishDate != nil { @@ -147,7 +144,7 @@ extension ScoreEntry { }) dispatchGroup.enter() - database.queryByView("leader-board", ofDesign: "LeaderBoard", usingParameters: [Database.QueryParameters.limit(10) ,Database.QueryParameters.descending(false)], callback: { (documents, error) in + database.queryByView("leader-board", ofDesign: "LeaderBoard", usingParameters: [Database.QueryParameters.limit(10) ,Database.QueryParameters.descending(false)], callback: { documents, error in if let documents = documents { for document in documents["rows"].arrayValue { if let newEntry = ScoreEntry(document: document["value"]) { @@ -158,11 +155,15 @@ extension ScoreEntry { dispatchGroup.leave() }) dispatchGroup.notify(queue: DispatchQueue.global(qos: .default), execute: { - //entries.sorted(by: { $0.totalTime > $1.totalTime }) - completion(entries, nil) + let uniqueEntries = Array(Set(entries)) + let sortedEntries = uniqueEntries.sorted { + guard let first = $0.totalTime, let second = $1.totalTime else { + return false + } + return first < second + } + completion(sortedEntries, nil) }) - - } } diff --git a/Server/Sources/Application/Model/ScoreEntry.swift b/Server/Sources/Application/Model/ScoreEntry.swift index 0bad5f4..2673cb6 100644 --- a/Server/Sources/Application/Model/ScoreEntry.swift +++ b/Server/Sources/Application/Model/ScoreEntry.swift @@ -24,3 +24,13 @@ struct ScoreEntry: Codable { var objects: [ObjectEntry]? var totalTime: Double? } + +extension ScoreEntry: Hashable { + var hashValue: Int { + return id?.hashValue ?? Int(INT_MAX) + } + + static func == (lhs: ScoreEntry, rhs: ScoreEntry) -> Bool { + return lhs.id == rhs.id + } +} diff --git a/Server/Sources/Application/Routes/ScoreRoutes.swift b/Server/Sources/Application/Routes/ScoreRoutes.swift index 641a663..68b46c1 100644 --- a/Server/Sources/Application/Routes/ScoreRoutes.swift +++ b/Server/Sources/Application/Routes/ScoreRoutes.swift @@ -93,7 +93,7 @@ func getLeaderBoardForUser(id: String, completion: @escaping ([ScoreEntry]?, Req guard let client = client else { return completion(nil, .failedDependency) } - ScoreEntry.Persistence.getLeaderBoardData(from: client) { entries, error in + ScoreEntry.Persistence.getLeaderBoardDataForUser(id: id, from: client) { entries, error in return completion(entries, error as? RequestError) } } diff --git a/iOS/rainbow/Controller/Leaderboard/LeaderboardTableViewController.swift b/iOS/rainbow/Controller/Leaderboard/LeaderboardTableViewController.swift index 0a57098..42beef5 100644 --- a/iOS/rainbow/Controller/Leaderboard/LeaderboardTableViewController.swift +++ b/iOS/rainbow/Controller/Leaderboard/LeaderboardTableViewController.swift @@ -19,11 +19,17 @@ class LeaderboardTableViewCell: UITableViewCell { class LeaderboardTableViewController: UITableViewController { var leaderboard: [ScoreEntry]? + var yourUser: ScoreEntry? override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) SVProgressHUD.show(withStatus: "Loading Leaderboard...") - getLeaderboard() + do { + yourUser = try ScoreEntry.ClientPersistence.get() + getLeaderboard() + } catch { + print("Could not load your user") + } } override func viewDidLoad() { @@ -46,7 +52,7 @@ class LeaderboardTableViewController: UITableViewController { } private func getLeaderboard() { - ScoreEntry.ServerCalls.getAll { entries, error in + ScoreEntry.ServerCalls.getAll(for: yourUser?.id) { entries, error in DispatchQueue.main.async { if error != nil { SVProgressHUD.showError(withStatus: "Could not load leaderboard") @@ -98,6 +104,9 @@ class LeaderboardTableViewController: UITableViewController { cell.avatarImageView?.kf.indicatorType = .activity cell.avatarImageView?.kf.setImage(with: url) } + if yourUser?.username == currentEntry.username { + cell.backgroundColor = UIColor.RainbowColors.neutral + } return cell } diff --git a/iOS/rainbow/Model/ScoreEntry+Client.swift b/iOS/rainbow/Model/ScoreEntry+Client.swift index 35eb9a5..43234ba 100644 --- a/iOS/rainbow/Model/ScoreEntry+Client.swift +++ b/iOS/rainbow/Model/ScoreEntry+Client.swift @@ -17,7 +17,8 @@ extension UIApplication { var rainbowServerBaseURL: String { var baseURL = UIApplication.shared.isDebugMode ? "http://localhost:8080" : "https://rainbow-scavenger-viz-rec.mybluemix.net" // need to update when we deploy - baseURL = "https://watsonml-vivatech.mybluemix.net/" + baseURL = "https://watsonml-vivatech.mybluemix.net/" + baseURL = "http://localhost:8080" return baseURL } } @@ -73,15 +74,38 @@ extension ScoreEntry { } } - static func getAll(completion: @escaping (_ entries: [ScoreEntry]?, _ error: RainbowClientError?) -> Void) { +// static func getAll(completion: @escaping (_ entries: [ScoreEntry]?, _ error: RainbowClientError?) -> Void) { +// guard let client = KituraKit(baseURL: UIApplication.shared.rainbowServerBaseURL) else { +// return completion(nil, RainbowClientError.couldNotCreateClient) +// } +// client.get("/watsonml/leaderboard") { (entries: [ScoreEntry]?, error: RequestError?) in +// if error != nil { +// return completion(nil, RainbowClientError.couldNotGetEntries) +// } else { +// return completion(entries, nil) +// } +// } +// } + + static func getAll(for identifier: String?, completion: @escaping (_ entries: [ScoreEntry]?, _ error: RainbowClientError?) -> Void) { guard let client = KituraKit(baseURL: UIApplication.shared.rainbowServerBaseURL) else { return completion(nil, RainbowClientError.couldNotCreateClient) } - client.get("/watsonml/leaderboard") { (entries: [ScoreEntry]?, error: RequestError?) in - if error != nil { - return completion(nil, RainbowClientError.couldNotGetEntries) - } else { - return completion(entries, nil) + if let identifier = identifier { + client.get("/watsonml/leaderboard", identifier: identifier) { (entries: [ScoreEntry]?, error: RequestError?) in + if error != nil { + return completion(nil, RainbowClientError.couldNotGetEntries) + } else { + return completion(entries, nil) + } + } + } else { + client.get("/watsonml/leaderboard") { (entries: [ScoreEntry]?, error: RequestError?) in + if error != nil { + return completion(nil, RainbowClientError.couldNotGetEntries) + } else { + return completion(entries, nil) + } } } } diff --git a/iOS/rainbow/Model/ScoreEntry.swift b/iOS/rainbow/Model/ScoreEntry.swift index 0bad5f4..2673cb6 100644 --- a/iOS/rainbow/Model/ScoreEntry.swift +++ b/iOS/rainbow/Model/ScoreEntry.swift @@ -24,3 +24,13 @@ struct ScoreEntry: Codable { var objects: [ObjectEntry]? var totalTime: Double? } + +extension ScoreEntry: Hashable { + var hashValue: Int { + return id?.hashValue ?? Int(INT_MAX) + } + + static func == (lhs: ScoreEntry, rhs: ScoreEntry) -> Bool { + return lhs.id == rhs.id + } +} From 43f902418246d76a3b3d791615c6a58ed122a61f Mon Sep 17 00:00:00 2001 From: David Okun Date: Thu, 31 May 2018 18:52:18 -0500 Subject: [PATCH 3/4] Removed commented code --- iOS/rainbow/Model/ScoreEntry+Client.swift | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/iOS/rainbow/Model/ScoreEntry+Client.swift b/iOS/rainbow/Model/ScoreEntry+Client.swift index 43234ba..5ba113a 100644 --- a/iOS/rainbow/Model/ScoreEntry+Client.swift +++ b/iOS/rainbow/Model/ScoreEntry+Client.swift @@ -18,7 +18,6 @@ extension UIApplication { var rainbowServerBaseURL: String { var baseURL = UIApplication.shared.isDebugMode ? "http://localhost:8080" : "https://rainbow-scavenger-viz-rec.mybluemix.net" // need to update when we deploy baseURL = "https://watsonml-vivatech.mybluemix.net/" - baseURL = "http://localhost:8080" return baseURL } } @@ -74,19 +73,6 @@ extension ScoreEntry { } } -// static func getAll(completion: @escaping (_ entries: [ScoreEntry]?, _ error: RainbowClientError?) -> Void) { -// guard let client = KituraKit(baseURL: UIApplication.shared.rainbowServerBaseURL) else { -// return completion(nil, RainbowClientError.couldNotCreateClient) -// } -// client.get("/watsonml/leaderboard") { (entries: [ScoreEntry]?, error: RequestError?) in -// if error != nil { -// return completion(nil, RainbowClientError.couldNotGetEntries) -// } else { -// return completion(entries, nil) -// } -// } -// } - static func getAll(for identifier: String?, completion: @escaping (_ entries: [ScoreEntry]?, _ error: RainbowClientError?) -> Void) { guard let client = KituraKit(baseURL: UIApplication.shared.rainbowServerBaseURL) else { return completion(nil, RainbowClientError.couldNotCreateClient) From b456f91461ef0da34b8612cb5803a6ddb6182403 Mon Sep 17 00:00:00 2001 From: David Okun Date: Thu, 31 May 2018 18:53:17 -0500 Subject: [PATCH 4/4] Updated project settings --- iOS/rainbow.xcodeproj/project.pbxproj | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/iOS/rainbow.xcodeproj/project.pbxproj b/iOS/rainbow.xcodeproj/project.pbxproj index 4f6d368..aa7fbec 100644 --- a/iOS/rainbow.xcodeproj/project.pbxproj +++ b/iOS/rainbow.xcodeproj/project.pbxproj @@ -43,9 +43,7 @@ 531AAF8920A4B0690056B24B /* Booklet.json in Resources */ = {isa = PBXBuildFile; fileRef = 531AAF8620A4B0690056B24B /* Booklet.json */; }; 531AAF9620A4B98F0056B24B /* Lumina.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 531AAF9420A4B98F0056B24B /* Lumina.framework */; }; 531AAF9720A4B98F0056B24B /* VisualRecognitionV3.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 531AAF9520A4B98F0056B24B /* VisualRecognitionV3.framework */; }; - 531AAF9820A4B9C80056B24B /* Lumina.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 531AAF9420A4B98F0056B24B /* Lumina.framework */; }; 531AAF9920A4B9C80056B24B /* Lumina.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 531AAF9420A4B98F0056B24B /* Lumina.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 531AAF9A20A4B9C80056B24B /* VisualRecognitionV3.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 531AAF9520A4B98F0056B24B /* VisualRecognitionV3.framework */; }; 531AAF9B20A4B9C80056B24B /* VisualRecognitionV3.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 531AAF9520A4B98F0056B24B /* VisualRecognitionV3.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 531AAF9D20A4BA280056B24B /* StyleGuides.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531AAF9C20A4BA280056B24B /* StyleGuides.swift */; }; 53381902209757B900DE66CB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53381901209757B900DE66CB /* AppDelegate.swift */; }; @@ -61,7 +59,6 @@ 5341F4CF209BEAD600AD37EF /* ChecklistTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5341F4CE209BEAD600AD37EF /* ChecklistTableViewController.swift */; }; 5365924020AB8B3500F76E37 /* Date+WatsonML.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5365923F20AB8B3500F76E37 /* Date+WatsonML.swift */; }; 5365924220AB8F0900F76E37 /* SVProgressHUD.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5365924120AB8F0900F76E37 /* SVProgressHUD.framework */; }; - 5365924320AB8F1000F76E37 /* SVProgressHUD.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5365924120AB8F0900F76E37 /* SVProgressHUD.framework */; }; 5365924420AB8F1000F76E37 /* SVProgressHUD.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5365924120AB8F0900F76E37 /* SVProgressHUD.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 53864AD32098DD5D006B8264 /* ScoreEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53864AD22098DD5D006B8264 /* ScoreEntry.swift */; }; 538D191420ACB03100742E17 /* Fireworks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 538D191320ACB03100742E17 /* Fireworks.swift */; }; @@ -74,20 +71,16 @@ 53AC588920A9382B0031EDC9 /* GameStartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53AC588820A9382B0031EDC9 /* GameStartView.swift */; }; 53AC588B20A9E9160031EDC9 /* GameObjects.json in Resources */ = {isa = PBXBuildFile; fileRef = 53AC588A20A9E9160031EDC9 /* GameObjects.json */; }; 53AC588D20AA17130031EDC9 /* ObjectConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53AC588C20AA17130031EDC9 /* ObjectConfig.swift */; }; - 53AC589120AA2FF50031EDC9 /* BMSCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53AC588E20AA2FF50031EDC9 /* BMSCore.framework */; }; - 53AC589220AA2FF50031EDC9 /* BMSAnalyticsAPI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53AC588F20AA2FF50031EDC9 /* BMSAnalyticsAPI.framework */; }; 53AC589320AA2FF50031EDC9 /* BMSPush.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53AC589020AA2FF50031EDC9 /* BMSPush.framework */; }; 53AC589420AA30030031EDC9 /* BMSAnalyticsAPI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53AC588F20AA2FF50031EDC9 /* BMSAnalyticsAPI.framework */; }; 53AC589520AA30030031EDC9 /* BMSAnalyticsAPI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 53AC588F20AA2FF50031EDC9 /* BMSAnalyticsAPI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 53AC589620AA30030031EDC9 /* BMSCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53AC588E20AA2FF50031EDC9 /* BMSCore.framework */; }; 53AC589720AA30030031EDC9 /* BMSCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 53AC588E20AA2FF50031EDC9 /* BMSCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 53AC589820AA30030031EDC9 /* BMSPush.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53AC589020AA2FF50031EDC9 /* BMSPush.framework */; }; 53AC589920AA30030031EDC9 /* BMSPush.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 53AC589020AA2FF50031EDC9 /* BMSPush.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 53BAF34820AB3BB200583BE6 /* AvatarClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BAF34720AB3BB200583BE6 /* AvatarClient.swift */; }; 53BAF34C20AB3E4A00583BE6 /* DefaultAvatar.json in Resources */ = {isa = PBXBuildFile; fileRef = 53BAF34B20AB3E4A00583BE6 /* DefaultAvatar.json */; }; 53BAF35020AB52DF00583BE6 /* MainTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BAF34F20AB52DF00583BE6 /* MainTabBarController.swift */; }; 53C06E3320BEF3C700C03BA6 /* Kingfisher.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53C06E3220BEF3C700C03BA6 /* Kingfisher.framework */; }; - 53C06E3420BEF3CD00C03BA6 /* Kingfisher.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53C06E3220BEF3C700C03BA6 /* Kingfisher.framework */; }; 53C06E3520BEF3CD00C03BA6 /* Kingfisher.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 53C06E3220BEF3C700C03BA6 /* Kingfisher.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 53C6D18B20ADBB10008DF112 /* ProjectRainbowModel_1753554316.mlmodel in Sources */ = {isa = PBXBuildFile; fileRef = 53C6D18A20ADBB10008DF112 /* ProjectRainbowModel_1753554316.mlmodel */; }; 53C953A220ABA1E40059F593 /* KituraServerCredentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C953A120ABA1E40059F593 /* KituraServerCredentials.swift */; }; @@ -232,16 +225,9 @@ 531AAF9620A4B98F0056B24B /* Lumina.framework in Frameworks */, 53AC589420AA30030031EDC9 /* BMSAnalyticsAPI.framework in Frameworks */, 531AAF9720A4B98F0056B24B /* VisualRecognitionV3.framework in Frameworks */, - 531AAF9820A4B9C80056B24B /* Lumina.framework in Frameworks */, 53AC589320AA2FF50031EDC9 /* BMSPush.framework in Frameworks */, - 5365924320AB8F1000F76E37 /* SVProgressHUD.framework in Frameworks */, 53C06E3320BEF3C700C03BA6 /* Kingfisher.framework in Frameworks */, 53AC589620AA30030031EDC9 /* BMSCore.framework in Frameworks */, - 53C06E3420BEF3CD00C03BA6 /* Kingfisher.framework in Frameworks */, - 53AC589220AA2FF50031EDC9 /* BMSAnalyticsAPI.framework in Frameworks */, - 53AC589120AA2FF50031EDC9 /* BMSCore.framework in Frameworks */, - 531AAF9A20A4B9C80056B24B /* VisualRecognitionV3.framework in Frameworks */, - 53AC589820AA30030031EDC9 /* BMSPush.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -553,7 +539,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0930; - LastUpgradeCheck = 0930; + LastUpgradeCheck = 0940; ORGANIZATIONNAME = IBM; TargetAttributes = { 533818FD209757B900DE66CB = { @@ -825,7 +811,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.3; + IPHONEOS_DEPLOYMENT_TARGET = 11.4; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -879,7 +865,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.3; + IPHONEOS_DEPLOYMENT_TARGET = 11.4; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule;