Merge branch '75-elo-system' into 'development'
Resolve "ELO-System" Closes #75 See merge request marcel.schwarz/software-projekt-2!122
This commit is contained in:
commit
1039f48859
@ -44,6 +44,7 @@
|
||||
9EC86B9F245C88A300796EF3 /* Modal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EC86B9E245C88A300796EF3 /* Modal.swift */; };
|
||||
9EEDE02D246FCD770096C735 /* SpinningLogoEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EEDE02C246FCD770096C735 /* SpinningLogoEntity.swift */; };
|
||||
AB21D7D5246C748A00B09CBA /* MapFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB21D7D4246C748A00B09CBA /* MapFactory.swift */; };
|
||||
AB671B252494ECF0003FBE8D /* EloHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB671B242494ECF0003FBE8D /* EloHelper.swift */; };
|
||||
ABA03DA0244BD54F00A66916 /* Base.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABA03D9F244BD54F00A66916 /* Base.swift */; };
|
||||
ABC0C3732481509300387B8F /* MapUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC0C3722481509300387B8F /* MapUtils.swift */; };
|
||||
C04783EE2468583F004961FB /* intro-music.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C04783ED2468583F004961FB /* intro-music.mp3 */; };
|
||||
@ -109,6 +110,7 @@
|
||||
9ECD3699245C91F7008DEEBD /* GoldWars.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = GoldWars.entitlements; sourceTree = "<group>"; };
|
||||
9EEDE02C246FCD770096C735 /* SpinningLogoEntity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpinningLogoEntity.swift; sourceTree = "<group>"; };
|
||||
AB21D7D4246C748A00B09CBA /* MapFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapFactory.swift; sourceTree = "<group>"; };
|
||||
AB671B242494ECF0003FBE8D /* EloHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EloHelper.swift; sourceTree = "<group>"; };
|
||||
ABA03D9F244BD54F00A66916 /* Base.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Base.swift; sourceTree = "<group>"; };
|
||||
ABC0C3722481509300387B8F /* MapUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapUtils.swift; sourceTree = "<group>"; };
|
||||
C04783ED2468583F004961FB /* intro-music.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = "intro-music.mp3"; sourceTree = "<group>"; };
|
||||
@ -182,6 +184,7 @@
|
||||
9E0E459624796262009817A6 /* GameCenterManager.swift */,
|
||||
C04783EF24685995004961FB /* SettingsScene.swift */,
|
||||
3EAD889424801B6A0048A10A /* RoundTimer.swift */,
|
||||
AB671B242494ECF0003FBE8D /* EloHelper.swift */,
|
||||
);
|
||||
path = GoldWars;
|
||||
sourceTree = "<group>";
|
||||
@ -407,6 +410,7 @@
|
||||
9EC2FBA72476B1EC00ABF11F /* PlayerInfoComponent.swift in Sources */,
|
||||
9EEDE02D246FCD770096C735 /* SpinningLogoEntity.swift in Sources */,
|
||||
9E174C86245DD91500209FF0 /* ButtonComponent.swift in Sources */,
|
||||
AB671B252494ECF0003FBE8D /* EloHelper.swift in Sources */,
|
||||
11036113244B3E30008610AF /* MenuScene.swift in Sources */,
|
||||
C099579C246C5E5C0016AA22 /* DataService.swift in Sources */,
|
||||
AB21D7D5246C748A00B09CBA /* MapFactory.swift in Sources */,
|
||||
|
60
GoldWars/GoldWars/EloHelper.swift
Normal file
60
GoldWars/GoldWars/EloHelper.swift
Normal file
@ -0,0 +1,60 @@
|
||||
//
|
||||
// EloHelper.swift
|
||||
// GoldWars
|
||||
//
|
||||
// Created by Marcel Schwarz on 13.06.20.
|
||||
// Copyright © 2020 SP2. All rights reserved.
|
||||
//
|
||||
|
||||
import GameKit
|
||||
import os
|
||||
|
||||
struct EloDataForPeer : Codable {
|
||||
let scoreToReport: Int64
|
||||
}
|
||||
|
||||
class EloHelper {
|
||||
|
||||
static private let LOG = OSLog.init(subsystem: "EloHelper", category: "EloHelper")
|
||||
|
||||
static let IDENTIFIER = "de.hft.stuttgart.ip2.goldwars.matchmaking"
|
||||
|
||||
static func updateEloScore(winner: GKPlayer, hatDenNikoGemacht looser: GKPlayer) {
|
||||
|
||||
let leaderboard = GKLeaderboard.init(players: [winner, looser])
|
||||
leaderboard.identifier = EloHelper.IDENTIFIER
|
||||
|
||||
leaderboard.loadScores{scores, error in
|
||||
|
||||
// Get Scores
|
||||
let R_looser = scores?.filter { $0.player == looser }.first ?? GKScore(leaderboardIdentifier: EloHelper.IDENTIFIER, player: looser)
|
||||
let R_winner = scores?.filter { $0.player == winner }.first ?? GKScore(leaderboardIdentifier: EloHelper.IDENTIFIER, player: winner)
|
||||
|
||||
// Calc ELO
|
||||
let Q_looser = pow(10.0, Double(R_looser.value) / 400.0)
|
||||
let Q_winner = pow(10.0, Double(R_winner.value) / 400.0)
|
||||
let E_looser = Q_looser / (Q_looser + Q_winner)
|
||||
let E_winner = Q_winner / (Q_looser + Q_winner)
|
||||
|
||||
let R_winner_new = Int64(Double(R_winner.value) + 10.0 * (1.0 - E_winner))
|
||||
let R_looser_new = Int64(Double(R_looser.value) + 10.0 * (0.0 - E_looser))
|
||||
|
||||
// Update Elo on leaderboard
|
||||
let winner_new = GKScore(leaderboardIdentifier: EloHelper.IDENTIFIER, player: winner)
|
||||
winner_new.value = R_winner_new
|
||||
let looser_new = GKScore(leaderboardIdentifier: EloHelper.IDENTIFIER, player: looser)
|
||||
looser_new.value = R_looser_new
|
||||
|
||||
let scoreForPeer = winner == GameCenterManager.sharedInstance.localPlayer ? looser_new : winner_new
|
||||
let scoreForHost = winner == GameCenterManager.sharedInstance.localPlayer ? winner_new : looser_new
|
||||
|
||||
MultiplayerNetwork.sharedInstance.sendEloData(scoreToReport: scoreForPeer)
|
||||
|
||||
GKScore.report([scoreForHost], withCompletionHandler: { error in
|
||||
os_log("New Scores reported to EloSystem", log: LOG, type: .info)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -121,77 +121,6 @@ final class GameCenterManager: NSObject, GKMatchmakerViewControllerDelegate, GKG
|
||||
}
|
||||
}
|
||||
|
||||
func submitLeaderboardScore(identifier: String, score: Int64) {
|
||||
let reportedScore = GKScore(leaderboardIdentifier: identifier)
|
||||
reportedScore.value = score
|
||||
GKScore.report([reportedScore]) { (error) in
|
||||
guard error == nil else {
|
||||
print(error?.localizedDescription ?? "")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func calculateLeaderboardScore(identifier: String, scoreOffset: Int64) {
|
||||
GKLeaderboard.loadLeaderboards { (leaderboards: [GKLeaderboard]?, err: Error?) in
|
||||
leaderboards?.forEach({ (leaderboard: GKLeaderboard) in
|
||||
if leaderboard.identifier == identifier {
|
||||
leaderboard.loadScores { (scores: [GKScore]?, err: Error?) in
|
||||
scores?.forEach({ (score: GKScore) in
|
||||
if score.player == self.localPlayer {
|
||||
score.value += scoreOffset
|
||||
GKScore.report([score]) { (error) in
|
||||
guard error == nil else {
|
||||
print(error?.localizedDescription ?? "")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: not finished -> DELETE if not usefull
|
||||
// Possible way to implement matchmaking based on 2 players
|
||||
// can be changed into method with fixed leaderboard and offset, boolean hasWon: true/false to calculate outcome of a match
|
||||
func calculateLeaderboardScoreExperimentalMatchmaking(identifier: String, scoreOffset: Int64, opponentPlayer: GKPlayer) {
|
||||
// Iterate through leaderboards
|
||||
GKLeaderboard.loadLeaderboards { (leaderboards: [GKLeaderboard]?, err: Error?) in
|
||||
leaderboards?.forEach({ (leaderboard: GKLeaderboard) in
|
||||
if leaderboard.identifier == identifier {
|
||||
leaderboard.loadScores { (scores: [GKScore]?, err: Error?) in
|
||||
// Iterate through scores
|
||||
var currentScore: GKScore = GKScore.init()
|
||||
currentScore.value = -1
|
||||
var opponetScore: GKScore = GKScore.init()
|
||||
currentScore.value = 0
|
||||
// Get scores of self and opponent
|
||||
scores?.forEach({ (score: GKScore) in
|
||||
if score.player == self.localPlayer {
|
||||
currentScore = score
|
||||
opponetScore = score
|
||||
}
|
||||
if score.player == opponentPlayer {
|
||||
opponetScore = score
|
||||
}
|
||||
})
|
||||
// do silly calculation
|
||||
currentScore.value += scoreOffset + (opponetScore.value - currentScore.value)
|
||||
GKScore.report([currentScore]) { (error) in
|
||||
guard error == nil else {
|
||||
print(error?.localizedDescription ?? "")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func match(_ match: GKMatch, didReceive data: Data, fromRemotePlayer player: GKPlayer) {
|
||||
if myMatch != match { return }
|
||||
let jsonDecoder = JSONDecoder()
|
||||
@ -275,6 +204,15 @@ final class GameCenterManager: NSObject, GKMatchmakerViewControllerDelegate, GKG
|
||||
os_log("Notification erhalten", log: LOG, type: .info)
|
||||
NotificationCenter.default.post(name: Notification.Name(rawValue: notification.name), object: nil)
|
||||
}
|
||||
|
||||
if let eloData = try? jsonDecoder.decode(EloDataForPeer.self, from: data) {
|
||||
print("Recieved elo data: \(eloData.scoreToReport)")
|
||||
let score = GKScore(leaderboardIdentifier: EloHelper.IDENTIFIER, player: self.localPlayer)
|
||||
score.value = eloData.scoreToReport
|
||||
GKScore.report([score], withCompletionHandler: { error in
|
||||
os_log("New Scores reported to EloSystem", log: self.LOG, type: .info)
|
||||
})
|
||||
}
|
||||
MultiplayerNetwork.sharedInstance.isSending = false
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,12 @@ class MultiplayerNetwork{
|
||||
sendData(data: encoded)
|
||||
}
|
||||
|
||||
func sendEloData(scoreToReport: GKScore) {
|
||||
let encoder = JSONEncoder()
|
||||
let encoded = (try? encoder.encode(EloDataForPeer(scoreToReport: scoreToReport.value)))!
|
||||
sendData(data: encoded)
|
||||
}
|
||||
|
||||
func sendNotificationToPlayer(name: String) {
|
||||
let encoder = JSONEncoder()
|
||||
let encoded = (try? encoder.encode(NotificationModel(name: name)))!
|
||||
|
@ -160,6 +160,14 @@ class RoundCalculatorService {
|
||||
winner == GameCenterManager.sharedInstance.hostingPlayer?.displayName ? GameCenterManager.sharedInstance.sendStateToPeers(state: State(state: 4)) : GameCenterManager.sharedInstance.sendStateToPeers(state: State(state: 5))
|
||||
GameCenterManager.sharedInstance.winner = winner
|
||||
GameCenterManager.sharedInstance.gameEnded = true
|
||||
|
||||
// Update EloSystem
|
||||
if winner == GameCenterManager.sharedInstance.hostingPlayer?.displayName {
|
||||
EloHelper.updateEloScore(winner: GameCenterManager.sharedInstance.hostingPlayer!, hatDenNikoGemacht: GameCenterManager.sharedInstance.peerPlayer!)
|
||||
} else {
|
||||
EloHelper.updateEloScore(winner: GameCenterManager.sharedInstance.peerPlayer!, hatDenNikoGemacht: GameCenterManager.sharedInstance.hostingPlayer!)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
currentRound += 1
|
||||
|
Loading…
Reference in New Issue
Block a user