Advertisement
Guest User

HS legend climb sim

a guest
Mar 22nd, 2020
995
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 7.87 KB | None | 0 0
  1. import java.util.*
  2. import java.util.concurrent.Executors
  3. import java.util.concurrent.Future
  4. import java.util.concurrent.ThreadLocalRandom
  5.  
  6. fun main(args: Array<String>) {
  7.     val rolls = 10000000
  8.     println("Number of rolls: $rolls\n\n")
  9.  
  10.     for (bonus in 1..11) {
  11.         println("star multiplier: $bonus\n")
  12.  
  13.         print("win rate | ")
  14.         print("mean silver 10 | median silver 10 | ")
  15.         print("mean gold 10 | median gold 10 | ")
  16.         print("mean platinum 10 | median platinum 10 | ")
  17.         print("mean diamond 10 | median diamond 10 | ")
  18.         print("mean legend | median legend")
  19.         println()
  20.         println(":--|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:")
  21.  
  22.         for (rate in 50..60) {
  23.             val initialState = PlayerState(5, 10, 1, bonus, 0)
  24.             val results = GameCalc.calculateAverageTimeToRanking(initialState, rate, rolls)
  25.  
  26.             print("$rate% | ")
  27.             //print("%.1f | %d | ".format(Locale.ENGLISH, results.bronze5Mean, results.bronze5Median))
  28.             print("%.1f | %d | ".format(Locale.ENGLISH, results.silver10Mean, results.silver10Median))
  29.             //print("%.1f | %d | ".format(Locale.ENGLISH, results.silver5Mean, results.silver5Median))
  30.             print("%.1f | %d | ".format(Locale.ENGLISH, results.gold10Mean, results.gold10Median))
  31.             //print("%.1f | %d | ".format(Locale.ENGLISH, results.gold5Mean, results.gold5Median))
  32.             print("%.1f | %d | ".format(Locale.ENGLISH, results.platinum10Mean, results.platinum10Median))
  33.             //print("%.1f | %d | ".format(Locale.ENGLISH, results.platinum5Mean, results.platinum5Median))
  34.             print("%.1f | %d | ".format(Locale.ENGLISH, results.diamond10Mean, results.diamond10Median))
  35.             //print("%.1f | %d | ".format(Locale.ENGLISH, results.diamond5Mean, results.diamond5Median))
  36.             print("%.1f | %d".format(Locale.ENGLISH, results.legendMean, results.legendMedian))
  37.             println()
  38.         }
  39.         println()
  40.     }
  41. }
  42.  
  43. /**
  44.  * - league: 5 is bronze, 0 is legend
  45.  * - rank: 10 to 1
  46.  * - stars: 0 to 3
  47.  * - multiplier: 1 to 11
  48.  */
  49. data class PlayerState(
  50.     var league: Int,
  51.     var rank: Int,
  52.     var stars: Int,
  53.     var starMultiplier: Int,
  54.     var gamesPlayed: Int
  55. ) {
  56.     val isLegend: Boolean
  57.         get() = league < 1
  58.  
  59.     private var winStreak: Int = 0
  60.  
  61.     fun addWin() {
  62.         gamesPlayed++
  63.         winStreak++
  64.  
  65.         val baseStarsWon =
  66.             if (winStreak > 2 && (league > 1 || league == 1 && rank > 5)) 2
  67.             else 1
  68.  
  69.         val wonStars = baseStarsWon * starMultiplier
  70.         val totalStars = stars + wonStars
  71.         val mod = totalStars % 3
  72.         stars =
  73.             if (mod == 0) 3
  74.             else mod
  75.  
  76.         val ranksWon = (totalStars - 1) / 3
  77.         val totalRank = rank - ranksWon
  78.         if (ranksWon > 0) {
  79.             if (rank > 5 && totalRank < 6)
  80.                 starMultiplier--
  81.  
  82.             if (totalRank < 1)
  83.                 starMultiplier--
  84.  
  85.             if (totalRank < -4)
  86.                 starMultiplier--
  87.  
  88.             if (starMultiplier < 1)
  89.                 starMultiplier = 1
  90.  
  91.             rank =
  92.                 if (totalRank > 0) {
  93.                     totalRank
  94.                 } else {
  95.                     league--
  96.                     totalRank + 10
  97.                 }
  98.         }
  99.     }
  100.  
  101.     fun addLoss() {
  102.         gamesPlayed++
  103.         winStreak = 0
  104.         stars--
  105.  
  106.         if (stars < 0) {
  107.             stars =
  108.                 if (rank == 10 || rank == 5) {
  109.                     0
  110.                 } else {
  111.                     rank++
  112.                     2
  113.                 }
  114.         }
  115.     }
  116. }
  117.  
  118. object GameCalc {
  119.     fun calculateAverageTimeToRanking(initialState: PlayerState, winRate: Int, n: Int): CalculationResult {
  120.         val executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())
  121.         val tasks = ArrayList<Future<SimResult>>(n)
  122.  
  123.         repeat(n) {
  124.             tasks.add(executor.submit<SimResult> {
  125.                 val rng = ThreadLocalRandom.current()
  126.                 val state = initialState.copy()
  127.                 val result = SimResult()
  128.  
  129.                 while (!state.isLegend) {
  130.                     if (rng.nextInt(100) < winRate)
  131.                         state.addWin()
  132.                     else
  133.                         state.addLoss()
  134.  
  135.                     if (result.bronze5 == -1 && (state.league < 5 || state.rank < 6))
  136.                         result.bronze5 = state.gamesPlayed
  137.  
  138.                     if (result.silver10 == -1 && state.league <= 4)
  139.                         result.silver10 = state.gamesPlayed
  140.                     if (result.silver5 == -1 && (state.league < 4 || state.league == 4 && state.rank < 6))
  141.                         result.silver5 = state.gamesPlayed
  142.  
  143.                     if (result.gold10 == -1 && state.league <= 3)
  144.                         result.gold10 = state.gamesPlayed
  145.                     if (result.gold5 == -1 && (state.league < 3 || state.league == 3 && state.rank < 6))
  146.                         result.gold5 = state.gamesPlayed
  147.  
  148.                     if (result.platinum10 == -1 && state.league <= 2)
  149.                         result.platinum10 = state.gamesPlayed
  150.                     if (result.platinum5 == -1 && (state.league < 2 || state.league == 2 && state.rank < 6))
  151.                         result.platinum5 = state.gamesPlayed
  152.  
  153.                     if (result.diamond10 == -1 && state.league <= 1)
  154.                         result.diamond10 = state.gamesPlayed
  155.                     if (result.diamond5 == -1 && (state.league < 1 || state.league == 1 && state.rank < 6))
  156.                         result.diamond5 = state.gamesPlayed
  157.                 }
  158.  
  159.                 result.legend = state.gamesPlayed
  160.  
  161.                 result
  162.             })
  163.         }
  164.  
  165.         executor.shutdown()
  166.  
  167.         val sims = tasks.map { it.get() }
  168.  
  169.         return CalculationResult(
  170.             sims.mean { it.bronze5 }, sims.median { it.bronze5 },
  171.             sims.mean { it.silver10 }, sims.median { it.silver10 },
  172.             sims.mean { it.silver5 }, sims.median { it.silver5 },
  173.             sims.mean { it.gold10 }, sims.median { it.gold10 },
  174.             sims.mean { it.gold5 }, sims.median { it.gold5 },
  175.             sims.mean { it.platinum10 }, sims.median { it.platinum10 },
  176.             sims.mean { it.platinum5 }, sims.median { it.platinum5 },
  177.             sims.mean { it.diamond10 }, sims.median { it.diamond10 },
  178.             sims.mean { it.diamond5 }, sims.median { it.diamond5 },
  179.             sims.mean { it.legend }, sims.median { it.legend }
  180.         )
  181.     }
  182.  
  183.     private inline fun List<SimResult>.mean(value: (SimResult) -> Int): Double =
  184.         foldRight(0L) { ele, partial -> value(ele) + partial } / size.toDouble()
  185.  
  186.     private inline fun List<SimResult>.median(crossinline value: (SimResult) -> Int): Int =
  187.         value(sortedBy { value(it) }[this.size / 2])
  188. }
  189.  
  190. data class SimResult(
  191.     var bronze5: Int = -1,
  192.     var silver10: Int = -1,
  193.     var silver5: Int = -1,
  194.     var gold10: Int = -1,
  195.     var gold5: Int = -1,
  196.     var platinum10: Int = -1,
  197.     var platinum5: Int = -1,
  198.     var diamond10: Int = -1,
  199.     var diamond5: Int = -1,
  200.     var legend: Int = -1
  201. )
  202.  
  203. data class CalculationResult(
  204.     var bronze5Mean: Double = -1.0, var bronze5Median: Int = -1,
  205.     var silver10Mean: Double = -1.0, var silver10Median: Int = -1,
  206.     var silver5Mean: Double = -1.0, var silver5Median: Int = -1,
  207.     var gold10Mean: Double = -1.0, var gold10Median: Int = -1,
  208.     var gold5Mean: Double = -1.0, var gold5Median: Int = -1,
  209.     var platinum10Mean: Double = -1.0, var platinum10Median: Int = -1,
  210.     var platinum5Mean: Double = -1.0, var platinum5Median: Int = -1,
  211.     var diamond10Mean: Double = -1.0, var diamond10Median: Int = -1,
  212.     var diamond5Mean: Double = -1.0, var diamond5Median: Int = -1,
  213.     var legendMean: Double = -1.0, var legendMedian: Int = -1
  214. )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement