Advertisement
Guest User

hs legend sim

a guest
Feb 16th, 2017
886
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 6.46 KB | None | 0 0
  1. package hs
  2.  
  3. import java.util.HashMap
  4. import java.util.Random
  5. import java.util.TreeMap
  6. import java.util.concurrent.Executors
  7. import java.util.concurrent.TimeUnit
  8.  
  9. class PlayerState(initRank: Int = 5, initStars: Int = 1) {
  10.     init {
  11.         if (initRank < 1 || initRank > 20)
  12.             throw IllegalArgumentException("The initial rank must be between 1 and 20!")
  13.  
  14.         if (initStars < 0)
  15.             throw IllegalArgumentException("The initial stars must not be negative!")
  16.  
  17.         if (initStars > 5)
  18.             throw IllegalArgumentException("The initial stars must not be over 5!")
  19.     }
  20.  
  21.     private var currentRank = initRank
  22.  
  23.     private var currentStars = initStars
  24.  
  25.     private var winStreak = 0
  26.  
  27.     private var amountOfGames = 0
  28.  
  29.     val rank: Int
  30.         get() = currentRank
  31.  
  32.     val stars: Int
  33.         get() = currentStars
  34.  
  35.     val gamesPlayed: Int
  36.         get() = amountOfGames
  37.  
  38.     fun addWin() {
  39.         amountOfGames++
  40.         winStreak++
  41.         if (currentRank > 5 && winStreak > 2) {
  42.             currentStars += 2
  43.         } else {
  44.             currentStars++
  45.         }
  46.  
  47.         rankCheckWin()
  48.     }
  49.  
  50.     fun addLoss() {
  51.         amountOfGames++
  52.         winStreak = 0
  53.         currentStars--
  54.  
  55.         rankCheckLoss()
  56.         //rankCheckLossNew()
  57.     }
  58.  
  59.     private fun rankCheckWin() {
  60.         if (currentRank <= 10 && currentStars > 5) {
  61.             currentRank--
  62.             currentStars -= 5
  63.         } else if (currentRank > 10 && currentRank <= 15 && currentStars > 4) {
  64.             currentRank--
  65.             currentStars -= 4
  66.         } else if (currentRank > 15 && currentRank <= 20 && currentStars > 3) {
  67.             currentRank--
  68.             currentStars -= 3
  69.         }
  70.     }
  71.  
  72.     private fun rankCheckLoss() {
  73.         if (currentStars < 0) {
  74.             currentRank++
  75.             when {
  76.                 currentRank <= 10 -> currentStars = 4
  77.                 currentRank <= 15 -> currentStars = 3
  78.                 currentRank <= 20 -> currentStars = 2
  79.                 else              -> {
  80.                     currentRank = 20
  81.                     currentStars = 0
  82.                 }
  83.             }
  84.         }
  85.     }
  86.  
  87.     private fun rankCheckLossNew() {
  88.         if (currentStars < 0) {
  89.             if (currentRank == 5 || currentRank == 10 || currentRank == 15) {
  90.                 currentStars = 0
  91.                 return
  92.             }
  93.  
  94.             currentRank++
  95.             when {
  96.                 currentRank <= 10 -> currentStars = 4
  97.                 currentRank <= 15 -> currentStars = 3
  98.                 currentRank <= 20 -> currentStars = 2
  99.                 else              -> {
  100.                     currentRank = 20
  101.                     currentStars = 0
  102.                 }
  103.             }
  104.         }
  105.     }
  106. }
  107.  
  108. object GameCalc {
  109.     fun simulateLegendClimbs(n: Int, winRate: Int): IntArray {
  110.         val results = IntArray(n)
  111.         val rng = Random()
  112.  
  113.         for (i in 0..(n - 1)) {
  114.             val player = PlayerState()
  115.  
  116.             while (player.rank > 0) {
  117.                 if (rng.nextInt(100) < winRate) {
  118.                     player.addWin()
  119.                 } else {
  120.                     player.addLoss()
  121.                 }
  122.             }
  123.  
  124.             results[i] = player.gamesPlayed
  125.         }
  126.  
  127.         return results
  128.     }
  129.  
  130.     fun simulateLegendClimbsThreaded(n: Int, winRate: Int): IntArray {
  131.         val cpus = Runtime.getRuntime().availableProcessors()
  132.         val executor = Executors.newFixedThreadPool(cpus)
  133.         val partialResults = Array(cpus, { IntArray(1) })
  134.         val partialResultAmount = n / cpus
  135.  
  136.         for (x in 1..cpus) {
  137.             executor.execute {
  138.                 partialResults[x - 1] = simulateLegendClimbs(partialResultAmount, winRate)
  139.             }
  140.         }
  141.  
  142.         executor.shutdown()
  143.         executor.awaitTermination(java.lang.Long.MAX_VALUE, TimeUnit.SECONDS)
  144.  
  145.         val results = IntArray(partialResultAmount * cpus)
  146.         var index = 0
  147.         for (array in partialResults) {
  148.             for (i in 0..(array.size - 1)) {
  149.                 results[index++] = array[i]
  150.             }
  151.         }
  152.  
  153.         return results
  154.     }
  155.  
  156.     fun calculateLegendClimbsMap(n: Int, winRate: Int, initRank: Int, rankGoal: Int): Map<Int, Int> {
  157.         val results = HashMap<Int, Int>(2000)
  158.         val rng = Random()
  159.  
  160.         for (i in 0..(n - 1)) {
  161.             val player = PlayerState(initRank)
  162.  
  163.             while (player.rank > rankGoal) {
  164.                 if (rng.nextInt(100) < winRate) {
  165.                     player.addWin()
  166.                 } else {
  167.                     player.addLoss()
  168.                 }
  169.             }
  170.  
  171.             results[player.gamesPlayed] = results.getOrDefault(player.gamesPlayed, 0) + 1
  172.         }
  173.  
  174.         return results
  175.     }
  176.  
  177.     fun calculateAverageTimeToRank(n: Int, winRate: Int, initRank: Int, rankGoal: Int): Pair<Double, Int> {
  178.         val cpus = Runtime.getRuntime().availableProcessors()
  179.         val executor = Executors.newFixedThreadPool(cpus)
  180.         val partialResults = Array<Map<Int, Int>>(cpus, { emptyMap() })
  181.         val partialResultAmount = n / cpus
  182.  
  183.         for (x in 1..cpus) {
  184.             executor.execute {
  185.                 partialResults[x - 1] = calculateLegendClimbsMap(partialResultAmount, winRate, initRank, rankGoal)
  186.             }
  187.         }
  188.  
  189.         executor.shutdown()
  190.         executor.awaitTermination(java.lang.Long.MAX_VALUE, TimeUnit.SECONDS)
  191.  
  192.         val results = TreeMap<Int, Int>()
  193.         for (map in partialResults)
  194.             map.forEach { results[it.key] = results.getOrElse(it.key, { 0 }) + it.value }
  195.  
  196.         val mean = results.map { it.key.toLong() * it.value }.sum().toDouble() / n
  197.         val median: Int = {
  198.             var x = 0
  199.             var i = 0
  200.             val index = results.iterator()
  201.             while (i < n / 2 && index.hasNext()) {
  202.                 val tmp = index.next()
  203.                 x = tmp.key
  204.                 i += tmp.value
  205.             }
  206.             x
  207.         }()
  208.  
  209.         return Pair(mean, median)
  210.     }
  211. }
  212.  
  213. fun main(args: Array<String>) {
  214.     val rolls = 10000000
  215.     println("Number of rolls: $rolls\n\n")
  216.  
  217.     for (rate in 50..60) {
  218.         val winRate = rate
  219.         val (mean, median) = GameCalc.calculateAverageTimeToRank(rolls, winRate, 20, 5)
  220.  
  221.         println("Win rate: $winRate%")
  222.         println("Mean amount of games to reach legend: $mean")
  223.         println("Median amount of games to reach legend: $median")
  224.         println()
  225.     }
  226. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement