Implement EloSystem in EloHelper
Calculate new EloData for both sides on serverside Report scores on both sides New Data type for sharing EloData
This commit is contained in:
parent
875524d170
commit
f852aae859
@ -44,6 +44,7 @@
|
|||||||
9EC86B9F245C88A300796EF3 /* Modal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EC86B9E245C88A300796EF3 /* Modal.swift */; };
|
9EC86B9F245C88A300796EF3 /* Modal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EC86B9E245C88A300796EF3 /* Modal.swift */; };
|
||||||
9EEDE02D246FCD770096C735 /* SpinningLogoEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EEDE02C246FCD770096C735 /* SpinningLogoEntity.swift */; };
|
9EEDE02D246FCD770096C735 /* SpinningLogoEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EEDE02C246FCD770096C735 /* SpinningLogoEntity.swift */; };
|
||||||
AB21D7D5246C748A00B09CBA /* MapFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB21D7D4246C748A00B09CBA /* MapFactory.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 */; };
|
ABA03DA0244BD54F00A66916 /* Base.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABA03D9F244BD54F00A66916 /* Base.swift */; };
|
||||||
ABC0C3732481509300387B8F /* MapUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC0C3722481509300387B8F /* MapUtils.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 */; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
C04783ED2468583F004961FB /* intro-music.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = "intro-music.mp3"; sourceTree = "<group>"; };
|
||||||
@ -182,6 +184,7 @@
|
|||||||
9E0E459624796262009817A6 /* GameCenterManager.swift */,
|
9E0E459624796262009817A6 /* GameCenterManager.swift */,
|
||||||
C04783EF24685995004961FB /* SettingsScene.swift */,
|
C04783EF24685995004961FB /* SettingsScene.swift */,
|
||||||
3EAD889424801B6A0048A10A /* RoundTimer.swift */,
|
3EAD889424801B6A0048A10A /* RoundTimer.swift */,
|
||||||
|
AB671B242494ECF0003FBE8D /* EloHelper.swift */,
|
||||||
);
|
);
|
||||||
path = GoldWars;
|
path = GoldWars;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -407,6 +410,7 @@
|
|||||||
9EC2FBA72476B1EC00ABF11F /* PlayerInfoComponent.swift in Sources */,
|
9EC2FBA72476B1EC00ABF11F /* PlayerInfoComponent.swift in Sources */,
|
||||||
9EEDE02D246FCD770096C735 /* SpinningLogoEntity.swift in Sources */,
|
9EEDE02D246FCD770096C735 /* SpinningLogoEntity.swift in Sources */,
|
||||||
9E174C86245DD91500209FF0 /* ButtonComponent.swift in Sources */,
|
9E174C86245DD91500209FF0 /* ButtonComponent.swift in Sources */,
|
||||||
|
AB671B252494ECF0003FBE8D /* EloHelper.swift in Sources */,
|
||||||
11036113244B3E30008610AF /* MenuScene.swift in Sources */,
|
11036113244B3E30008610AF /* MenuScene.swift in Sources */,
|
||||||
C099579C246C5E5C0016AA22 /* DataService.swift in Sources */,
|
C099579C246C5E5C0016AA22 /* DataService.swift in Sources */,
|
||||||
AB21D7D5246C748A00B09CBA /* MapFactory.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)
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -120,77 +120,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) {
|
func match(_ match: GKMatch, didReceive data: Data, fromRemotePlayer player: GKPlayer) {
|
||||||
if myMatch != match { return }
|
if myMatch != match { return }
|
||||||
@ -275,6 +204,15 @@ final class GameCenterManager: NSObject, GKMatchmakerViewControllerDelegate, GKG
|
|||||||
os_log("Notification erhalten", log: LOG, type: .info)
|
os_log("Notification erhalten", log: LOG, type: .info)
|
||||||
NotificationCenter.default.post(name: Notification.Name(rawValue: notification.name), object: nil)
|
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
|
MultiplayerNetwork.sharedInstance.isSending = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +60,12 @@ class MultiplayerNetwork{
|
|||||||
sendData(data: encoded)
|
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) {
|
func sendNotificationToPlayer(name: String) {
|
||||||
let encoder = JSONEncoder()
|
let encoder = JSONEncoder()
|
||||||
let encoded = (try? encoder.encode(NotificationModel(name: name)))!
|
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))
|
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.winner = winner
|
||||||
GameCenterManager.sharedInstance.gameEnded = true
|
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
|
return
|
||||||
}
|
}
|
||||||
currentRound += 1
|
currentRound += 1
|
||||||
|
Loading…
Reference in New Issue
Block a user