-
-
Save nathanmerrill/25618561552e64c1d692 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package game.tournaments | |
import game.Game | |
import game.Player | |
import game.Scoreboard | |
import utils.combinations | |
import java.util.* | |
class MamTournament( | |
val gameFactory: (List<Player>) -> Game, | |
val players: List<Player>, | |
val numIterations: Int, | |
val gameSize: Int = players.size | |
): Tournament { | |
override fun run(scoreboard: Scoreboard) { | |
val votes: List<Scoreboard> = (0..numIterations).map { | |
gameFactory(players).run() | |
} | |
val tiebreaker = generateTiebreaker() | |
val votesPreferences: HashMap<Pair<Player, Player>, Int> = HashMap() | |
val majorities: MutableSet<Pair<Player, Player>> = HashSet() | |
for ((player1, player2) in players.combinations(2)){ | |
val p1Preferred = getPreferenceCount(votes, player1, player2) | |
val p2Preferred = getPreferenceCount(votes, player2, player1) | |
if (p1Preferred > p2Preferred) { | |
majorities.add(Pair(player1, player2)) | |
} else if (p2Preferred > p1Preferred) { | |
majorities.add(Pair(player2, player1)) | |
} | |
} | |
val sortedMajorities = majorities.sortedWith(ImportanceComparator(votesPreferences, tiebreaker)) | |
val affirmations: MutableSet<Pair<Player, Player>> = HashSet() | |
for (majority in sortedMajorities){ | |
affirm(majority, affirmations) | |
} | |
val topCandidates = players.filter { | |
player -> players.none { | |
affirmations.contains(Pair(it, player)) | |
} | |
}.toMutableList() | |
scoreboard.addScore(topCandidates.maxBy { tiebreaker[it]!! }!!, 1.0) | |
} | |
fun affirm(pair: Pair<Player, Player>, affirmations: MutableSet<Pair<Player, Player>>){ | |
affirmations.add(pair) | |
for (player in players){ | |
if (player != pair.first && player != pair.second){ | |
if (affirmations.contains(Pair(player, pair.first)) && | |
!affirmations.contains(Pair(player, pair.second))){ | |
affirm(Pair(player, pair.second), affirmations) | |
} | |
if (affirmations.contains(Pair(pair.second, player)) && | |
!affirmations.contains(Pair(pair.first, player))){ | |
affirm(Pair(pair.first, player), affirmations) | |
} | |
} | |
} | |
} | |
class ImportanceComparator(val preferences: HashMap<Pair<Player, Player>, Int>, val tiebreaker: Map<Player, Int>) | |
:Comparator<Pair<Player, Player>> { | |
override fun compare(p0: Pair<Player, Player>?, p1: Pair<Player, Player>?): Int { | |
if (p0 == null || p1 == null){ | |
throw NullPointerException() | |
} | |
val preferred = preferences[p0]!! - preferences[p1]!! | |
if (preferred != 0){ | |
return preferred | |
} | |
val opposition = preferences[Pair(p1.second, p1.first)]!! - preferences[Pair(p0.second, p0.first)]!! | |
if (opposition != 0){ | |
return opposition | |
} | |
if (p0.second == p1.second){ | |
return tiebreaker[p0.first]!! - tiebreaker[p1.first]!! | |
} else { | |
return tiebreaker[p0.second]!! - tiebreaker[p1.second]!! | |
} | |
} | |
} | |
fun getPreferenceCount(votes: List<Scoreboard>, player1: Player, player2: Player): Int{ | |
return votes.count { it.getAggregatedScore(player1) > it.getAggregatedScore(player2) } | |
} | |
fun generateTiebreaker(): Map<Player, Int>{ | |
val shuffled: MutableList<Player> = ArrayList(players) | |
Collections.shuffle(shuffled) | |
return shuffled.withIndex().associate { Pair(it.value, it.index) } | |
//Todo: generate tiebreaker from ballots | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment