<commit_before>/*
 * This file is part of Evo2DSimAnalyzer.
 *
 * Evo2DSimAnalyzer is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Evo2DSimAnalyzer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Evo2DSimAnalyzer.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.vastness.evo2dsim.analyzer.gui

import org.vastness.evo2dsim.gui._
import spray.json._
import org.vastness.evo2dsim.utils.MyJsonProtocol._
import scala.swing._
import scalax.file.Path
import scalax.io.Input
import java.io.File
import org.vastness.evo2dsim.evolution.Genome
import org.vastness.evo2dsim.environment.{Environment, EnvironmentBuilder}
import scala.concurrent._
import ExecutionContext.Implicits.global
import scala.swing.event.{Key, KeyPressed}
import org.vastness.evo2dsim.simulator.light.{LightCategory, LightManager}
import org.vastness.evo2dsim.teem.enki.sbot.{SBotLightSensor, SBotController, SBot}


class MainWindow extends MainFrame with RenderManager {
  val worldView: Surface = new Surface
  var e: Option[Environment] = None
  var renderComponents = Set.empty[Component]

  var timeStep: Int = 50
  var dataDir: Option[File] = None
  var evalDir: Option[Path] = None
  var group: Int = 0
  var generation: Map[Int, (Double, Genome)] = Map.empty

  def lm: Option[LightManager] = e.map(_.sim.lightManager)

  var envBuilder: EnvironmentBuilder = EnvironmentBuilder.Basic

  title = "Evo2DSim Analyzer"

  override def closeOperation() {
    e.map(_.running = false)
    super.closeOperation()
  }

  menuBar = new MenuBar {
    contents += new MenuItem(Action ("Select data directory") {
      val fc = new FileChooser(dataDir.getOrElse(new File(".")))
      fc.fileSelectionMode = FileChooser.SelectionMode.DirectoriesOnly

      dataDir = fc.showOpenDialog(this) match {
        case FileChooser.Result.Approve if fc.selectedFile.exists() => Some(fc.selectedFile)
        case _ => dataDir
      }
    })
    contents += new MenuItem( Action("Select evaluation run") {
      evalDir = dataDir map {d => Path(d)} map showEvaluations
    })
    contents += new MenuItem( Action("Select generation") {
      generation = evalDir map showStats match {
        case Some(gen) => loadGeneration(evalDir.get, gen)
        case None => Map.empty
      }
    })
    contents += new MenuItem( Action("Select group") {
      group = showGroups
    })
    contents += new MenuItem( Action("Init") {
      initEnvironment()
    })
    contents += new MenuItem( Action("Env") {
      selectEnvironment()
    })
    contents += new MenuItem( Action("Agent View") {
      showAgentView()
    })
  }
  contents = new BorderPanel {
    import BorderPanel._
    add(worldView, Position.Center)

    listenTo(keys)
    reactions += {
      case KeyPressed(_, Key.R, _, _)                     => initEnvironment()
      case KeyPressed(_, Key.T, _, _)                     => toggleText()
      case KeyPressed(_, Key.P, _, _)                     => pause()
      case KeyPressed(_, Key.A, Key.Modifier.Control, _)  => lm.map(_.disableCategory(LightCategory.AgentLight))
      case KeyPressed(_, Key.A, Key.Modifier.Shift, _)    => lm.map(_.enableCategory(LightCategory.AgentLight))
      case KeyPressed(_, Key.A, _, _)                     => lm.map(_.toggleCategory(LightCategory.AgentLight))
      case KeyPressed(_, Key.F, Key.Modifier.Control, _)  => lm.map(_.disableCategory(LightCategory.FoodSourceLight))
      case KeyPressed(_, Key.F, Key.Modifier.Shift, _)    => lm.map(_.enableCategory(LightCategory.FoodSourceLight))
      case KeyPressed(_, Key.F, _, _)                     => lm.map(_.toggleCategory(LightCategory.FoodSourceLight))
    }

    focusable = true
    requestFocus()
  }

  size = new Dimension(300, 200)

  def selectEnvironment() {
    envBuilder = Dialog.showInput[EnvironmentBuilder](message = "Please select an Environment", entries = EnvironmentBuilder.values.toSeq, initial = envBuilder) match {
      case Some(eBuilder) => eBuilder
      case None => envBuilder
    }
  }

  def showAgentView() {
    val agent = Dialog.showInput[Int](message = "Please choose Agent",
      entries = e map { _.agents.map(_._1).toSeq } getOrElse Seq.empty[Int] , initial = 0) match {
      case Some(a) => e map { _.agents(a)}
      case None => None
    }
    agent flatMap (_.controller map { case sC: SBotController => sC.lightSensor }) map { //TODO: Simplify
      cam => {
        val cv = new CameraView(cam)
        val dialog = new ComponentDialog(this, cv, this)
        dialog.showDialog()
      }

    }
  }

  def pause() = e map {e => e.pause = if (e.pause) false else true}

  def toggleText() {
    EnvironmentManager.showData = if (EnvironmentManager.showData) false else true
  }

  def loadGeneration(dir: Path, generation: Int): Map[Int, (Double, Genome)] = {
    val genFile = dir resolve "Gen_%04d.json".format(generation)
    val input: Input = genFile.inputStream()
    val gen = input.string.asJson.convertTo[Map[String, (Double, Genome)]]
    gen.map (x => x._1.toInt -> x._2)
  }

  def loadEvaluations(dir: Path) = {
    (IndexedSeq("Dir"), dir.children().filter(_.isDirectory).toArray.sorted map {c => Array(c.name)} )<commit_msg>adapts to upstream Evo2DSim version<commit_after>/*
 * This file is part of Evo2DSimAnalyzer.
 *
 * Evo2DSimAnalyzer is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Evo2DSimAnalyzer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Evo2DSimAnalyzer.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.vastness.evo2dsim.analyzer.gui

import org.vastness.evo2dsim.gui._
import spray.json._
import org.vastness.evo2dsim.utils.MyJsonProtocol._
import scala.swing._
import scalax.file.Path
import scalax.io.Input
import java.io.File
import org.vastness.evo2dsim.evolution.Genome
import org.vastness.evo2dsim.environment.{Environment, EnvironmentBuilder}
import scala.concurrent._
import ExecutionContext.Implicits.global
import scala.swing.event.{Key, KeyPressed}
import org.vastness.evo2dsim.simulator.light.{LightCategory, LightManager}
import org.vastness.evo2dsim.teem.enki.sbot.{SBotLightSensor, SBotController, SBot}


class MainWindow extends MainFrame with RenderManager {
  val worldView: Surface = new Surface
  var e: Option[Environment] = None
  var renderComponents = Set.empty[Component]

  var timeStep: Int = 50
  var dataDir: Option[File] = None
  var evalDir: Option[Path] = None
  var group: Int = 0
  var generation: Map[Int, (Double, Genome)] = Map.empty

  def lm: Option[LightManager] = e.map(_.sim.lightManager)

  var envBuilder: EnvironmentBuilder = EnvironmentBuilder.Basic

  title = "Evo2DSim Analyzer"

  override def closeOperation() {
    e.map(_.running = false)
    super.closeOperation()
  }

  menuBar = new MenuBar {
    contents += new MenuItem(Action ("Select data directory") {
      val fc = new FileChooser(dataDir.getOrElse(new File(".")))
      fc.fileSelectionMode = FileChooser.SelectionMode.DirectoriesOnly

      dataDir = fc.showOpenDialog(this) match {
        case FileChooser.Result.Approve if fc.selectedFile.exists() => Some(fc.selectedFile)
        case _ => dataDir
      }
    })
    contents += new MenuItem( Action("Select evaluation run") {
      evalDir = dataDir map {d => Path(d)} map showEvaluations
    })
    contents += new MenuItem( Action("Select generation") {
      generation = evalDir map showStats match {
        case Some(gen) => loadGeneration(evalDir.get, gen)
        case None => Map.empty
      }
    })
    contents += new MenuItem( Action("Select group") {
      group = showGroups
    })
    contents += new MenuItem( Action("Init") {
      initEnvironment()
    })
    contents += new MenuItem( Action("Env") {
      selectEnvironment()
    })
    contents += new MenuItem( Action("Agent View") {
      showAgentView()
    })
  }
  contents = new BorderPanel {
    import BorderPanel._
    add(worldView, Position.Center)

    listenTo(keys)
    reactions += {
      case KeyPressed(_, Key.R, _, _)                     => initEnvironment()
      case KeyPressed(_, Key.T, _, _)                     => toggleText()
      case KeyPressed(_, Key.P, _, _)                     => pause()
      case KeyPressed(_, Key.A, Key.Modifier.Control, _)  => lm.map(_.disableCategory(LightCategory.AgentLight))
      case KeyPressed(_, Key.A, Key.Modifier.Shift, _)    => lm.map(_.enableCategory(LightCategory.AgentLight))
      case KeyPressed(_, Key.A, _, _)                     => lm.map(_.toggleCategory(LightCategory.AgentLight))
      case KeyPressed(_, Key.F, Key.Modifier.Control, _)  => lm.map(_.disableCategory(LightCategory.FoodSourceLight))
      case KeyPressed(_, Key.F, Key.Modifier.Shift, _)    => lm.map(_.enableCategory(LightCategory.FoodSourceLight))
      case KeyPressed(_, Key.F, _, _)                     => lm.map(_.toggleCategory(LightCategory.FoodSourceLight))
    }

    focusable = true
    requestFocus()
  }

  size = new Dimension(300, 200)

  def selectEnvironment() {
    envBuilder = Dialog.showInput[EnvironmentBuilder](message = "Please select an Environment", entries = EnvironmentBuilder.values.toSeq, initial = envBuilder) match {
      case Some(eBuilder) => eBuilder
      case None => envBuilder
    }
  }

  def showAgentView() {
    val agent = Dialog.showInput[Int](message = "Please choose Agent",
      entries = e map { _.agents.map(_._1).toSeq } getOrElse Seq.empty[Int] , initial = 0) match {
      case Some(a) => e map { _.agents(a)}
      case None => None
    }
    agent flatMap (_.controller map { case sC: SBotController => sC.lightSensor }) map { //TODO: Simplify
      cam => {
        val cv = new CameraView(cam)
        val dialog = new ComponentDialog(this, cv, this)
        dialog.showDialog()
      }

    }
  }

  def pause() = e map {e => e.toggle_pause()}

  def toggleText() {
    EnvironmentManager.showData = if (EnvironmentManager.showData) false else true
  }

  def loadGeneration(dir: Path, generation: Int): Map[Int, (Double, Genome)] = {
    val genFile = dir resolve "Gen_%04d.json".format(generation)
    val input: Input = genFile.inputStream()
    val gen = input.string.asJson.convertTo[Map[String, (Double, Genome)]]
    gen.map (x => x._1.toInt -> x._2)
  }

  def loadEvaluations(dir: Path) = {
    (IndexedSeq("Dir"), dir.children().filter(_.isDirectory).toArray.sorted map {c => Array(c.name)} )
{'fraction_non_alphanumeric': 0.11436170212765957, 'fraction_numerical': 0.0050531914893617025, 'mean_word_length': 3.263416477702192, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6720715', 'n_tokens_mistral': 3506, 'n_tokens_neox': 3378, 'n_words': 905}