Skip to content

Commit

Permalink
Merge pull request #12 from halotukozak/todos
Browse files Browse the repository at this point in the history
Todos
  • Loading branch information
Corvette653 authored Jan 24, 2024
2 parents 97c4eb7 + a3195a7 commit c1f4919
Show file tree
Hide file tree
Showing 27 changed files with 679 additions and 219 deletions.
4 changes: 2 additions & 2 deletions src/main/kotlin/backend/Simulation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ class Simulation(
private suspend fun nextDay() {
println("${day.updateAndGet { it + 1 }} day!")
map.growAnimals()
map.removeDeadAnimals { statisticsService.registerDeath(day.value, it) }
map.removeDeadAnimals { statisticsService.registerDeath(it.size) }
map.rotateAnimals()
map.moveAnimals()
map.consumePlants()
map.breedAnimals { launch { statisticsService.registerBirth(day.value) } }
map.growPlants(config.plantsPerDay)

statisticsService.registerEndOfDay(day.value, plants.value, aliveAnimals.value.flattenValues())
statisticsService.registerEndOfDay(day.value, plants.value.size, aliveAnimals.value.flattenValues())
}

private var simulationJob: Job = launch {
Expand Down
18 changes: 8 additions & 10 deletions src/main/kotlin/backend/map/EquatorMap.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,21 @@ class EquatorMap(config: Config) : AbstractMap(config) {
override suspend fun growPlants(plantsCount: Int) = _plants.update { plants ->
fun IntRange.emptyFields(x: Int) = fields.filter { it.x == x && it.y in this } - plants

val emptyFieldsOnEquator = (0..<config.mapWidth).flatMap { equator.emptyFields(it) }
val plantsOnEquator = minOf(emptyFieldsOnEquator.size, (plantsCount * 0.8).roundToInt())

val emptyFieldsOnEquator = _preferredFields.value.toList().ifEmpty {
(0..<config.mapWidth).flatMap { equator.emptyFields(it) }
}
val emptyFieldsBesideEquator = (0..<config.mapWidth).flatMap { x ->
(0..<equator.first).emptyFields(x) + (equator.last + 1..<config.mapHeight).emptyFields(x)
}

val plantsOnEquator = minOf(emptyFieldsOnEquator.size, (plantsCount * 0.8).roundToInt())
val plantsBesideEquator = minOf(emptyFieldsBesideEquator.size, plantsCount - plantsOnEquator)

(plants + emptyFieldsOnEquator.takeRandom(plantsOnEquator, random) + emptyFieldsBesideEquator.takeRandom(
plantsBesideEquator,
random,
)).also {
(plants +
emptyFieldsOnEquator.takeRandom(plantsOnEquator, random) +
emptyFieldsBesideEquator.takeRandom(plantsBesideEquator, random)).also { newPlants ->
_preferredFields.update {
equator
.flatMap { y -> (0..<config.mapWidth).map { x -> Vector(x, y) } }
.toSet() - _plants.value
(0..<config.mapWidth).flatMap { x -> equator.map { y -> Vector(x, y) } }.toSet() - newPlants
}
}
}
Expand Down
47 changes: 10 additions & 37 deletions src/main/kotlin/backend/map/JungleMap.kt
Original file line number Diff line number Diff line change
@@ -1,58 +1,31 @@
package backend.map

import backend.config.Config
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.update
import shared.takeRandom
import kotlin.math.roundToInt


class JungleMap(config: Config) : AbstractMap(config) {
@OptIn(ExperimentalCoroutinesApi::class)

override suspend fun growPlants(plantsCount: Int) {
_plants.update { plants ->
val preferredPositions = plants
.asFlow()
.flatMapMerge { it.surroundingPositions }
.filter { it.inMap() }
.toSet()

val otherPositions = (fields - preferredPositions)
val preferredPositions = _preferredFields.value
val otherPositions = fields - preferredPositions - plants

val plantsOnPreferredPositions = minOf(preferredPositions.size, (plantsCount * 0.8).roundToInt())
val plantsOnOtherPositions = minOf(otherPositions.size, plantsCount - plantsOnPreferredPositions)

(plants + seedRandomly(preferredPositions.toList(), plantsOnPreferredPositions) + seedRandomly(
otherPositions,
plantsOnOtherPositions,
)).also { fields ->
(plants +
preferredPositions.toList().takeRandom(plantsOnPreferredPositions, random) +
otherPositions.takeRandom(plantsOnOtherPositions, random)).also { fields ->
_preferredFields.update {
fields
.asFlow()
.flatMapMerge { it.surroundingPositions }
.filter { it.inMap() }
.flatMap { it.surroundingPositions }
.filter { it.x in 0..<config.mapWidth && it.y in 0..<config.mapHeight }
.toSet() - fields
}
}
}
}

private fun Vector.inMap() = x in 0..<config.mapWidth && y in 0..<config.mapHeight

private val Vector.surroundingPositions
get() = flowOf(
Vector(x - 1, y - 1),
Vector(x, y - 1),
Vector(x + 1, y - 1),
Vector(x - 1, y),
Vector(x + 1, y),
Vector(x - 1, y + 1),
Vector(x, y + 1),
Vector(x + 1, y + 1)
)


private fun seedRandomly(emptyFields: List<Vector>, numberOfSeeds: Int) =
generateSequence { emptyFields[random.nextInt(emptyFields.size)] }
.distinct()
.take(numberOfSeeds)
}
13 changes: 13 additions & 0 deletions src/main/kotlin/backend/map/Vector.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,17 @@ data class Vector(val x: Int, val y: Int) {
operator fun plus(vector: Vector): Vector = Vector(this.x + vector.x, this.y + vector.y)
operator fun minus(vector: Vector): Vector = Vector(this.x - vector.x, this.y - vector.y)


val surroundingPositions: List<Vector> by lazy {
listOf(
Vector(x - 1, y - 1),
Vector(x, y - 1),
Vector(x + 1, y - 1),
Vector(x - 1, y),
Vector(x + 1, y),
Vector(x - 1, y + 1),
Vector(x, y + 1),
Vector(x + 1, y + 1)
)
}
}
3 changes: 2 additions & 1 deletion src/main/kotlin/backend/model/Animal.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ data class Animal(
val children: Int = 0,
val id: UUID = UUID.randomUUID(),
val parents: Pair<UUID, UUID>? = null,
val consumedPlants: Int = 0,
) : Comparable<Animal> {

val isDead by lazy { energy <= 0 }

fun rotate(): Animal = this.copy(direction = direction + genome.next())
fun turnBack(): Animal = this.copy(direction = direction.opposite)
fun grow(): Animal = this.copy(energy = energy - 1, age = age + 1)
fun eat(energy: Int): Animal = this.copy(energy = this.energy + energy)
fun eat(energy: Int): Animal = this.copy(energy = this.energy + energy, consumedPlants = this.consumedPlants + 1)

private fun decreaseEnergy(energy: Int): Animal = this.copy(energy = this.energy - energy)
private fun withChild(): Animal = this.copy(children = this.children + 1)
Expand Down
2 changes: 2 additions & 0 deletions src/main/kotlin/backend/model/Genome.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class Genome(val genes: List<Gen>, private var curr: Int) : Iterator<Gen> {

override fun next(): Gen = genes[(curr++) % genes.size]

fun currentGene(): Gen = genes[curr % genes.size]

val frequencyMap by lazy { this.genes.groupingBy { it }.eachCount() }

}
Expand Down
35 changes: 17 additions & 18 deletions src/main/kotlin/backend/statistics/StatisticsService.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package backend.statistics

import backend.config.Config
import backend.map.Vector
import backend.model.Animal
import backend.model.Gen
import backend.model.Genome
Expand Down Expand Up @@ -39,11 +38,11 @@ class StatisticsService(simulationConfig: Config) {
}

val isDeathsMetricsEnabled = simulationConfig.deaths
private val _deathMetrics by lazy { MutableACounter<Int>(range) }
private val _deathMetrics by lazy { MutableCounter<Int>(range) }
private val _minDeathMetrics by lazy(::MutableMinimumMetrics)
private val _maxDeathMetrics by lazy(::MutableMaximumMetrics)
private val _avgDeathMetrics by lazy(::MutableAverageMetrics)
val deathMetrics: ACounter<Int> by lazy { _deathMetrics }
val deathMetrics: Counter<Int> by lazy { _deathMetrics }
val deathTripleMetrics by lazy {
combine(_minDeathMetrics, _maxDeathMetrics, _avgDeathMetrics, ::Triple)
}
Expand All @@ -61,11 +60,11 @@ class StatisticsService(simulationConfig: Config) {
val isPlantDensityMetricsEnabled = simulationConfig.plantDensity
private val _plantDensityMetrics by lazy { MutableCounter<Int>(range) }
private val _minPlantDensityMetrics by lazy(::MutableMinimumMetrics)
private val _maxPlantMetrics by lazy(::MutableMaximumMetrics)
private val _avgPlantMetrics by lazy(::MutableAverageMetrics)
private val _maxPlantDensityMetrics by lazy(::MutableMaximumMetrics)
private val _avgPlantDensityMetrics by lazy(::MutableAverageMetrics)
val plantDensityMetrics: Counter<Int> by lazy { _plantDensityMetrics }
val plantDensityTriple: Flow<MinMaxAvgTriple> by lazy {
combine(_minPlantDensityMetrics, _maxPlantMetrics, _avgPlantMetrics, ::Triple)
combine(_minPlantDensityMetrics, _maxPlantDensityMetrics, _avgPlantDensityMetrics, ::Triple)
}

val isDailyAverageAgeMetricsEnabled = simulationConfig.dailyAverageAge
Expand Down Expand Up @@ -94,7 +93,7 @@ class StatisticsService(simulationConfig: Config) {

val presentGens by lazy {
genCollector.map {
it.toList().lastOrNull()?.second?.sortedBy { it.first }?.map { (gen, count) ->
it.lastOrNull()?.second?.sortedBy { it.first }?.map { (gen, count) ->
PieChart.Data(gen.name, count.toDouble())
}
}
Expand All @@ -113,21 +112,21 @@ class StatisticsService(simulationConfig: Config) {
}
}

fun registerDeath(day: Day, animals: List<Animal>) {
fun registerDeath(animals: Int) {
if (isDeathsMetricsEnabled) {
_deathMetrics.register(day, animals.size)
_minDeathMetrics.register(animals.size)
_maxDeathMetrics.register(animals.size)
_avgDeathMetrics.register(animals.size)
_deathMetrics.register(animals)
_minDeathMetrics.register(animals)
_maxDeathMetrics.register(animals)
_avgDeathMetrics.register(animals)
}
}

private fun registerPlants(n: Int) {
if (isPlantDensityMetricsEnabled) {
_plantDensityMetrics.register(n)
_minPlantDensityMetrics.register(n)
_maxPlantMetrics.register(n)
_avgPlantMetrics.register(n)
_maxPlantDensityMetrics.register(n)
_avgPlantDensityMetrics.register(n)
}
}

Expand All @@ -138,14 +137,14 @@ class StatisticsService(simulationConfig: Config) {
_maxPopulationMetrics.register(animals.size)
_avgPopulationMetrics.register(animals.size)
}
if (isDailyAverageEnergyMetricsEnabled) {
if (isDailyAverageAgeMetricsEnabled) {
val avg = animals.map(Animal::age).average()
_dailyAverageAgeMetrics.register(avg)
_minDailyAverageAgeMetrics.register(avg)
_maxDailyAverageAgeMetrics.register(avg)
_avgDailyAverageAgeMetrics.register(avg)
}
if (isDailyAverageAgeMetricsEnabled){
if (isDailyAverageEnergyMetricsEnabled){
val avg = animals.map(Animal::energy).average()
_dailyAverageEnergyMetrics.register(avg)
_minDailyAverageEnergyMetrics.register(avg)
Expand All @@ -170,8 +169,8 @@ class StatisticsService(simulationConfig: Config) {
.sortedByDescending { it.second })
}

fun registerEndOfDay(day: Day, plants: Set<Vector>, animals: List<Animal>) {
registerPlants(plants.size)
fun registerEndOfDay(day: Day, plants: Int, animals: List<Animal>) {
registerPlants(plants)
registerAnimals(animals)

if (isCsvExportEnabled) export(day)
Expand Down
45 changes: 40 additions & 5 deletions src/main/kotlin/frontend/DarwinStyles.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@ import tornadofx.DrawerStyles.Companion.drawer

class DarwinStyles : Stylesheet() {
private val thumbArea by cssclass()

private val centered by cssclass()
companion object Colors {
const val GREEN = "#4e6d4e"
const val LIGHTGREEN = "#b8c9b8"
const val WHITE = "#f2f2f2"
const val BLACK = "#2f2f2f"
const val LICORICE = "#190303"
const val CHOCOLATE_COSMOS = "#450920"
const val RASPBERRY_ROSE = "#A53860"
const val BLUSH = "#DA627D"
const val PROCESS_CYAN = "#30BCED"
const val YINMN_BLUE = "#355070"
}

init {
Expand All @@ -30,20 +36,49 @@ class DarwinStyles : Stylesheet() {
}

thumbArea {
backgroundColor += c(LIGHTGREEN)
backgroundColor = multi(c(LIGHTGREEN))
}

selected {
thumbArea {
backgroundColor = multi(c(GREEN))
}
}

selected {
thumb {
backgroundColor = multi(c(GREEN), c(WHITE))
}
}

tab {
and(selected) {
backgroundColor += c(GREEN)
backgroundColor = multi(c(GREEN), c(WHITE))
}
}

centered {
alignment = javafx.geometry.Pos.CENTER
label {
alignment = javafx.geometry.Pos.CENTER
}
}

scrollBar {
and(horizontal) {
visibility = FXVisibility.HIDDEN
backgroundColor = multi(c(GREEN))
}
}

drawer {
toggleButton {
and(selected) {
backgroundColor += c(GREEN)
backgroundColor = multi(c(GREEN))
}
}
contentArea {
backgroundColor += c(WHITE)
backgroundColor = multi(c(WHITE))
}
}

Expand Down
Loading

0 comments on commit c1f4919

Please sign in to comment.