Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.util.*
- import java.util.concurrent.Executors
- import java.util.concurrent.Future
- import java.util.concurrent.ThreadLocalRandom
- fun main(args: Array<String>) {
- val rolls = 10000000
- println("Number of rolls: $rolls\n\n")
- for (bonus in 1..11) {
- println("star multiplier: $bonus\n")
- print("win rate | ")
- print("mean silver 10 | median silver 10 | ")
- print("mean gold 10 | median gold 10 | ")
- print("mean platinum 10 | median platinum 10 | ")
- print("mean diamond 10 | median diamond 10 | ")
- print("mean legend | median legend")
- println()
- println(":--|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:")
- for (rate in 50..60) {
- val initialState = PlayerState(5, 10, 1, bonus, 0)
- val results = GameCalc.calculateAverageTimeToRanking(initialState, rate, rolls)
- print("$rate% | ")
- //print("%.1f | %d | ".format(Locale.ENGLISH, results.bronze5Mean, results.bronze5Median))
- print("%.1f | %d | ".format(Locale.ENGLISH, results.silver10Mean, results.silver10Median))
- //print("%.1f | %d | ".format(Locale.ENGLISH, results.silver5Mean, results.silver5Median))
- print("%.1f | %d | ".format(Locale.ENGLISH, results.gold10Mean, results.gold10Median))
- //print("%.1f | %d | ".format(Locale.ENGLISH, results.gold5Mean, results.gold5Median))
- print("%.1f | %d | ".format(Locale.ENGLISH, results.platinum10Mean, results.platinum10Median))
- //print("%.1f | %d | ".format(Locale.ENGLISH, results.platinum5Mean, results.platinum5Median))
- print("%.1f | %d | ".format(Locale.ENGLISH, results.diamond10Mean, results.diamond10Median))
- //print("%.1f | %d | ".format(Locale.ENGLISH, results.diamond5Mean, results.diamond5Median))
- print("%.1f | %d".format(Locale.ENGLISH, results.legendMean, results.legendMedian))
- println()
- }
- println()
- }
- }
- /**
- * - league: 5 is bronze, 0 is legend
- * - rank: 10 to 1
- * - stars: 0 to 3
- * - multiplier: 1 to 11
- */
- data class PlayerState(
- var league: Int,
- var rank: Int,
- var stars: Int,
- var starMultiplier: Int,
- var gamesPlayed: Int
- ) {
- val isLegend: Boolean
- get() = league < 1
- private var winStreak: Int = 0
- fun addWin() {
- gamesPlayed++
- winStreak++
- val baseStarsWon =
- if (winStreak > 2 && (league > 1 || league == 1 && rank > 5)) 2
- else 1
- val wonStars = baseStarsWon * starMultiplier
- val totalStars = stars + wonStars
- val mod = totalStars % 3
- stars =
- if (mod == 0) 3
- else mod
- val ranksWon = (totalStars - 1) / 3
- val totalRank = rank - ranksWon
- if (ranksWon > 0) {
- if (rank > 5 && totalRank < 6)
- starMultiplier--
- if (totalRank < 1)
- starMultiplier--
- if (totalRank < -4)
- starMultiplier--
- if (starMultiplier < 1)
- starMultiplier = 1
- rank =
- if (totalRank > 0) {
- totalRank
- } else {
- league--
- totalRank + 10
- }
- }
- }
- fun addLoss() {
- gamesPlayed++
- winStreak = 0
- stars--
- if (stars < 0) {
- stars =
- if (rank == 10 || rank == 5) {
- 0
- } else {
- rank++
- 2
- }
- }
- }
- }
- object GameCalc {
- fun calculateAverageTimeToRanking(initialState: PlayerState, winRate: Int, n: Int): CalculationResult {
- val executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())
- val tasks = ArrayList<Future<SimResult>>(n)
- repeat(n) {
- tasks.add(executor.submit<SimResult> {
- val rng = ThreadLocalRandom.current()
- val state = initialState.copy()
- val result = SimResult()
- while (!state.isLegend) {
- if (rng.nextInt(100) < winRate)
- state.addWin()
- else
- state.addLoss()
- if (result.bronze5 == -1 && (state.league < 5 || state.rank < 6))
- result.bronze5 = state.gamesPlayed
- if (result.silver10 == -1 && state.league <= 4)
- result.silver10 = state.gamesPlayed
- if (result.silver5 == -1 && (state.league < 4 || state.league == 4 && state.rank < 6))
- result.silver5 = state.gamesPlayed
- if (result.gold10 == -1 && state.league <= 3)
- result.gold10 = state.gamesPlayed
- if (result.gold5 == -1 && (state.league < 3 || state.league == 3 && state.rank < 6))
- result.gold5 = state.gamesPlayed
- if (result.platinum10 == -1 && state.league <= 2)
- result.platinum10 = state.gamesPlayed
- if (result.platinum5 == -1 && (state.league < 2 || state.league == 2 && state.rank < 6))
- result.platinum5 = state.gamesPlayed
- if (result.diamond10 == -1 && state.league <= 1)
- result.diamond10 = state.gamesPlayed
- if (result.diamond5 == -1 && (state.league < 1 || state.league == 1 && state.rank < 6))
- result.diamond5 = state.gamesPlayed
- }
- result.legend = state.gamesPlayed
- result
- })
- }
- executor.shutdown()
- val sims = tasks.map { it.get() }
- return CalculationResult(
- sims.mean { it.bronze5 }, sims.median { it.bronze5 },
- sims.mean { it.silver10 }, sims.median { it.silver10 },
- sims.mean { it.silver5 }, sims.median { it.silver5 },
- sims.mean { it.gold10 }, sims.median { it.gold10 },
- sims.mean { it.gold5 }, sims.median { it.gold5 },
- sims.mean { it.platinum10 }, sims.median { it.platinum10 },
- sims.mean { it.platinum5 }, sims.median { it.platinum5 },
- sims.mean { it.diamond10 }, sims.median { it.diamond10 },
- sims.mean { it.diamond5 }, sims.median { it.diamond5 },
- sims.mean { it.legend }, sims.median { it.legend }
- )
- }
- private inline fun List<SimResult>.mean(value: (SimResult) -> Int): Double =
- foldRight(0L) { ele, partial -> value(ele) + partial } / size.toDouble()
- private inline fun List<SimResult>.median(crossinline value: (SimResult) -> Int): Int =
- value(sortedBy { value(it) }[this.size / 2])
- }
- data class SimResult(
- var bronze5: Int = -1,
- var silver10: Int = -1,
- var silver5: Int = -1,
- var gold10: Int = -1,
- var gold5: Int = -1,
- var platinum10: Int = -1,
- var platinum5: Int = -1,
- var diamond10: Int = -1,
- var diamond5: Int = -1,
- var legend: Int = -1
- )
- data class CalculationResult(
- var bronze5Mean: Double = -1.0, var bronze5Median: Int = -1,
- var silver10Mean: Double = -1.0, var silver10Median: Int = -1,
- var silver5Mean: Double = -1.0, var silver5Median: Int = -1,
- var gold10Mean: Double = -1.0, var gold10Median: Int = -1,
- var gold5Mean: Double = -1.0, var gold5Median: Int = -1,
- var platinum10Mean: Double = -1.0, var platinum10Median: Int = -1,
- var platinum5Mean: Double = -1.0, var platinum5Median: Int = -1,
- var diamond10Mean: Double = -1.0, var diamond10Median: Int = -1,
- var diamond5Mean: Double = -1.0, var diamond5Median: Int = -1,
- var legendMean: Double = -1.0, var legendMedian: Int = -1
- )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement