Skip to content
This repository has been archived by the owner on Jan 22, 2021. It is now read-only.

Leaderboard.user #77

Merged
merged 4 commits into from
Jun 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions Server/Sources/Application/Model/EntryPersistence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import Foundation
import CouchDB
import SwiftyJSON
import Dispatch

enum RainbowPersistenceError: Error {
case noAvatar
Expand Down Expand Up @@ -124,6 +125,49 @@ 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]()

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: {
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)
})
}
}


static func getScores(from client: CouchDBClient, completion: @escaping (_ entries: [ScoreEntry]?, _ error: Error?) -> Void) {
getDatabase(from: client) { database, error in
guard let database = database else {
Expand Down
4 changes: 4 additions & 0 deletions Server/Sources/Application/Model/ScoreEntry+SwiftyJSON.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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? {
Expand Down
10 changes: 10 additions & 0 deletions Server/Sources/Application/Model/ScoreEntry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
11 changes: 11 additions & 0 deletions Server/Sources/Application/Routes/ScoreRoutes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down Expand Up @@ -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.getLeaderBoardDataForUser(id: id, 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: [])
Expand Down
20 changes: 3 additions & 17 deletions iOS/rainbow.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand All @@ -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 */; };
Expand All @@ -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 */; };
Expand Down Expand Up @@ -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;
};
Expand Down Expand Up @@ -553,7 +539,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0930;
LastUpgradeCheck = 0930;
LastUpgradeCheck = 0940;
ORGANIZATIONNAME = IBM;
TargetAttributes = {
533818FD209757B900DE66CB = {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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")
Expand Down Expand Up @@ -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
}

Expand Down
24 changes: 17 additions & 7 deletions iOS/rainbow/Model/ScoreEntry+Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ 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/"
return baseURL
}
}
Expand Down Expand Up @@ -73,15 +73,25 @@ extension ScoreEntry {
}
}

static func getAll(completion: @escaping (_ entries: [ScoreEntry]?, _ error: RainbowClientError?) -> Void) {
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)
}
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions iOS/rainbow/Model/ScoreEntry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}