From 4baac33476488cc0134f124a209541f7416dda34 Mon Sep 17 00:00:00 2001 From: Danilo Pianini Date: Thu, 12 Feb 2026 22:36:00 +0100 Subject: [PATCH 1/8] fixup!: partial migration --- alchemist-api/.attach_pid3210525 | 0 .../cognitive/HeterogeneousPedestrianModel.kt | 1 + .../model/cognitive/HumanProperty.kt | 1 + .../navigation/ReachKnownDestination.kt | 43 +++++------ alchemist-composeui/build.gradle.kts | 6 +- .../it/unibo/alchemist/core/BatchEngine.kt | 21 ++---- .../SimpleNetworkArrivals.kt | 6 +- .../build.gradle.kts | 2 +- .../alchemist/scala/PimpMyAlchemist.scala | 12 +-- .../it/unibo/alchemist/boundary/Extractor.kt | 73 +++++++++---------- .../it/unibo/alchemist/boundary/Loader.kt | 37 ++++++---- .../alchemist/model/positionfilters/Or.kt | 9 ++- .../alchemist/model/positionfilters/Xor.kt | 12 ++- .../common/renderer/BitmapRendererTest.kt | 4 +- .../kotlin/kotlin-jvm-convention.gradle.kts | 6 ++ gradle/libs.versions.toml | 18 ++++- kotlin-js-store/yarn.lock | 54 ++++++++------ 17 files changed, 172 insertions(+), 133 deletions(-) create mode 100644 alchemist-api/.attach_pid3210525 diff --git a/alchemist-api/.attach_pid3210525 b/alchemist-api/.attach_pid3210525 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/HeterogeneousPedestrianModel.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/HeterogeneousPedestrianModel.kt index cad2a49766..7b50eff728 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/HeterogeneousPedestrianModel.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/HeterogeneousPedestrianModel.kt @@ -46,6 +46,7 @@ data class HeterogeneousPedestrianModel, A : Transformation> * Value between 0 and 1 representing the probability this pedestrian will help another pedestrian in difficulty. * * @param toHelp The pedestrian who needs help. + * @param isGroupMember Whether the pedestrian in difficulty is a member of the helper's group. */ fun probabilityOfHelping(toHelp: HeterogeneousPedestrianModel, isGroupMember: Boolean): Double = helpAttitude.level(toHelp.age, toHelp.gender, isGroupMember) diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/HumanProperty.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/HumanProperty.kt index 0be728a8ef..ab535cffd0 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/HumanProperty.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/HumanProperty.kt @@ -50,6 +50,7 @@ interface HumanProperty, A : Transformation> : NodeProperty< * Value between 0 and 1 representing the probability this pedestrian will help another pedestrian in difficulty. * * @param toHelp The pedestrian who needs help. + * @param isGroupMember Whether the pedestrian in difficulty is a member of the helper's group. */ fun probabilityOfHelping(toHelp: HeterogeneousPedestrianModel, isGroupMember: Boolean): Double = helpAttitude.level(toHelp.age, toHelp.gender, isGroupMember) diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/ReachKnownDestination.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/ReachKnownDestination.kt index 103e9d90d4..61ffee5b36 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/ReachKnownDestination.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/ReachKnownDestination.kt @@ -45,28 +45,29 @@ open class ReachKnownDestination( final override val route: List init { - route = emptyList().takeIf { destinations.isEmpty() } ?: with(action) { - val currPos = environment.getPosition(navigatingNode) - val (closestDest, distanceToClosestDest) = - destinations - .asSequence() + route = if (destinations.isEmpty()) { + emptyList() + } else { + with(action) { + val currPos = environment.getPosition(navigatingNode) + val (closestDest, distanceToClosestDest) = destinations.asSequence() .map { it to it.distanceTo(currPos) } - .minByOrNull { it.second } - ?: throw IllegalArgumentException("internal error: destinations can't be empty at this point") - destinations - .asSequence() - .sortedBy { it.distanceTo(currPos) } - .map { it to findKnownPathTo(it) } - .filter { (_, path) -> - /* - * A path leading to a destination is considered "valid" when: - * - it's not empty - * - the path's start is closer to currPos than the closest destination (this - * because otherwise it's more convenient to just pursue the latter). - */ - path.isNotEmpty() && currPos.distanceTo(path.first().centroid) < distanceToClosestDest - }.map { (destination, path) -> path.map { it.centroid } + destination } - .firstOrNull() ?: listOf(closestDest) + .minBy { it.second } + destinations.asSequence() + .sortedBy { it.distanceTo(currPos) } + .map { it to findKnownPathTo(it) } + .filter { (_, path) -> + /* + * A path leading to a destination is considered "valid" when: + * - it's not empty + * - the path's start is closer to currPos than the closest destination (this + * because otherwise it's more convenient to just pursue the latter). + */ + path.isNotEmpty() && currPos.distanceTo(path.first().centroid) < distanceToClosestDest + } + .map { (destination, path) -> path.map { it.centroid } + destination } + .firstOrNull() ?: listOf(closestDest) + } } setDestination(route[0]) } diff --git a/alchemist-composeui/build.gradle.kts b/alchemist-composeui/build.gradle.kts index 4fc6c69da1..a2f881b9ac 100644 --- a/alchemist-composeui/build.gradle.kts +++ b/alchemist-composeui/build.gradle.kts @@ -28,11 +28,7 @@ kotlin { sourceSets { val commonMain by getting { dependencies { - implementation(compose.runtime) - implementation(compose.ui) - implementation(compose.foundation) - implementation(compose.material) - implementation(compose.components.resources) + implementation(libs.bundles.compose) } } } diff --git a/alchemist-engine/src/main/kotlin/it/unibo/alchemist/core/BatchEngine.kt b/alchemist-engine/src/main/kotlin/it/unibo/alchemist/core/BatchEngine.kt index 90cdecfafc..2d87579848 100644 --- a/alchemist-engine/src/main/kotlin/it/unibo/alchemist/core/BatchEngine.kt +++ b/alchemist-engine/src/main/kotlin/it/unibo/alchemist/core/BatchEngine.kt @@ -27,9 +27,9 @@ import org.slf4j.LoggerFactory * This class implements a simulation. It offers a wide number of static * factories to ease the creation process. * - * @param concentration type - * @param

[Position] type -

*/ + * @param T concentration type + * @param P [Position] type + */ class BatchEngine> : Engine { private val outputReplayStrategy: OutputReplayStrategy private val executeLock = Any() @@ -124,9 +124,8 @@ class BatchEngine> : Engine { val futureResults = tasks.awaitAll() val newStep = step + batchSize.toLong() currentStep = newStep - val resultsOrderedByTime = - futureResults - .sortedWith(Comparator.comparing { result: TaskResult -> result.eventTime }) + val resultsOrderedByTime = futureResults + .sortedWith(Comparator.comparing { result: TaskResult -> result.eventTime }) currentTime = if (maxSlidingWindowTime > time) maxSlidingWindowTime else time doStepDoneAllMonitors(resultsOrderedByTime) } catch (e: InterruptedException) { @@ -218,7 +217,6 @@ class BatchEngine> : Engine { /** * Safely set simulation status. */ - @SuppressWarnings("ForbiddenVoid") override fun newStatus(next: Status): CompletableFuture { synchronized(this) { return super.newStatus(next) } } @@ -249,12 +247,9 @@ class BatchEngine> : Engine { Reply.name -> Reply else -> error( - """ - Invalid output reply strategy $this. Available choices: ${listOf( - Aggregate, - Reply, - ).map { it.name }} - """.trimIndent(), + "Invalid output reply strategy $this. Available choices: ${ + listOf(Aggregate, Reply).map { it.name } + }", ) } } diff --git a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/timedistributions/SimpleNetworkArrivals.kt b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/timedistributions/SimpleNetworkArrivals.kt index 6413c3ccb8..559b5b845e 100644 --- a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/timedistributions/SimpleNetworkArrivals.kt +++ b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/timedistributions/SimpleNetworkArrivals.kt @@ -176,11 +176,11 @@ class SimpleNetworkArrivals private constructor( } /** Computes the packet size, defaulting to 1.0 if not specified or invalid. */ + @Suppress("UnreachableCode") // Detekt false positive. Remove once fixed. val packetSize: Double get() = constantPacketSize - ?: incarnation.getProperty(node, packetSizeMolecule, packetSizeProperty).takeIf { - it.isFinite() && it >= 0 - } ?: 1.0 + ?: incarnation.getProperty(node, packetSizeMolecule, packetSizeProperty).takeIf { it.isFinite() && it >= 0 } + ?: 1.0 /** Computes the propagation delay from constants or properties. */ val propagationDelay: Double diff --git a/alchemist-incarnation-biochemistry/build.gradle.kts b/alchemist-incarnation-biochemistry/build.gradle.kts index 6fb3df97cd..affba6e24c 100644 --- a/alchemist-incarnation-biochemistry/build.gradle.kts +++ b/alchemist-incarnation-biochemistry/build.gradle.kts @@ -8,7 +8,7 @@ */ import Libs.alchemist -import io.gitlab.arturbosch.detekt.Detekt +import dev.detekt.gradle.Detekt import it.unibo.alchemist.build.allVerificationTasks import org.gradle.jvm.tasks.Jar import org.jetbrains.dokka.gradle.tasks.DokkaBaseTask diff --git a/alchemist-incarnation-scafi/src/main/scala/it/unibo/alchemist/scala/PimpMyAlchemist.scala b/alchemist-incarnation-scafi/src/main/scala/it/unibo/alchemist/scala/PimpMyAlchemist.scala index 0ad20ff946..dc51eeefc7 100644 --- a/alchemist-incarnation-scafi/src/main/scala/it/unibo/alchemist/scala/PimpMyAlchemist.scala +++ b/alchemist-incarnation-scafi/src/main/scala/it/unibo/alchemist/scala/PimpMyAlchemist.scala @@ -16,20 +16,22 @@ import it.unibo.alchemist.model.geometry.Vector import it.unibo.alchemist.model.molecules.SimpleMolecule import it.unibo.alchemist.model.times.DoubleTime +import scala.language.implicitConversions + @SuppressFBWarnings object PimpMyAlchemist { /** Wraps a Position, providing + and - operations. */ implicit class RichPosition[P <: Position[P] with Vector[P]](position: P) { - def -(p: P) = position.minus(p) - def +(p: P) = position.plus(p) + def -(p: P): P = position.minus(p) + def +(p: P): P = position.plus(p) } /** Shortcut for DoubleTime.ZERO_TIME */ - implicit val zeroTime = Time.ZERO - implicit def time2Double(time: Time): Double = time.toDouble() + implicit val zeroTime: Time = Time.ZERO + implicit def time2Double(time: Time): Double = time.toDouble implicit def double2Time(time: Double): Time = new DoubleTime(time) implicit def molecule2String(molecule: Molecule): String = molecule.toString implicit def string2Molecule(str: String): Molecule = new SimpleMolecule(str) - implicit def function2CacheLoader[F, T](f: F => T) = new CacheLoader[F, T] { def load(key: F) = f(key) } + implicit def function2CacheLoader[F, T](f: F => T): CacheLoader[F, T] = new CacheLoader[F, T] { def load(key: F): T = f(key) } } diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Extractor.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Extractor.kt index 54f2ab1f7f..878493b1bc 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Extractor.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Extractor.kt @@ -15,34 +15,29 @@ import it.unibo.alchemist.model.Time /** * An object that is able to extract numeric informations from an Alchemist - * {@link Environment}, given the current - * {@link it.unibo.alchemist.core.Simulation} {@link Time}, the last - * {@link Reaction} executed and the current simulation step. - * + * [Environment], given the current simulation [Time], the last executed + * [Actionable] (usually a [Reaction] or null) and the current simulation step. */ interface Extractor { /** - * Extracts properties from an environment. The returned map must either: - * - contain a single element, - * - have the keys matching [columnNames], or - * - be iterable in predictable order - * (namely, implement [SortedMap] or extend one of [LinkedHashMap] or [ConcurrentLinkedHashMap]). + * Extracts properties from an environment. + * + * Implementations must return a map whose iteration order is predictable or whose + * keys match [columnNames]. Concretely the returned map must satisfy at least one + * of the following: + * - contain a single element, + * - have keys matching [columnNames], or + * - be an ordered map (for example a [java.util.SortedMap], a [java.util.LinkedHashMap] + * or any map with deterministic iteration order). * - * @param environment - * the {@link Environment} - * @param reaction - * the last executed {@link Reaction} - * @param time - * the current {@link Time} - * @param step - * the simulation step - * @param concentration type - * @return - * the extracted properties with their names. The returned map must either: - * - contain a single element, - * - have the keys matching [columnNames], or - * - be iterable in predictable order - * (namely, implement [SortedMap] or extend [LinkedHashMap]). + * @param environment the environment from which to extract values + * @param reaction the last executed actionable (may be null) + * @param time the current simulation time + * @param step the current simulation step + * @param T the concentration type used by the environment + * @return a map of property names to extracted values. The map must follow one of the + * ordering/key contracts described above so that callers can consistently + * determine column ordering when producing tabular outputs. */ fun extractData( environment: Environment, @@ -52,19 +47,19 @@ interface Extractor { ): Map /** - * Same as [extractData], but specifically meant for textual outputs. Captures [E] to [String] conversions. - * The default implementation just runs a `toString()` conversion ver [extractData]'s return value's values. + * Same as [extractData], but specifically meant for textual outputs. * - * @param environment - * the {@link Environment} - * @param reaction - * the last executed {@link Reaction} - * @param time - * the current {@link Time} - * @param step - * the simulation step - * @param concentration type - * @return the extracted properties in textual format with their names. + * The default implementation converts each extracted value to its textual + * representation via [Any.toString]. Implementations may override this method + * to provide custom formatting (for example numeric formatting or localized + * representations). + * + * @param environment the environment from which to extract values + * @param reaction the last executed actionable (may be null) + * @param time the current simulation time + * @param step the current simulation step + * @param T the concentration type used by the environment + * @return a map of property names to their textual representations */ fun extractDataAsText( environment: Environment, @@ -74,8 +69,10 @@ interface Extractor { ): Map = extractData(environment, reaction, time, step).mapValues { it.value.toString() } /** - * @return the name of the properties that this [Extractor] can - * provide + * The names of the properties that this [Extractor] can provide as columns. + * + * Implementations should return a list whose order matches the expected + * column ordering when the returned map from [extractData] uses the same keys. */ val columnNames: List } diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Loader.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Loader.kt index 4133de8a3e..83edd39112 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Loader.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Loader.kt @@ -52,22 +52,33 @@ interface Loader : Serializable { val variables: Map> /** - * @param concentration type - * @param

position type - * @return an [Simulation] with all the variables set at their - * default values -

*/ + * Returns a simulation with all the variables set to their default values. + * + * This is equivalent to calling [getWith] with an empty values map. + * + * Type parameters: + * - T: the concentration type used by the simulation + * - P: the position type used by the simulation + * + * @return an instance of [Simulation] with variables initialized to their defaults + */ fun > getDefault(): Simulation = getWith(emptyMap()) /** - * @param values a map specifying name-value bindings for the variables in this - * scenario - * @param concentration type - * @param

position type - * @return an [Simulation] with all the variables set at the - * specified values. If the value is unspecified, the default is - * used instead -

*/ + * Returns a simulation with variables set according to the provided [values] map. + * + * Each entry in [values] maps a variable name to the desired value. Variables not + * present in the map will be initialized to their default values. + * + * Parameters: + * - values: a map specifying name-value bindings for the variables in this scenario + * + * Type parameters: + * - T: the concentration type used by the simulation + * - P: the position type used by the simulation + * + * @return an instance of [Simulation] with variables initialized to the specified values + */ fun > getWith(values: Map): Simulation /** diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Or.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Or.kt index 30a274847e..27cfa86b3e 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Or.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Or.kt @@ -13,9 +13,12 @@ import it.unibo.alchemist.model.Position import it.unibo.alchemist.model.PositionBasedFilter /** - * Check if either [positionBasedFilterA] or [positionBasedFilterB] is satisfied. - * @param positionBasedFilterA the first filter. - * @param positionBasedFilterB the second filter. + * A position-based filter that matches when at least one of two underlying filters + * matches the provided position (logical OR behaviour). + * + * @param P the concrete position type used by the filters + * @param positionBasedFilterA the first filter + * @param positionBasedFilterB the second filter */ data class Or

>( val positionBasedFilterA: PositionBasedFilter

, diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Xor.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Xor.kt index 822a5445ef..10b832cf9c 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Xor.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Xor.kt @@ -13,16 +13,20 @@ import it.unibo.alchemist.model.Position import it.unibo.alchemist.model.PositionBasedFilter /** - * Check if only one between [positionBasedFilterA] and [positionBasedFilterB] is satisfied. - * @param positionBasedFilterA the first filter. - * @param positionBasedFilterB the second filter. + * A position-based filter that matches when exactly one of two underlying filters + * matches the provided position (exclusive-or behaviour). + * + * @param P the concrete position type used by the filters + * @param positionBasedFilterA the first filter + * @param positionBasedFilterB the second filter */ data class Xor

>( val positionBasedFilterA: PositionBasedFilter

, val positionBasedFilterB: PositionBasedFilter

, ) : PositionBasedFilter

{ /** - * Returns true if only one [positionBasedFilterA] and [positionBasedFilterB] is satisfied. + * Returns true if exactly one of [positionBasedFilterA] or [positionBasedFilterB] + * contains the given [position]. */ override operator fun contains(position: P) = position in positionBasedFilterA != position in positionBasedFilterB } diff --git a/alchemist-web-renderer/src/commonTest/kotlin/it/unibo/alchemist/boundary/webui/common/renderer/BitmapRendererTest.kt b/alchemist-web-renderer/src/commonTest/kotlin/it/unibo/alchemist/boundary/webui/common/renderer/BitmapRendererTest.kt index bfb24dd6d3..e394774225 100644 --- a/alchemist-web-renderer/src/commonTest/kotlin/it/unibo/alchemist/boundary/webui/common/renderer/BitmapRendererTest.kt +++ b/alchemist-web-renderer/src/commonTest/kotlin/it/unibo/alchemist/boundary/webui/common/renderer/BitmapRendererTest.kt @@ -43,8 +43,8 @@ class BitmapRendererTest { fun `bitmap renderer should output a Bitmap32 correctly`() { val bmp = renderer.render(envSurrogate) assertTrue(bmp is Bitmap32, "Expected a Bitmap32 output") - val encoded = jsonFormat.encodeToString(Bitmap32Serializer, (bmp as Bitmap32).toBMP32IfRequired()) - val decoded = jsonFormat.decodeFromString(Bitmap32Serializer, encoded) as Bitmap32 + val encoded = jsonFormat.encodeToString(Bitmap32Serializer, bmp.toBMP32IfRequired()) + val decoded = jsonFormat.decodeFromString(Bitmap32Serializer, encoded) assertEquals(bmp.height, decoded.height, "Height should match after serialization round-trip") assertEquals(bmp.width, decoded.width, "Width should match after serialization round-trip") assertEquals(bmp.ints.toList(), decoded.ints.toList(), "Pixel data should match after round-trip") diff --git a/buildSrc/src/main/kotlin/kotlin-jvm-convention.gradle.kts b/buildSrc/src/main/kotlin/kotlin-jvm-convention.gradle.kts index 83123a3250..3261aca5aa 100644 --- a/buildSrc/src/main/kotlin/kotlin-jvm-convention.gradle.kts +++ b/buildSrc/src/main/kotlin/kotlin-jvm-convention.gradle.kts @@ -64,3 +64,9 @@ javaQA { enabled = false } } + +tasks.withType().configureEach { + javaLauncher = javaToolchains.launcherFor { + languageVersion.set(JavaLanguageVersion.of(25)) + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5e31de5a15..0cfd0d2548 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ graphstream = "2.0" junit = "6.0.2" konf = "1.1.2" kotest = "6.1.3" -kotlin = "2.2.21" +kotlin = "2.3.10" kotlinx-coroutines = "1.10.2" ktor = "3.3.3" mockito = "5.21.0" @@ -35,6 +35,11 @@ appdirs = "net.harawata:appdirs:1.5.0" arrow-core = { module = "io.arrow-kt:arrow-core", version.ref = "arrow" } boilerplate = "org.danilopianini:boilerplate:0.2.2" caffeine = "com.github.ben-manes.caffeine:caffeine:3.2.3" +compose-components-resources = { module = "org.jetbrains.compose.components:components-resources", version.ref = "compose-multiplatform" } +compose-foundation = { module = "org.jetbrains.compose.foundation:foundation", version.ref = "compose-multiplatform" } +compose-material = { module = "org.jetbrains.compose.material:material", version.ref = "compose-multiplatform" } +compose-runtime = { module = "org.jetbrains.compose.runtime:runtime", version.ref = "compose-multiplatform" } +compose-ui = { module = "org.jetbrains.compose.ui:ui", version.ref = "compose-multiplatform" } classgraph = "io.github.classgraph:classgraph:4.8.184" conrec = "org.danilopianini:conrec:0.1.1" dokka-gradle-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokka" } @@ -53,7 +58,7 @@ gson = "com.google.code.gson:gson:2.13.2" gson-extras = "org.danilopianini:gson-extras:3.3.0" guava = "com.google.guava:guava:33.5.0-jre" javalib-java7 = "org.danilopianini:javalib-java7:0.6.1" -java-quality-assurance-plugin = "org.danilopianini.gradle-java-qa:org.danilopianini.gradle-java-qa.gradle.plugin:1.163.0" +java-quality-assurance-plugin = "org.danilopianini.gradle-java-qa:org.danilopianini.gradle-java-qa.gradle.plugin:1.166.0" jgit = "org.eclipse.jgit:org.eclipse.jgit:7.5.0.202512021534-r" jgrapht-core = "org.jgrapht:jgrapht-core:1.5.2" jirf = "org.danilopianini:jirf:0.4.37" @@ -80,7 +85,7 @@ kotlin-multiplatform-plugin = { module = "org.jetbrains.kotlin.multiplatform:org kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } kotlin-test-annotations = { module = "org.jetbrains.kotlin:kotlin-test-annotations-common", version.ref = "kotlin" } kotlin-power-assert-plugin = { module = "org.jetbrains.kotlin.plugin.power-assert:org.jetbrains.kotlin.plugin.power-assert.gradle.plugin", version.ref = "kotlin" } -kotlin-quality-assurance-plugin = "org.danilopianini.gradle-kotlin-qa:org.danilopianini.gradle-kotlin-qa.gradle.plugin:0.100.0" +kotlin-quality-assurance-plugin = "org.danilopianini.gradle-kotlin-qa:org.danilopianini.gradle-kotlin-qa.gradle.plugin:0.101.1-dev04.dabc24e" kotlin-react = { module = "org.jetbrains.kotlin-wrappers:kotlin-react", version.ref = "react" } kotlin-react-dom = { module = "org.jetbrains.kotlin-wrappers:kotlin-react-dom", version.ref = "react" } kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" } @@ -132,6 +137,13 @@ svgsalamander = "guru.nidi.com.kitfox:svgSalamander:1.1.3" trove4j = "net.sf.trove4j:trove4j:3.0.3" [bundles] +compose = [ + "compose-components-resources", + "compose-foundation", + "compose-material", + "compose-runtime", + "compose-ui" +] graphhopper = [ "graphhopper-core" ] graphql-server = [ "graphql-server", "graphql-server-ktor" ] kotlin-react = [ "kotlin-react", "kotlin-react-dom" ] diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index 4e38f4b014..26d77284f7 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -1134,13 +1134,13 @@ engine.io@~6.6.0: engine.io-parser "~5.2.1" ws "~8.17.1" -enhanced-resolve@^5.17.2: - version "5.18.3" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz#9b5f4c5c076b8787c78fe540392ce76a88855b44" - integrity sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww== +enhanced-resolve@^5.17.3: + version "5.19.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz#6687446a15e969eaa63c2fa2694510e17ae6d97c" + integrity sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg== dependencies: graceful-fs "^4.2.4" - tapable "^2.2.0" + tapable "^2.3.0" ent@~2.2.0: version "2.2.2" @@ -1709,6 +1709,11 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-plain-obj@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" @@ -1845,10 +1850,9 @@ karma-webpack@5.0.1: minimatch "^9.0.3" webpack-merge "^4.1.5" -karma@6.4.4: +"karma@github:Kotlin/karma#6.4.5": version "6.4.4" - resolved "https://registry.yarnpkg.com/karma/-/karma-6.4.4.tgz#dfa5a426cf5a8b53b43cd54ef0d0d09742351492" - integrity sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w== + resolved "https://codeload.github.com/Kotlin/karma/tar.gz/239a8fc984584f0d96b1dd750e7a5e2c79da93a6" dependencies: "@colors/colors" "1.5.0" body-parser "^1.19.0" @@ -1880,10 +1884,10 @@ kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -kotlin-web-helpers@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/kotlin-web-helpers/-/kotlin-web-helpers-2.1.0.tgz#6cd4b0f0dc3baea163929c8638155b8d19c55a74" - integrity sha512-NAJhiNB84tnvJ5EQx7iER3GWw7rsTZkX9HVHZpe7E3dDBD/dhTzqgSwNU3MfQjniy2rB04bP24WM9Z32ntUWRg== +kotlin-web-helpers@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/kotlin-web-helpers/-/kotlin-web-helpers-3.0.0.tgz#3ed6b48f694f74bb60a737a9d7e2c0e3b29abdb9" + integrity sha512-kdQO4AJQkUPvpLh9aglkXDRyN+CfXO7pKq+GESEnxooBFkQpytLrqZis3ABvmFN1cGw/ZQ/K38u5sRGW+NfBnw== dependencies: format-util "^1.0.5" @@ -2070,10 +2074,10 @@ mkdirp@^0.5.5: dependencies: minimist "^1.2.6" -mocha@11.7.1: - version "11.7.1" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-11.7.1.tgz#91948fecd624fb4bd154ed260b7e1ad3910d7c7a" - integrity sha512-5EK+Cty6KheMS/YLPPMJC64g5V61gIR25KsRItHw6x4hEKT6Njp1n9LOlH4gpevuwMVS66SXaBBpg+RWZkza4A== +mocha@11.7.5: + version "11.7.5" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-11.7.5.tgz#58f5bbfa5e0211ce7e5ee6128107cefc2515a627" + integrity sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig== dependencies: browser-stdout "^1.3.1" chokidar "^4.0.1" @@ -2083,6 +2087,7 @@ mocha@11.7.1: find-up "^5.0.0" glob "^10.4.5" he "^1.2.0" + is-path-inside "^3.0.3" js-yaml "^4.1.0" log-symbols "^4.1.0" minimatch "^9.0.5" @@ -2893,11 +2898,16 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -tapable@^2.1.1, tapable@^2.2.0: +tapable@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +tapable@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.3.0.tgz#7e3ea6d5ca31ba8e078b560f0d83ce9a14aa8be6" + integrity sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg== + terser-webpack-plugin@^5.3.11: version "5.3.14" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz#9031d48e57ab27567f02ace85c7d690db66c3e06" @@ -3150,10 +3160,10 @@ webpack-sources@^3.3.3: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.3.3.tgz#d4bf7f9909675d7a070ff14d0ef2a4f3c982c723" integrity sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg== -webpack@5.100.2: - version "5.100.2" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.100.2.tgz#e2341facf9f7de1d702147c91bcb65b693adf9e8" - integrity sha512-QaNKAvGCDRh3wW1dsDjeMdDXwZm2vqq3zn6Pvq4rHOEOGSaUMgOOjG2Y9ZbIGzpfkJk9ZYTHpDqgDfeBDcnLaw== +webpack@5.101.3: + version "5.101.3" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.101.3.tgz#3633b2375bb29ea4b06ffb1902734d977bc44346" + integrity sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A== dependencies: "@types/eslint-scope" "^3.7.7" "@types/estree" "^1.0.8" @@ -3165,7 +3175,7 @@ webpack@5.100.2: acorn-import-phases "^1.0.3" browserslist "^4.24.0" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.17.2" + enhanced-resolve "^5.17.3" es-module-lexer "^1.2.1" eslint-scope "5.1.1" events "^3.2.0" From 95de47ca6bbcbd73035c928602746e7eade006e6 Mon Sep 17 00:00:00 2001 From: Danilo Pianini Date: Fri, 13 Feb 2026 00:38:09 +0100 Subject: [PATCH 2/8] refactor: improve documentation for various properties and actions --- .../it/unibo/alchemist/model/Actionable.kt | 6 +- .../kotlin/it/unibo/alchemist/model/Node.kt | 17 +++-- .../model/cognitive/CognitiveModel.kt | 29 ++++++-- .../model/cognitive/CognitiveProperty.kt | 10 ++- .../unibo/alchemist/model/cognitive/Group.kt | 8 ++- .../model/cognitive/GroupSteeringAction.kt | 9 ++- .../model/cognitive/GroupWithLeader.kt | 7 +- .../cognitive/HeterogeneousPedestrianModel.kt | 31 ++++----- .../model/cognitive/Human2DProperty.kt | 2 + .../model/cognitive/HumanProperty.kt | 31 ++++----- .../model/cognitive/NavigationAction.kt | 51 +++++++------- .../model/cognitive/NavigationStrategy.kt | 37 +++++----- .../model/cognitive/NavigationStrategy2D.kt | 4 +- .../model/cognitive/OrientingAgent.kt | 26 +++---- .../model/cognitive/OrientingAgent2D.kt | 2 +- .../model/cognitive/OrientingProperty.kt | 35 +++++----- .../model/cognitive/PedestrianProperty.kt | 8 ++- .../model/cognitive/PerceptiveProperty.kt | 10 +-- .../cognitive/PhysicalSteeringStrategy.kt | 32 +++++---- .../cognitive/RunningPedestrianProperty.kt | 8 +-- .../model/cognitive/SocialProperty.kt | 8 +-- .../model/cognitive/SteeringAction.kt | 11 ++- .../cognitive/SteeringActionWithTarget.kt | 15 ++++- .../model/cognitive/SteeringStrategy.kt | 20 +++--- .../cognitive/WalkingPedestrianProperty.kt | 8 +-- .../actions/CognitiveAgentCohesion.kt | 2 + .../actions/CognitiveAgentCombineSteering.kt | 21 +++--- .../cognitive/actions/CognitiveAgentFlee.kt | 12 ++-- .../actions/CognitiveAgentFollowLayer.kt | 12 ++-- .../cognitive/actions/CognitiveAgentPursue.kt | 10 ++- .../CognitiveAgentReachKnownDestination.kt | 10 ++- .../cognitive/actions/CognitiveAgentSeek.kt | 15 +++-- .../actions/CognitiveAgentSeparation.kt | 12 ++-- .../cognitive/actions/CognitiveAgentWander.kt | 25 +++---- .../cognitive/navigation/DynamicallyPursue.kt | 22 +++--- .../model/cognitive/navigation/Explore.kt | 6 +- .../model/cognitive/navigation/FollowRoute.kt | 24 +++---- .../navigation/GoalOrientedExploration.kt | 27 ++++---- .../model/cognitive/navigation/Pursue.kt | 25 +++---- .../cognitive/navigation/ReachDestination.kt | 31 ++++----- .../navigation/ReachKnownDestination.kt | 10 +-- .../cognitive/reactions/BlendedSteering.kt | 13 ++-- .../cognitive/reactions/CognitiveBehavior.kt | 13 ++-- .../NavigationPrioritizedSteering.kt | 23 ++++--- .../cognitive/reactions/PrioritySteering.kt | 12 ++-- .../cognitive/reactions/SteeringBehavior.kt | 25 +++---- .../cognitive/steering/DistanceWeighted.kt | 17 ++--- .../model/cognitive/steering/Filtered.kt | 15 ++--- .../model/cognitive/steering/Nearest.kt | 18 ++--- .../cognitive/steering/SinglePrevalent.kt | 44 ++++++------ .../model/cognitive/steering/TypeBased.kt | 15 ++--- .../model/cognitive/steering/Weighted.kt | 26 ++++--- .../kotlin/it/unibo/alchemist/core/Engine.kt | 40 +++++------ .../actions/ConstantDistanceRandomWalk.kt | 22 +++--- .../actions/EuclideanConfigurableMoveNode.kt | 45 ++++++++----- .../model/actions/FollowAtDistance.kt | 20 +++--- .../model/geometry/GeometricShapeFactory.kt | 42 ++++++------ .../geometry/navigationgraph/NaviGator.kt | 67 +++++++++---------- alchemist-graphql/build.gradle.kts | 8 ++- .../graphql/client/DefaultGraphQLClient.kt | 8 +-- .../boundary/graphql/client/GraphQLClient.kt | 38 ++++++----- .../graphql/client/GraphQLClientFactory.kt | 14 ++-- .../graphql/client/SimulationHandler.kt | 27 ++++---- .../graphql/utils/DefaultGraphQLSettings.kt | 10 +-- ...TestEnvironmentsDiameterWithHopDistance.kt | 4 +- build.gradle.kts | 2 +- 66 files changed, 658 insertions(+), 599 deletions(-) diff --git a/alchemist-api/src/main/kotlin/it/unibo/alchemist/model/Actionable.kt b/alchemist-api/src/main/kotlin/it/unibo/alchemist/model/Actionable.kt index 3004bfa4b0..df9b70e1e8 100644 --- a/alchemist-api/src/main/kotlin/it/unibo/alchemist/model/Actionable.kt +++ b/alchemist-api/src/main/kotlin/it/unibo/alchemist/model/Actionable.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2022, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the @@ -91,12 +91,12 @@ sealed interface Actionable : /** * Updates the scheduling of this reaction. * - * @param hasBeenExecuted - * true if the reaction have just been executed. * @param currentTime * the current [Time] of execution. This is mandatory in * order to correctly compute the time shift of an * already-scheduled reaction + * @param hasBeenExecuted + * true if the reaction have just been executed. * @param environment * the current environment */ diff --git a/alchemist-api/src/main/kotlin/it/unibo/alchemist/model/Node.kt b/alchemist-api/src/main/kotlin/it/unibo/alchemist/model/Node.kt index 61a1f03341..d8eaff217d 100644 --- a/alchemist-api/src/main/kotlin/it/unibo/alchemist/model/Node.kt +++ b/alchemist-api/src/main/kotlin/it/unibo/alchemist/model/Node.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2023, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the @@ -188,16 +188,19 @@ interface Node : */ companion object { /** - * returns a [NodeProperty] of the provided type [C]. - * @param [C] type of capability - * @return a capability of the provided type [C] + * Returns the node property of the reified type [C]. + * + * @receiver the node from which to retrieve the property. + * @return the property of type [C]. + * @throws IllegalArgumentException if no compatible property is present. */ inline fun > Node.asProperty(): C = asProperty(C::class) /** - * returns a [NodeProperty] of the provided type [C] or null if the node does not have a compatible property. - * @param [C] type of capability - * @return if present, a capability of the provided type [C] + * Returns the node property of the reified type [C], or null if the node does not have a compatible property. + * + * @receiver the node from which to retrieve the property. + * @return the property of type [C] if present, or null otherwise. */ inline fun > Node.asPropertyOrNull(): C? = when { properties.size <= 1 -> properties.firstOrNull() as? C diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/CognitiveModel.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/CognitiveModel.kt index 35c66bf945..e8cf104ed2 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/CognitiveModel.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/CognitiveModel.kt @@ -10,36 +10,51 @@ package it.unibo.alchemist.model.cognitive /** - * Theoretical model to describe the cognitive processes underlying in an agent. + * Theoretical model that describes the cognitive processes of an agent. + * + * Implementations provide measures for the agent's belief about danger, fear level, + * and competing intentions to escape or remain. */ interface CognitiveModel { /** - * Value representing the current belief of the situation dangerousness. + * Returns the agent's current belief about the situation's dangerousness. + * + * @return the perceived level of dangerousness as a [Double]. */ fun dangerBelief(): Double /** - * Value representing the level of fear. + * Returns the agent's current fear level. + * + * @return the fear level as a [Double]. */ fun fear(): Double /** - * Value representing the intention to escape. Opposed to [remainIntention]. + * Returns the agent's intention to escape. This value is opposed to [remainIntention]. + * + * @return the intention to escape as a [Double]. */ fun escapeIntention(): Double /** - * Value representing the intention to remain. Opposed to [escapeIntention] + * Returns the agent's intention to remain. This value is opposed to [escapeIntention]. + * + * @return the intention to remain as a [Double]. */ fun remainIntention(): Double /** - * Update the current intensity of the aforementioned feelings considering a [frequency]. + * Update the model internal state using the provided update frequency. + * + * @param frequency the update frequency (time between updates or update rate), represented as a [Double]. */ fun update(frequency: Double) /** - * Whether or not this node intends to escape. + * Whether the agent currently intends to escape. + * + * @return true if the escape intention is greater than the remain intention; false otherwise. */ fun wantsToEscape(): Boolean = escapeIntention() > remainIntention() } diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/CognitiveProperty.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/CognitiveProperty.kt index b2cd0c2533..755c79a2d3 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/CognitiveProperty.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/CognitiveProperty.kt @@ -15,11 +15,13 @@ import it.unibo.alchemist.model.Node.Companion.asPropertyOrNull import it.unibo.alchemist.model.NodeProperty /** - * The pedestrian's cognitive capability. + * Cognitive capability attached to a node. + * + * @param T the concentration type of the environment. */ interface CognitiveProperty : NodeProperty { /** - * The molecule associated with danger in the environment. + * The molecule used to signal danger in the environment, if any. */ val danger: Molecule? @@ -29,7 +31,9 @@ interface CognitiveProperty : NodeProperty { val cognitiveModel: CognitiveModel /** - * The mind model of all people considered influential for this cognitive pedestrian. + * The cognitive models of people considered influential for this pedestrian. + * + * @return a list of [CognitiveModel] instances representing influential people. */ fun influentialPeople(): List = node .asProperty>() diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/Group.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/Group.kt index 1d3cd0bb01..134f172678 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/Group.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/Group.kt @@ -3,11 +3,15 @@ package it.unibo.alchemist.model.cognitive import it.unibo.alchemist.model.Node /** - * A group of nodes. + * Represents a group of nodes (pedestrians) that can be treated collectively. + * + * @param T the concentration type used by nodes in the group. */ interface Group : MutableList> { /** - * The list of pedestrians belonging to this group. + * The list of nodes that belong to this group. + * + * @return a [List] of [Node] instances representing the group's members. */ val members: List> get() = this } diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/GroupSteeringAction.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/GroupSteeringAction.kt index ead5edb0c6..763bda6238 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/GroupSteeringAction.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/GroupSteeringAction.kt @@ -14,11 +14,16 @@ import it.unibo.alchemist.model.Position import it.unibo.alchemist.model.geometry.Vector /** - * A [SteeringAction] related to a group of pedestrians. + * A [SteeringAction] that is influenced by a group of pedestrians. + * + * @param T the concentration type. + * @param P the position/vector type used by the steering action. */ interface GroupSteeringAction : SteeringAction where P : Position

, P : Vector

{ /** - * The list of pedestrians influencing this action. + * Returns the list of nodes (pedestrians) that influence this group steering action. + * + * @return a [List] of [Node] instances representing the influencing group. */ fun group(): List> } diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/GroupWithLeader.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/GroupWithLeader.kt index 333847252c..891a4711f3 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/GroupWithLeader.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/GroupWithLeader.kt @@ -12,11 +12,14 @@ package it.unibo.alchemist.model.cognitive import it.unibo.alchemist.model.Node /** - * A group with a special member acting as a leader. + * A group that designates a special member as the leader. + * + * @param T the concentration type. + * @param N the concrete node type used for the leader. */ interface GroupWithLeader> : Group { /** - * The leader of the group. + * The node acting as the group's leader. */ val leader: N } diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/HeterogeneousPedestrianModel.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/HeterogeneousPedestrianModel.kt index 7b50eff728..39c368b9c8 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/HeterogeneousPedestrianModel.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/HeterogeneousPedestrianModel.kt @@ -18,35 +18,32 @@ import it.unibo.alchemist.model.geometry.Transformation import it.unibo.alchemist.model.geometry.Vector /** - * A pedestrian with individual characteristics. + * Model of a pedestrian with heterogeneous individual characteristics. + * + * @param T the concentration type. + * @param S the concrete Vector type used for geometry operations. + * @param A the concrete Transformation type compatible with [S]. */ data class HeterogeneousPedestrianModel, A : Transformation>( - /** - * The age of this pedestrian. - */ + /** The age of this pedestrian. */ val age: Age, - /** - * The gender of this pedestrian. - */ + /** The gender of this pedestrian. */ val gender: Gender, - /** - * The speed of an agent considering its age, gender and a random factor. - */ + /** The agent's speed considering age, gender and randomness. */ val speed: Speed, /** - * Value between 0 and 1 representing the attitude towards conforming to social rules of this pedestrian. + * Value between 0 and 1 representing the attitude toward conforming to social rules. */ val compliance: Double = Compliance(age, gender).level, - /** - * The attitude of an agent towards helping another agent. - */ + /** The attitude toward helping other agents. */ val helpAttitude: HelpAttitude = HelpAttitude(age, gender), ) { /** - * Value between 0 and 1 representing the probability this pedestrian will help another pedestrian in difficulty. + * Returns the probability that this pedestrian will help another pedestrian. * - * @param toHelp The pedestrian who needs help. - * @param isGroupMember Whether the pedestrian in difficulty is a member of the helper's group. + * @param toHelp the pedestrian who may receive help. + * @param isGroupMember true if the pedestrian in difficulty is a member of the helper's group. + * @return a probability in [0.0, 1.0] representing the likelihood of offering help. */ fun probabilityOfHelping(toHelp: HeterogeneousPedestrianModel, isGroupMember: Boolean): Double = helpAttitude.level(toHelp.age, toHelp.gender, isGroupMember) diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/Human2DProperty.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/Human2DProperty.kt index fa44dca179..1f7cc88583 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/Human2DProperty.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/Human2DProperty.kt @@ -14,5 +14,7 @@ import it.unibo.alchemist.model.positions.Euclidean2DPosition /** * A capability representing a pedestrian's individual characteristics in a 2D space. + * + * @param T the concentration type. */ typealias Human2DProperty = HumanProperty diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/HumanProperty.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/HumanProperty.kt index ab535cffd0..3c75cdebb8 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/HumanProperty.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/HumanProperty.kt @@ -18,39 +18,36 @@ import it.unibo.alchemist.model.geometry.Transformation import it.unibo.alchemist.model.geometry.Vector /** - * A capability representing a pedestrian's individual characteristics. + * Capability representing a pedestrian's individual characteristics. + * + * @param T the concentration type. + * @param S the concrete Vector type used for geometry operations. + * @param A the concrete Transformation type compatible with [S]. */ interface HumanProperty, A : Transformation> : NodeProperty { - /** - * The age of this pedestrian. - */ + /** The age of this pedestrian. */ val age: Age - /** - * The gender of this pedestrian. - */ + /** The gender of this pedestrian. */ val gender: Gender - /** - * The speed of an agent considering its age, gender and a random factor. - */ + /** The agent's speed considering age, gender and randomness. */ val speed: Speed /** - * Value between 0 and 1 representing the attitude towards conforming to social rules of this pedestrian. + * Value between 0 and 1 representing the attitude toward conforming to social rules. */ val compliance: Double - /** - * The attitude of an agent towards helping another agent. - */ + /** The attitude toward helping other agents. */ val helpAttitude: HelpAttitude /** - * Value between 0 and 1 representing the probability this pedestrian will help another pedestrian in difficulty. + * Returns the probability that this pedestrian will help another pedestrian. * - * @param toHelp The pedestrian who needs help. - * @param isGroupMember Whether the pedestrian in difficulty is a member of the helper's group. + * @param toHelp the pedestrian who may receive help. + * @param isGroupMember true if the pedestrian in difficulty is a member of the helper's group. + * @return a probability in [0.0, 1.0] representing the likelihood of offering help. */ fun probabilityOfHelping(toHelp: HeterogeneousPedestrianModel, isGroupMember: Boolean): Double = helpAttitude.level(toHelp.age, toHelp.gender, isGroupMember) diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/NavigationAction.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/NavigationAction.kt index bef41e4c0f..b78089329b 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/NavigationAction.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/NavigationAction.kt @@ -18,16 +18,17 @@ import it.unibo.alchemist.model.geometry.Transformation import it.unibo.alchemist.model.geometry.Vector /** - * A [SteeringAction] allowing a node to navigate an environment consciously (e.g. without getting stuck in - * U-shaped obstacles). Names are inspired to indoor environments, but this interface works for outdoor ones as well. + * A [SteeringAction] allowing a node to navigate an environment consciously (for example, avoiding + * getting stuck in U-shaped obstacles). Names are inspired by indoor environments, but this + * interface also works for outdoor scenarios. * * @param T the concentration type. - * @param P the [Position] type and [Vector] type for the space the node is into. - * @param A the transformations supported by the shapes in this space. - * @param L the type of landmarks of the node's cognitive map. - * @param R the type of edges of the node's cognitive map, representing the [R]elations between landmarks. - * @param N the type of nodes of the navigation graph provided by the [environment]. - * @param E the type of edges of the navigation graph provided by the [environment]. + * @param P the [Position] and [Vector] type used by the space the node occupies. + * @param A the transformation type supported by the shapes in this space. + * @param L the type of landmarks in the node's cognitive map. + * @param R the type of edges in the node's cognitive map, representing relations between landmarks. + * @param N the type of navigation-area shapes provided by the [environment]. + * @param E the type of edges (passages) of the navigation graph provided by the [environment]. */ interface NavigationAction : SteeringAction @@ -35,48 +36,42 @@ interface NavigationAction : A : Transformation

, L : ConvexShape, N : ConvexShape { - /** - * The owner of this action. - */ + /** The owner of this action. */ val navigatingNode: Node - /** - * The [navigatingNode]'s orientingProperty. - */ + /** The [navigatingNode]'s orienting property. */ val orientingProperty get() = navigatingNode.asProperty>() - /** - * The environment the [navigatingNode] is into. - */ + /** The environment the [navigatingNode] is in. */ val environment: EnvironmentWithGraph<*, T, P, A, N, E> - /** - * The position of the [navigatingNode] in the [environment]. - */ + /** The position of the [navigatingNode] in the [environment]. */ val pedestrianPosition: P - /** - * The room (= environment's area) the [navigatingNode] is into. - */ + /** The room (environment area) the [navigatingNode] is in, if any. */ val currentRoom: N? /** - * @returns the doors (= passages/edges) the node can perceive. + * Returns the doors (passages/edges) the node can perceive. + * + * @return a [List] of visible door edges of type [E]. */ fun doorsInSight(): List /** - * Moves the node across the provided [door], which must be among [doorsInSight]. + * Moves the node across the provided [door], which must be among the doors returned by [doorsInSight]. + * + * @param door the door (edge) to cross. */ fun crossDoor(door: E) /** * Moves the node to the given final [destination], which must be inside [currentRoom]. + * + * @param destination the final destination position inside the current room. */ fun moveToFinal(destination: P) - /** - * Stops moving the node. - */ + /** Stops the node by moving it to its current position. */ fun stop() = moveToFinal(pedestrianPosition) } diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/NavigationStrategy.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/NavigationStrategy.kt index d2062a191f..b43814f6e3 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/NavigationStrategy.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/NavigationStrategy.kt @@ -15,16 +15,17 @@ import it.unibo.alchemist.model.geometry.Transformation import it.unibo.alchemist.model.geometry.Vector /** - * Defines what a node should do when in a new room (= environment's area), this is designed to be used jointly - * with a [NavigationAction]: the latter defines how to properly move the node, while delegating the decision on - * where to move it to a [NavigationStrategy]. + * Defines what a node should do when it enters a new room (an area of the environment). + * + * This interface is intended to be used together with a [NavigationAction]: the action + * provides movement primitives (how to move), while the strategy decides where to move. * * @param T the concentration type. - * @param P the [Position] type and [Vector] type for the space the node is into. - * @param A the transformations supported by the shapes in this space. - * @param L the type of landmarks of the node's cognitive map. - * @param R the type of edges of the node's cognitive map, representing the [R]elations between landmarks. - * @param N the type of nodes of the navigation graph provided by the environment. + * @param P the [Position] and [Vector] type used by the environment. + * @param A the transformation type supported by shapes in the environment. + * @param L the type of landmarks in the node's cognitive map. + * @param R the type of edges in the node's cognitive map, representing relations between landmarks. + * @param N the type of navigation-area shapes provided by the environment. * @param E the type of edges of the navigation graph provided by the environment. */ interface NavigationStrategy @@ -32,24 +33,26 @@ interface NavigationStrategy A : Transformation

, L : ConvexShape, N : ConvexShape { - /** - * The [NavigationAction] used to navigate the environment. - */ + /** The [NavigationAction] used to navigate the environment. */ val action: NavigationAction - /** - * The node's orienting capability. - */ + /** The node's orienting capability. */ val orientingCapability get() = action.orientingProperty /** - * This is called whenever the node enters a new room. + * Called whenever the node enters a new room. + * + * @param newRoom the room that the node has just entered. */ fun inNewRoom(newRoom: N) /** - * This is called in place of [inNewRoom] when the node ends up in an unexpected room while moving. - * By default, unexpected rooms are treated just like expected ones. + * Called when the node ends up in an unexpected room while moving. + * By default, unexpected rooms are treated the same as expected ones. + * + * @param previousRoom the room the node was in before moving. + * @param expectedNewRoom the room the node was expected to enter. + * @param actualNewRoom the room the node actually entered. */ fun inUnexpectedNewRoom(previousRoom: N, expectedNewRoom: N, actualNewRoom: N) = inNewRoom(actualNewRoom) } diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/NavigationStrategy2D.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/NavigationStrategy2D.kt index 31f6645ab5..509dc17c0d 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/NavigationStrategy2D.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/NavigationStrategy2D.kt @@ -13,7 +13,9 @@ import it.unibo.alchemist.model.geometry.Euclidean2DTransformation import it.unibo.alchemist.model.positions.Euclidean2DPosition /** - * A [NavigationStrategy] in a bidimensional euclidean space. + * A [NavigationStrategy] specialized for bidimensional Euclidean space. + * + * @param T the concentration type. */ typealias NavigationStrategy2D = NavigationStrategy diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/OrientingAgent.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/OrientingAgent.kt index ecb0d8247e..cb2650523b 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/OrientingAgent.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/OrientingAgent.kt @@ -17,37 +17,37 @@ import it.unibo.alchemist.model.geometry.navigationgraph.NavigationGraph /** * An agent capable of orienting itself inside an environment. * - * @param V the [Vector] type for the space this agent is inside. - * @param A the transformations supported by the shapes in this space. - * @param L the type of landmarks. See [cognitiveMap]. - * @param R the type of edges of the [cognitiveMap], representing the [R]elations between landmarks. + * @param V the [Vector] type for the space this agent occupies. + * @param A the transformation type supported by the shapes in this space. + * @param L the type of landmarks stored in the cognitive map. + * @param R the type of edges in the cognitive map, representing relations between landmarks. */ interface OrientingAgent where V : Vector, A : Transformation, L : ConvexShape { /** - * The knowledge degree of the agent concerning the environment. This is a Double value in [0, 1] describing the - * percentage of environment the agent is familiar with prior to the start of the simulation (thus it does not - * take into account the knowledge the node will gain during it, namely the [volatileMemory]). + * The degree of prior knowledge about the environment, in [0.0, 1.0]. + * This value describes the portion of the environment the agent is familiar with before the simulation starts + * and does not include memory gained during the simulation (see [volatileMemory]). */ val knowledgeDegree: Double /** - * The cognitive map of the agent. It's a graph composed of landmarks (elements of the environment easy to - * remember due to their uniqueness) and spatial relations between them. It's modeled as a [NavigationGraph]. + * The agent's cognitive map: a [NavigationGraph] of landmarks and spatial relations. */ val cognitiveMap: NavigationGraph /** - * The volatile memory of the agent: it models the ability to remember areas of the environment already visited - * since the start of the simulation. Each area is paired with the number of visits. Areas are assumed to be - * represented as [ConvexShape]s, as in [NavigationGraph]s. + * Volatile memory that tracks areas visited since the simulation started. The map pairs each visited area + * with the number of visits. */ val volatileMemory: MutableMap, Int> /** - * Registers a visit to the provided [area] in the agent's [volatileMemory]. + * Registers a visit to the provided [area] in the agent's volatile memory. + * + * @param area the area that has been visited. */ fun > registerVisit(area: M) { volatileMemory[area] = (volatileMemory[area] ?: 0) + 1 diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/OrientingAgent2D.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/OrientingAgent2D.kt index 2cf94c7385..2e14a3e783 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/OrientingAgent2D.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/OrientingAgent2D.kt @@ -15,6 +15,6 @@ import it.unibo.alchemist.model.positions.Euclidean2DPosition import org.jgrapht.graph.DefaultEdge /** - * An agent capable of orienting itself inside an Euclidean environment. + * A specialization of [OrientingAgent] for two-dimensional Euclidean space. */ typealias OrientingAgent2D = OrientingAgent diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/OrientingProperty.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/OrientingProperty.kt index b37e029ee8..156d75c03a 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/OrientingProperty.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/OrientingProperty.kt @@ -18,7 +18,14 @@ import it.unibo.alchemist.model.geometry.Vector import it.unibo.alchemist.model.geometry.navigationgraph.NavigationGraph /** - * A node's capability to orient. + * A node's orienting capability. + * + * @param T the concentration type. + * @param P the [Position] and [Vector] type used by the environment. + * @param A the transformation type supported by shapes in this environment. + * @param L the type of landmarks in the cognitive map. + * @param N the type of navigation-area shapes used to derive landmarks. + * @param E the type of edges in the navigation graph. */ interface OrientingProperty : NodeProperty @@ -28,40 +35,38 @@ interface OrientingProperty : L : ConvexShape, N : ConvexShape { /** - * The knowledge degree of the agent concerning the environment. This is a Double value in [0, 1] describing the - * percentage of environment the agent is familiar with prior to the start of the simulation (thus it does not - * take into account the knowledge the pedestrian will gain during it, namely the [volatileMemory]). + * The degree of prior knowledge about the environment, in [0.0, 1.0]. */ val knowledgeDegree: Double - /** - * The environment in which the node moves. - */ + /** The environment in which the node moves. */ val environment: EnvironmentWithGraph<*, T, P, A, N, E> /** - * The cognitive map of the agent. It's a graph composed of landmarks (elements of the environment easy to - * remember due to their uniqueness) and spatial relations between them. It's modeled as a [NavigationGraph]. + * The agent's cognitive map: a [NavigationGraph] of landmarks and spatial relations. */ val cognitiveMap: NavigationGraph /** - * The volatile memory of the agent: it models the ability to remember areas of the environment already visited - * since the start of the simulation. Each area is paired with the number of visits. Areas are assumed to be - * represented as [ConvexShape]s, as in [NavigationGraph]s. + * Volatile memory tracking visited areas paired with the number of visits. */ val volatileMemory: MutableMap, Int> /** - * Registers a visit to the provided [area] in the agent's [volatileMemory]. + * Registers a visit to the provided [area] in the volatile memory. + * + * @param area the area that has been visited. */ fun > registerVisit(area: M) { volatileMemory[area] = (volatileMemory[area] ?: 0) + 1 } /** - * Creates a landmark entirely contained in the given area. If such area contains one or more destinations, the - * returned landmark must contain at least one of them. + * Creates a landmark entirely contained in the given [area]. If [area] contains one or more destinations, + * the returned landmark must contain at least one of them. + * + * @param area the navigation-area used to create the landmark. + * @return a landmark of type [L] contained in the provided area. */ fun createLandmarkIn(area: N): L } diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/PedestrianProperty.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/PedestrianProperty.kt index 5a366a00d7..45a1a2c6e4 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/PedestrianProperty.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/PedestrianProperty.kt @@ -10,13 +10,17 @@ package it.unibo.alchemist.model.cognitive /** - * A node capability to move. It includes both [WalkingPedestrianProperty] and [RunningPedestrianProperty]. + * Capability that enables node movement, combining walking and running pedestrian properties. + * + * @param T the concentration type. */ interface PedestrianProperty : WalkingPedestrianProperty, RunningPedestrianProperty { /** - * The speed at which the pedestrian is moving. + * Returns the current speed of the pedestrian. + * + * @return the pedestrian's speed as a [Double]. */ fun speed(): Double } diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/PerceptiveProperty.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/PerceptiveProperty.kt index 872b9b6937..a69aa454fc 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/PerceptiveProperty.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/PerceptiveProperty.kt @@ -13,16 +13,16 @@ import it.unibo.alchemist.model.NodeProperty import it.unibo.alchemist.model.physics.InfluenceSphere /** - * The pedestrian's capability to influence other pedestrians. + * The pedestrian's capability to perceive and influence other pedestrians. + * + * @param T the concentration type. */ interface PerceptiveProperty : NodeProperty { - /** - * The field of view of the pedestrian. - */ + /** The agent's primary field of view. */ val fieldOfView: InfluenceSphere /** - * The list of influence spheres belonging to this pedestrian (by default, only its [fieldOfView]). + * The set of influence spheres associated with this pedestrian. By default only [fieldOfView] is present. */ val senses: Map> get() = mapOf("view" to fieldOfView) } diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/PhysicalSteeringStrategy.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/PhysicalSteeringStrategy.kt index 30bec06872..7e24df9dda 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/PhysicalSteeringStrategy.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/PhysicalSteeringStrategy.kt @@ -16,40 +16,44 @@ import it.unibo.alchemist.model.geometry.Transformation import it.unibo.alchemist.model.geometry.Vector /** - * Defines how physical forces and steering actions (which may be seen as intentional forces) are combined to compute - * the overall next position reached by a physical [node]. The combination of steering actions is delegated to a - * [nonPhysicalStrategy]. The resulting intentional force is then combined with the physical ones to determine the - * next position reached by [node]. + * Strategy that combines physical forces with intentional steering actions to compute a node's next position. + * + * The aggregation of steering actions and target computation is delegated to [nonPhysicalStrategy]. The resulting + * intentional force is then combined with the physical forces to compute the final displacement of [node]. + * + * @param T the concentration type. + * @param P the [Position] and [Vector] type used by the environment. + * @param A the transformation type supported by shapes in this space. + * @param F the geometric shape factory used by the environment. */ interface PhysicalSteeringStrategy : SteeringStrategy where P : Position

, P : Vector

, A : Transformation

, F : GeometricShapeFactory { - /** - * The node to be moved. - */ + /** The node to be moved. */ val node: Node /** - * The combination of intentional forces (= steering actions) and [computeTarget] are delegated to this strategy. + * Strategy responsible for combining intentional steering actions and computing the target. */ val nonPhysicalStrategy: SteeringStrategy /** - * Computes the next relative position reached by the node, given the overall intentional force. + * Computes the next relative position given the overall intentional force. + * + * @param overallIntentionalForce the combined intentional force as a vector of type [P]. + * @return the next relative position as a [P]. */ fun computeNextPosition(overallIntentionalForce: P): P /** - * Computes the next relative position reached by the node, taking into account both the intentional and the - * physical forces acting on [node] (intentional forces = [actions]). + * Computes the next position by delegating the combination of steering actions to [nonPhysicalStrategy] + * and then applying physical dynamics. */ override fun computeNextPosition(actions: List>): P = computeNextPosition(nonPhysicalStrategy.computeNextPosition(actions)) - /** - * Delegated to [nonPhysicalStrategy]. - */ + /** Delegates target computation to [nonPhysicalStrategy]. */ override fun computeTarget(actions: List>): P = nonPhysicalStrategy.computeTarget(actions) } diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/RunningPedestrianProperty.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/RunningPedestrianProperty.kt index 7f8a13eb26..6844c37b1e 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/RunningPedestrianProperty.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/RunningPedestrianProperty.kt @@ -12,11 +12,11 @@ package it.unibo.alchemist.model.cognitive import it.unibo.alchemist.model.NodeProperty /** - * A node's capability to run. + * Capability that allows a node to run. + * + * @param T the concentration type. */ interface RunningPedestrianProperty : NodeProperty { - /** - * The node's running speed. - */ + /** The node's running speed. */ val runningSpeed: Double } diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/SocialProperty.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/SocialProperty.kt index d76dfd1322..82662a3814 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/SocialProperty.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/SocialProperty.kt @@ -12,11 +12,11 @@ package it.unibo.alchemist.model.cognitive import it.unibo.alchemist.model.NodeProperty /** - * The pedestrian's capability for form groups. + * Capability that enables a pedestrian to form and belong to groups. + * + * @param T the concentration type. */ interface SocialProperty : NodeProperty { - /** - * Pedestrian's [Group]. - */ + /** The group the pedestrian currently belongs to. */ val group: Group } diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/SteeringAction.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/SteeringAction.kt index 9f82db7b44..f76efc537f 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/SteeringAction.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/SteeringAction.kt @@ -13,12 +13,17 @@ import it.unibo.alchemist.model.Action import it.unibo.alchemist.model.Position /** - * Action whose purpose is moving a node inside the environment it is in. + * An action that describes movement of a node inside its environment. + * + * @param T the concentration type. + * @param P the [Position] type used by the action. */ interface SteeringAction> : Action { /** - * The position the owner of this action moves to when it is executed, - * in relative coordinates with respect to its current position. + * Returns the target relative position the owner will move to when this action is executed. + * The position is relative to the owner's current position. + * + * @return the next relative position as a [P]. */ fun nextPosition(): P } diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/SteeringActionWithTarget.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/SteeringActionWithTarget.kt index 03e8dd8355..e4fe0c6aeb 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/SteeringActionWithTarget.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/SteeringActionWithTarget.kt @@ -15,16 +15,25 @@ import it.unibo.alchemist.model.Position import it.unibo.alchemist.model.geometry.Vector /** - * A [SteeringAction] with a defined target. + * A [SteeringAction] that exposes an absolute target position. + * + * @param T the concentration type. + * @param P the [Position] and [Vector] type used by the environment. */ interface SteeringActionWithTarget : SteeringAction where P : Position

, P : Vector

{ /** - * The position the owner of this action moves towards, in absolute coordinates. + * Returns the absolute target position this action points to. + * + * @return the target position as a [P]. */ fun target(): P /** - * Computes the distance between this action's target and the given [node]. + * Computes the distance between this action's target and the given [node] within the provided [environment]. + * + * @param node the node to measure distance to. + * @param environment the environment containing the node. + * @return the distance from the action's target to the node's position. */ fun targetDistanceTo(node: Node, environment: Environment): Double = target().distanceTo(environment.getPosition(node)) diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/SteeringStrategy.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/SteeringStrategy.kt index e64e648de1..0e9ee06d8a 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/SteeringStrategy.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/SteeringStrategy.kt @@ -12,25 +12,25 @@ package it.unibo.alchemist.model.cognitive import it.unibo.alchemist.model.Position /** - * Strategy interface describing how the next points of the steering actions - * are combined to calculate the next position to move on. + * Strategy describing how steering actions are combined to compute the next position. + * + * @param T the concentration type. + * @param P the [Position] type used by actions. */ interface SteeringStrategy> { /** - * Computes the next position starting from the steering actions the node obey to, - * in relative coordinates with respect to its current position. + * Computes the next relative position by combining the provided steering actions. * - * @param actions - * the list of actions to combine. + * @param actions the list of actions to combine. + * @return the next position relative to the current position as a [P]. */ fun computeNextPosition(actions: List>): P /** - * Computes the target to reach starting from the steering actions the node obey to, - * in absolute coordinates. + * Computes the absolute target position derived from the provided steering actions. * - * @param actions - * the list of actions to combine. + * @param actions the list of actions to combine. + * @return the target position as a [P]. */ fun computeTarget(actions: List>): P } diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/WalkingPedestrianProperty.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/WalkingPedestrianProperty.kt index ce65c8cd98..1e93d7ddd6 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/WalkingPedestrianProperty.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/WalkingPedestrianProperty.kt @@ -12,11 +12,11 @@ package it.unibo.alchemist.model.cognitive import it.unibo.alchemist.model.NodeProperty /** - * A node capability to walk. + * Capability that enables a node to walk. + * + * @param T the concentration type. */ interface WalkingPedestrianProperty : NodeProperty { - /** - * The node's walking speed. - */ + /** The node's walking speed. */ val walkingSpeed: Double } diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentCohesion.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentCohesion.kt index ac9d05fff3..631c601cae 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentCohesion.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentCohesion.kt @@ -26,6 +26,8 @@ import it.unibo.alchemist.model.geometry.Vector * the environment inside which the node moves. * @param reaction * the reaction which executes this action. + * @param pedestrian + * the owner of this action. */ class CognitiveAgentCohesion( environment: Environment, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentCombineSteering.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentCombineSteering.kt index c7cd4cec71..7b06a00235 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentCombineSteering.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentCombineSteering.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2023, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the @@ -20,16 +20,17 @@ import it.unibo.alchemist.model.geometry.Transformation import it.unibo.alchemist.model.geometry.Vector /** - * Combination of multiple steering actions. + * Combines multiple steering actions into a single steering behavior. * - * @param environment - * the environment inside which the node moves. - * @param pedestrian - * the owner of this action. - * @param actions - * the list of actions to combine to determine the node movement. - * @param steerStrategy - * the logic according to the steering actions are combined. + * @constructor Creates a new composite steering action. + * @param environment the environment in which the node moves. + * @param reaction the reaction that executes this action. + * @param pedestrian the owner of this action. + * @param actions the list of steering actions to combine. + * @param steerStrategy the strategy used to combine the steering actions. + * @param T the type of the concentration. + * @param P the type of the position. + * @param A */ class CognitiveAgentCombineSteering( environment: Environment, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFlee.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFlee.kt index 79ba39d5ed..288a7e945b 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFlee.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFlee.kt @@ -20,14 +20,10 @@ import it.unibo.alchemist.model.geometry.Vector /** * Move the agent away from a target position. It's the opposite of [CognitiveAgentSeek]. * - * @param environment - * the environment inside which the node moves. - * @param reaction - * the reaction which executes this action. - * @param pedestrian - * the owner of this action. - * @param coords - * the coordinates of the position the node moves away. + * @param environment the environment inside which the node moves. + * @param reaction the reaction which executes this action. + * @param pedestrian the owner of this action. + * @param coords the coordinates of the position the node moves away from. */ open class CognitiveAgentFlee( environment: Environment, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFollowLayer.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFollowLayer.kt index 7bbfd868d8..fc7181c86e 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFollowLayer.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFollowLayer.kt @@ -19,14 +19,10 @@ import it.unibo.alchemist.model.positions.Euclidean2DPosition /** * Move the node towards positions of the environment with a high concentration of the target molecule. * - * @param euclidean - * the environment inside which the node moves. - * @param reaction - * the reaction which executes this action. - * @param pedestrian - * the owner of this action. - * @param targetMolecule - * the {@link Molecule} you want to know the concentration in the different positions of the environment. + * @param euclidean the environment inside which the node moves. + * @param reaction the reaction which executes this action. + * @param pedestrian the owner of this action. + * @param targetMolecule the molecule whose concentration defines the scalar field to follow. */ open class CognitiveAgentFollowLayer( euclidean: Euclidean2DEnvironment, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentPursue.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentPursue.kt index c091007f6b..c25b04e4d4 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentPursue.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentPursue.kt @@ -18,11 +18,15 @@ import it.unibo.alchemist.model.geometry.Euclidean2DConvexShape import it.unibo.alchemist.model.geometry.navigationgraph.Euclidean2DPassage /** - * A [CognitiveAgentNavigationAction2D] using [Pursue] navigation strategy. + * A cognitive navigation action that pursues a static destination using the [Pursue] strategy. * * @param T the concentration type. - * @param L the type of landmarks of the node's cognitive map. - * @param R the type of edges of the node's cognitive map, representing the [R]elations between landmarks. + * @param L the landmark shape type used by the node's cognitive map. + * @param R the relation/edge type used by the node's cognitive map. + * @param environment the environment hosting the node. + * @param reaction the reaction executing this action. + * @param pedestrian the owner pedestrian property. + * @param destination coordinates (vararg) describing the destination position. */ class CognitiveAgentPursue( environment: Euclidean2DEnvironmentWithGraph<*, T, ConvexPolygon, Euclidean2DPassage>, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentReachKnownDestination.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentReachKnownDestination.kt index 8f543c6a82..0317e10e2e 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentReachKnownDestination.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentReachKnownDestination.kt @@ -21,11 +21,15 @@ import it.unibo.alchemist.util.Arrays.toPositions import it.unibo.alchemist.util.lazyMutable /** - * A [CognitiveAgentNavigationAction2D] using [ReachKnownDestination] navigation strategy. + * A cognitive navigation action that pursues known destinations using [ReachKnownDestination] strategy. * * @param T the concentration type. - * @param L the type of landmarks of the node's cognitive map. - * @param R the type of edges of the node's cognitive map, representing the [R]elations between landmarks. + * @param L the landmark shape type used by the node's cognitive map. + * @param R the relation/edge type used by the node's cognitive map. + * @param environment the environment hosting the node. + * @param reaction the reaction executing this action. + * @param pedestrian the owner pedestrian property. + * @param destinations vararg coordinates representing known destinations. */ class CognitiveAgentReachKnownDestination( environment: Euclidean2DEnvironmentWithGraph<*, T, ConvexPolygon, Euclidean2DPassage>, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeek.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeek.kt index 93ec278675..e4322b7652 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeek.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeek.kt @@ -18,14 +18,15 @@ import it.unibo.alchemist.model.geometry.Transformation import it.unibo.alchemist.model.geometry.Vector /** - * Move the node towards the target position as fast as possible. + * Moves the node towards the target position as fast as possible. * - * @param environment - * the environment inside which the node moves. - * @param pedestrian - * the owner of this action. - * @param target - * the position the node moves towards. + * @param T the concentration type. + * @param P the position type. + * @param A the transformation type compatible with [P]. + * @param environment the environment in which the node moves. + * @param reaction the reaction executing this action. + * @property pedestrian the owner pedestrian property. + * @param target the position the node moves towards. */ open class CognitiveAgentSeek( environment: Environment, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeparation.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeparation.kt index 207ef96393..3c8e9985dd 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeparation.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeparation.kt @@ -19,14 +19,12 @@ import it.unibo.alchemist.model.physics.environments.Physics2DEnvironment import it.unibo.alchemist.model.positions.Euclidean2DPosition /** - * Move the agent away from the pedestrians near to him. + * Steering action that moves the agent away from nearby pedestrians (separation behavior). * - * @param environment - * the environment inside which the node moves. - * @param reaction - * the reaction which executes this action. - * @param pedestrian - * the owner of this action. + * @param T the concentration type. + * @property environment the physics environment in which the node moves. + * @param reaction the reaction executing this action. + * @property pedestrian the owner pedestrian property. */ class CognitiveAgentSeparation( val environment: Physics2DEnvironment, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentWander.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentWander.kt index c373663d5f..a46a032ead 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentWander.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentWander.kt @@ -24,19 +24,20 @@ import it.unibo.alchemist.util.RandomGenerators.nextDouble import org.apache.commons.math3.random.RandomGenerator /** - * Give the impression of a random walk through the environment targeting an ever changing pseudo-randomly point - * of a circumference at a given distance and with a given radius from the current node position. + * Produces a wandering steering action that simulates a random walk by targeting + * points on a circle centered at a given offset from the node and with a given radius. * - * @param environment - * the environment inside which the node moves. - * @param pedestrian - * the owner of this action. - * @param randomGenerator - * the simulation {@link RandomGenerator}. - * @param offset - * the distance from the node position of the center of the circle. - * @param radius - * the radius of the circle. + * The node's heading is set randomly and subsequent target points are chosen on a + * circumference around the heading with the specified [offset] and [radius]. The + * resulting target is constrained by the node's maximum walking distance. + * + * @param T the concentration type. + * @param reaction the reaction executing this action. + * @property environment the physics environment in which the node moves. + * @property pedestrian the owner of this action. + * @property randomGenerator the random number generator used to select directions. + * @property offset the distance from the node position to the center of the circle. + * @property radius the radius of the circle from which target points are sampled. */ open class CognitiveAgentWander( private val environment: Physics2DEnvironment, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/DynamicallyPursue.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/DynamicallyPursue.kt index cc380515d7..f53d932810 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/DynamicallyPursue.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/DynamicallyPursue.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2023, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the @@ -18,11 +18,13 @@ import it.unibo.alchemist.model.geometry.navigationgraph.Euclidean2DPassage import it.unibo.alchemist.model.positions.Euclidean2DPosition /** - * [Pursue] strategy allowing to dynamically change [destination]. + * A [Pursue] strategy variant that allows changing the destination dynamically. * * @param T the concentration type. - * @param L the type of landmarks of the node's cognitive map. - * @param R the type of edges of the node's cognitive map, representing the [R]elations between landmarks. + * @param L the landmark shape type used by the node's cognitive map. + * @param R the relation/edge type used by the node's cognitive map. + * @param action the navigation action backing this strategy. + * @property destination the initial destination position. */ open class DynamicallyPursue( action: NavigationAction2D, @@ -30,17 +32,17 @@ open class DynamicallyPursue( ) : Pursue(action, destination) { /** * Changes the destination of the strategy. If [voidVolatileMemory] is true, the node's - * volatile memory is set to zero. This has two effects: - * - known impasses remain stored (hence the node will keep avoiding them) - * - rooms visited while pursuing the previous destination won't be penalised (= won't be avoided) - * Defaults to false. + * volatile memory is reset to zero while preserving known impasses. + * + * @param newDestination the new destination position. + * @param voidVolatileMemory whether to reset volatile memory (defaults to false). */ fun setDestination(newDestination: Euclidean2DPosition, voidVolatileMemory: Boolean = false) { destination = newDestination action.currentRoom?.let { /* * If the node is inside a room, we force the re-computation of what to do. Otherwise - * he/she's crossing a door and inNewRoom will be called as soon as a room is reached. + * the node is crossing a door and inNewRoom will be called as soon as a room is reached. */ inNewRoom(it) } @@ -48,7 +50,7 @@ open class DynamicallyPursue( /* * clear() would cause volatileMemory[anyArea] to be null, which in turn means the node would * forget known impasses as well (an impasse is known when volatileMemory[area] != null). Setting - * volatileMemory[anyArea] to zero allows to remember known impasses. + * volatileMemory[anyArea] to zero allows remembering known impasses while resetting visit penalties. */ node.asProperty>().volatileMemory.replaceAll { _, _ -> 0 } } diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/Explore.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/Explore.kt index dfe9ba6b85..c668301a2b 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/Explore.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/Explore.kt @@ -30,8 +30,10 @@ import kotlin.math.pow * [Andresen et al.](https://doi.org/10.1080/23249935.2018.1432717), see [weight]. * * @param T the concentration type. - * @param L the type of landmarks of the pedestrian's cognitive map. - * @param R the type of edges of the pedestrian's cognitive map, representing the [R]elations between landmarks. + * @param L the landmark shape type used by the pedestrian's cognitive map. + * @param R the relation/edge type used by the pedestrian's cognitive map. + * @property action the navigation action driving this strategy. + * @property knownImpasseWeight weight assigned to known impasses (see [impasseFactor]). */ open class Explore( override val action: NavigationAction2D, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/FollowRoute.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/FollowRoute.kt index 220abc3a1b..0a8d79d816 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/FollowRoute.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/FollowRoute.kt @@ -17,25 +17,21 @@ import it.unibo.alchemist.model.geometry.navigationgraph.Euclidean2DPassage import it.unibo.alchemist.model.positions.Euclidean2DPosition /** - * A [NavigationStrategy] allowing to follow a given route. - * The route consists of a list of positions (= waypoints) that may or may not be in sight of each - * other (i.e. the path leading from a waypoint to the next one may or may not be representable - * as a single segment), for this reason [Pursue] behavior is used to reach each waypoint. - * In this context, a waypoint is considered reached when it's inside the current room (not when the - * node reach that exact position), apart from the last waypoint which is actually approached. - * Cuts to the route are allowed (i.e. if the node finds a waypoint which is farther than the - * expected next one, he/she skips all the waypoints in between). + * A [NavigationStrategy] that follows a predefined route composed of waypoints. + * Each waypoint is considered reached when the pedestrian is inside the waypoint's room + * (except for the final waypoint, which is actually approached). The strategy uses + * [Pursue] to reach each intermediate waypoint and allows skipping intermediate waypoints + * when a farther waypoint becomes available. * - * @param route the route to follow. * @param T the concentration type. - * @param L the type of landmarks of the node's cognitive map. - * @param R the type of edges of the node's cognitive map, representing the [R]elations between landmarks. + * @param L the landmark shape type used by the node's cognitive map. + * @param R the relation/edge type used by the node's cognitive map. + * @param action the navigation action driving this strategy. + * @property route the route to follow as a list of waypoints. */ open class FollowRoute constructor( action: NavigationAction2D, - /** - * The route to follow. - */ + /** The route to follow. */ protected open val route: List, ) : DynamicallyPursue(action, action.environment.origin.takeIf { route.isEmpty() } ?: route[0]) { private var indexOfNextWaypoint: Int = 0 diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/GoalOrientedExploration.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/GoalOrientedExploration.kt index 7d42329be0..bd38df6573 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/GoalOrientedExploration.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/GoalOrientedExploration.kt @@ -9,7 +9,6 @@ package it.unibo.alchemist.model.cognitive.navigation -import it.unibo.alchemist.model.cognitive.NavigationStrategy import it.unibo.alchemist.model.cognitive.actions.NavigationAction2D import it.unibo.alchemist.model.geometry.ConvexPolygon import it.unibo.alchemist.model.geometry.Euclidean2DConvexShape @@ -17,16 +16,15 @@ import it.unibo.alchemist.model.geometry.navigationgraph.Euclidean2DPassage import it.unibo.alchemist.model.positions.Euclidean2DPosition /** - * A [NavigationStrategy] allowing to explore the environment looking for something specific whose position - * is unknown. - * The client can specify a list of [unknownDestinations]: these can be recognized once they're in sight, - * but the node doesn't know their position until that moment (think e.g. of exits in an evacuation - * scenario). More specifically, unknown destinations can be detected if located in a room adjacent to the - * room the node is into. Once a destination is detected, the node will reach it and stop. + * Navigation strategy that explores the environment looking for unknown destination points. + * Unknown destinations are not known a priori but can be detected when they are inside a room + * adjacent to the node's current room. When detected, the node approaches the destination and stops. * * @param T the concentration type. - * @param L the type of landmarks of the node's cognitive map. - * @param R the type of edges of the node's cognitive map, representing the [R]elations between landmarks. + * @param L the landmark shape type used by the node's cognitive map. + * @param R the relation/edge type used by the node's cognitive map. + * @param action the navigation action driving this strategy. + * @param unknownDestinations list of static destinations that can be detected when in sight. */ open class GoalOrientedExploration( action: NavigationAction2D, @@ -36,10 +34,9 @@ open class GoalOrientedExploration( reachUnknownDestination(newRoom, orElse = { super.inNewRoom(newRoom) }) /** - * If one or more unknown destinations are inside [newRoom] (= the room the node is into), the closest - * one is approached. Otherwise, if one or more destinations are in a room adjacent to the current one, the - * related doors are weighted using [weightExit] and the one with minimum weight is crossed. [orElse] is - * executed otherwise. + * If any unknown destination is inside [newRoom], approach the closest one. Otherwise, if any unknown + * destination lies in an adjacent room, pick the best door using [weightExit] and cross it. If none applies, + * execute [orElse]. */ protected open fun reachUnknownDestination(newRoom: ConvexPolygon, orElse: () -> Unit) = with(action) { unknownDestinations @@ -58,8 +55,8 @@ open class GoalOrientedExploration( } /** - * Assigns a weight to a door (= passage) leading to an unknown destination (e.g. an exit). - * By default, the exit's distance and its congestion are considered. + * Assigns a weight to a door leading to an unknown destination. By default it considers + * the exit's distance and congestion. */ protected open fun weightExit(door: Euclidean2DPassage): Double = with(door) { distanceToPedestrian() * congestionFactor(head) diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/Pursue.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/Pursue.kt index a950e77e91..0200ce89bc 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/Pursue.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/Pursue.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2023, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the @@ -22,19 +22,20 @@ import org.jgrapht.graph.DefaultEdge import org.jgrapht.graph.DefaultUndirectedWeightedGraph /** - * A [NavigationStrategy] allowing to pursue a known (static) [destination] without knowing any - * path leading there, this is also known as path searching. - * In this context, knowing a destination means knowing its position, which, in turn, means - * knowing two things: - * - the direction that connects the destination and the current position as the crow flies, - * - an estimation of the distance between the destination and the current position. - * In order to reach the [destination] without a route to follow, the weighting system used - * in [Explore] is extended so as to take into account the (estimated) suitability of each - * door to reach the provided [destination], see [suitabilityFactor]. + * A [NavigationStrategy] that pursues a known static [destination] without a predefined route + * (also known as path searching). + * + * Knowing a destination provides the straight-line direction and a distance estimate. To reach + * the destination the weighting system from [Explore] is extended with a suitability factor + * that estimates how appropriate each visible door is to reach the destination (see + * [suitabilityFactor] and [computeDoorsRankings]). * * @param T the concentration type. - * @param L the type of landmarks of the pedestrian's cognitive map. - * @param R the type of edges of the pedestrian's cognitive map, representing the [R]elations between landmarks. + * @param L the landmark shape type used by the pedestrian's cognitive map. + * @param R the relation/edge type used by the pedestrian's cognitive map. + * @param action the navigation action that provides perception (visible doors, current room) + * and movement helpers used by this strategy. + * @property destination the static target position to pursue. */ open class Pursue( action: NavigationAction2D, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/ReachDestination.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/ReachDestination.kt index 1d546ed70e..362e8c7664 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/ReachDestination.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/ReachDestination.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2023, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the @@ -9,7 +9,6 @@ package it.unibo.alchemist.model.cognitive.navigation -import it.unibo.alchemist.model.cognitive.NavigationStrategy import it.unibo.alchemist.model.cognitive.actions.NavigationAction2D import it.unibo.alchemist.model.geometry.ConvexPolygon import it.unibo.alchemist.model.geometry.Euclidean2DConvexShape @@ -17,27 +16,25 @@ import it.unibo.alchemist.model.geometry.navigationgraph.Euclidean2DPassage import it.unibo.alchemist.model.positions.Euclidean2DPosition /** - * A [NavigationStrategy] allowing to reach a (static) destination. - * The client can specify a list of [knownDestinations] (see [Pursue]) and [unknownDestinations] (see - * [GoalOrientedExploration]). - * The pedestrian will try to reach the closest known destination for which a valid path leading there is - * known, but in case another destination is found along the way (either known or unknown), the latter will - * be approached instead of the chosen known destination. To put it in another way, this behavior mixes - * [ReachKnownDestination] and [GoalOrientedExploration]. + * Navigation strategy that aims to reach a static destination. + * + * The strategy mixes known-target routing ([ReachKnownDestination]) and exploratory + * goal-oriented behavior ([GoalOrientedExploration]). The pedestrian prefers the + * closest known destination for which a path exists, but will divert to any + * destination encountered along the way (either known or unknown). * * @param T the concentration type. - * @param L the type of landmarks of the pedestrian's cognitive map. - * @param R the type of edges of the pedestrian's cognitive map, representing the [R]elations between landmarks. + * @param L the landmark shape type used by the pedestrian's cognitive map. + * @param R the relation/edge type used by the pedestrian's cognitive map. + * @param action the navigation action driving this strategy. + * @param knownDestinations a list of known static destinations (may be empty). + * @param unknownDestinations optional unknown destinations to consider while exploring. */ open class ReachDestination( action: NavigationAction2D, - /** - * Known destinations, can be empty. - */ + /** Known destinations, can be empty. */ private val knownDestinations: List, - /** - * Unknown destinations, defaults to an empty list. - */ + /** Unknown destinations, defaults to an empty list. */ private val unknownDestinations: List = emptyList(), ) : GoalOrientedExploration( action, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/ReachKnownDestination.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/ReachKnownDestination.kt index 61ffee5b36..3c6af520b7 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/ReachKnownDestination.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/navigation/ReachKnownDestination.kt @@ -29,14 +29,14 @@ import org.jgrapht.alg.shortestpath.BFSShortestPath * cognitive map to obtain a route to follow. * * @param T the concentration type. - * @param L the type of landmarks of the pedestrian's cognitive map. - * @param R the type of edges of the pedestrian's cognitive map, representing the [R]elations between landmarks. + * @param L the landmark shape type used by the pedestrian's cognitive map. + * @param R the relation/edge type used by the pedestrian's cognitive map. + * @param action the navigation action driving this strategy. + * @param destinations list of known destinations (must not be empty). */ open class ReachKnownDestination( action: NavigationAction2D, - /** - * Known destinations (must not be empty). - */ + /** Known destinations (must not be empty). */ private val destinations: List, /* * An empty list is passed to super method, because route is initialised in this class' init block. diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/BlendedSteering.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/BlendedSteering.kt index d41cee59d0..db14ac72f7 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/BlendedSteering.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/BlendedSteering.kt @@ -15,15 +15,12 @@ import it.unibo.alchemist.model.cognitive.steering.DistanceWeighted import it.unibo.alchemist.model.environments.Euclidean2DEnvironment /** - * Steering behavior using [DistanceWeighted] steering strategy (= steering actions are summed with different - * weights depending on the distance to their target). + * Steering behavior that blends multiple steering actions using a [DistanceWeighted] strategy. * - * @param environment - * the environment inside which the pedestrian moves. - * @param pedestrian - * the owner of this reaction. - * @param timeDistribution - * the time distribution according to this the reaction executes. + * @param T the concentration type. + * @param environment the environment in which the pedestrian moves. + * @property pedestrian the owner of this reaction. + * @param timeDistribution the time distribution governing reaction execution. */ open class BlendedSteering( environment: Euclidean2DEnvironment, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/CognitiveBehavior.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/CognitiveBehavior.kt index 1931e6bd68..ad0d1a9f2b 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/CognitiveBehavior.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/CognitiveBehavior.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2023, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the @@ -20,12 +20,13 @@ import it.unibo.alchemist.model.geometry.Vector import it.unibo.alchemist.model.reactions.AbstractReaction /** - * Reaction representing the cognitive behavior of a pedestrian. + * Reaction representing a pedestrian's cognitive behavior. * - * @param node - * the owner of this reaction. - * @param timeDistribution - * the time distribution according to this the reaction executes. + * @param T the concentration type. + * @param V the vector type used by the node's position/geometry. + * @param A the transformation type compatible with [V]. + * @param node the owner of this reaction. + * @param timeDistribution the time distribution governing reaction execution. */ class CognitiveBehavior(node: Node, timeDistribution: TimeDistribution) : AbstractReaction(node, timeDistribution) diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/NavigationPrioritizedSteering.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/NavigationPrioritizedSteering.kt index 80a9687c02..4b066cf57c 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/NavigationPrioritizedSteering.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/NavigationPrioritizedSteering.kt @@ -19,11 +19,16 @@ import it.unibo.alchemist.model.geometry.ConvexPolygon import it.unibo.alchemist.model.positions.Euclidean2DPosition /** - * A [SteeringBehavior] using [SinglePrevalent] steering strategy and accepting a collection of actions - * containing a single [NavigationAction2D], which is used as the prevalent one. + * A [SteeringBehavior] that prioritizes a single navigation action using the [SinglePrevalent] strategy. + * The provided actions must contain a single [NavigationAction2D], used as the prevalent action. * - * @param T concentration type - * @param N type of nodes of the environment's graph. + * @param T the concentration type. + * @param N the polygon type used by the environment's navigation graph. + * @param environment the environment containing the navigation graph. + * @property pedestrian the owner pedestrian's property. + * @param timeDistribution the time distribution that schedules reaction execution. + * @param toleranceAngle tolerance angle in degrees for the SinglePrevalent strategy. + * @param alpha smoothing alpha for exponential smoothing used by SinglePrevalent. */ open class NavigationPrioritizedSteering @JvmOverloads @@ -31,13 +36,9 @@ constructor( environment: Euclidean2DEnvironmentWithGraph<*, T, N, *>, override val pedestrian: PedestrianProperty, timeDistribution: TimeDistribution, - /** - * Tolerance angle in degrees (see [SinglePrevalent]). - */ + /** Tolerance angle in degrees (see [SinglePrevalent]). */ toleranceAngle: Double = Math.toDegrees(SinglePrevalent.DEFAULT_TOLERANCE_ANGLE), - /** - * Alpha value for exponential smoothing (see [SinglePrevalent]). - */ + /** Alpha value for exponential smoothing (see [SinglePrevalent]). */ alpha: Double = SinglePrevalent.DEFAULT_ALPHA, ) : SteeringBehavior( environment, @@ -54,7 +55,7 @@ constructor( ) { private companion object { /** - * @returns the only navigation action contained in the list or throws an exception. + * Returns the only navigation action contained in the list or throws an exception. */ private fun ActionList.singleNavigationAction(): NaviAction = this .filterIsInstance>() diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/PrioritySteering.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/PrioritySteering.kt index 0fd4ed86f9..87cf202fe3 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/PrioritySteering.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/PrioritySteering.kt @@ -15,14 +15,12 @@ import it.unibo.alchemist.model.cognitive.steering.Nearest import it.unibo.alchemist.model.environments.Euclidean2DEnvironment /** - * Steering behavior using [Nearest] steering strategy (= the only action executed is the one with the nearest target). + * Steering behavior that executes only the steering action targeting the nearest destination. * - * @param environment - * the environment inside which the pedestrian moves. - * @param pedestrian - * the owner of this reaction. - * @param timeDistribution - * the time distribution according to this the reaction executes. + * @param T the concentration type. + * @param environment the environment in which the pedestrian moves. + * @property pedestrian the owner of this reaction. + * @param timeDistribution the time distribution governing reaction execution. */ class PrioritySteering( environment: Euclidean2DEnvironment, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/SteeringBehavior.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/SteeringBehavior.kt index 0fd2a19492..ac5024007a 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/SteeringBehavior.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/SteeringBehavior.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2023, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the @@ -22,29 +22,22 @@ import it.unibo.alchemist.model.positions.Euclidean2DPosition import it.unibo.alchemist.model.reactions.AbstractReaction /** - * Reaction representing the steering behavior of a pedestrian. + * Reaction representing a pedestrian's steering behavior. * - * @param environment - * the environment inside which the pedestrian moves. - * @param pedestrian - * the owner of this reaction. - * @param timeDistribution - * the time distribution according to which this reaction executes. - * @param steerStrategy - * the strategy used to combine steering actions. + * @param T the concentration type. + * @param timeDistribution the time distribution that schedules reaction execution. + * @property environment the Euclidean environment where the pedestrian moves. + * @property pedestrian the owner pedestrian's property. + * @property steerStrategy the strategy used to combine steering actions. */ open class SteeringBehavior( private val environment: Environment, - /** - * The pedestrian property of the owner of this reaction. - */ + /** The pedestrian property of the owner of this reaction. */ protected open val pedestrian: PedestrianProperty, timeDistribution: TimeDistribution, open val steerStrategy: SteeringStrategy, ) : AbstractReaction(pedestrian.node, timeDistribution) { - /** - * The list of steering actions in this reaction. - */ + /** The list of steering actions in this reaction. */ fun steerActions(): List> = actions.filterIsInstance>() diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/DistanceWeighted.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/DistanceWeighted.kt index 81e4629b1e..8242ef8f92 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/DistanceWeighted.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/DistanceWeighted.kt @@ -14,21 +14,18 @@ import it.unibo.alchemist.model.cognitive.SteeringActionWithTarget import it.unibo.alchemist.model.environments.Euclidean2DEnvironment /** - * [Weighted] strategy where the weight of each steering action is the inverse of the node's distance from the - * action's target (the closer the target, the more important the action). [defaultWeight] is used for actions without - * a target. + * Weighted steering strategy where each steering action's weight is the inverse + * of the node's distance to the action's target. Closer targets yield higher weight. + * Actions without a target receive [defaultWeight]. * - * @param environment - * the environment in which the node moves. - * @param node - * the owner of the steering action this strategy belongs to. + * @param T the concentration type. + * @param environment the environment in which the node moves. + * @param node the owner of the steering action this strategy belongs to. + * @param defaultWeight default weight for steering actions without a defined target. */ class DistanceWeighted( environment: Euclidean2DEnvironment, node: Node, - /** - * Default weight for steering actions without a defined target. - */ private val defaultWeight: Double = 1.0, ) : Weighted( environment, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/Filtered.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/Filtered.kt index e3f194a741..aae69604f1 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/Filtered.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/Filtered.kt @@ -15,21 +15,20 @@ import it.unibo.alchemist.model.cognitive.SteeringStrategy import it.unibo.alchemist.model.geometry.Vector /** - * [SteeringStrategy] decorator applying a [filter] to the list of steering actions (see [computeNextPosition]). + * Decorator for a [SteeringStrategy] that filters the provided steering actions before + * delegating the combination logic to the wrapped strategy. * - * @param steerStrategy - * computeNextPosition is delegated to this strategy. - * @param filter - * the filter to apply on the list of steering actions. + * @param T the concentration type. + * @param P the [Position] type used by the strategy. + * @param steerStrategy the underlying strategy to which the filtered actions are delegated. + * @param filter the filter function applied to the actions list before delegation. */ open class Filtered( private val steerStrategy: SteeringStrategy, private val filter: List>.() -> List>, ) : SteeringStrategy by steerStrategy where P : Position

, P : Vector

{ - /** - * Delegated to [steerStrategy] after [filter]ing the given [actions]. - */ + /** Delegates to [steerStrategy] after applying [filter] to [actions]. */ override fun computeNextPosition(actions: List>) = steerStrategy.computeNextPosition(actions.filter()) } diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/Nearest.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/Nearest.kt index 51d76eee35..a9393a6b64 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/Nearest.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/Nearest.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2023, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the @@ -18,13 +18,12 @@ import it.unibo.alchemist.model.environments.Euclidean2DEnvironment import it.unibo.alchemist.model.positions.Euclidean2DPosition /** - * [Filtered] strategy considering only the group steering action and the non-group steering action whose targets are - * nearest to the node's position. The two actions are combined using [DistanceWeighted] strategy. + * Strategy that considers the group steering action (if present) and the nearest + * non-group steering action, then combines them using a [DistanceWeighted] strategy. * - * @param environment - * the environment in which the node moves. - * @param node - * the owner of the steering action this strategy belongs to. + * @param T the concentration type. + * @param environment the environment in which the node moves. + * @param node the owner of the steering action this strategy belongs to. */ class Nearest(environment: Euclidean2DEnvironment, node: Node) : Filtered( @@ -40,8 +39,9 @@ class Nearest(environment: Euclidean2DEnvironment, node: Node) : ) { private companion object { /** - * Picks the [SteeringActionWithTarget] whose target is nearest to the [node]'s current position, or the first - * action of the list if none of them has a defined target. If the list is empty, null is returned. + * Picks the [SteeringActionWithTarget] whose target is nearest to the [node]'s current position, + * or the first action of the list if none of the actions has a defined target. + * Returns null for an empty list. */ private fun List>.pickNearestOrFirst( environment: Environment, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/SinglePrevalent.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/SinglePrevalent.kt index ae30f8ca24..b9381519c6 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/SinglePrevalent.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/SinglePrevalent.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2023, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the @@ -14,7 +14,6 @@ import it.unibo.alchemist.model.cognitive.NavigationAction import it.unibo.alchemist.model.cognitive.SteeringAction import it.unibo.alchemist.model.cognitive.SteeringStrategy import it.unibo.alchemist.model.cognitive.actions.NavigationAction2D -import it.unibo.alchemist.model.cognitive.steering.SinglePrevalent.ExponentialSmoothing import it.unibo.alchemist.model.environments.Euclidean2DEnvironmentWithGraph import it.unibo.alchemist.model.geometry.ConvexPolygon import it.unibo.alchemist.model.geometry.Vector @@ -23,27 +22,28 @@ import it.unibo.alchemist.model.positions.Euclidean2DPosition private typealias SteeringActions = List> /** - * A [SteeringStrategy] in which one action is prevalent. Only [NavigationAction]s can be prevalent, because - * they guarantee to navigate the environment consciously (e.g. without getting stuck in obstacles). The - * purpose of this strategy is to linearly combine the potentially contrasting forces to which the node - * is subject, while maintaining that warranty. Such forces are combined as follows: - * let f be the prevalent force, - * - if f leads the node outside the room (= environment's area) he/she is into, no combination is performed - * and f is used as it is. This because crossing doors can be a thorny issue, and we don't want to introduce - * disturbing forces. - * - Otherwise, a linear combination is performed: f is assigned unitary weight, all other forces are assigned - * weight w equal to the maximum value in [0,1] so that the resulting force: - * - forms with f an angle smaller than or equal to the specified [toleranceAngle], - * - doesn't lead the node outside the current room. - * The idea is to decrease the intensity of non-prevalent forces until the resulting one enters some tolerance - * sector defined by both the tolerance angle and the current room's boundary. With a suitable tolerance angle - * this allows to steer the node towards the target defined by the prevalent force, while using a trajectory - * which takes into account other urges as well. - * Finally, an exponential smoothing with the given [alpha] is applied to the resulting force in order to decrease - * oscillatory movements (this also known as shaking behavior). + * A [SteeringStrategy] in which one navigation action is prevalent and others are combined + * with a reduced weight so that the resulting force stays within a tolerance sector around + * the prevalent force while remaining inside the current room. * - * @param T concentration type - * @param N type of nodes of the environment's graph. + * The steps are: + * 1. Identify the prevalent navigation action (must be a [NavigationAction]). + * 2. If the prevalent action leads outside the current room, it is used unchanged. + * 3. Otherwise, linearly combine the prevalent force (weight 1) and the other forces + * (weight w ∈ [0,1]) and reduce w until the combined force is within the tolerance + * angle and keeps the node inside the room. + * 4. Apply exponential smoothing to reduce oscillations. + * + * @param T the concentration type. + * @param N the polygon type used by the environment's navigation graph. + * @param environment the environment with navigation graph. + * @param node the node owning the steering strategy. + * @param prevalent function selecting the prevalent [NavigationAction]. + * @param toleranceAngle tolerance angle in radians. + * @param alpha smoothing alpha for exponential smoothing. + * @param maxWalk function computing the maximum allowed walk distance. + * @param maxWalkRatio minimum magnitude ratio for the resulting force. + * @param delta decrement step used when searching for a suitable weight w. */ class SinglePrevalent( environment: Euclidean2DEnvironmentWithGraph<*, T, N, *>, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/TypeBased.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/TypeBased.kt index 43c146f086..fac01c0098 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/TypeBased.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/TypeBased.kt @@ -16,15 +16,14 @@ import it.unibo.alchemist.model.positions.Euclidean2DPosition import kotlin.reflect.KClass /** - * A [Weighted] steering strategy assigning weights based on actions' types (each type has its own weight, specified - * by the client). + * A [Weighted] steering strategy assigning weights based on actions' types; the client provides a weight + * for each action KClass. * - * @param environment - * the environment in which the node moves. - * @param node - * the owner of the steering actions combined by this strategy. - * @param typeWeights - * the weight for each type of steering action. + * @param T the concentration type. + * @param environment the environment in which the node moves. + * @param node the owner of the steering actions combined by this strategy. + * @param typeWeights the map of weights for each steering action KClass. + * @param defaultWeight fallback weight used when an action's type is not present in [typeWeights]. */ class TypeBased( environment: Euclidean2DEnvironment, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/Weighted.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/Weighted.kt index 65aee31226..e034754e86 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/Weighted.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/steering/Weighted.kt @@ -18,15 +18,25 @@ import it.unibo.alchemist.model.environments.Euclidean2DEnvironment import it.unibo.alchemist.model.positions.Euclidean2DPosition /** - * A [SteeringStrategy] performing a weighted sum of steering actions (see [computeNextPosition]). + * SteeringStrategy that computes the agent's next position as a weighted sum of steering actions. * - * @param environment - * the environment in which the node moves. - * @param node - * the owner of the steering actions combined by this strategy. - * @param weight - * lambda used to assign a weight to each steering action: the higher the weight, the greater the - * importance of the action. + * Actions are partitioned into group steering actions (instances of [GroupSteeringAction]) and + * non-group steering actions. For each partition the strategy computes a weighted average of + * the actions' next positions using the provided [weight] lambda; the two resulting vectors are + * then summed (with unitary weight) to obtain the final displacement. + * + * The [weight] parameter is an extension lambda on [SteeringAction] invoked as `action.weight()`. + * It must return a numeric weight (a non-negative [Double]) used to compute the weighted average. + * If the total weight of a partition is zero, the implementation falls back to the first action's + * next position; if there are no actions at all, the environment origin is returned. + * + * The strategy also computes a target position by selecting the closest target among + * [SteeringActionWithTarget] actions; if none are present, the current node position is returned. + * + * @param T the concentration type of the simulation. + * @param environment the environment in which the node moves. + * @param node the owner of the steering actions combined by this strategy. + * @param weight an extension lambda that assigns a numeric weight to each steering action. */ open class Weighted( private val environment: Euclidean2DEnvironment, diff --git a/alchemist-engine/src/main/kotlin/it/unibo/alchemist/core/Engine.kt b/alchemist-engine/src/main/kotlin/it/unibo/alchemist/core/Engine.kt index e5b4036b41..9a457de749 100644 --- a/alchemist-engine/src/main/kotlin/it/unibo/alchemist/core/Engine.kt +++ b/alchemist-engine/src/main/kotlin/it/unibo/alchemist/core/Engine.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2025, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the @@ -121,12 +121,6 @@ open class Engine>( } } - /** - * Executes an action while holding the status lock. - * - * @param action the action to execute - * @return the result of the action - */ private fun doOnStatus(action: () -> R): R = statusLock.run { lock() try { @@ -232,17 +226,15 @@ open class Engine>( */ protected open fun newStatus(next: Status): CompletableFuture { val future = CompletableFuture() - schedule( - CheckedRunnable { - doOnStatus { - if (next.isReachableFrom(status)) { - status = next - lockForStatus(next).releaseAll() - } - future.complete(null) + schedule { + doOnStatus { + if (next.isReachableFrom(status)) { + status = next + lockForStatus(next).releaseAll() } - }, - ) + future.complete(null) + } + } return future } @@ -543,18 +535,18 @@ open class Engine>( override val reactionsToUpdate: Sequence> = sequenceOf(sourceReaction) } - /** Handles the removal of a reaction. */ - private inner class ReactionRemoval(source: Actionable) : AbstractUpdateOnReaction(source) { + /** Handles the addition of a reaction. */ + private inner class ReactionAddition(source: Actionable) : AbstractUpdateOnReaction(source) { override fun performChanges() { - dependencyGraph.removeDependencies(sourceReaction) - scheduler.removeReaction(sourceReaction) + this@Engine.scheduleReaction(sourceReaction) } } - /** Handles the addition of a reaction. */ - private inner class ReactionAddition(source: Actionable) : AbstractUpdateOnReaction(source) { + /** Handles the removal of a reaction. */ + private inner class ReactionRemoval(source: Actionable) : AbstractUpdateOnReaction(source) { override fun performChanges() { - this@Engine.scheduleReaction(sourceReaction) + dependencyGraph.removeDependencies(sourceReaction) + scheduler.removeReaction(sourceReaction) } } diff --git a/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/actions/ConstantDistanceRandomWalk.kt b/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/actions/ConstantDistanceRandomWalk.kt index 51771c2158..859ec07b75 100644 --- a/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/actions/ConstantDistanceRandomWalk.kt +++ b/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/actions/ConstantDistanceRandomWalk.kt @@ -17,19 +17,19 @@ import org.apache.commons.math3.distribution.DiracDeltaDistribution import org.apache.commons.math3.random.RandomGenerator /** - * Moves for [distance] toward a uniformly random chosen direction at a constant [speed], - * then changes direction and walks another [distance], and so on. + * Walks a fixed [distance] in a uniformly random direction at the given [speed], + * then repeats the move by selecting a new random direction. * - * Automatically changes direction on impact with obstacles - * if the [environment] supports them. + * The walker automatically changes direction on impact with obstacles when the + * provided [environment] supports obstacle handling. * - * @param concentration type - * @param environment environment containing the node - * @param node the node to move - * @param reaction the reaction containing this action - * @param randomGenerator random number generator to use for the decisions - * @param distance the distance to travel before picking another one - * @param speed the speed + * @param T the concentration type. + * @param node the node to move. + * @param reaction the reaction that contains this action. + * @param environment the environment containing the node. + * @param randomGenerator the random generator used to pick directions. + * @param distance the distance to travel before choosing a new direction. + * @param speed the walking speed. */ class ConstantDistanceRandomWalk( node: Node, diff --git a/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/actions/EuclideanConfigurableMoveNode.kt b/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/actions/EuclideanConfigurableMoveNode.kt index 2d66030069..6e2573960e 100644 --- a/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/actions/EuclideanConfigurableMoveNode.kt +++ b/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/actions/EuclideanConfigurableMoveNode.kt @@ -21,16 +21,18 @@ import it.unibo.alchemist.model.movestrategies.TargetSelectionStrategy import it.unibo.alchemist.model.movestrategies.speed.GloballyConstantSpeed /** - * It's an [AbstractConfigurableMoveNode] in the Euclidean world, which provides a default [interpolatePositions] - * that is accurate with respect to the target given and the current maximum walking distance. + * An [AbstractConfigurableMoveNode] specialized for Euclidean spaces. * - * @param Concentration type - * @param

position type - * @param environment the [Environment] which is executing the simulation - * @param node the [Node] which is executing the current [Action] - * @param routingStrategy the [RoutingStrategy] selected for this [Action] - * @param targetSelectionStrategy the [TargetSelectionStrategy] selected for this [Action] - * @param speedSelectionStrategy the [SpeedSelectionStrategy] selected for this [Action] + * This class provides a default [interpolatePositions] implementation that + * moves the node toward a target without exceeding a provided maximum step length. + * + * @param T the concentration type. + * @param P the [Position] type used for spatial coordinates and vectors. + * @param environment the [Environment] executing the simulation. + * @param node the [Node] executing this [Action]. + * @param routingStrategy the [RoutingStrategy] selected for this action. + * @param targetSelectionStrategy the [TargetSelectionStrategy] selected for this action. + * @param speedSelectionStrategy the [SpeedSelectionStrategy] selected for this action. */ open class EuclideanConfigurableMoveNode( environment: Environment, @@ -46,13 +48,15 @@ open class EuclideanConfigurableMoveNode( speedSelectionStrategy, ) where P : Position

, P : Vector

{ /** - * @param environment the [Environment] which is executing the simulation - * @param node the [Node] which is executing the current [Action] - * @param reaction the reaction which is executing the current [Action] - * @param routingStrategy the [RoutingStrategy] selected for this [Action] - * @param targetSelectionStrategy the [TargetSelectionStrategy] selected for this [Action] - * @param speed the maximum speed set to a [GloballyConstantSpeed] instance - * @return an [AbstractConfigurableMoveNode] implementation using a [GloballyConstantSpeed] + * Secondary constructor that uses a [GloballyConstantSpeed]. + * + * @param environment the [Environment] executing the simulation. + * @param node the [Node] executing this [Action]. + * @param reaction the reaction executing this [Action]. + * @param routingStrategy the [RoutingStrategy] selected for this action. + * @param targetSelectionStrategy the [TargetSelectionStrategy] selected for this action. + * @param speed the maximum speed used to create a [GloballyConstantSpeed]. + * @return an [AbstractConfigurableMoveNode] implementation using [GloballyConstantSpeed]. */ constructor( environment: Environment, @@ -70,8 +74,13 @@ open class EuclideanConfigurableMoveNode( ) /** - * @returns the next relative position reached by the node. If [maxWalk] is greater than the distance to - * the [target], the node positions precisely on [target] without going farther. + * Computes the next position toward [target], constrained by [maxWalk]. + * + * @param current the current position. + * @param target the target position to reach. + * @param maxWalk the maximum distance that can be traveled in this step. + * @return the next relative position as a [P]. If [maxWalk] is greater than the distance + * to the [target], the returned position is exactly [target]. */ override fun interpolatePositions(current: P, target: P, maxWalk: Double): P = (target - current).coerceAtMost(maxWalk) diff --git a/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/actions/FollowAtDistance.kt b/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/actions/FollowAtDistance.kt index 56c9adc207..0045b339b4 100644 --- a/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/actions/FollowAtDistance.kt +++ b/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/actions/FollowAtDistance.kt @@ -22,16 +22,18 @@ import kotlin.math.min import kotlin.math.sin /** - * Makes the [Node] follow a [target] defined in a [Molecule] with some [speed], - * but keeping a [distance] from it. + * Causes a node to follow a destination read from a [Molecule], maintaining a fixed [distance] + * and respecting a maximum [speed]. * - * @param concentration type - * @param environment the environment containing the nodes - * @param node the follower - * @param reaction the reaction hosting this action - * @param target molecule from which to read the destination to follow in the form of coordinates or a tuple - * @param distance the distance to keep from the destination - * @param speed the maximum speed + * The destination is read from the specified [target] molecule and interpreted as coordinates or a tuple. + * + * @param T the concentration type. + * @param node the follower node. + * @param reaction the reaction hosting this action. + * @param environment the environment containing the nodes. + * @param target the molecule carrying the destination coordinates. + * @param distance the distance to keep from the destination. + * @param speed the maximum movement speed. */ class FollowAtDistance( node: Node, diff --git a/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/geometry/GeometricShapeFactory.kt b/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/geometry/GeometricShapeFactory.kt index e3cb2d5eeb..7dc1cdd0fe 100644 --- a/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/geometry/GeometricShapeFactory.kt +++ b/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/geometry/GeometricShapeFactory.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2023, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the @@ -13,34 +13,35 @@ import it.unibo.alchemist.model.geometry.shapes.AdimensionalShape import java.io.Serializable /** - * Generic factory for [Shape]. + * Generic factory for [Shape] instances. + * + * @param S the [Vector] type used by the shapes created by this factory. + * @param A the [Transformation] type supported by the shapes. */ interface GeometricShapeFactory, A : Transformation> : Serializable { /** - * A special shape which does not occupy space and does not intersect with any other, not even with itself. + * A special shape that occupies no space and does not intersect any other shape. */ fun adimensional(): AdimensionalShape /** - * Requires that the given shape is compatible with the ones provided by this factory, + * Requires that the given shape is compatible with those provided by this factory; * otherwise throws an exception. * - * @param shape the shape to check - * @return the same shape + * @param shape the shape to check. + * @return the same shape if compatible. */ fun requireCompatible(shape: Shape<*, *>): Shape - /** - * Factory methods for [Shape]. - */ + /** Factory methods for [Shape]. */ companion object { /** - * Retrieves a factory of [Shape] compatible with the given vector type. + * Retrieves a factory of [Shape] compatible with the given vector and transformation types. * - * @param The type of vector used - * @param The supported geometric transformations - * @param The interface of the factory requested - * @return the factory + * @param S The type of vector used. + * @param A The supported geometric transformations. + * @param F The factory interface requested. + * @return an instance of the requested factory interface [F]. */ inline fun getInstance(): F where S : Vector, @@ -49,14 +50,13 @@ interface GeometricShapeFactory, A : Transformation> : Serializ getInstance(F::class.java) /** - * Retrieves a factory of [Shape] compatible with the given space. - * (This method is meant for compatibility with java). + * Retrieves a factory of [Shape] compatible with the given space (Java-friendly overload). * - * @param The type of vector used - * @param The supported geometric transformations - * @param The interface of the factory requested - * @param type The interface of the factory requested - * @return the factory + * @param S The type of vector used. + * @param A The supported geometric transformations. + * @param F The factory interface requested. + * @param type the [Class] object representing the requested factory interface. + * @return an instance of the requested factory interface [F]. */ @JvmStatic @Suppress("UNCHECKED_CAST") diff --git a/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/geometry/navigationgraph/NaviGator.kt b/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/geometry/navigationgraph/NaviGator.kt index 317739737c..7558657f8f 100644 --- a/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/geometry/navigationgraph/NaviGator.kt +++ b/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/geometry/navigationgraph/NaviGator.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2023, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the @@ -166,15 +166,13 @@ object NaviGator { } val intersectedSeeds: () -> List = { seeds.filter { - /* - * A seed is considered intersected if it intersects with the polygon and, in particular, with the - * remaining portion of the advancing edge. Similarly for obstacles below. - */ + /* + * A seed is considered intersected if it intersects with the polygon and, in particular, with the + * remaining portion of the advancing edge. Similarly for obstacles below. + */ it != this && it.intersects(asAwtShape()) && - polygonToInterval(it).intersectsBoundsExcluded( - remaining, - ) + polygonToInterval(it).intersectsBoundsExcluded(remaining) } } val intersectedObstacles: () -> List = { @@ -190,38 +188,33 @@ object NaviGator { return emptyList() } } - val newRemaining = - remaining.subtractAll( - intersectedObstacles().map { shapeToInterval(it) }, - ) - val neighborToIntervals = - intersectedSeeds().map { neighbor -> - /* - * Maps each neighbor to a collection of intervals representing - * the portions of the advancing edge leading to that neighbor. - */ - neighbor to - newRemaining.mapNotNull { remaining -> - polygonToInterval(neighbor).intersect(remaining) - } + val newRemaining = remaining.subtractAll( + intersectedObstacles().map { shapeToInterval(it) }, + ) + val neighborToIntervals = intersectedSeeds().map { neighbor -> + /* + * Maps each neighbor to a collection of intervals representing + * the portions of the advancing edge leading to that neighbor. + */ + neighbor to newRemaining.mapNotNull { interval -> + polygonToInterval(neighbor).intersect(interval) } - val passages = - neighborToIntervals.flatMap { (neighbor, intervals) -> - /* - * Intervals should be mapped to actual segments, considering the - * coordinate we ignored so far of the oldEdge. - */ - intervals.map { - val passageShape = - when { - oldEdge.isHorizontal -> - createSegment(it.start, oldEdge.first.y, x2 = it.endInclusive) - else -> - createSegment(oldEdge.first.x, it.start, y2 = it.endInclusive) - } - Euclidean2DPassage(this, neighbor, passageShape) + } + val passages = neighborToIntervals.flatMap { (neighbor, intervals) -> + /* + * Intervals should be mapped to actual segments, considering the + * coordinate we ignored so far of the oldEdge. + */ + intervals.map { + val passageShape = when { + oldEdge.isHorizontal -> + createSegment(it.start, oldEdge.first.y, x2 = it.endInclusive) + else -> + createSegment(oldEdge.first.x, it.start, y2 = it.endInclusive) } + Euclidean2DPassage(this, neighbor, passageShape) } + } return passages + newRemaining .flatMap { diff --git a/alchemist-graphql/build.gradle.kts b/alchemist-graphql/build.gradle.kts index a5220908f0..aff7426795 100644 --- a/alchemist-graphql/build.gradle.kts +++ b/alchemist-graphql/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2025, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the @@ -11,6 +11,7 @@ import Libs.alchemist import Libs.incarnation import com.apollographql.apollo3.gradle.internal.ApolloGenerateSourcesTask import com.expediagroup.graphql.plugin.gradle.tasks.AbstractGenerateClientTask +import dev.detekt.gradle.Detekt import it.unibo.alchemist.build.allVerificationTasks plugins { @@ -126,3 +127,8 @@ publishing.publications { } } } + +// exclude files in build from Detekt +tasks.withType().configureEach { + exclude("**/boundary/graphql/client/**") +} diff --git a/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/client/DefaultGraphQLClient.kt b/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/client/DefaultGraphQLClient.kt index 6c780a3b61..9ba4e4422c 100644 --- a/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/client/DefaultGraphQLClient.kt +++ b/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/client/DefaultGraphQLClient.kt @@ -19,11 +19,11 @@ import com.apollographql.apollo3.network.ws.WebSocketNetworkTransport import it.unibo.alchemist.boundary.graphql.utils.DefaultGraphQLSettings /** - * Default GraphQL client implementation. + * Default GraphQL client implementation backed by Apollo. * - * @param host the host of the GraphQL server - * @param port the port of the GraphQL server - * @param enableSubscription whether to enable subscriptions or not + * @param host the GraphQL server host. + * @param port the GraphQL server port. + * @param enableSubscription whether to enable subscription support (WebSocket transport). */ data class DefaultGraphQLClient( override val host: String = DefaultGraphQLSettings.DEFAULT_HOST, diff --git a/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/client/GraphQLClient.kt b/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/client/GraphQLClient.kt index aed3ef80e9..c449ce8b31 100644 --- a/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/client/GraphQLClient.kt +++ b/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/client/GraphQLClient.kt @@ -15,55 +15,61 @@ import com.apollographql.apollo3.api.Query import com.apollographql.apollo3.api.Subscription /** - * The most basic GraphQL client, capable of executing queries, mutations and subscriptions. + * Basic GraphQL client capable of preparing queries, mutations, and subscriptions for execution. */ interface GraphQLClient { - /** - * The address of the GraphQL server. - */ + /** The address of the GraphQL server. */ val host: String - /** - * The port of the GraphQL server. - */ + /** The port of the GraphQL server. */ val port: Int /** - * The URL of the GraphQL server. + * Returns the HTTP URL of the GraphQL endpoint. + * + * @return the HTTP server URL where GraphQL requests should be sent. */ fun serverUrl(): String = "http://$host:$port/graphql" /** - * The URL of the GraphQL server subscription. + * Returns the URL to use for GraphQL subscriptions (often a WebSocket URL). + * + * @return the subscription URL as a [String]. */ fun subscriptionUrl(): String /** * Prepare a query to be executed. - * @param query the query to be executed - * @return the associated [ApolloCall] that can be executed + * + * @param D the query data type produced by the query. + * @param query the query to be executed. + * @return an [ApolloCall] that can be executed to perform the query. * @see ApolloCall */ fun query(query: Query): ApolloCall /** * Prepare a mutation to be executed. - * @param mutation the mutation to be executed - * @return the associated [ApolloCall] that can be executed + * + * @param D the mutation data type produced by the mutation. + * @param mutation the mutation to be executed. + * @return an [ApolloCall] that can be executed to perform the mutation. * @see ApolloCall */ fun mutation(mutation: Mutation): ApolloCall /** * Prepare a subscription to be executed. - * @param subscription the subscription to be executed - * @return the associated [ApolloCall] that can be executed + * + * @param D the subscription data type produced by the subscription. + * @param subscription the subscription to be executed. + * @return an [ApolloCall] that can be executed to perform the subscription. * @see ApolloCall */ fun subscription(subscription: Subscription): ApolloCall /** - * Closes the client. + * Closes any resources held by the client. */ fun close() } diff --git a/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/client/GraphQLClientFactory.kt b/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/client/GraphQLClientFactory.kt index 2f1c5e3fc7..9c23c59b6a 100644 --- a/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/client/GraphQLClientFactory.kt +++ b/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/client/GraphQLClientFactory.kt @@ -12,15 +12,16 @@ package it.unibo.alchemist.boundary.graphql.client import it.unibo.alchemist.boundary.graphql.utils.DefaultGraphQLSettings /** - * Factory for [GraphQLClient]s. + * Factory for creating [GraphQLClient] instances. */ object GraphQLClientFactory { /** * Returns a lightweight [GraphQLClient] capable of executing queries and mutations. - * Note: this client is not capable of executing subscriptions. + * This client does not support subscriptions. * - * @param host the host of the GraphQL server - * @param port the port of the GraphQL server + * @param host the GraphQL server host. + * @param port the GraphQL server port. + * @return a [GraphQLClient] instance configured without subscription support. */ fun basicClient( host: String = DefaultGraphQLSettings.DEFAULT_HOST, @@ -30,8 +31,9 @@ object GraphQLClientFactory { /** * Returns a [GraphQLClient] capable of executing queries, mutations and subscriptions. * - * @param host the host of the GraphQL server - * @param port the port of the GraphQL server + * @param host the GraphQL server host. + * @param port the GraphQL server port. + * @return a [GraphQLClient] instance configured with subscription support. */ fun subscriptionClient( host: String = DefaultGraphQLSettings.DEFAULT_HOST, diff --git a/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/client/SimulationHandler.kt b/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/client/SimulationHandler.kt index 489bc2875a..ce221f0414 100644 --- a/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/client/SimulationHandler.kt +++ b/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/client/SimulationHandler.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2023, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the @@ -12,27 +12,26 @@ package it.unibo.alchemist.boundary.graphql.client import com.apollographql.apollo3.api.Mutation /** - * Utility class to handle simulation lifecycle through GraphQL queries. + * Utility to control simulation lifecycle through GraphQL operations. * - * @param graphqlClient the GraphQL client connected to the server + * @param graphqlClient the GraphQL client connected to the server. */ class SimulationHandler(private val graphqlClient: GraphQLClient) { - /** - * Pauses the simulation. - */ + /** Pauses the simulation and returns the mutation data. */ suspend fun pause() = handleSimulation( PauseSimulationMutation(), ) as PauseSimulationMutation.Data - /** - * Terminates the simulation. - */ + /** Terminates the simulation and returns the mutation data. */ suspend fun terminate() = handleSimulation( TerminateSimulationMutation(), ) as TerminateSimulationMutation.Data /** - * Plays the simulation. + * Starts or resumes the simulation and returns the mutation data. The method checks that the + * returned status is "RUNNING" and throws an exception otherwise. + * + * @return the [PlaySimulationMutation.Data] containing the simulation status. */ suspend fun play(): PlaySimulationMutation.Data { val status = @@ -45,7 +44,9 @@ class SimulationHandler(private val graphqlClient: GraphQLClient) { } /** - * Returns the status of the simulation. + * Returns the current simulation status string (if available) or null. + * + * @return the simulation status string or null if unavailable. */ suspend fun status() = graphqlClient .query(SimulationStatusQuery()) @@ -54,5 +55,7 @@ class SimulationHandler(private val graphqlClient: GraphQLClient) { ?.simulation ?.status - private suspend fun handleSimulation(action: Mutation<*>) = graphqlClient.mutation(action).execute().data!! + private suspend fun handleSimulation(action: Mutation<*>) = checkNotNull( + graphqlClient.mutation(action).execute().data, + ) } diff --git a/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/utils/DefaultGraphQLSettings.kt b/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/utils/DefaultGraphQLSettings.kt index 8628edd0a5..0304aea554 100644 --- a/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/utils/DefaultGraphQLSettings.kt +++ b/alchemist-graphql/src/commonMain/kotlin/it/unibo/alchemist/boundary/graphql/utils/DefaultGraphQLSettings.kt @@ -10,16 +10,12 @@ package it.unibo.alchemist.boundary.graphql.utils /** - * Default settings for GraphQL environment. + * Default settings for the GraphQL environment. */ object DefaultGraphQLSettings { - /** - * Default host for the GraphQL server. - */ + /** Default host for the GraphQL server. */ const val DEFAULT_HOST = "127.0.0.1" - /** - * Default port for the GraphQL server. - */ + /** Default port for the GraphQL server. */ const val DEFAULT_PORT = 8081 } diff --git a/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestEnvironmentsDiameterWithHopDistance.kt b/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestEnvironmentsDiameterWithHopDistance.kt index b6ea6b8028..3a83ef66b5 100644 --- a/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestEnvironmentsDiameterWithHopDistance.kt +++ b/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestEnvironmentsDiameterWithHopDistance.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2025, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the @@ -24,7 +24,7 @@ object TestEnvironmentsDiameterWithHopDistance { private fun Environment.specificNodeInASegmentedNetworkShouldHaveHopDiameter( index: Int, expected: Double, - ) = { + ) { require(index < nodes.size) assertEquals(expected, allSubNetworksByNodeWithHopDistance()[nodes[index]]?.diameter!!) } diff --git a/build.gradle.kts b/build.gradle.kts index d0f8814d0e..e5e1cb9871 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2025, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the From 9487f2f1e7e4c389c8ff716dba342acb358169fb Mon Sep 17 00:00:00 2001 From: Danilo Pianini Date: Fri, 13 Feb 2026 17:03:07 +0100 Subject: [PATCH 3/8] refactor: enhance documentation and exclude additional files from Detekt --- .../actions/AbstractGroupSteeringAction.kt | 2 +- .../cognitive/actions/AbstractLayerAction.kt | 2 +- .../actions/AbstractNavigationAction.kt | 6 ++-- .../actions/AbstractSteeringAction.kt | 2 +- .../AbstractSteeringActionWithTarget.kt | 2 +- .../cognitive/actions/CognitiveAgentArrive.kt | 2 +- .../actions/CognitiveAgentAvoidLayer.kt | 2 +- .../actions/CognitiveAgentCohesion.kt | 2 +- .../actions/CognitiveAgentCombineSteering.kt | 2 +- .../actions/CognitiveAgentExplore.kt | 2 +- .../cognitive/actions/CognitiveAgentFlee.kt | 2 +- .../actions/CognitiveAgentFollowLayer.kt | 2 +- .../actions/CognitiveAgentFollowRoute.kt | 2 +- .../CognitiveAgentFollowScalarField.kt | 2 +- .../CognitiveAgentGoalOrientedExplore.kt | 12 ++++--- .../CognitiveAgentNavigationAction2D.kt | 16 +++++++--- .../CognitiveAgentObstacleAvoidance.kt | 16 ++++------ .../cognitive/actions/CognitiveAgentPursue.kt | 16 +++++----- .../actions/CognitiveAgentReachDestination.kt | 19 +++++++---- .../CognitiveAgentReachKnownDestination.kt | 16 +++++----- .../cognitive/actions/CognitiveAgentSeek.kt | 2 +- .../cognitive/actions/CognitiveAgentSeek2D.kt | 2 +- .../actions/CognitiveAgentSeparation.kt | 4 +-- .../cognitive/actions/CognitiveAgentWander.kt | 4 +-- .../cognitive/reactions/BlendedSteering.kt | 4 +-- .../NavigationPrioritizedSteering.kt | 2 +- ...avigationPrioritizedSteeringWithPhysics.kt | 2 +- .../reactions/PhysicalBlendedSteering.kt | 2 +- .../cognitive/reactions/PrioritySteering.kt | 2 +- .../cognitive/reactions/SteeringBehavior.kt | 13 ++++---- alchemist-composeui/build.gradle.kts | 7 ++++ .../kotlin/it/unibo/alchemist/core/Engine.kt | 8 ++--- .../geometry/navigationgraph/NaviGator.kt | 4 +-- .../surrogates/ConcentrationSurrogate.kt | 7 ++-- .../model/surrogates/GraphQLSurrogate.kt | 2 ++ .../schema/model/surrogates/LayerSurrogate.kt | 2 +- .../model/surrogates/MoleculeSurrogate.kt | 5 +-- .../schema/model/surrogates/NodeSurrogate.kt | 3 +- .../model/surrogates/Position2DSurrogate.kt | 6 ++-- .../model/surrogates/PositionSurrogate.kt | 4 +-- .../model/surrogates/ReactionSurrogate.kt | 6 +++- .../model/surrogates/SimulationSurrogate.kt | 1 + alchemist-graphql/build.gradle.kts | 1 + .../model/actions/ToggleMoleculeRandomly.kt | 6 ++-- .../layers/BidimensionalGaussianLayer.kt | 9 ++++-- .../linkingrules/ConnectToAccessPoint.kt | 8 ++++- .../linkingrules/ConnectViaAccessPoint.kt | 7 +++- .../movestrategies/speed/ConstantSpeed.kt | 7 ++-- .../movestrategies/target/FollowTarget.kt | 13 ++++---- .../model/neighborhoods/Neighborhoods.kt | 11 ++++--- .../alchemist/model/routes/PolygonalChain.kt | 4 +-- .../alchemist/model/terminators/AfterTime.kt | 6 +++- .../model/terminators/StableForSteps.kt | 8 ++--- .../alchemist/model/terminators/StepCount.kt | 4 ++- .../kotlin/it/unibo/alchemist/util/Anys.kt | 12 +++---- .../it/unibo/alchemist/util/Iterables.kt | 7 ++-- .../it/unibo/alchemist/util/math/Math.kt | 13 +++++--- .../distribution/DiracDeltaDistribution.kt | 8 ----- .../protelis/AlchemistExecutionContext.kt | 26 +++++++++------ .../model/protelis/ProtelisIncarnation.kt | 6 +++- .../protelis/actions/RunProtelisProgram.kt | 8 ++++- .../model/protelis/actions/SendToNeighbor.kt | 10 +++--- .../protelis/properties/ProtelisDevice.kt | 10 +++--- .../it/unibo/alchemist/boundary/Extractor.kt | 6 ++-- .../it/unibo/alchemist/boundary/Loader.kt | 32 ++++++------------- .../boundary/exporters/AbstractExporter.kt | 8 ++++- .../boundary/exporters/CSVExporter.kt | 19 ++++++----- .../boundary/exporters/GlobalExporter.kt | 9 ++++-- .../boundary/exporters/MongoDBExporter.kt | 11 ++++--- .../AbstractAggregatingDoubleExporter.kt | 2 +- .../boundary/extractors/MoleculeReader.kt | 15 +++++---- .../boundary/loader/SimulationModel.kt | 7 ++-- .../boundary/variables/JSR223Variable.kt | 7 ++-- .../deployments/AbstractRandomDeployment.kt | 13 ++++---- .../alchemist/model/deployments/Polygon.kt | 4 ++- .../alchemist/model/positionfilters/And.kt | 6 ++-- .../alchemist/model/positionfilters/Not.kt | 4 ++- .../alchemist/model/positionfilters/Or.kt | 8 ++--- .../alchemist/model/positionfilters/Xor.kt | 8 ++--- .../maps/movestrategies/target/FollowTrace.kt | 3 +- .../alchemist/model/physics/FieldOfView2D.kt | 10 +++--- .../model/physics/InfluenceSphere2D.kt | 10 +++--- .../AbstractLimitedContinuous2D.kt | 1 + .../environments/Continuous2DObstacles.kt | 5 ++- .../boundary/swingui/monitor/impl/SwingGUI.kt | 26 ++++++++++----- .../alchemist/test/EuclideanSimulation.kt | 23 +++++++------ alchemist-web-renderer/build.gradle.kts | 7 ++++ .../server/modules/StartBrowserModule.kt | 4 +-- gradle/libs.versions.toml | 2 +- 89 files changed, 374 insertions(+), 279 deletions(-) diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractGroupSteeringAction.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractGroupSteeringAction.kt index b6f7081226..cac7032c34 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractGroupSteeringAction.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractGroupSteeringAction.kt @@ -23,7 +23,7 @@ import it.unibo.alchemist.model.geometry.Vector abstract class AbstractGroupSteeringAction( environment: Environment, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, ) : AbstractSteeringAction(environment, reaction, pedestrian), GroupSteeringAction where P : Position

, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractLayerAction.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractLayerAction.kt index 9851efa0c4..e754fe1bb2 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractLayerAction.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractLayerAction.kt @@ -35,7 +35,7 @@ import it.unibo.alchemist.model.positions.Euclidean2DPosition abstract class AbstractLayerAction( protected val environment: Euclidean2DEnvironment, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, protected val targetMolecule: Molecule, ) : AbstractSteeringAction(environment, reaction, pedestrian) { abstract override fun cloneAction(node: Node, reaction: Reaction): AbstractLayerAction diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractNavigationAction.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractNavigationAction.kt index 14cb92646b..ebeaaccdbf 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractNavigationAction.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractNavigationAction.kt @@ -43,15 +43,15 @@ import it.unibo.alchemist.model.physics.properties.OccupiesSpaceProperty */ abstract class AbstractNavigationAction( override val environment: EnvironmentWithGraph<*, T, P, A, N, E>, - override val reaction: Reaction, - override val pedestrian: PedestrianProperty, + reaction: Reaction, + pedestrian: PedestrianProperty, ) : AbstractSteeringAction(environment, reaction, pedestrian), NavigationAction where P : Position

, P : Vector

, A : Transformation

, L : ConvexShape, N : ConvexShape { - override val navigatingNode = node + final override val navigatingNode = node /** * The strategy used to navigate the environment. diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractSteeringAction.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractSteeringAction.kt index 4fb40c2a63..855c6832e1 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractSteeringAction.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractSteeringAction.kt @@ -33,7 +33,7 @@ abstract class AbstractSteeringAction( /** * The pedestrian property of the owner of this action. */ - protected open val pedestrian: PedestrianProperty, + protected val pedestrian: PedestrianProperty, ) : AbstractMoveNode(environment, pedestrian.node), SteeringAction where P : Position

, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractSteeringActionWithTarget.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractSteeringActionWithTarget.kt index 73ee43074a..496a72f93d 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractSteeringActionWithTarget.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/AbstractSteeringActionWithTarget.kt @@ -31,7 +31,7 @@ import it.unibo.alchemist.model.movestrategies.TargetSelectionStrategy abstract class AbstractSteeringActionWithTarget( environment: Environment, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, private val targetSelectionStrategy: TargetSelectionStrategy, ) : AbstractSteeringAction(environment, reaction, pedestrian), SteeringActionWithTarget diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentArrive.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentArrive.kt index f0334ad62e..97060f8272 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentArrive.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentArrive.kt @@ -39,7 +39,7 @@ import it.unibo.alchemist.model.geometry.Vector open class CognitiveAgentArrive( environment: Environment, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, protected val decelerationRadius: Double, protected val arrivalTolerance: Double, protected val target: P, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentAvoidLayer.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentAvoidLayer.kt index 8ca7120fd8..b708f4a89c 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentAvoidLayer.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentAvoidLayer.kt @@ -38,7 +38,7 @@ class CognitiveAgentAvoidLayer constructor( environment: Euclidean2DEnvironment, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, targetMolecule: Molecule, private val viewDepth: Double = Double.POSITIVE_INFINITY, ) : AbstractLayerAction(environment, reaction, pedestrian, targetMolecule) { diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentCohesion.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentCohesion.kt index 631c601cae..396ac75205 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentCohesion.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentCohesion.kt @@ -32,7 +32,7 @@ import it.unibo.alchemist.model.geometry.Vector class CognitiveAgentCohesion( environment: Environment, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, ) : AbstractGroupSteeringAction(environment, reaction, pedestrian) where P : Position

, P : Vector

, A : Transformation

{ diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentCombineSteering.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentCombineSteering.kt index 7b06a00235..bc86d074a9 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentCombineSteering.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentCombineSteering.kt @@ -35,7 +35,7 @@ import it.unibo.alchemist.model.geometry.Vector class CognitiveAgentCombineSteering( environment: Environment, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, private val actions: List>, private val steerStrategy: SteeringStrategy, ) : AbstractSteeringAction(environment, reaction, pedestrian) diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentExplore.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentExplore.kt index 6485cc11c8..863c31528b 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentExplore.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentExplore.kt @@ -27,7 +27,7 @@ import it.unibo.alchemist.model.geometry.navigationgraph.Euclidean2DPassage class CognitiveAgentExplore( environment: Euclidean2DEnvironmentWithGraph<*, T, ConvexPolygon, Euclidean2DPassage>, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, ) : CognitiveAgentNavigationAction2D(environment, reaction, pedestrian) { init { strategy = Explore(this) diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFlee.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFlee.kt index 288a7e945b..226f6d77b9 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFlee.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFlee.kt @@ -28,7 +28,7 @@ import it.unibo.alchemist.model.geometry.Vector open class CognitiveAgentFlee( environment: Environment, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, vararg coords: Double, ) : AbstractSteeringAction(environment, reaction, pedestrian) where P : Position

, P : Vector

, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFollowLayer.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFollowLayer.kt index fc7181c86e..8684ae26ca 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFollowLayer.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFollowLayer.kt @@ -27,7 +27,7 @@ import it.unibo.alchemist.model.positions.Euclidean2DPosition open class CognitiveAgentFollowLayer( euclidean: Euclidean2DEnvironment, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, targetMolecule: Molecule, ) : AbstractLayerAction(euclidean, reaction, pedestrian, targetMolecule) { private val followScalarField = diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFollowRoute.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFollowRoute.kt index 833fe8cbe0..0e07f2aeb9 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFollowRoute.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFollowRoute.kt @@ -28,7 +28,7 @@ import it.unibo.alchemist.util.Arrays.toPositions class CognitiveAgentFollowRoute( environment: Euclidean2DEnvironmentWithGraph<*, T, ConvexPolygon, Euclidean2DPassage>, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, vararg route: Number, ) : CognitiveAgentNavigationAction2D(environment, reaction, pedestrian) { init { diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFollowScalarField.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFollowScalarField.kt index 1ec60b0736..92e7b862fc 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFollowScalarField.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentFollowScalarField.kt @@ -25,7 +25,7 @@ import it.unibo.alchemist.model.physics.PhysicsEnvironment class CognitiveAgentFollowScalarField( environment: Environment, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, /** * The position of either maximum or minimum value of the scalar field, can be null if such a position doesn't * exist or isn't known. Its use is explained in [nextPosition]. diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentGoalOrientedExplore.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentGoalOrientedExplore.kt index a5d8858f7e..228c5bfd80 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentGoalOrientedExplore.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentGoalOrientedExplore.kt @@ -21,14 +21,18 @@ import it.unibo.alchemist.util.Arrays.toPositions /** * A [CognitiveAgentNavigationAction2D] using [GoalOrientedExploration] navigation strategy. * - * @param T the concentration type. - * @param L the type of landmarks of the node's cognitive map. - * @param R the type of edges of the node's cognitive map, representing the [R]elations between landmarks. + * @param T the concentration type + * @param L the landmark shape type used by the node's cognitive map + * @param R the relation/edge type used by the node's cognitive map + * @param environment the environment hosting the node + * @param reaction the reaction that executes this action + * @param pedestrian the owner pedestrian property + * @param unknownDestinations vararg coordinates representing unknown destinations */ class CognitiveAgentGoalOrientedExplore( environment: Euclidean2DEnvironmentWithGraph<*, T, ConvexPolygon, Euclidean2DPassage>, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, vararg unknownDestinations: Number, ) : CognitiveAgentNavigationAction2D(environment, reaction, pedestrian) { init { diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentNavigationAction2D.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentNavigationAction2D.kt index f09be19a72..86d1c394ca 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentNavigationAction2D.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentNavigationAction2D.kt @@ -11,6 +11,7 @@ package it.unibo.alchemist.model.cognitive.actions import it.unibo.alchemist.model.Node import it.unibo.alchemist.model.Reaction +import it.unibo.alchemist.model.cognitive.NavigationAction import it.unibo.alchemist.model.cognitive.PedestrianProperty import it.unibo.alchemist.model.environments.Euclidean2DEnvironmentWithGraph import it.unibo.alchemist.model.geometry.ConvexPolygon @@ -27,14 +28,19 @@ private typealias AbstractNavigationAction2D = * Implementation of a [NavigationAction2D]. This action accepts an [Euclidean2DEnvironmentWithGraph] whose graph * contains [ConvexPolygon]al nodes and [Euclidean2DPassage]s as edges. * - * @param T the concentration type. - * @param L the type of landmarks of the node's cognitive map. - * @param R the type of edges of the node's cognitive map, representing the [R]elations between landmarks. + * @param T the concentration type + * @param L the type of landmarks in the node's cognitive map + * @param R the type of edges in the node's cognitive map representing relations + * @property environment the Euclidean environment with navigation graph + * @param reaction the reaction executing this action + * @param pedestrian the owner pedestrian property + * @param wallRepulsionFactor factor used to push nodes away from passage walls + * @property DEFAULT_WALL_REPULSION_FACTOR default value for the wall repulsion factor */ open class CognitiveAgentNavigationAction2D( - override val environment: Euclidean2DEnvironmentWithGraph<*, T, ConvexPolygon, Euclidean2DPassage>, + final override val environment: Euclidean2DEnvironmentWithGraph<*, T, ConvexPolygon, Euclidean2DPassage>, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, /** * When crossing [Euclidean2DPassage]s, the node is pushed away from the wall of * a quantity equal to (this factor * the width of the passage). This is performed to prevent diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentObstacleAvoidance.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentObstacleAvoidance.kt index a4c7df4040..5957707038 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentObstacleAvoidance.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentObstacleAvoidance.kt @@ -21,19 +21,17 @@ import kotlin.reflect.jvm.jvmName /** * Move the agent avoiding potential obstacles in its path. * - * @param environment - * the environment inside which the node moves. - * @param reaction - * the reaction which executes this action. - * @param pedestrian - * the owner of this action. - * @param proximityRange - * the distance at which an obstacle is perceived by the node. + * @param W the obstacle type (2D) + * @param T the concentration type + * @property environment the 2D environment with obstacles + * @property reaction the steering behavior reaction executing this action + * @param pedestrian the owner pedestrian property + * @property proximityRange the distance at which an obstacle is perceived by the node */ class CognitiveAgentObstacleAvoidance, T>( private val environment: Environment2DWithObstacles, override val reaction: SteeringBehavior, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, private val proximityRange: Double, ) : AbstractSteeringAction(environment, reaction, pedestrian) { override fun cloneAction(node: Node, reaction: Reaction): CognitiveAgentObstacleAvoidance { diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentPursue.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentPursue.kt index c25b04e4d4..7bdad2e9a4 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentPursue.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentPursue.kt @@ -20,18 +20,18 @@ import it.unibo.alchemist.model.geometry.navigationgraph.Euclidean2DPassage /** * A cognitive navigation action that pursues a static destination using the [Pursue] strategy. * - * @param T the concentration type. - * @param L the landmark shape type used by the node's cognitive map. - * @param R the relation/edge type used by the node's cognitive map. - * @param environment the environment hosting the node. - * @param reaction the reaction executing this action. - * @param pedestrian the owner pedestrian property. - * @param destination coordinates (vararg) describing the destination position. + * @param T the concentration type + * @param L the landmark shape type used by the node's cognitive map + * @param R the relation/edge type used by the node's cognitive map + * @param environment the environment hosting the node + * @param reaction the reaction executing this action + * @param pedestrian the owner pedestrian property + * @param destination vararg coordinates describing the destination position */ class CognitiveAgentPursue( environment: Euclidean2DEnvironmentWithGraph<*, T, ConvexPolygon, Euclidean2DPassage>, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, vararg destination: Number, ) : CognitiveAgentNavigationAction2D(environment, reaction, pedestrian) { init { diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentReachDestination.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentReachDestination.kt index f1c0aedf8d..7315de1c48 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentReachDestination.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentReachDestination.kt @@ -29,21 +29,26 @@ import org.jgrapht.Graphs * Accepts an array of coordinates representing the destinations and uses [inferIsKnown] to partition them into * known and unknown ones. * - * @param T the concentration type. - * @param L the type of landmarks of the node's cognitive map. - * @param R the type of edges of the node's cognitive map, representing the [R]elations between landmarks. + * @param T the concentration type + * @param L the type of landmarks of the node's cognitive map + * @param R the type of edges of the node's cognitive map, representing relations + * @param environment the environment hosting the node + * @param reaction the reaction executing this action + * @param pedestrian the owner pedestrian property + * @param destinations vararg coordinates representing destinations */ class CognitiveAgentReachDestination( environment: Euclidean2DEnvironmentWithGraph<*, T, ConvexPolygon, Euclidean2DPassage>, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, vararg destinations: Number, ) : CognitiveAgentNavigationAction2D(environment, reaction, pedestrian) { /** - * Infers if a [destination] is known by the [navigatingNode] - * (see [it.unibo.alchemist.model.cognitive.navigation.Pursue]). A destination is considered - * to be known if the node's cognitive map contains at least one landmark located in the same + * Infers if a [destination] is known by the [navigatingNode]. A destination is considered + * known if the node's cognitive map contains at least one landmark located in the same * room (= [environment]'s area) of the destination, or in an adjacent room. + * + * @param destination the position to check */ private fun inferIsKnown(destination: Euclidean2DPosition): Boolean = environment.graph.nodeContaining(destination)?.let { room -> diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentReachKnownDestination.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentReachKnownDestination.kt index 0317e10e2e..c16b813f81 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentReachKnownDestination.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentReachKnownDestination.kt @@ -23,18 +23,18 @@ import it.unibo.alchemist.util.lazyMutable /** * A cognitive navigation action that pursues known destinations using [ReachKnownDestination] strategy. * - * @param T the concentration type. - * @param L the landmark shape type used by the node's cognitive map. - * @param R the relation/edge type used by the node's cognitive map. - * @param environment the environment hosting the node. - * @param reaction the reaction executing this action. - * @param pedestrian the owner pedestrian property. - * @param destinations vararg coordinates representing known destinations. + * @param T the concentration type + * @param L the landmark shape type used by the node's cognitive map + * @param R the relation/edge type used by the node's cognitive map + * @param environment the environment hosting the node + * @param reaction the reaction executing this action + * @param pedestrian the owner pedestrian property + * @param destinations vararg coordinates representing known destinations */ class CognitiveAgentReachKnownDestination( environment: Euclidean2DEnvironmentWithGraph<*, T, ConvexPolygon, Euclidean2DPassage>, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, vararg destinations: Number, ) : CognitiveAgentNavigationAction2D(environment, reaction, pedestrian) { override var strategy: NavigationStrategy2D by lazyMutable { diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeek.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeek.kt index e4322b7652..61b4596c9c 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeek.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeek.kt @@ -31,7 +31,7 @@ import it.unibo.alchemist.model.geometry.Vector open class CognitiveAgentSeek( environment: Environment, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, target: P, ) : CognitiveAgentArrive(environment, reaction, pedestrian, 0.0, 0.0, target) where P : Position

, P : Vector

, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeek2D.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeek2D.kt index 3df6caab73..9e5b410f8c 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeek2D.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeek2D.kt @@ -29,7 +29,7 @@ open class CognitiveAgentSeek2D( */ protected val environment: EuclideanEnvironment, reaction: Reaction, - final override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, /** * The position the node wants to reach. */ diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeparation.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeparation.kt index 3c8e9985dd..bc982e593b 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeparation.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentSeparation.kt @@ -24,12 +24,12 @@ import it.unibo.alchemist.model.positions.Euclidean2DPosition * @param T the concentration type. * @property environment the physics environment in which the node moves. * @param reaction the reaction executing this action. - * @property pedestrian the owner pedestrian property. + * @param pedestrian the owner pedestrian property. */ class CognitiveAgentSeparation( val environment: Physics2DEnvironment, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, ) : AbstractGroupSteeringAction(environment, reaction, pedestrian) { override fun cloneAction(node: Node, reaction: Reaction): CognitiveAgentSeparation = CognitiveAgentSeparation(environment, reaction, node.pedestrianProperty) diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentWander.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentWander.kt index a46a032ead..da2507e96d 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentWander.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/actions/CognitiveAgentWander.kt @@ -34,7 +34,7 @@ import org.apache.commons.math3.random.RandomGenerator * @param T the concentration type. * @param reaction the reaction executing this action. * @property environment the physics environment in which the node moves. - * @property pedestrian the owner of this action. + * @param pedestrian the owner of this action. * @property randomGenerator the random number generator used to select directions. * @property offset the distance from the node position to the center of the circle. * @property radius the radius of the circle from which target points are sampled. @@ -42,7 +42,7 @@ import org.apache.commons.math3.random.RandomGenerator open class CognitiveAgentWander( private val environment: Physics2DEnvironment, reaction: Reaction, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, protected val randomGenerator: RandomGenerator, protected val offset: Double, protected val radius: Double, diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/BlendedSteering.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/BlendedSteering.kt index db14ac72f7..799254b0a0 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/BlendedSteering.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/BlendedSteering.kt @@ -19,11 +19,11 @@ import it.unibo.alchemist.model.environments.Euclidean2DEnvironment * * @param T the concentration type. * @param environment the environment in which the pedestrian moves. - * @property pedestrian the owner of this reaction. + * @param pedestrian the owner of this reaction. * @param timeDistribution the time distribution governing reaction execution. */ open class BlendedSteering( environment: Euclidean2DEnvironment, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, timeDistribution: TimeDistribution, ) : SteeringBehavior(environment, pedestrian, timeDistribution, DistanceWeighted(environment, pedestrian.node)) diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/NavigationPrioritizedSteering.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/NavigationPrioritizedSteering.kt index 4b066cf57c..809114ab77 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/NavigationPrioritizedSteering.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/NavigationPrioritizedSteering.kt @@ -34,7 +34,7 @@ open class NavigationPrioritizedSteering @JvmOverloads constructor( environment: Euclidean2DEnvironmentWithGraph<*, T, N, *>, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, timeDistribution: TimeDistribution, /** Tolerance angle in degrees (see [SinglePrevalent]). */ toleranceAngle: Double = Math.toDegrees(SinglePrevalent.DEFAULT_TOLERANCE_ANGLE), diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/NavigationPrioritizedSteeringWithPhysics.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/NavigationPrioritizedSteeringWithPhysics.kt index a76ce31bc7..7cba9b9b89 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/NavigationPrioritizedSteeringWithPhysics.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/NavigationPrioritizedSteeringWithPhysics.kt @@ -26,7 +26,7 @@ class NavigationPrioritizedSteeringWithPhysics @JvmOverloads constructor( environment: EuclideanPhysics2DEnvironmentWithGraph<*, T, N, *>, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, timeDistribution: TimeDistribution, /** * Tolerance angle in degrees (see [SinglePrevalent]). diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/PhysicalBlendedSteering.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/PhysicalBlendedSteering.kt index faa729f646..bc5ab66034 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/PhysicalBlendedSteering.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/PhysicalBlendedSteering.kt @@ -27,7 +27,7 @@ class PhysicalBlendedSteering( * The environment in which the node is moving. */ val environment: Dynamics2DEnvironment, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, timeDistribution: TimeDistribution, ) : BlendedSteering(environment, pedestrian, timeDistribution) { private var previouslyAppliedForce = Euclidean2DPosition.zero diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/PrioritySteering.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/PrioritySteering.kt index 87cf202fe3..94d55b55da 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/PrioritySteering.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/PrioritySteering.kt @@ -24,6 +24,6 @@ import it.unibo.alchemist.model.environments.Euclidean2DEnvironment */ class PrioritySteering( environment: Euclidean2DEnvironment, - override val pedestrian: PedestrianProperty, + pedestrian: PedestrianProperty, timeDistribution: TimeDistribution, ) : SteeringBehavior(environment, pedestrian, timeDistribution, Nearest(environment, pedestrian.node)) diff --git a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/SteeringBehavior.kt b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/SteeringBehavior.kt index ac5024007a..4f8d20b70f 100644 --- a/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/SteeringBehavior.kt +++ b/alchemist-cognitive-agents/src/main/kotlin/it/unibo/alchemist/model/cognitive/reactions/SteeringBehavior.kt @@ -24,16 +24,17 @@ import it.unibo.alchemist.model.reactions.AbstractReaction /** * Reaction representing a pedestrian's steering behavior. * - * @param T the concentration type. - * @param timeDistribution the time distribution that schedules reaction execution. - * @property environment the Euclidean environment where the pedestrian moves. - * @property pedestrian the owner pedestrian's property. - * @property steerStrategy the strategy used to combine steering actions. + * @param T the concentration type + * @property environment the Euclidean environment where the pedestrian moves (property) + * @property pedestrian the owner pedestrian's property + * @param timeDistribution the time distribution that schedules reaction execution + * @property steerStrategy the strategy used to combine steering actions + * @property steerActions list of steering actions in this reaction */ open class SteeringBehavior( private val environment: Environment, /** The pedestrian property of the owner of this reaction. */ - protected open val pedestrian: PedestrianProperty, + protected val pedestrian: PedestrianProperty, timeDistribution: TimeDistribution, open val steerStrategy: SteeringStrategy, ) : AbstractReaction(pedestrian.node, timeDistribution) { diff --git a/alchemist-composeui/build.gradle.kts b/alchemist-composeui/build.gradle.kts index a2f881b9ac..0de97ab72e 100644 --- a/alchemist-composeui/build.gradle.kts +++ b/alchemist-composeui/build.gradle.kts @@ -1,5 +1,7 @@ +import dev.detekt.gradle.Detekt import it.unibo.alchemist.build.devServer import it.unibo.alchemist.build.webCommonConfiguration +import org.gradle.kotlin.dsl.withType import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl /* @@ -44,3 +46,8 @@ publishing.publications.withType().configureEach { } } } + +// exclude files in build from Detekt +tasks.withType().configureEach { + exclude("**/alchemist_composeui/**") +} diff --git a/alchemist-engine/src/main/kotlin/it/unibo/alchemist/core/Engine.kt b/alchemist-engine/src/main/kotlin/it/unibo/alchemist/core/Engine.kt index 9a457de749..3b6a20e5fb 100644 --- a/alchemist-engine/src/main/kotlin/it/unibo/alchemist/core/Engine.kt +++ b/alchemist-engine/src/main/kotlin/it/unibo/alchemist/core/Engine.kt @@ -43,7 +43,7 @@ import org.slf4j.LoggerFactory * * @param T the concentration type * @param P the position type, extending [Position] - * @property environment the simulation environment + * @param environment the simulation environment * @property scheduler the scheduler managing event execution */ open class Engine>( @@ -529,7 +529,7 @@ open class Engine>( /** * Represents an update affecting a specific reaction. * - * @param sourceReaction the reaction affected by this update + * @property sourceReaction the reaction affected by this update */ private open inner class AbstractUpdateOnReaction(val sourceReaction: Actionable) : Update() { override val reactionsToUpdate: Sequence> = sequenceOf(sourceReaction) @@ -553,8 +553,8 @@ open class Engine>( /** * Handles neighborhood changes, ensuring updates to relevant reactions. * - * @param sourceNode the node initiating the change - * @param targetNode the node affected by the change + * @property sourceNode the node initiating the change + * @property targetNode the node affected by the change */ private open inner class NeighborhoodChanged(val sourceNode: Node, val targetNode: Node) : Update() { override val reactionsToUpdate: Sequence> diff --git a/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/geometry/navigationgraph/NaviGator.kt b/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/geometry/navigationgraph/NaviGator.kt index 7558657f8f..4976e827ac 100644 --- a/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/geometry/navigationgraph/NaviGator.kt +++ b/alchemist-euclidean-geometry/src/main/kotlin/it/unibo/alchemist/model/geometry/navigationgraph/NaviGator.kt @@ -167,8 +167,8 @@ object NaviGator { val intersectedSeeds: () -> List = { seeds.filter { /* - * A seed is considered intersected if it intersects with the polygon and, in particular, with the - * remaining portion of the advancing edge. Similarly for obstacles below. + * A seed is considered intersected if it intersects with the polygon and, in particular, + * with the remaining portion of the advancing edge. Similarly, for obstacles below. */ it != this && it.intersects(asAwtShape()) && diff --git a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/ConcentrationSurrogate.kt b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/ConcentrationSurrogate.kt index 8c5d9616f2..f85f35d166 100644 --- a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/ConcentrationSurrogate.kt +++ b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/ConcentrationSurrogate.kt @@ -16,9 +16,12 @@ import it.unibo.alchemist.model.Concentration /** * A GraphQL surrogate for a [Concentration] object. - * **Note**: the content of the surrogate is a String (Json String) representation of the actual content inside the + * The content of the surrogate is a String (JSON String) representation of the actual content inside the * [origin]. - * @param T The type of the original concentration. + * + * @param T the type of the original concentration + * @property origin the original [Concentration] instance this surrogate represents + * @property content the JSON or string representation of the concentration content */ @GraphQLDescription("The concentration of a molecule, represented as a Json String or its string representation.") data class ConcentrationSurrogate( diff --git a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/GraphQLSurrogate.kt b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/GraphQLSurrogate.kt index 89e84ffd82..59d121b0ec 100644 --- a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/GraphQLSurrogate.kt +++ b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/GraphQLSurrogate.kt @@ -14,6 +14,8 @@ import com.expediagroup.graphql.generator.annotations.GraphQLIgnore /** * A surrogate for a GraphQL object. * Each surrogate has an [origin] object, which is the alchemist object that the surrogate represents. + * * @param T The type of the alchemist object that the surrogate represents. + * @property origin the original object wrapped by the surrogate */ open class GraphQLSurrogate(@param:GraphQLIgnore open val origin: T) diff --git a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/LayerSurrogate.kt b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/LayerSurrogate.kt index 2381cab689..e9b42c86fc 100644 --- a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/LayerSurrogate.kt +++ b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/LayerSurrogate.kt @@ -23,7 +23,7 @@ import it.unibo.alchemist.model.Position * * @param T the concentration type * @param P the position - * @param posMapping the position mapping function from a generic set of coordinates + * @property posMapping the position mapping function from a generic set of coordinates * represented as a list of numbers, to an instance of Alchemist [Position] object */ @GraphQLDescription("A layer containing a substance or a molecule with a spatial distribution") diff --git a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/MoleculeSurrogate.kt b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/MoleculeSurrogate.kt index 515b3cb185..36680ca45c 100644 --- a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/MoleculeSurrogate.kt +++ b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/MoleculeSurrogate.kt @@ -16,7 +16,8 @@ import it.unibo.alchemist.model.Molecule /** * A surrogate class for [Molecule]. * - * @param name the name of the molecule. + * @property name the name of the molecule + * @property origin the original Molecule wrapped by this surrogate */ @GraphQLDescription("A molecule with an associated name") data class MoleculeSurrogate(@param:GraphQLIgnore override val origin: Molecule, val name: String = origin.name) : @@ -33,7 +34,7 @@ fun Molecule.toGraphQLMoleculeSurrogate() = MoleculeSurrogate(this) * the use of a full [Molecule] or [MoleculeSurrogate] when * client executes operations that require a molecule as parameter. * - * @param name the name of the molecule. + * @property name the name of the molecule. */ @GraphQLDescription("A molecule with an associated name, used as input object") data class MoleculeInput(val name: String) diff --git a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/NodeSurrogate.kt b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/NodeSurrogate.kt index cb029e9fc1..45382fc64b 100644 --- a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/NodeSurrogate.kt +++ b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/NodeSurrogate.kt @@ -18,7 +18,8 @@ import it.unibo.alchemist.model.Node /** * A GraphQL surrogate for a [Node] object. * @param T The type of the concentration. - * @param id The id of the node. + * @property id The id of the node. + * @property origin the original Node wrapped by this surrogate */ @GraphQLDescription("A node in the environment") data class NodeSurrogate(@param:GraphQLIgnore override val origin: Node, val id: Int = origin.id) : diff --git a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/Position2DSurrogate.kt b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/Position2DSurrogate.kt index d9dfe09b1e..205e540d20 100644 --- a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/Position2DSurrogate.kt +++ b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/Position2DSurrogate.kt @@ -15,8 +15,10 @@ import it.unibo.alchemist.model.Position /** * A 2D surrogate for a [Position] object. * - * @param x the x coordinate of the position. - * @param y the y coordinate of the position. + * @property x the x coordinate of the position + * @property y the y coordinate of the position + * @property coordinates the list of coordinates of the position, in this case [x, y] + * @property dimensions the number of dimensions of the position, in this case 2 */ @GraphQLDescription("A position in a two dimensional space") data class Position2DSurrogate( diff --git a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/PositionSurrogate.kt b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/PositionSurrogate.kt index b103d4d06f..74d9fedaae 100644 --- a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/PositionSurrogate.kt +++ b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/PositionSurrogate.kt @@ -41,8 +41,8 @@ interface PositionSurrogate { * the use of a full [Position] or [PositionSurrogate] when * client executes operations that require a position as parameter. * - * @param coordinates the coordinates of the position. - * @param dimensions the dimension of the position. + * @property coordinates the coordinates of the position. + * @property dimensions the dimension of the position. */ @GraphQLDescription("Position in space, used as input parameter") data class PositionInput(val coordinates: List, val dimensions: Int = coordinates.size) diff --git a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/ReactionSurrogate.kt b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/ReactionSurrogate.kt index b571450645..d9e15c7234 100644 --- a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/ReactionSurrogate.kt +++ b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/ReactionSurrogate.kt @@ -16,9 +16,13 @@ import it.unibo.alchemist.model.Reaction /** * A surrogate class for [Reaction]. + * * @param inputContext the input context of the reaction * @param outputContext the output context of the reaction - * @param node the [NodeSurrogate] in which this [ReactionSurrogate] executes + * @property node the [NodeSurrogate] in which this [ReactionSurrogate] executes + * @property origin the original Reaction wrapped by this surrogate + * @property outputContext + * @property inputContext */ @GraphQLDescription("A generic reaction") data class ReactionSurrogate( diff --git a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/SimulationSurrogate.kt b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/SimulationSurrogate.kt index 5c4fe2bc14..70e94d6817 100644 --- a/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/SimulationSurrogate.kt +++ b/alchemist-graphql-surrogates/src/main/kotlin/it/unibo/alchemist/boundary/graphql/schema/model/surrogates/SimulationSurrogate.kt @@ -18,6 +18,7 @@ import it.unibo.alchemist.model.Position * A surrogate for [Simulation]. * @param T the concentration type * @param P the position + * @property origin the original [Simulation] wrapped by this surrogate */ @GraphQLDescription("The simulation") data class SimulationSurrogate>(@param:GraphQLIgnore override val origin: Simulation) : diff --git a/alchemist-graphql/build.gradle.kts b/alchemist-graphql/build.gradle.kts index aff7426795..8a9a5b2722 100644 --- a/alchemist-graphql/build.gradle.kts +++ b/alchemist-graphql/build.gradle.kts @@ -131,4 +131,5 @@ publishing.publications { // exclude files in build from Detekt tasks.withType().configureEach { exclude("**/boundary/graphql/client/**") + exclude("**/io/kotest/framework/runtime/**") } diff --git a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/actions/ToggleMoleculeRandomly.kt b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/actions/ToggleMoleculeRandomly.kt index 0272824822..f40633229d 100644 --- a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/actions/ToggleMoleculeRandomly.kt +++ b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/actions/ToggleMoleculeRandomly.kt @@ -19,12 +19,12 @@ import org.apache.commons.math3.random.RandomGenerator * * if it is present, then with probability [odds] it's removed from [node]; * * otherwise, with probability [odds] it is inserted in [node] with the provided [concentration]. * - * @param concentration type + * @param T the concentration type * @param node the node containing the molecule to toggle - * @param randomGenerator random number generator to use + * @property randomGenerator random number generator to use * @param molecule the molecule to toggle * @param concentration the concentration to use for the "on" state - * @param odds probability to toggle the molecule every time the action is triggered + * @property odds probability to toggle the molecule every time the action is triggered */ open class ToggleMoleculeRandomly( node: Node, diff --git a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/layers/BidimensionalGaussianLayer.kt b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/layers/BidimensionalGaussianLayer.kt index 5e9d73c89d..5006aea318 100644 --- a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/layers/BidimensionalGaussianLayer.kt +++ b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/layers/BidimensionalGaussianLayer.kt @@ -15,8 +15,13 @@ import it.unibo.alchemist.util.math.BidimensionalGaussian /** * A [Layer] based on a [2D gaussian function][BidimensionalGaussian] and an optional baseline value. * - * @param centerX x coord of the layer's center. - * @param centerY y coord of the layer's center. + * @param P the position type + * @param baseline the baseline value added to the gaussian (default: 0.0) + * @property centerX the x coordinate of the layer's center + * @property centerY the y coordinate of the layer's center + * @param norm normalization (amplitude) factor of the gaussian function + * @param sigmaX standard deviation along the X axis + * @param sigmaY standard deviation along the Y axis (defaults to [sigmaX]) */ open class BidimensionalGaussianLayer

> @JvmOverloads diff --git a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/linkingrules/ConnectToAccessPoint.kt b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/linkingrules/ConnectToAccessPoint.kt index 197b94a4c7..69066f8127 100644 --- a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/linkingrules/ConnectToAccessPoint.kt +++ b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/linkingrules/ConnectToAccessPoint.kt @@ -17,7 +17,13 @@ import it.unibo.alchemist.model.Position import it.unibo.alchemist.model.neighborhoods.Neighborhoods /** - * @param accessPointId the id of the access point. + * Linking rule that connects nodes within a specified radius but filters + * connections through a designated access point when the center is not an AP itself. + * + * @param T the concentration type + * @param P the position type + * @param radius the maximum connection radius + * @property accessPointId the molecule id used to mark access-point nodes */ class ConnectToAccessPoint>(radius: Double, val accessPointId: Molecule) : ConnectWithinDistance(radius) { diff --git a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/linkingrules/ConnectViaAccessPoint.kt b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/linkingrules/ConnectViaAccessPoint.kt index d5cf54a099..cbe49f591a 100644 --- a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/linkingrules/ConnectViaAccessPoint.kt +++ b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/linkingrules/ConnectViaAccessPoint.kt @@ -17,7 +17,12 @@ import it.unibo.alchemist.model.Position import it.unibo.alchemist.model.neighborhoods.Neighborhoods /** - * @param accessPointId the id of the access point. + * Linking rule that connects nodes to the closest access point and other nodes connected to the same AP. + * + * @param T the concentration type + * @param P the position type + * @param radius the maximum connection radius + * @property accessPointId the molecule id used to mark access-point nodes */ class ConnectViaAccessPoint>(radius: Double, val accessPointId: Molecule) : ConnectWithinDistance(radius) { diff --git a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/movestrategies/speed/ConstantSpeed.kt b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/movestrategies/speed/ConstantSpeed.kt index 72ec514432..715382f32a 100644 --- a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/movestrategies/speed/ConstantSpeed.kt +++ b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/movestrategies/speed/ConstantSpeed.kt @@ -21,10 +21,9 @@ import java.io.Serial * rate, but if the [it.unibo.alchemist.model.TimeDistribution] has a high variance, the movements * on the map will inherit this tract. * - * @param Concentration type - * @param

Position type - * - * @param reaction the reaction + * @param T Concentration type + * @param P Position type + * @param reaction the reaction used to compute movement timing * @param speed the speed, in meters/second */ class ConstantSpeed>(private val reaction: Reaction<*>, private val speed: Double) : diff --git a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/movestrategies/target/FollowTarget.kt b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/movestrategies/target/FollowTarget.kt index 036d500722..e0a0667bdf 100644 --- a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/movestrategies/target/FollowTarget.kt +++ b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/movestrategies/target/FollowTarget.kt @@ -18,14 +18,15 @@ import org.danilopianini.util.regex.Patterns import org.slf4j.LoggerFactory /** - * This strategy reads the value of a "target" molecule and tries to interpret + * Strategy that reads the value of a "target" molecule and tries to interpret * it as a coordinate. * - * @param environment the environment - * @param node the node - * @param targetMolecule the target molecule - * @param Concentration type - */ + * @param T the concentration type + * @param P the position type + * @property environment the environment + * @property node the node + * @property targetMolecule the target molecule used to determine the destination + */ open class FollowTarget>( protected val environment: Environment, private val node: Node, diff --git a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/neighborhoods/Neighborhoods.kt b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/neighborhoods/Neighborhoods.kt index 0c25c326fd..10f923162b 100644 --- a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/neighborhoods/Neighborhoods.kt +++ b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/neighborhoods/Neighborhoods.kt @@ -19,11 +19,12 @@ object Neighborhoods { /** * Creates a [SimpleNeighborhood]. * - * @param environment The environment of the neighborhood. - * @param center The center of the neighborhood. - * @param neighbors The neighbors in the neighborhood, defaults to empty. - * - * @return The newly created [SimpleNeighborhood]. + * @param T the concentration type + * @param P the position type + * @param environment the environment of the neighborhood + * @param center the center node of the neighborhood + * @param neighbors the neighbors in the neighborhood (defaults to empty) + * @return the newly created [SimpleNeighborhood] */ @JvmStatic @JvmOverloads fun > make( diff --git a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/routes/PolygonalChain.kt b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/routes/PolygonalChain.kt index 3cbfb09e77..316d0c343f 100644 --- a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/routes/PolygonalChain.kt +++ b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/routes/PolygonalChain.kt @@ -17,8 +17,8 @@ import kotlin.reflect.full.isSuperclassOf /** * Abstract route implementation. * - * @param

the type of position that the route is composed - * @param points the positions this route traverses + * @param P the type of position that composes the route + * @property points the positions this route traverses */ open class PolygonalChain

>(override val points: List

) : Route

{ private var distance = Double.NaN diff --git a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/terminators/AfterTime.kt b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/terminators/AfterTime.kt index cb8ec49964..249acacce4 100644 --- a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/terminators/AfterTime.kt +++ b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/terminators/AfterTime.kt @@ -15,7 +15,11 @@ import it.unibo.alchemist.model.TerminationPredicate import it.unibo.alchemist.model.Time /** - * @param endTime the end time. + * Terminates the simulation when a given time is reached. + * + * @param T the concentration type + * @param P the position type + * @property endTime the end time at which the simulation should terminate */ data class AfterTime>(val endTime: Time) : TerminationPredicate { override fun invoke(environment: Environment) = environment.simulation.time >= endTime diff --git a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/terminators/StableForSteps.kt b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/terminators/StableForSteps.kt index be8a7074e8..6ef6f8ac82 100644 --- a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/terminators/StableForSteps.kt +++ b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/terminators/StableForSteps.kt @@ -38,10 +38,8 @@ import java.util.function.Predicate * to avoid missing checks. * * @constructor Creates a new [StableForSteps] with the given values. - * - * @param checkInterval The recurrence of the test - * @param equalIntervals The amount of [checkInterval] intervals that need to pass - * (during which the environment doesn't change) for [test] to return true + * @property checkInterval the recurrence of the test + * @property equalIntervals the number of [checkInterval] intervals required to be unchanged for [test] to return true */ data class StableForSteps(private val checkInterval: Long, private val equalIntervals: Long) : TerminationPredicate> { @@ -60,7 +58,7 @@ data class StableForSteps(private val checkInterval: Long, private val val newPositions = environment.associateBy({ it }, { environment.getPosition(it) }) val newContents = makeTable(environment.nodeCount) environment.forEach { node -> - node.contents.forEach { molecule, concentration -> + node.contents.forEach { (molecule, concentration) -> newContents.put(node, molecule, concentration) } } diff --git a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/terminators/StepCount.kt b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/terminators/StepCount.kt index 191acc8dc0..93e1f12085 100644 --- a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/terminators/StepCount.kt +++ b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/model/terminators/StepCount.kt @@ -18,7 +18,9 @@ import it.unibo.alchemist.model.TerminationPredicate * If the simulation is uninitialized (thus, the environment returns null when asked for the simulation), * this predicate always returns false. * - * @param lastStep the last step. + * @param T the concentration type + * @param P the position type + * @property lastStep the last step at which the simulation should terminate */ data class StepCount>(val lastStep: Long) : TerminationPredicate { override fun invoke(environment: Environment): Boolean = environment.simulation.step >= lastStep diff --git a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/Anys.kt b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/Anys.kt index cda0876171..e3e746e7a6 100644 --- a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/Anys.kt +++ b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/Anys.kt @@ -19,13 +19,11 @@ object Anys { /** * The opposite of [fold]. * - * @param extractor A function that provides a sequence of - * elements given a specific element of the same type. - * @receiver The starting element to unfold. - * @return A sequence of [E] generated by unfolding on each - * element provided by the [extractor] function. - * - * @See [fold]. + * @param E the element type produced by unfolding + * @receiver The starting element to unfold + * @param extractor A function that provides a sequence of elements given a specific element of the same type + * @return A sequence of [E] generated by unfolding on each element provided by the [extractor] function + * @see fold */ fun E.unfold(extractor: (E) -> Sequence): Sequence = sequenceOf(this) + extractor(this).flatMap { it.unfold(extractor) } diff --git a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/Iterables.kt b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/Iterables.kt index 5e2d608f7f..67569b111a 100644 --- a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/Iterables.kt +++ b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/Iterables.kt @@ -17,12 +17,11 @@ import org.apache.commons.math3.random.RandomGenerator */ object Iterables { /** - * Fisher–Yates shuffle algorithm - * using a [RandomGenerator]. + * Fisher–Yates shuffle algorithm using a [RandomGenerator]. * More information [on Wikipedia](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle). * - * @param randomGenerator - * the simulation {@link RandomGenerator}. + * @param R the element type + * @param randomGenerator the simulation random generator used to shuffle */ fun Iterable.shuffled(randomGenerator: RandomGenerator): Iterable = toMutableList().apply { for (i in size - 1 downTo 1) { diff --git a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/math/Math.kt b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/math/Math.kt index 81674c4b40..7721a49a6d 100644 --- a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/math/Math.kt +++ b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/math/Math.kt @@ -24,15 +24,20 @@ private const val DOUBLE_EQUALITY_EPSILON = 10e-12 /** * [Logistic function](https://en.wikipedia.org/wiki/Logistic_function). * - * @param sigma Steepness parameter of the logistic function. - * @param tau Threshold parameter of the logistic function. + * @param sigma Steepness parameter of the logistic function + * @param tau Threshold parameter of the logistic function + * @param parameters additional input parameters whose sum is used as input + * @return logistic function result in (0,1) */ fun logistic(sigma: Double, tau: Double, vararg parameters: Double) = 1 / (1 + E.pow(-sigma * (parameters.sum() - tau))) /** + * Advanced logistic variant that recenters the output. * - * @param sigma Steepness parameter of the advanced logistic function. - * @param tau Threshold parameter of the advanced logistic function. + * @param sigma Steepness parameter of the advanced logistic function + * @param tau Threshold parameter of the advanced logistic function + * @param parameters additional input parameters whose sum is used as input + * @return adjusted logistic value */ fun advancedLogistic(sigma: Double, tau: Double, vararg parameters: Double) = logistic(sigma, tau, *parameters) - 1 / (1 + E.pow(sigma * tau)) * (1 + E.pow(-sigma * tau)) diff --git a/alchemist-implementationbase/src/main/kotlin/org/apache/commons/math3/distribution/DiracDeltaDistribution.kt b/alchemist-implementationbase/src/main/kotlin/org/apache/commons/math3/distribution/DiracDeltaDistribution.kt index d33cde2ef9..bfdbc7d435 100644 --- a/alchemist-implementationbase/src/main/kotlin/org/apache/commons/math3/distribution/DiracDeltaDistribution.kt +++ b/alchemist-implementationbase/src/main/kotlin/org/apache/commons/math3/distribution/DiracDeltaDistribution.kt @@ -25,14 +25,6 @@ import org.apache.commons.math3.random.RandomGenerator class DiracDeltaDistribution constructor(val value: Double) : RealDistribution, java.io.Serializable { - /** - * This constructor is meant for reflection compatibility only. - * [randomGenerator] is unused. - */ - constructor( - @Suppress("UNUSED_PARAMETER") randomGenerator: RandomGenerator? = null, - value: Double, - ) : this(value) override fun probability(x: Double) = if (x == value) 1.0 else 0.0 diff --git a/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/AlchemistExecutionContext.kt b/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/AlchemistExecutionContext.kt index d21153c0db..e28211771b 100644 --- a/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/AlchemistExecutionContext.kt +++ b/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/AlchemistExecutionContext.kt @@ -38,24 +38,30 @@ import org.protelis.vm.TimeAwareDevice import org.protelis.vm.impl.AbstractExecutionContext /** - * @param

position type - * @param environmentAccess the simulation [it.unibo.alchemist.model.Environment] - * @param node the local [it.unibo.alchemist.model.Node] - * @param protelisDevice the local [it.unibo.alchemist.model.protelis.properties.ProtelisDevice] - * @param reaction the [it.unibo.alchemist.model.Reaction] hosting the program - * @param randomGenerator the [org.apache.commons.math3.random.RandomGenerator] for this simulation - * @param networkManager the [AlchemistNetworkManager] to be used -*/ + * Execution context that bridges the Alchemist simulation and the Protelis VM. + * + * This class provides Protelis with the device identity, coordinates, timing + * and network-related information retrieved from the hosting Alchemist + * simulation objects. + * + * @param P the position type used by the environment + * @property environmentAccess the simulation environment used to query positions and distances + * @param node the local node hosting this execution context + * @param protelisDevice the device wrapper exposing node properties to Protelis + * @param reaction the reaction hosting the running Protelis program + * @property randomGenerator the random generator instance used by this execution context + * @param networkManager the network manager used to share state among neighbouring devices + */ class AlchemistExecutionContext

>( /** - * @return experimental access to the simulated environment, for building oracles + * Experimental access to the simulated environment, for building oracles. */ val environmentAccess: Environment, private val node: Node, private val protelisDevice: ProtelisDevice

, private val reaction: Reaction, /** - * @return the internal [org.apache.commons.math3.random.RandomGenerator] + * The internal random generator used by the execution context. */ val randomGenerator: RandomGenerator, networkManager: AlchemistNetworkManager, diff --git a/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/ProtelisIncarnation.kt b/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/ProtelisIncarnation.kt index 7b1938bc8b..87681433b2 100644 --- a/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/ProtelisIncarnation.kt +++ b/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/ProtelisIncarnation.kt @@ -395,7 +395,11 @@ class ProtelisIncarnation

> : Incarnation { override fun addProperty(nodeProperty: NodeProperty) = notImplemented() - @Suppress("UnusedPrivateMember") + /** + * Ensures that deserialization of this sentinel object returns the canonical instance. + * Called reflectively by the Java serialization subsystem; kept private intentionally. + */ + @Suppress("unused") private fun readResolve(): Any = NoNode private fun notImplemented(): A = diff --git a/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/actions/RunProtelisProgram.kt b/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/actions/RunProtelisProgram.kt index 99aa4c5b6c..0a66003db3 100644 --- a/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/actions/RunProtelisProgram.kt +++ b/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/actions/RunProtelisProgram.kt @@ -229,7 +229,13 @@ class RunProtelisProgram

> private constructor( isComputationalCycleComplete = false } - @Suppress("UnusedPrivateMember") + /** + * Called reflectively by the Java serialization subsystem during deserialization. + * This method is intentionally private and may appear unused to static analyzers. + * + * After default deserialization, recreate transient components tied to the device. + */ + @Suppress("unused") private fun readObject(stream: ObjectInputStream) { stream.defaultReadObject() // After deserialization, recreate the components using the device diff --git a/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/actions/SendToNeighbor.kt b/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/actions/SendToNeighbor.kt index c64a87acf6..0675fb5bb5 100644 --- a/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/actions/SendToNeighbor.kt +++ b/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/actions/SendToNeighbor.kt @@ -18,11 +18,11 @@ import java.io.Serial import java.util.Objects /** - * @param node - * the local node - * @param reaction - * the reaction - * @param protelisProgram the [RunProtelisProgram] whose data will be sent + * Action that broadcasts the content of a Protelis program to neighbours. + * + * @param node the local node hosting the action + * @param reaction the reaction triggering this action + * @property protelisProgram the [RunProtelisProgram] whose data will be sent */ class SendToNeighbor(node: Node, reaction: Reaction, val protelisProgram: RunProtelisProgram<*>) : AbstractAction(node) { diff --git a/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/properties/ProtelisDevice.kt b/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/properties/ProtelisDevice.kt index 644cf740ce..2dcbd40fcc 100644 --- a/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/properties/ProtelisDevice.kt +++ b/alchemist-incarnation-protelis/src/main/kotlin/it/unibo/alchemist/model/protelis/properties/ProtelisDevice.kt @@ -13,7 +13,6 @@ import it.unibo.alchemist.model.Environment import it.unibo.alchemist.model.Node import it.unibo.alchemist.model.NodeProperty import it.unibo.alchemist.model.Position -import it.unibo.alchemist.model.Reaction import it.unibo.alchemist.model.protelis.AlchemistExecutionContext import it.unibo.alchemist.model.protelis.AlchemistNetworkManager import it.unibo.alchemist.model.protelis.ProtelisIncarnation @@ -100,11 +99,10 @@ constructor( /** * Adds a new [AlchemistNetworkManager]. * - * @param program - * the [RunProtelisProgram] - * @param networkManager - * the [AlchemistNetworkManager] - * @deprecated Use networkManagerOf instead for better encapsulation + * Deprecated: prefer [networkManagerOf] for better encapsulation. + * + * @param program the [RunProtelisProgram] + * @param networkManager the [AlchemistNetworkManager] */ @Deprecated("Use networkManagerOf instead", ReplaceWith("networkManagerOf")) fun addNetworkManger(program: RunProtelisProgram<*>, networkManager: AlchemistNetworkManager) { diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Extractor.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Extractor.kt index 878493b1bc..9a44eda2ff 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Extractor.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Extractor.kt @@ -17,6 +17,8 @@ import it.unibo.alchemist.model.Time * An object that is able to extract numeric informations from an Alchemist * [Environment], given the current simulation [Time], the last executed * [Actionable] (usually a [Reaction] or null) and the current simulation step. + * + * @param E the type of extracted values */ interface Extractor { /** @@ -30,11 +32,11 @@ interface Extractor { * - be an ordered map (for example a [java.util.SortedMap], a [java.util.LinkedHashMap] * or any map with deterministic iteration order). * + * @param T the concentration type used by the environment * @param environment the environment from which to extract values * @param reaction the last executed actionable (may be null) * @param time the current simulation time * @param step the current simulation step - * @param T the concentration type used by the environment * @return a map of property names to extracted values. The map must follow one of the * ordering/key contracts described above so that callers can consistently * determine column ordering when producing tabular outputs. @@ -54,11 +56,11 @@ interface Extractor { * to provide custom formatting (for example numeric formatting or localized * representations). * + * @param T the concentration type used by the environment * @param environment the environment from which to extract values * @param reaction the last executed actionable (may be null) * @param time the current simulation time * @param step the current simulation step - * @param T the concentration type used by the environment * @return a map of property names to their textual representations */ fun extractDataAsText( diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Loader.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Loader.kt index 83edd39112..bcedb5a930 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Loader.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Loader.kt @@ -19,35 +19,27 @@ interface Loader : Serializable { /** * Allows to access the currently defined constants, namely variables defined in the simulation file whose value is * constant and does not depend on the value of any free variable (directly or indirectly). - * - * @return a [Map] between variable names and their computed value */ val constants: Map /** - * @return remote dependencies files + * Remote dependency files referenced by the simulation definition. */ val remoteDependencies: List /** - * Returns the launcher to be used in to manage the simulation lifecycle. - * - * @return launcher + * Returns the launcher to be used to manage the simulation lifecycle. */ val launcher: Launcher /** - * Allows to access the currently defined dependent variable (those variables whose value can be determined given a + * Allows to access the currently defined dependent variables (those variables whose value can be determined given a * valid set of values for the free variables). - * - * @return a [Map] between variable names and their actual - * representation */ val dependentVariables: Map> /** - * @return a [Map] between variable names and their actual - * representation + * A map between variable names and their actual representation. */ val variables: Map> @@ -56,10 +48,8 @@ interface Loader : Serializable { * * This is equivalent to calling [getWith] with an empty values map. * - * Type parameters: - * - T: the concentration type used by the simulation - * - P: the position type used by the simulation - * + * @param T the concentration type + * @param P the position type used by the simulation * @return an instance of [Simulation] with variables initialized to their defaults */ fun > getDefault(): Simulation = getWith(emptyMap()) @@ -70,13 +60,9 @@ interface Loader : Serializable { * Each entry in [values] maps a variable name to the desired value. Variables not * present in the map will be initialized to their default values. * - * Parameters: - * - values: a map specifying name-value bindings for the variables in this scenario - * - * Type parameters: - * - T: the concentration type used by the simulation - * - P: the position type used by the simulation - * + * @param T the concentration type + * @param P the position type used by the simulation + * @param values a map specifying name-value bindings for the variables in this scenario * @return an instance of [Simulation] with variables initialized to the specified values */ fun > getWith(values: Map): Simulation diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/AbstractExporter.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/AbstractExporter.kt index 5b51511112..65e464b6bb 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/AbstractExporter.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/AbstractExporter.kt @@ -20,9 +20,15 @@ import it.unibo.alchemist.model.Time /** * Abstract implementation of a [Exporter]. - * @param samplingInterval the sampling time, defaults to [DEFAULT_INTERVAL]. + * + * @param T the concentration type + * @param P the position type + * @param samplingInterval the sampling time, defaults to [DEFAULT_INTERVAL] */ abstract class AbstractExporter>(private val samplingInterval: Double) : Exporter { + /** + * The list of bound data extractors. + */ final override lateinit var dataExtractors: List> private set diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/CSVExporter.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/CSVExporter.kt index 41b700d8da..7790d7db08 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/CSVExporter.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/CSVExporter.kt @@ -27,14 +27,18 @@ import kotlin.io.path.createTempDirectory import kotlin.reflect.KClass import org.slf4j.LoggerFactory +private lateinit var outputPrintStream: PrintStream + /** - * Writes on file data provided by a number of {@link Extractor}s. Produces a - * CSV with '#' as comment character.e - * @param fileNameRoot the starting name of the file to export data to. - * @param interval the sampling time, defaults to [AbstractExporter.DEFAULT_INTERVAL]. - * @param exportPath if no path is specified it will generate the file inside a temporary folder. - * @param appendTime if true it will always generate a new file, false to overwrite. - * @param fileExtension the extension for the exported files, by default 'csv' + * Writes data provided by a number of extractors to a CSV file. The CSV uses '#' as the comment character. + * + * @param T the concentration type + * @param P the position type + * @property fileNameRoot the starting name of the file to export data to + * @property interval the sampling time; defaults to [AbstractExporter.DEFAULT_INTERVAL] + * @property exportPath the directory to write exported files (temporary folder is used when omitted) + * @property appendTime if true a timestamp is appended to the file name to avoid overwriting + * @property fileExtension the extension for the exported files (default: 'csv') */ class CSVExporter> @JvmOverloads @@ -52,7 +56,6 @@ constructor( val fileExtension: String = "csv", private val appendTime: Boolean = false, ) : AbstractExporter(interval) { - private lateinit var outputPrintStream: PrintStream override fun setup(environment: Environment) { if (!File(exportPath).exists()) { diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/GlobalExporter.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/GlobalExporter.kt index 7afce0c71d..825ca926a4 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/GlobalExporter.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/GlobalExporter.kt @@ -17,9 +17,12 @@ import it.unibo.alchemist.model.Position import it.unibo.alchemist.model.Time /** - * Contains all exporters selected in the configuration file. - * Implements the [OutputMonitor] interface and delegate the export phase to each one of his internal exporters. - * @param exporters The list of [Exporter]. + * Aggregates and delegates to multiple exporters selected in the configuration file. + * Implements the [OutputMonitor] interface and delegates the export phase to each internal exporter. + * + * @param T the concentration type + * @param P the position type + * @property exporters the list of exporters to delegate to */ class GlobalExporter>(val exporters: List>) : OutputMonitor { @Override diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/MongoDBExporter.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/MongoDBExporter.kt index 1c939c961e..18e84dc46b 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/MongoDBExporter.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/MongoDBExporter.kt @@ -18,10 +18,13 @@ import org.bson.Document /** * Exports data to a MongoDB instance. * - * @param uri the connection URI of the database instance. - * @param dbName the name the database to export data to. - * @param interval the sampling time, defaults to [AbstractExporter.DEFAULT_INTERVAL]. - * @param appendTime if true it will always generate a new Mongo document, false to overwrite. + * @param T the concentration type + * @param P the position type + * @property uri the connection URI of the database instance + * @property dbName the name of the database to export data to + * @property interval the sampling time, defaults to [AbstractExporter.DEFAULT_INTERVAL] + * @property appendTime if true it will always generate a new Mongo document, false to overwrite + * @property collectionName the name of the collection used for the current simulation */ class MongoDBExporter> @JvmOverloads diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/extractors/AbstractAggregatingDoubleExporter.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/extractors/AbstractAggregatingDoubleExporter.kt index acb4c52896..328c120a6c 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/extractors/AbstractAggregatingDoubleExporter.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/extractors/AbstractAggregatingDoubleExporter.kt @@ -39,7 +39,7 @@ constructor( ) : this( filter = CommonFilters.fromString(filter), aggregatorNames = aggregatorNames, - precision = null, + precision = precision, ) /** diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/extractors/MoleculeReader.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/extractors/MoleculeReader.kt index 5325f61a0e..41b2434785 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/extractors/MoleculeReader.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/extractors/MoleculeReader.kt @@ -21,18 +21,19 @@ import kotlin.math.min /** * Reads the value of a molecule and logs it. * - * @param moleculeName + * @property moleculeName * the target molecule - * @param property + * @property property * the target property - * @param incarnation + * @property incarnation * the target incarnation - * @param filter - * the [FilteringPolicy] to use + * @property filter + * the [ExportFilter] to use * @param aggregatorNames - * the names of the [UnivariateStatistic] to use for + * the names of the [org.apache.commons.math3.stat.descriptive.UnivariateStatistic] to use for * aggregating data. If an empty list is passed, then the values - * will be logged indipendently for each node. + * will be logged independently for each node. + * @param precision the number of decimal digits to use when writing the output, null for no rounding */ class MoleculeReader @JvmOverloads diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/loader/SimulationModel.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/loader/SimulationModel.kt index ebc7f045bf..79f3a37277 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/loader/SimulationModel.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/loader/SimulationModel.kt @@ -706,9 +706,10 @@ internal object SimulationModel { incarnationFactory: ReactionComponentFunction, genericFactory: (Context, Any?) -> Result?, ): Result? { - fun create(parameter: Any?, makeWith: ReactionComponentFunction): Result = runCatching { - makeWith(simulationRNG, environment, node, timeDistribution, actionable, parameter) - } + fun create(withParameter: Any?, makeWith: ReactionComponentFunction): Result = + runCatching { + makeWith(simulationRNG, environment, node, timeDistribution, actionable, withParameter) + } return when (parameter) { is String -> create(parameter, incarnationFactory) is Map<*, *> -> diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/variables/JSR223Variable.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/variables/JSR223Variable.kt index dfe061b578..55709122ed 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/variables/JSR223Variable.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/variables/JSR223Variable.kt @@ -24,10 +24,9 @@ import kotlinx.coroutines.withTimeout * This variable loads any [JSR-233](https://archive.is/PGdk8) language available in the classpath. * * @constructor builds a new JSR223Variable given a language name and a script. - * - * @param language can be the name of the language, the file extension, or its mime type - * @param formula the script that will get interpreted - * @param timeout how long should the interpreter be allowed to compute before giving up, in ms. Defaults to 1000ms. + * @property language the language name, file extension, or mime type + * @property formula the script that will get interpreted + * @property timeout how long should the interpreter be allowed to compute before giving up, in ms. Defaults to 1000ms */ data class JSR223Variable @JvmOverloads diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/deployments/AbstractRandomDeployment.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/deployments/AbstractRandomDeployment.kt index 9828d99ab5..fd427ec518 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/deployments/AbstractRandomDeployment.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/deployments/AbstractRandomDeployment.kt @@ -15,13 +15,12 @@ import java.util.stream.Stream import org.apache.commons.math3.random.RandomGenerator /** - * @param environment - * the [Environment] - * @param randomGenerator - * the [RandomGenerator] - * @param nodeCount - * the number of nodes - * @param

+ * Abstract base for random deployments of nodes inside an environment. + * + * @param P the position type + * @property environment the simulation environment + * @property randomGenerator the random number generator + * @property nodeCount the number of nodes to deploy */ abstract class AbstractRandomDeployment

>( protected val environment: Environment<*, P>, diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/deployments/Polygon.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/deployments/Polygon.kt index 1016f7c7a2..949d2b1576 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/deployments/Polygon.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/deployments/Polygon.kt @@ -25,8 +25,10 @@ private typealias Point2D = Pair /** * Creates a new Polygon with the given points. * + * @param P the position2D type + * @param environment the simulation environment + * @param randomGenerator the RNG used for placements * @param nodes the count of nodes that need to get displaced inside the polygon - * * @param pointsInput the points of the polygon. * The class does not check for "malformed" polygons (e.g. with intersections). * If the provided points do not represent a valid polygon in bidimensional space, the behaviour of this class is diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/And.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/And.kt index 2da198917e..f998433caa 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/And.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/And.kt @@ -14,8 +14,10 @@ import it.unibo.alchemist.model.PositionBasedFilter /** * Check if both [positionBasedFilterA] and [positionBasedFilterB] are satisfied. - * @param positionBasedFilterA the first filter. - * @param positionBasedFilterB the second filter. + * + * @param P the position type + * @property positionBasedFilterA the first filter + * @property positionBasedFilterB the second filter */ data class And

>( val positionBasedFilterA: PositionBasedFilter

, diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Not.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Not.kt index 887aeea807..c4a2f79ab6 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Not.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Not.kt @@ -14,7 +14,9 @@ import it.unibo.alchemist.model.PositionBasedFilter /** * Negates the [positionBasedFilter]'s test. - * @param [positionBasedFilter] the filter to be negated. + * + * @param P the position type + * @property positionBasedFilter the filter to be negated */ class Not

>(val positionBasedFilter: PositionBasedFilter

) : PositionBasedFilter

{ /** diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Or.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Or.kt index 27cfa86b3e..b9b67fceeb 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Or.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Or.kt @@ -13,12 +13,12 @@ import it.unibo.alchemist.model.Position import it.unibo.alchemist.model.PositionBasedFilter /** - * A position-based filter that matches when at least one of two underlying filters + * Position-based filter that matches when at least one of two underlying filters * matches the provided position (logical OR behaviour). * - * @param P the concrete position type used by the filters - * @param positionBasedFilterA the first filter - * @param positionBasedFilterB the second filter + * @param P the position type + * @property positionBasedFilterA the first filter + * @property positionBasedFilterB the second filter */ data class Or

>( val positionBasedFilterA: PositionBasedFilter

, diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Xor.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Xor.kt index 10b832cf9c..bf3acc1897 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Xor.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/model/positionfilters/Xor.kt @@ -13,12 +13,12 @@ import it.unibo.alchemist.model.Position import it.unibo.alchemist.model.PositionBasedFilter /** - * A position-based filter that matches when exactly one of two underlying filters + * Position-based filter that matches when exactly one of two underlying filters * matches the provided position (exclusive-or behaviour). * - * @param P the concrete position type used by the filters - * @param positionBasedFilterA the first filter - * @param positionBasedFilterB the second filter + * @param P the position type + * @property positionBasedFilterA the first filter + * @property positionBasedFilterB the second filter */ data class Xor

>( val positionBasedFilterA: PositionBasedFilter

, diff --git a/alchemist-maps/src/main/kotlin/it/unibo/alchemist/model/maps/movestrategies/target/FollowTrace.kt b/alchemist-maps/src/main/kotlin/it/unibo/alchemist/model/maps/movestrategies/target/FollowTrace.kt index fd5153d22c..6ff2518f06 100644 --- a/alchemist-maps/src/main/kotlin/it/unibo/alchemist/model/maps/movestrategies/target/FollowTrace.kt +++ b/alchemist-maps/src/main/kotlin/it/unibo/alchemist/model/maps/movestrategies/target/FollowTrace.kt @@ -19,7 +19,8 @@ import it.unibo.alchemist.model.movestrategies.TargetSelectionStrategy /** * A strategy that follows a [it.unibo.alchemist.model.Route]. * - * @param reaction the associated reaction + * @param T the concentration type handled by nodes using this strategy + * @property reaction the associated [Reaction] used to obtain time for trace progression */ class FollowTrace(private val reaction: Reaction<*>) : AbstractStrategyWithGPS(), diff --git a/alchemist-physics/src/main/kotlin/it/unibo/alchemist/model/physics/FieldOfView2D.kt b/alchemist-physics/src/main/kotlin/it/unibo/alchemist/model/physics/FieldOfView2D.kt index e1fdcd0cd2..f882915460 100644 --- a/alchemist-physics/src/main/kotlin/it/unibo/alchemist/model/physics/FieldOfView2D.kt +++ b/alchemist-physics/src/main/kotlin/it/unibo/alchemist/model/physics/FieldOfView2D.kt @@ -15,14 +15,16 @@ import it.unibo.alchemist.model.physics.environments.Physics2DEnvironment /** * A sphere of influence representing the sight of a node in the Euclidean world. * + * @param T + * the concentration type * @param environment - * the environment where this sphere of influence is. + * the environment where this sphere of influence is defined * @param owner - * the node who owns this sphere of influence. + * the node that owns this sphere of influence * @param distance - * the distance in meters at which the sight arrives. + * the maximum sight distance in meters * @param aperture - * the amplitude of the field of view in radians. + * the amplitude of the field of view in radians */ class FieldOfView2D(environment: Physics2DEnvironment, owner: Node, distance: Double, aperture: Double) : InfluenceSphere2D(environment, owner, environment.shapeFactory.circleSector(distance, aperture, 0.0)) diff --git a/alchemist-physics/src/main/kotlin/it/unibo/alchemist/model/physics/InfluenceSphere2D.kt b/alchemist-physics/src/main/kotlin/it/unibo/alchemist/model/physics/InfluenceSphere2D.kt index 089f0859f2..fb81e8b824 100644 --- a/alchemist-physics/src/main/kotlin/it/unibo/alchemist/model/physics/InfluenceSphere2D.kt +++ b/alchemist-physics/src/main/kotlin/it/unibo/alchemist/model/physics/InfluenceSphere2D.kt @@ -16,12 +16,10 @@ import it.unibo.alchemist.model.physics.environments.Physics2DEnvironment /** * A sphere of influence in the Euclidean world. * - * @param environment - * the environment where this sphere of influence is. - * @param owner - * the node who owns this sphere of influence. - * @param shape - * the shape of this sphere of influence + * @param T the concentration type + * @param environment the environment where this sphere of influence exists + * @param owner the node that owns this sphere + * @param shape the geometric shape defining the sphere of influence */ open class InfluenceSphere2D( private val environment: Physics2DEnvironment, diff --git a/alchemist-physics/src/main/kotlin/it/unibo/alchemist/model/physics/environments/AbstractLimitedContinuous2D.kt b/alchemist-physics/src/main/kotlin/it/unibo/alchemist/model/physics/environments/AbstractLimitedContinuous2D.kt index 58ae0f998b..4e1c583caf 100644 --- a/alchemist-physics/src/main/kotlin/it/unibo/alchemist/model/physics/environments/AbstractLimitedContinuous2D.kt +++ b/alchemist-physics/src/main/kotlin/it/unibo/alchemist/model/physics/environments/AbstractLimitedContinuous2D.kt @@ -19,6 +19,7 @@ import java.io.Serial * Nodes cannot move to positions that are not allowed. * * @param T the concentration type + * @param incarnation the incarnation used to build nodes and concentrations */ abstract class AbstractLimitedContinuous2D(incarnation: Incarnation) : ContinuousPhysics2DEnvironment(incarnation) { diff --git a/alchemist-physics/src/main/kotlin/it/unibo/alchemist/model/physics/environments/Continuous2DObstacles.kt b/alchemist-physics/src/main/kotlin/it/unibo/alchemist/model/physics/environments/Continuous2DObstacles.kt index 1c8e2be49a..93bbe44f64 100644 --- a/alchemist-physics/src/main/kotlin/it/unibo/alchemist/model/physics/environments/Continuous2DObstacles.kt +++ b/alchemist-physics/src/main/kotlin/it/unibo/alchemist/model/physics/environments/Continuous2DObstacles.kt @@ -23,7 +23,10 @@ import java.io.ObjectOutputStream import java.io.Serial /** - * @param T concentration type + * A 2D continuous environment that supports rectangular obstacles and prevents nodes from moving through them. + * + * @param T the concentration type + * @param incarnation the incarnation used to build nodes and concentrations */ open class Continuous2DObstacles(incarnation: Incarnation) : AbstractLimitedContinuous2D(incarnation), diff --git a/alchemist-swingui/src/main/kotlin/it/unibo/alchemist/boundary/swingui/monitor/impl/SwingGUI.kt b/alchemist-swingui/src/main/kotlin/it/unibo/alchemist/boundary/swingui/monitor/impl/SwingGUI.kt index 554b2ae1c4..57d9f5eaa4 100644 --- a/alchemist-swingui/src/main/kotlin/it/unibo/alchemist/boundary/swingui/monitor/impl/SwingGUI.kt +++ b/alchemist-swingui/src/main/kotlin/it/unibo/alchemist/boundary/swingui/monitor/impl/SwingGUI.kt @@ -30,9 +30,17 @@ import org.slf4j.LoggerFactory /** * Creates a Swing-based graphical interface for the provided [environment]. - * The actual implementation of the [main] display is chosen based on the type of [environment] + * The actual implementation of the [main] display is chosen based on the type of [environment]. * - * @deprecated The Entire Swing UI is deprecated and is set to be replaced with a modern UI + * @param T the concentration type used by the environment + * @param P the concrete [Position2D] type used by the environment + * @param environment the simulation environment for this GUI (property) + * @param graphicsFile optional effects file to load (may be null) + * @param closeOperation the JFrame close operation constant + * @param failOnHeadless if true, throw when running in headless mode; otherwise only warn + * @param main the main display component backing this monitor (property) + * @property headAttached true when a display is available on this JVM (not headless) + * @property timeStepMonitor internal monitor for time steps */ @Deprecated("The Swing UI must be replaced by a web UI") class SwingGUI> private constructor( @@ -47,8 +55,9 @@ class SwingGUI> private constructor( /** * Builds a single-use graphical interface. * - * @param environment the simulation for this GUI - * @param graphicsFile the effect file + * @param environment the simulation environment for this GUI + * @param graphicsFile optional effects file to load + * @param failOnHeadless if true, throw when running in headless mode; otherwise only warn * @param closeOperation the type of close operation for this GUI */ constructor( @@ -59,10 +68,11 @@ class SwingGUI> private constructor( ) : this(environment, graphicsFile, closeOperation, failOnHeadless, makeSwingComponent(environment)) /** - * Builds a single-use graphical interface. + * Builds a single-use graphical interface from an effects file path. * - * @param environment the simulation for this GUI - * @param graphics the effect file + * @param environment the simulation environment for this GUI + * @param graphics optional path to an effects file + * @param failOnHeadless if true, throw when running in headless mode; otherwise only warn * @param closeOperation the type of close operation for this GUI */ @JvmOverloads @@ -118,7 +128,7 @@ class SwingGUI> private constructor( frame.isVisible = true } else { LoggerFactory.getLogger(SwingGUI::class.java).warn( - "Swing GUI requested, but this JVM instance is running in headless mode. To fail istead of printing" + + "Swing GUI requested, but this JVM instance is running in headless mode. To fail instead of printing" + "this warning, pass `failOnHeadless: true` as an output monitor parameter", ) } diff --git a/alchemist-test/src/main/kotlin/it/unibo/alchemist/test/EuclideanSimulation.kt b/alchemist-test/src/main/kotlin/it/unibo/alchemist/test/EuclideanSimulation.kt index ce238cb31d..d32145127c 100644 --- a/alchemist-test/src/main/kotlin/it/unibo/alchemist/test/EuclideanSimulation.kt +++ b/alchemist-test/src/main/kotlin/it/unibo/alchemist/test/EuclideanSimulation.kt @@ -24,14 +24,12 @@ import org.kaikikm.threadresloader.ResourceLoader /** * Run the simulation this environment owns. * - * @param onceInitialized - * the lambda to execute when the simulation begins. - * @param atEachStep - * the lambda to execute on each step of the simulation. - * @param whenFinished - * the lambda to execute at the end of the simulation. - * @param steps - * the number of steps the simulation must execute. + * @param T the concentration type used by the simulation + * @param P the position/vector type used by the simulation + * @param onceInitialized the lambda to execute when the simulation begins + * @param atEachStep the lambda to execute on each step of the simulation + * @param whenFinished the lambda to execute at the end of the simulation + * @param steps the number of steps the simulation must execute */ fun Simulation.startSimulation( onceInitialized: (EuclideanEnvironment) -> Unit = { }, @@ -69,10 +67,11 @@ fun Simulation.startSimulation( /** * Loads a simulation from a YAML file. * - * @param resource - * the name of the file containing the simulation to load. - * @param vars - * a map specifying name-value bindings for the variables in this scenario. + * @param T the concentration type + * @param P the position/vector type + * @param resource the name of the file containing the simulation to load + * @param vars a map specifying name-value bindings for the variables in this scenario + * @return the loaded [Simulation] */ fun loadYamlSimulation( resource: String, diff --git a/alchemist-web-renderer/build.gradle.kts b/alchemist-web-renderer/build.gradle.kts index b59cbdd46c..2015342b55 100644 --- a/alchemist-web-renderer/build.gradle.kts +++ b/alchemist-web-renderer/build.gradle.kts @@ -10,6 +10,7 @@ import Libs.alchemist import Libs.incarnation import com.google.devtools.ksp.gradle.KspAATask +import dev.detekt.gradle.Detekt plugins { id("kotlin-multiplatform-convention") @@ -84,3 +85,9 @@ publishing.publications.withType().configureEach { } } } + +// exclude files in build from Detekt +tasks.withType().configureEach { + exclude("**/boundary/graphql/client/**") + exclude("**/io/kotest/**") +} diff --git a/alchemist-web-renderer/src/jvmMain/kotlin/it/unibo/alchemist/boundary/webui/server/modules/StartBrowserModule.kt b/alchemist-web-renderer/src/jvmMain/kotlin/it/unibo/alchemist/boundary/webui/server/modules/StartBrowserModule.kt index 8f50756beb..e49ae6bd2f 100644 --- a/alchemist-web-renderer/src/jvmMain/kotlin/it/unibo/alchemist/boundary/webui/server/modules/StartBrowserModule.kt +++ b/alchemist-web-renderer/src/jvmMain/kotlin/it/unibo/alchemist/boundary/webui/server/modules/StartBrowserModule.kt @@ -16,9 +16,9 @@ import java.net.URI /** * Start the default browser of the user on the server address. */ -suspend fun Application.startBrowserModule() { +suspend fun startBrowserModule(app: Application) { if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { - engine.resolvedConnectors().forEach { + app.engine.resolvedConnectors().forEach { Desktop.getDesktop().browse(URI("${it.type.name.lowercase()}://${it.host}:${it.port}")) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0cfd0d2548..59f05b8c72 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -85,7 +85,7 @@ kotlin-multiplatform-plugin = { module = "org.jetbrains.kotlin.multiplatform:org kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } kotlin-test-annotations = { module = "org.jetbrains.kotlin:kotlin-test-annotations-common", version.ref = "kotlin" } kotlin-power-assert-plugin = { module = "org.jetbrains.kotlin.plugin.power-assert:org.jetbrains.kotlin.plugin.power-assert.gradle.plugin", version.ref = "kotlin" } -kotlin-quality-assurance-plugin = "org.danilopianini.gradle-kotlin-qa:org.danilopianini.gradle-kotlin-qa.gradle.plugin:0.101.1-dev04.dabc24e" +kotlin-quality-assurance-plugin = "org.danilopianini.gradle-kotlin-qa:org.danilopianini.gradle-kotlin-qa.gradle.plugin:1.0.1-dev03.9adca76" kotlin-react = { module = "org.jetbrains.kotlin-wrappers:kotlin-react", version.ref = "react" } kotlin-react-dom = { module = "org.jetbrains.kotlin-wrappers:kotlin-react-dom", version.ref = "react" } kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" } From 31555163f15596d548f8865a1f251c3671b72b9e Mon Sep 17 00:00:00 2001 From: Danilo Pianini Date: Fri, 13 Feb 2026 17:55:12 +0100 Subject: [PATCH 4/8] docs: fix dokka dangling link --- .../src/main/kotlin/it/unibo/alchemist/boundary/Extractor.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Extractor.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Extractor.kt index 9a44eda2ff..2ca409a79f 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Extractor.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/Extractor.kt @@ -14,9 +14,10 @@ import it.unibo.alchemist.model.Environment import it.unibo.alchemist.model.Time /** - * An object that is able to extract numeric informations from an Alchemist + * An object that is able to extract numeric information from an Alchemist * [Environment], given the current simulation [Time], the last executed - * [Actionable] (usually a [Reaction] or null) and the current simulation step. + * [Actionable] (usually a [it.unibo.alchemist.model.Reaction] or null) + * and the current simulation step. * * @param E the type of extracted values */ From c1db786ea6ad09a550659a30eaae00bb709de166 Mon Sep 17 00:00:00 2001 From: Danilo Pianini Date: Fri, 13 Feb 2026 18:33:51 +0100 Subject: [PATCH 5/8] oh my god the diameters are bugged again --- .../it/unibo/alchemist/util/Environments.kt | 3 +- .../unibo/alchemist/util/TestDiameterUtils.kt | 29 ++++++++----------- ...TestEnvironmentsDiameterWithHopDistance.kt | 4 +-- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/Environments.kt b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/Environments.kt index 1ed481d1ec..ba7f286ef1 100644 --- a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/Environments.kt +++ b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/Environments.kt @@ -72,7 +72,7 @@ object Environments { when (val subnetwork = subnetworks[centerIndex]) { null -> { val newSubnetwork = MutableNetwork(0.0, mutableListOf(centerNode)) - result.put(centerNode, newSubnetwork) + result[centerNode] = newSubnetwork val centerRow = paths.row(centerIndex) for (potentialNeighborIndex in centerIndex + 1 until nodeCount) { val distanceToNeighbor = centerRow[potentialNeighborIndex] @@ -84,6 +84,7 @@ object Environments { } } else -> { + result[centerNode] = subnetwork // The subnetwork is already computed subnetwork.diameter = max( subnetwork.diameter, diff --git a/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestDiameterUtils.kt b/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestDiameterUtils.kt index ff83559197..112e24f196 100644 --- a/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestDiameterUtils.kt +++ b/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestDiameterUtils.kt @@ -103,33 +103,28 @@ val twoConnectedNodesAndOneIsolated = environmentWithNodesAt(ORIGIN, 3.0 to 0.0, */ val twoSubnetworksWithTwoNodesEach = environmentWithNodesAt(ORIGIN, 3.0 to 0.0, 10.0 to 0.0, 10.0 to 3.0) -/** - * Represents a network composed of two subnetworks, - * each with different amount of nodes. - */ -val twoSparseSubnetworks = environmentWithNodesAt( +private val positionsForTwoSubnets = arrayOf( + -3.0 to 3.0, ORIGIN, - 12.0 to 12.0, 0.0 to 6.0, - 12.0 to 14.0, - -3.0 to 3.0, - 9.0 to 15.0, 3.0 to 3.0, + 9.0 to 15.0, + 12.0 to 12.0, + 12.0 to 14.0, 15.0 to 15.0, ) +/** + * Represents a network composed of two subnetworks, + * each with different amount of nodes. + */ +val twoSparseSubnetworks = environmentWithNodesAt(*positionsForTwoSubnets) + /** * Represents a network composed of three subnetworks, * each with different amount of nodes. */ val threeSparseSubnetworks = environmentWithNodesAt( - ORIGIN, - 12.0 to 12.0, - 0.0 to 6.0, - 12.0 to 14.0, - -3.0 to 3.0, - 9.0 to 15.0, - 3.0 to 3.0, - 15.0 to 15.0, + *positionsForTwoSubnets, 25.0 to 25.0, ) diff --git a/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestEnvironmentsDiameterWithHopDistance.kt b/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestEnvironmentsDiameterWithHopDistance.kt index 3a83ef66b5..53c40c06fb 100644 --- a/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestEnvironmentsDiameterWithHopDistance.kt +++ b/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestEnvironmentsDiameterWithHopDistance.kt @@ -26,12 +26,12 @@ object TestEnvironmentsDiameterWithHopDistance { expected: Double, ) { require(index < nodes.size) - assertEquals(expected, allSubNetworksByNodeWithHopDistance()[nodes[index]]?.diameter!!) + assertEquals(expected, allSubNetworksByNodeWithHopDistance()[nodes[index]]?.diameter!!) } private infix fun Environment.mustNotBeSegmentedAndHaveHopDiameter(expected: Double) { assertFalse(isNetworkSegmented()) - assertEquals(expected, allSubNetworksWithHopDistance().single().diameter) + assertEquals(expected, allSubNetworksWithHopDistance().single().diameter) } @Test From a9eaff41dcfe7e8cbbbec6da3181a9ae66938ee1 Mon Sep 17 00:00:00 2001 From: Danilo Pianini Date: Sat, 14 Feb 2026 11:59:09 +0100 Subject: [PATCH 6/8] refactor: improve diameter assertions in environment tests --- .../it/unibo/alchemist/util/Environments.kt | 2 +- .../unibo/alchemist/util/TestDiameterUtils.kt | 31 ++++++++++ .../util/TestEnvironmentsDiameter.kt | 59 ++++++++----------- ...TestEnvironmentsDiameterWithHopDistance.kt | 44 +++++++------- 4 files changed, 79 insertions(+), 57 deletions(-) diff --git a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/Environments.kt b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/Environments.kt index ba7f286ef1..7fad2a21d3 100644 --- a/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/Environments.kt +++ b/alchemist-implementationbase/src/main/kotlin/it/unibo/alchemist/util/Environments.kt @@ -84,8 +84,8 @@ object Environments { } } else -> { - result[centerNode] = subnetwork // The subnetwork is already computed + result[centerNode] = subnetwork subnetwork.diameter = max( subnetwork.diameter, paths.row(centerIndex).asSequence() diff --git a/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestDiameterUtils.kt b/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestDiameterUtils.kt index 112e24f196..1d087afbef 100644 --- a/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestDiameterUtils.kt +++ b/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestDiameterUtils.kt @@ -15,8 +15,13 @@ import it.unibo.alchemist.model.linkingrules.ConnectWithinDistance import it.unibo.alchemist.model.nodes.GenericNode import it.unibo.alchemist.model.positions.Euclidean2DPosition import it.unibo.alchemist.model.protelis.ProtelisIncarnation +import it.unibo.alchemist.util.Environments.allSubNetworksByNode +import it.unibo.alchemist.util.Environments.allSubNetworksByNodeWithHopDistance import it.unibo.alchemist.util.Environments.isNetworkSegmented import it.unibo.alchemist.util.Environments.networkDiameter +import kotlin.test.assertContains +import kotlin.test.assertEquals +import kotlin.test.assertFalse import kotlin.test.assertTrue /** @@ -44,6 +49,20 @@ fun Environment.mustBeSegmented() { assertTrue(networkDiameter().isNaN()) } +/** + * + */ +fun Environment.mustHaveCoherentSubnetworks() { + val networks = allSubNetworksByNodeWithHopDistance() + assertEquals(nodes.size, networks.size) + assertEquals(nodes.sorted(), networks.values.flatMap { it.nodes }.distinct().sorted()) + networks.forEach { (pivot, network) -> + network.nodes.forEach { connectedNode -> + assertContains(networks[connectedNode]?.nodes.orEmpty(), pivot) + } + } +} + /** * Creates a [Subnetworks] object with the specified [count]. */ @@ -128,3 +147,15 @@ val threeSparseSubnetworks = environmentWithNodesAt( *positionsForTwoSubnets, 25.0 to 25.0, ) + +infix fun Environment.mustHave(expected: Subnetworks) = + assertEquals(expected.count, allSubNetworksByNode().values.distinct().size) + +infix fun Environment.mustNotBeSegmentedAndHaveDiameter(expected: Double) { + assertFalse(isNetworkSegmented()) + assertEquals( + expected, + allSubNetworksByNode().values.toSet().single().diameter, + absoluteTolerance = 10e-12, + ) +} diff --git a/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestEnvironmentsDiameter.kt b/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestEnvironmentsDiameter.kt index d5b61d1be8..7dbc6b0a66 100644 --- a/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestEnvironmentsDiameter.kt +++ b/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestEnvironmentsDiameter.kt @@ -10,38 +10,31 @@ package it.unibo.alchemist.util import it.unibo.alchemist.model.Environment +import it.unibo.alchemist.util.Environments.allSubNetworks import it.unibo.alchemist.util.Environments.allSubNetworksByNode import it.unibo.alchemist.util.Environments.isNetworkSegmented import java.math.BigDecimal import java.math.RoundingMode +import kotlin.math.hypot +import kotlin.math.sqrt import kotlin.test.assertEquals import kotlin.test.assertFalse import org.junit.jupiter.api.Test object TestEnvironmentsDiameter { - private infix fun Environment.mustHave(expected: Subnetworks) = - assertEquals(expected.count, allSubNetworksByNode().size) - - private infix fun Environment.mustNotBeSegmentedAndHaveDiameter(expected: Double) { - assertFalse(isNetworkSegmented()) - assertEquals( - expected, - allSubNetworksByNode().values.single().diameter.roundToTwoDecimals(), - ) - } - private fun Environment.specificNodeInASegmentedNetworkShouldHaveDiameter(index: Int, expected: Double) { - require(index < nodes.size) - val diameter = allSubNetworksByNode()[nodes[index]]?.diameter - if (diameter != null) { - assertEquals( - expected, - diameter.roundToTwoDecimals(), - ) - } + private const val EXPECTED_DIAMETER_LONG = 8.48528137423857 + private const val EXPECTED_DIAMETER_SHORT = 6.324555320336759 + + private fun Environment.subnetworksDiametersShouldBe(diameters: List) { + assertEquals(diameters.sorted(), allSubNetworks().map { it.diameter }.sorted()) } - private fun Double.roundToTwoDecimals(): Double = BigDecimal(this).setScale(2, RoundingMode.HALF_UP).toDouble() + private fun Environment.subnetworksDiametersShouldBe(vararg diameters: Double) = + subnetworksDiametersShouldBe(diameters.toList()) + + private fun Environment.networkDiameterShouldBe(diameter: Double) = + subnetworksDiametersShouldBe(listOf(diameter)) @Test fun `environments with a single node have diameter 0`() = @@ -51,7 +44,8 @@ object TestEnvironmentsDiameter { fun `two connected nodes should have diameter 3`() = twoConnectedNodes mustNotBeSegmentedAndHaveDiameter 3.0 @Test - fun `a triangle formation network is not segmented`() = nodesInATriangle mustNotBeSegmentedAndHaveDiameter 4.24 + fun `a triangle formation network is not segmented`() = + nodesInATriangle mustNotBeSegmentedAndHaveDiameter 3 * sqrt(2.0) @Test fun `three nodes in a row have diameter 8`() = threeNodesInARow mustNotBeSegmentedAndHaveDiameter 8.0 @@ -68,8 +62,7 @@ object TestEnvironmentsDiameter { with(twoConnectedNodesAndOneIsolated) { mustBeSegmented() mustHave(2.subnetworks()) - specificNodeInASegmentedNetworkShouldHaveDiameter(0, 3.0) - specificNodeInASegmentedNetworkShouldHaveDiameter(2, 0.0) + subnetworksDiametersShouldBe(listOf(0.0, 3.0)) } } @@ -78,19 +71,18 @@ object TestEnvironmentsDiameter { with(twoSubnetworksWithTwoNodesEach) { mustBeSegmented() mustHave(2.subnetworks()) - specificNodeInASegmentedNetworkShouldHaveDiameter(0, 3.0) - specificNodeInASegmentedNetworkShouldHaveDiameter(2, 3.0) + subnetworksDiametersShouldBe(listOf(3.0, 3.0)) } } @Test fun `a network of three nodes added dynamically and not in order should adapt accordingly`() = with(singleNodeEnvironment()) { - mustNotBeSegmentedAndHaveDiameter(expected = 0.0) - addNodeAt(1.0 to 4.0) - mustNotBeSegmentedAndHaveDiameter(expected = 4.12) - addNodeAt(-4.0 to -2.0) - mustNotBeSegmentedAndHaveDiameter(expected = 8.60) + networkDiameterShouldBe(0.0) + addNodeAt(1.0 to 1.0) + networkDiameterShouldBe(hypot(1.0, 1.0)) + addNodeAt(-1.0 to -1.0) + networkDiameterShouldBe(2 * sqrt(2.0)) } @Test @@ -98,8 +90,7 @@ object TestEnvironmentsDiameter { with(twoSparseSubnetworks) { mustBeSegmented() mustHave(2.subnetworks()) - specificNodeInASegmentedNetworkShouldHaveDiameter(0, 8.49) - specificNodeInASegmentedNetworkShouldHaveDiameter(1, 6.32) + subnetworksDiametersShouldBe(EXPECTED_DIAMETER_SHORT, EXPECTED_DIAMETER_LONG) } } @@ -108,9 +99,7 @@ object TestEnvironmentsDiameter { with(threeSparseSubnetworks) { mustBeSegmented() mustHave(3.subnetworks()) - specificNodeInASegmentedNetworkShouldHaveDiameter(0, 8.49) - specificNodeInASegmentedNetworkShouldHaveDiameter(1, 6.32) - specificNodeInASegmentedNetworkShouldHaveDiameter(nodeCount - 1, 0.0) + subnetworksDiametersShouldBe(EXPECTED_DIAMETER_SHORT, EXPECTED_DIAMETER_LONG, 0.0) } } } diff --git a/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestEnvironmentsDiameterWithHopDistance.kt b/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestEnvironmentsDiameterWithHopDistance.kt index 53c40c06fb..43fc084e27 100644 --- a/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestEnvironmentsDiameterWithHopDistance.kt +++ b/alchemist-implementationbase/src/test/kotlin/it/unibo/alchemist/util/TestEnvironmentsDiameterWithHopDistance.kt @@ -10,6 +10,7 @@ package it.unibo.alchemist.util import it.unibo.alchemist.model.Environment +import it.unibo.alchemist.model.Node import it.unibo.alchemist.util.Environments.allSubNetworksByNodeWithHopDistance import it.unibo.alchemist.util.Environments.allSubNetworksWithHopDistance import it.unibo.alchemist.util.Environments.isNetworkSegmented @@ -18,16 +19,14 @@ import kotlin.test.assertFalse import org.junit.jupiter.api.Test object TestEnvironmentsDiameterWithHopDistance { - private infix fun Environment.withHopDistanceMustHave(expected: Subnetworks) = + private infix fun Environment.mustHave(expected: Subnetworks) = assertEquals(expected.count, allSubNetworksWithHopDistance().size) - private fun Environment.specificNodeInASegmentedNetworkShouldHaveHopDiameter( - index: Int, - expected: Double, - ) { - require(index < nodes.size) - assertEquals(expected, allSubNetworksByNodeWithHopDistance()[nodes[index]]?.diameter!!) - } + private fun Environment.diameterOfSubnetworkWithNode(id: Int): Double = + diameterOfSubnetworkWithNode(getNodeByID(id)) + + private fun Environment.diameterOfSubnetworkWithNode(node: Node) = + allSubNetworksByNodeWithHopDistance().getValue(node).diameter private infix fun Environment.mustNotBeSegmentedAndHaveHopDiameter(expected: Double) { assertFalse(isNetworkSegmented()) @@ -59,9 +58,11 @@ object TestEnvironmentsDiameterWithHopDistance { fun `a network of three nodes with one isolated should be considered segmented`() { with(twoConnectedNodesAndOneIsolated) { mustBeSegmented() - withHopDistanceMustHave(2.subnetworks()) - specificNodeInASegmentedNetworkShouldHaveHopDiameter(0, 1.0) - specificNodeInASegmentedNetworkShouldHaveHopDiameter(2, 0.0) + mustHaveCoherentSubnetworks() + mustHave(2.subnetworks()) + assertEquals(1.0, diameterOfSubnetworkWithNode(0)) + assertEquals(1.0, diameterOfSubnetworkWithNode(1)) + assertEquals(0.0, diameterOfSubnetworkWithNode(2)) } } @@ -69,9 +70,11 @@ object TestEnvironmentsDiameterWithHopDistance { fun `a network of four nodes connected by two should be considered segmented with the same diameter`() { with(twoSubnetworksWithTwoNodesEach) { mustBeSegmented() - withHopDistanceMustHave(2.subnetworks()) - specificNodeInASegmentedNetworkShouldHaveHopDiameter(0, 1.0) - specificNodeInASegmentedNetworkShouldHaveHopDiameter(2, 1.0) + mustHaveCoherentSubnetworks() + mustHave(2.subnetworks()) + nodes.forEach { + assertEquals(1.0, diameterOfSubnetworkWithNode(it)) + } } } @@ -90,9 +93,8 @@ object TestEnvironmentsDiameterWithHopDistance { fun `two sparse subnetworks should be considered segmented`() { with(twoSparseSubnetworks) { mustBeSegmented() - withHopDistanceMustHave(2.subnetworks()) - specificNodeInASegmentedNetworkShouldHaveHopDiameter(0, 2.0) - specificNodeInASegmentedNetworkShouldHaveHopDiameter(1, 1.0) + mustHaveCoherentSubnetworks() + mustHave(2.subnetworks()) } } @@ -100,10 +102,10 @@ object TestEnvironmentsDiameterWithHopDistance { fun `three sparse subnetworks should be considered segmented`() { with(threeSparseSubnetworks) { mustBeSegmented() - withHopDistanceMustHave(3.subnetworks()) - specificNodeInASegmentedNetworkShouldHaveHopDiameter(0, 2.0) - specificNodeInASegmentedNetworkShouldHaveHopDiameter(1, 1.0) - specificNodeInASegmentedNetworkShouldHaveHopDiameter(nodeCount - 1, 0.0) + mustHaveCoherentSubnetworks() + mustHave(3.subnetworks()) + assertEquals(2.0, diameterOfSubnetworkWithNode(nodes.first())) + assertEquals(0.0, diameterOfSubnetworkWithNode(nodes.last())) } } } From 346ba901a2242a3317358ff6348ceebc62a90a0c Mon Sep 17 00:00:00 2001 From: Danilo Pianini Date: Sat, 14 Feb 2026 13:37:06 +0100 Subject: [PATCH 7/8] fix: restore outputPrintStream declaration --- .../it/unibo/alchemist/boundary/exporters/CSVExporter.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/CSVExporter.kt b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/CSVExporter.kt index 7790d7db08..047eef6405 100644 --- a/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/CSVExporter.kt +++ b/alchemist-loading/src/main/kotlin/it/unibo/alchemist/boundary/exporters/CSVExporter.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2023, Danilo Pianini and contributors + * Copyright (C) 2010-2026, Danilo Pianini and contributors * listed, for each module, in the respective subproject's build.gradle.kts file. * * This file is part of Alchemist, and is distributed under the terms of the @@ -27,8 +27,6 @@ import kotlin.io.path.createTempDirectory import kotlin.reflect.KClass import org.slf4j.LoggerFactory -private lateinit var outputPrintStream: PrintStream - /** * Writes data provided by a number of extractors to a CSV file. The CSV uses '#' as the comment character. * @@ -57,6 +55,8 @@ constructor( private val appendTime: Boolean = false, ) : AbstractExporter(interval) { + private lateinit var outputPrintStream: PrintStream + override fun setup(environment: Environment) { if (!File(exportPath).exists()) { File(exportPath).mkdirs() From 922d2efa2650ce807cce7569bbf12d3047a8a322 Mon Sep 17 00:00:00 2001 From: Danilo Pianini Date: Sat, 14 Feb 2026 13:58:09 +0100 Subject: [PATCH 8/8] style: add missing line breaks in testCSVExporter.yml for improved readability --- alchemist-loading/src/test/resources/testCSVExporter.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/alchemist-loading/src/test/resources/testCSVExporter.yml b/alchemist-loading/src/test/resources/testCSVExporter.yml index 2c63961f6a..61d7d5bb09 100644 --- a/alchemist-loading/src/test/resources/testCSVExporter.yml +++ b/alchemist-loading/src/test/resources/testCSVExporter.yml @@ -1,4 +1,5 @@ incarnation: protelis + variables: zoom: &zoom formula: 0.1 @@ -14,7 +15,9 @@ variables: people_count: &people_count type: GeometricVariable parameters: [300, 50, 500, 9] + seeds: { simulation: *seed, scenario: *scenario_seed} + export: - type: CSVExporter parameters: @@ -36,8 +39,11 @@ export: precision: 2 aggregators: [ mean, max, min, variance, median ] value-filter: onlyfinite + environment: { type: ImageEnvironment, parameters: [*image_path, *zoom] } + network-model: { type: ObstaclesBreakConnection, parameters: [5] } + deployments: type: Rectangle parameters: [*people_count, 62, 15, 95, 200]