Skip to content

Instantly share code, notes, and snippets.

@nathanmerrill
Created March 2, 2016 18:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nathanmerrill/25618561552e64c1d692 to your computer and use it in GitHub Desktop.
Save nathanmerrill/25618561552e64c1d692 to your computer and use it in GitHub Desktop.
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