package pl.edu.pw.mini.sg.mixed.adjuster

import pl.edu.pw.mini.sg.rng.RandomGenerator
import pl.edu.pw.mini.sg.game.deterministic.PlayerVisibleState
import pl.edu.pw.mini.sg.mixed.IterationInfo
import pl.edu.pw.mini.sg.mixed.tree.{ InnerResultNode, MixedStrategyNode, OptimizerStateType }



final case class DispariteAdjuster(
  inTree: StrategyAdjuster,
  outOfTree: OutOfTreeAdjuster,
  positive: PositivePhaseAdjuster
) extends StatefulAdjuster {
  override type AdjusterState = Unit
  override implicit val ost: OptimizerStateType[Unit] = MixedStrategyNode.unitST

  override def inTreeAdjust[
    DM, DS <: PlayerVisibleState[DM]
  ](
    mixedStrategy: MixedStrategyNode[DM,DS,Unit],
    desiredAttackerPayoff: InnerResultNode[DM,DS],
    optimalAttackerPayoff: InnerResultNode[DM,DS]
  )(
    implicit rng: RandomGenerator,
    iterationInfo: IterationInfo
  ): Boolean = inTree.adjust(mixedStrategy, desiredAttackerPayoff, optimalAttackerPayoff, rng)

  override def outOfTreeAdjust[
    DM, DS <: PlayerVisibleState[DM]
  ](
    mixedStrategy: MixedStrategyNode[DM,DS,Unit],
    optimalAttackerPayoff: InnerResultNode[DM,DS]
  )(
    implicit rng: RandomGenerator,
    iterationInfo: IterationInfo
  ): Boolean = outOfTree.adjust(mixedStrategy, optimalAttackerPayoff, rng)

  override def positiveAdjust[
    DM, DS <: PlayerVisibleState[DM]
  ](
    mixedStrategy: MixedStrategyNode[DM,DS,Unit],
    gamePayoff: InnerResultNode[DM,DS],
  )(
    implicit rng: RandomGenerator,
    iterationInfo: IterationInfo
  ): Boolean = positive.adjust(mixedStrategy, gamePayoff, rng)
}
