Skip to content

Commit

Permalink
feat: neighborhood now observe nodes movement from environment
Browse files Browse the repository at this point in the history
  • Loading branch information
giacomoaccursi committed Nov 22, 2023
1 parent c99d993 commit 9c29769
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 28 deletions.
4 changes: 2 additions & 2 deletions src/main/kotlin/entity/Environment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ interface Environment {
* Add a Node to the environment.
* @param node the node to add.
*/
fun addNode(node: Node)
suspend fun addNode(node: Node, position: Position)

/**
* Remove node from the environment.
* @param node the node to remove
*/
fun removeNode(node: Node)
suspend fun removeNode(node: Node)

/**
* Moves node in a new position.
Expand Down
23 changes: 13 additions & 10 deletions src/main/kotlin/entity/EnvironmentImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,38 @@

package entity

import kotlinx.coroutines.flow.MutableSharedFlow

/**
* An implementation of the environment.
*/
class EnvironmentImpl : Environment {
override val nodes = ArrayList<Node>()
class EnvironmentImpl(override val nodes: ArrayList<Node> = ArrayList(), private val linkingRule: LinkingRule) :
class EnvironmentImpl(private val linkingRule: LinkingRule) :
Environment {

override val neighborhoods: ArrayList<Neighborhood> = ArrayList(
nodes.map {
SimpleNeighborhood(it, this, linkingRule)
},
)
override val nodes: ArrayList<Node> = ArrayList()
override val nodeToPosition: HashMap<Int, Position> = HashMap()
override val neighborhoods: ArrayList<Neighborhood> = ArrayList()
private val nodeChangeFlow: MutableSharedFlow<NodeEvent> = MutableSharedFlow()

override fun addNode(node: Node) {
override suspend fun addNode(node: Node, position: Position) {
nodes.add(node)
neighborhoods.add(SimpleNeighborhood(node, this, linkingRule))
nodeToPosition[node.id] = position
val neighborhood = SimpleNeighborhood(node, this, linkingRule, nodeChangeFlow)
neighborhoods.add(neighborhood)
nodeChangeFlow.emit(NodeEvent.NodeAdded(node))
}

override suspend fun removeNode(node: Node) {
nodes.remove(node)
nodeToPosition.remove(node.id)
neighborhoods.remove(neighborhoods.find { it.getCenter() == node })
nodeChangeFlow.emit(NodeEvent.NodeRemoved(node))
}

override suspend fun moveNode(node: Node, position: Position) {
println("node ${node.id} moved in position $position")
nodeToPosition[node.id] = position
nodeChangeFlow.emit(NodeEvent.NodeMoved(node))
}

override fun getNodePosition(node: Node): Position {
Expand Down
9 changes: 9 additions & 0 deletions src/main/kotlin/entity/Neighborhood.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,19 @@

package entity

import kotlinx.coroutines.CoroutineScope

/**
* Interface for a neighborhood.
*/
interface Neighborhood {

/**
* Starts to observing environment nodes.
* @param scope the coroutine scope.
*/
suspend fun startObservingNodes(scope: CoroutineScope)

/**
* @return the center of the neighborhood.
*/
Expand Down
32 changes: 32 additions & 0 deletions src/main/kotlin/entity/NodeEvent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2023. Accursi Giacomo
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/

package entity

/**
* Interface for change events of a node.
*/
sealed interface NodeEvent {
/**
* New Node is added to the environment.
* @param node the added node.
*/
class NodeAdded(val node: Node) : NodeEvent

/**
* A node is removed from the environment.
* @param node the removed node.
*/
class NodeRemoved(val node: Node) : NodeEvent

/**
* A node is moved in the environment.
* @param node the moved node.
*/
class NodeMoved(val node: Node) : NodeEvent
}
70 changes: 54 additions & 16 deletions src/main/kotlin/entity/SimpleNeighborhood.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
package entity

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.launch
import java.util.concurrent.CountDownLatch
import kotlin.coroutines.CoroutineContext

/**
* A simple implementation of a neighborhood.
Expand All @@ -19,29 +21,65 @@ class SimpleNeighborhood(
private val center: Node,
private val environment: Environment,
private val linkingRule: LinkingRule,
private val nodeChangeFlow: MutableSharedFlow<NodeEvent>,
coroutineContext: CoroutineContext = Dispatchers.Default,
) : Neighborhood {

private var neighbors: Set<Node> = setOf()
override fun startObservingNodes(scope: CoroutineScope): CountDownLatch {
val latch = CountDownLatch(environment.nodes.size)
environment.nodes.forEach { node ->
latch.countDown()
scope.launch {
node.observeNodePosition().collect {
if (node != center) {
if (linkingRule.isNeighbor(center, node)) {
neighbors += node
} else {
neighbors -= node
}
}
init {
CoroutineScope(coroutineContext).launch {
startObservingNodes(this)
}
}

private var neighbors: Set<Node> =
linkingRule.computeNeighbors(center, environment)

override suspend fun startObservingNodes(scope: CoroutineScope) {
scope.launch {
nodeChangeFlow.collect { event ->
when (event) {
is NodeEvent.NodeAdded -> onNodeAdded(event.node)
is NodeEvent.NodeMoved -> onNodeMoved(event.node)
is NodeEvent.NodeRemoved -> onNodeRemoved(event.node)
}
}
}
}

private fun onNodeMoved(node: Node) {
if (node != center) {
if (linkingRule.isNeighbor(center, node, environment)) {
if (!neighbors.contains(node)) {
neighbors += node
}
} else {
if (neighbors.contains(node)) {
neighbors -= node
}
}
} else {
neighbors = linkingRule.computeNeighbors(center, environment)
}
}

private fun onNodeAdded(node: Node) {
if (node != center) {
if (linkingRule.isNeighbor(center, node, environment)) {
if (!neighbors.contains(node)) {
neighbors += node
}
}
}
}

private fun onNodeRemoved(node: Node) {
if (neighbors.contains(node)) {
neighbors -= node
}
return latch
}

override fun getCenter() = center

override fun getNeighbors() = neighbors

override fun addNeighbor(node: Node) {
Expand Down

0 comments on commit 9c29769

Please sign in to comment.