Skip to content

Instantly share code, notes, and snippets.

@torao
Created October 31, 2015 23:29
Show Gist options
  • Save torao/69844eeb2a922f31fcda to your computer and use it in GitHub Desktop.
Save torao/69844eeb2a922f31fcda to your computer and use it in GitHub Desktop.
// copy & paste to scala REPL
trait Mod { val name:String; val rarity:Int }
class HeatSink(val name:String, val effect:Double, val rarity:Int) extends Mod
case object CHS extends HeatSink("CHS", 0.3, 1)
case object RHS extends HeatSink("RHS", 0.5, 2)
case object VRHS extends HeatSink("VRHS", 0.7, 3)
val heatSink = Seq(CHS, RHS, VRHS)
class MultiHack(val name:String, val effect:Int, val rarity:Int) extends Mod
case object CMH extends MultiHack("CMH", 4, 1)
case object RMH extends MultiHack("RMH", 8, 2)
case object VRMH extends MultiHack("VRMH", 12, 3)
val multiHack = Seq(CMH, RMH, VRMH)
case class Slots(mods:Seq[Mod]){
lazy val hackCount = mods.collect{ case mh:MultiHack => mh }.sortBy{ - _.rarity }.toList match {
case Nil => 4
case mh :: Nil => 4 + mh.effect
case head :: rest => 4 + head.effect + rest.map{ _.effect / 2 }.sum
}
lazy val cooldown = mods.collect{ case hs:HeatSink => hs }.sortBy{ - _.rarity }.toList match {
case Nil => 5 * 60.0
case hs :: Nil => 5 * 60.0 * (1 - hs.effect)
case head :: rest => 5 * 60.0 * (1 - head.effect) * rest.map{ x => (1 - x.effect / 2.0) }.product
}
lazy val rarity = mods.map{ _.rarity }.sum
override def toString = mods.mkString(",")
}
val allSlotPatterns:Seq[Slots] = {
val mods = (heatSink ++ multiHack)
def select(rest:Int):Seq[Seq[Mod]] = if(rest == 0) Seq(Seq()) else {
select(rest - 1).flatMap { t =>
mods.map{ _ +: t }
}
}
(0 to 4).flatMap { maxMods => select(maxMods) }.map{ s => new Slots(s.sortBy{ _.name }.reverse) }.distinct
}
case class Hack(name:String, cost:Int, effect:Double)
val hackBonus = (1.625+0.5+0.4)/2 // 1.625
val glyphHack = Hack("glyph", 30, 1 + hackBonus)
val normalHack = Hack("normal", 5, 1.0)
val slotSpace = 0
(1 to 13).foreach{ portals =>
(1 to 3).foreach{ frackers =>
Seq(normalHack, glyphHack).foreach{ hack =>
val limit = frackers * 10.0 * 60.0
val hacks = allSlotPatterns.map{ slot =>
val interval = math.max(0, slot.cooldown - (portals - 1) * hack.cost) // 1周ごとに必要な待ち
val cycle = limit / (portals * hack.cost + interval)
val hackCount = math.min(cycle * portals, slot.hackCount * portals)
(hackCount, interval, slot)
}
hacks.filter{ _._3.mods.size <= 4 - slotSpace }.groupBy{ _._1 }.maxBy{ _._1 }._2.groupBy{ _._3.rarity }.minBy{ _._1 }._2.distinct.foreach{ case (hackCount, interval, slot) =>
println(f"$portals\t$frackers\t${hack.name}\t$slot\t${slot.cooldown}%.0f\t$interval%.0f\t$hackCount%.0f\t${hackCount*hack.effect*2}%.0f\t${150/(hackCount/frackers/portals)}%.1f")
}
}
}
}
// --------------------------------
(1 to 20).foreach{ portals =>
println(portals + "\t" +
Seq(normalHack, Hack("glyph(0%)", 30, 1 + 0.4), Hack("glyph(50%)", 30, 1 + hackBonus), Hack("glyph(100%)", 30, 1 + 1.625+0.5)).map{ hack =>
val limit = 5 * 10.0 * 60.0
val hacks = allSlotPatterns.map{ slot =>
val interval = math.max(0, slot.cooldown - (portals - 1) * hack.cost) // 1周ごとに必要な待ち
val cycle = limit / (portals * hack.cost + interval)
val hackCount = math.min(cycle * portals, slot.hackCount * portals)
(hackCount, interval, slot)
}
hacks.filter{ _._3.mods.size <= 4 - slotSpace }.groupBy{ _._1 }.maxBy{ _._1 }._2.groupBy{ _._3.rarity }.minBy{ _._1 }._2.distinct.head match { case (hackCount, interval, slot) =>
f"${hackCount*hack.effect*2}%.0f"
}
}.mkString("\t"))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment