From 6a742658af1a318f22ec4da1c66088e5f56bd1dc Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 9 Dec 2020 19:06:17 +0300 Subject: [PATCH] Server is alive! --- build.gradle.kts | 2 +- .../kotlin/ru/mipt/npm/sat/satServer.kt | 9 +++---- .../kotlin/hep/dataforge/vision/Colors.kt | 2 +- .../hep/dataforge/vision/VisionChange.kt | 24 ++++++++++--------- .../vision/editor/ColorValueChooser.kt | 3 ++- .../vision/editor/ComboBoxValueChooser.kt | 1 + .../hep/dataforge/vision/editor/MetaViewer.kt | 1 + .../hep/dataforge/vision/solid/FXMaterials.kt | 16 +++++++------ .../dataforge/vision/server/VisionServer.kt | 19 +++++++-------- .../vision/solid/three/ThreeMaterials.kt | 4 +++- 10 files changed, 45 insertions(+), 36 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index f3709349..6a5a615a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,7 +2,7 @@ plugins { id("ru.mipt.npm.project") } -val dataforgeVersion by extra("0.2.0") +val dataforgeVersion by extra("0.2.1-dev-4") val ktorVersion by extra("1.4.2") val htmlVersion by extra("0.7.2") val kotlinWrappersVersion by extra("pre.129-kotlin-1.4.20") diff --git a/demo/sat-demo/src/jvmMain/kotlin/ru/mipt/npm/sat/satServer.kt b/demo/sat-demo/src/jvmMain/kotlin/ru/mipt/npm/sat/satServer.kt index 6605b17d..d834e433 100644 --- a/demo/sat-demo/src/jvmMain/kotlin/ru/mipt/npm/sat/satServer.kt +++ b/demo/sat-demo/src/jvmMain/kotlin/ru/mipt/npm/sat/satServer.kt @@ -3,8 +3,8 @@ package ru.mipt.npm.sat import hep.dataforge.context.Global import hep.dataforge.names.asName +import hep.dataforge.names.toName import hep.dataforge.vision.VisionManager -import hep.dataforge.vision.get import hep.dataforge.vision.server.close import hep.dataforge.vision.server.serve import hep.dataforge.vision.server.show @@ -40,11 +40,12 @@ fun main() { vision("main".asName(), sat) } launch { + delay(1000) while (isActive) { - val currentLayer = Random.nextInt(10) - (sat["layer[$currentLayer]"] as? Solid)?.color(123) + val target = "layer[${Random.nextInt(1,10)}].segment[${Random.nextInt(3)},${Random.nextInt(3)}]".toName() + (sat[target] as? Solid)?.color("red") delay(300) - (sat["layer[$currentLayer]"] as? Solid)?.color = null + (sat[target] as? Solid)?.color = "green" } } } diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/Colors.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/Colors.kt index c8d18a08..7dc41632 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/Colors.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/Colors.kt @@ -1,11 +1,11 @@ package hep.dataforge.vision -import hep.dataforge.meta.Meta import hep.dataforge.meta.MetaItem import hep.dataforge.meta.get import hep.dataforge.meta.number import hep.dataforge.values.ValueType import hep.dataforge.values.int +import hep.dataforge.values.string import kotlin.math.max /** diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionChange.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionChange.kt index a51b4497..8c3fbf56 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionChange.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionChange.kt @@ -3,10 +3,9 @@ package hep.dataforge.vision import hep.dataforge.meta.* import hep.dataforge.names.Name import hep.dataforge.names.plus -import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.serialization.* @@ -15,7 +14,7 @@ import kotlin.time.Duration /** * An update for a [Vision] or a [VisionGroup] */ -public class VisionChangeBuilder: VisionContainerBuilder { +public class VisionChangeBuilder : VisionContainerBuilder { private val propertyChange = HashMap() private val childrenChange = HashMap() @@ -47,7 +46,8 @@ private fun Vision.isolate(manager: VisionManager): Vision { @Serializable public data class VisionChange( val propertyChange: Map, - val childrenChange: Map) { + val childrenChange: Map, +) { public fun isEmpty(): Boolean = propertyChange.isEmpty() && childrenChange.isEmpty() /** @@ -64,7 +64,7 @@ private fun CoroutineScope.collectChange( name: Name, source: Vision, mutex: Mutex, - collector: ()->VisionChangeBuilder, + collector: () -> VisionChangeBuilder, ) { //Collect properties change source.config.onChange(mutex) { propertyName, oldItem, newItem -> @@ -107,17 +107,19 @@ public fun Vision.flowChanges( val mutex = Mutex() var collector = VisionChangeBuilder() - scope.collectChange(Name.EMPTY, this@flowChanges, mutex){collector} + scope.collectChange(Name.EMPTY, this@flowChanges, mutex) { collector } - while (true) { + while (currentCoroutineContext().isActive) { //Wait for changes to accumulate - kotlinx.coroutines.delay(collectionDuration) + delay(collectionDuration) //Propagate updates only if something is changed if (!collector.isEmpty()) { //emit changes - emit(collector.isolate(manager)) - //Reset the collector - collector = VisionChangeBuilder() + mutex.withLock { + emit(collector.isolate(manager)) + //Reset the collector + collector = VisionChangeBuilder() + } } } } \ No newline at end of file diff --git a/visionforge-fx/src/main/kotlin/hep/dataforge/vision/editor/ColorValueChooser.kt b/visionforge-fx/src/main/kotlin/hep/dataforge/vision/editor/ColorValueChooser.kt index 117210c1..3487f95c 100644 --- a/visionforge-fx/src/main/kotlin/hep/dataforge/vision/editor/ColorValueChooser.kt +++ b/visionforge-fx/src/main/kotlin/hep/dataforge/vision/editor/ColorValueChooser.kt @@ -6,6 +6,7 @@ import hep.dataforge.names.asName import hep.dataforge.values.Null import hep.dataforge.values.Value import hep.dataforge.values.asValue +import hep.dataforge.values.string import javafx.scene.control.ColorPicker import javafx.scene.paint.Color import org.slf4j.LoggerFactory @@ -22,7 +23,7 @@ public class ColorValueChooser : ValueChooserBase() { this.value = Color.valueOf(value.string) } } catch (ex: Exception) { - LoggerFactory.getLogger(javaClass).warn("Invalid color field value: " + value.string) + LoggerFactory.getLogger(javaClass).warn("Invalid color field value: $value") } } } diff --git a/visionforge-fx/src/main/kotlin/hep/dataforge/vision/editor/ComboBoxValueChooser.kt b/visionforge-fx/src/main/kotlin/hep/dataforge/vision/editor/ComboBoxValueChooser.kt index 051469c7..5ce3d960 100644 --- a/visionforge-fx/src/main/kotlin/hep/dataforge/vision/editor/ComboBoxValueChooser.kt +++ b/visionforge-fx/src/main/kotlin/hep/dataforge/vision/editor/ComboBoxValueChooser.kt @@ -12,6 +12,7 @@ import hep.dataforge.names.Name import hep.dataforge.names.asName import hep.dataforge.values.Value import hep.dataforge.values.parseValue +import hep.dataforge.values.string import javafx.collections.FXCollections import javafx.scene.control.ComboBox import javafx.util.StringConverter diff --git a/visionforge-fx/src/main/kotlin/hep/dataforge/vision/editor/MetaViewer.kt b/visionforge-fx/src/main/kotlin/hep/dataforge/vision/editor/MetaViewer.kt index ca6edcc2..88079731 100644 --- a/visionforge-fx/src/main/kotlin/hep/dataforge/vision/editor/MetaViewer.kt +++ b/visionforge-fx/src/main/kotlin/hep/dataforge/vision/editor/MetaViewer.kt @@ -17,6 +17,7 @@ package hep.dataforge.vision.editor import hep.dataforge.meta.Meta +import hep.dataforge.values.string import hep.dataforge.vision.dfIconView import javafx.beans.property.SimpleStringProperty import javafx.scene.control.TreeItem diff --git a/visionforge-fx/src/main/kotlin/hep/dataforge/vision/solid/FXMaterials.kt b/visionforge-fx/src/main/kotlin/hep/dataforge/vision/solid/FXMaterials.kt index eb50f306..b42cd315 100644 --- a/visionforge-fx/src/main/kotlin/hep/dataforge/vision/solid/FXMaterials.kt +++ b/visionforge-fx/src/main/kotlin/hep/dataforge/vision/solid/FXMaterials.kt @@ -5,38 +5,40 @@ import hep.dataforge.meta.double import hep.dataforge.meta.get import hep.dataforge.meta.int import hep.dataforge.values.ValueType +import hep.dataforge.values.int +import hep.dataforge.values.string import hep.dataforge.vision.Colors import javafx.scene.paint.Color import javafx.scene.paint.Material import javafx.scene.paint.PhongMaterial -object FXMaterials { - val RED = PhongMaterial().apply { +public object FXMaterials { + public val RED: PhongMaterial = PhongMaterial().apply { diffuseColor = Color.DARKRED specularColor = Color.WHITE } - val WHITE = PhongMaterial().apply { + public val WHITE: PhongMaterial = PhongMaterial().apply { diffuseColor = Color.WHITE specularColor = Color.LIGHTBLUE } - val GREY = PhongMaterial().apply { + public val GREY: PhongMaterial = PhongMaterial().apply { diffuseColor = Color.DARKGREY specularColor = Color.WHITE } - val BLUE = PhongMaterial(Color.BLUE) + public val BLUE: PhongMaterial = PhongMaterial(Color.BLUE) } /** * Infer color based on meta item * @param opacity default opacity */ -fun MetaItem<*>.color(opacity: Double = 1.0): Color { +public fun MetaItem<*>.color(opacity: Double = 1.0): Color { return when (this) { is MetaItem.ValueItem -> if (this.value.type == ValueType.NUMBER) { - val int = value.number.toInt() + val int = value.int val red = int and 0x00ff0000 shr 16 val green = int and 0x0000ff00 shr 8 val blue = int and 0x000000ff diff --git a/visionforge-server/src/main/kotlin/hep/dataforge/vision/server/VisionServer.kt b/visionforge-server/src/main/kotlin/hep/dataforge/vision/server/VisionServer.kt index 4eaf75ed..0b4fb1c4 100644 --- a/visionforge-server/src/main/kotlin/hep/dataforge/vision/server/VisionServer.kt +++ b/visionforge-server/src/main/kotlin/hep/dataforge/vision/server/VisionServer.kt @@ -37,7 +37,9 @@ import io.ktor.util.error import io.ktor.websocket.WebSockets import io.ktor.websocket.webSocket import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.html.* import kotlinx.html.stream.createHTML import java.awt.Desktop @@ -115,15 +117,12 @@ public class VisionServer internal constructor( application.log.debug("Opened server socket for $name") val vision: Vision = visions[name.toName()] ?: error("Plot with id='$name' not registered") - try { - vision.flowChanges(visionManager, updateInterval.milliseconds).collect { update -> - val json = VisionManager.defaultJson.encodeToString(VisionChange.serializer(), update) - outgoing.send(Frame.Text(json)) - } - } catch (ex: Throwable) { - application.log.error("Closed server socket for $name with exception $ex") + vision.flowChanges(visionManager, updateInterval.milliseconds).onEach { update -> + val json = VisionManager.defaultJson.encodeToString(VisionChange.serializer(), update) + outgoing.send(Frame.Text(json)) + }.catch { ex -> application.log.error(ex) - } + }.launchIn(visionManager.context).join() } //Plots in their json representation get("vision") { @@ -208,7 +207,7 @@ public fun Application.visionModule(context: Context, route: String = DEFAULT_PA public fun VisionManager.serve( host: String = "localhost", port: Int = 7777, - block: VisionServer.()->Unit + block: VisionServer.() -> Unit, ): ApplicationEngine = context.embeddedServer(CIO, port, host) { visionModule(context).apply(block) }.start() diff --git a/visionforge-threejs/src/main/kotlin/hep/dataforge/vision/solid/three/ThreeMaterials.kt b/visionforge-threejs/src/main/kotlin/hep/dataforge/vision/solid/three/ThreeMaterials.kt index 8f1dcbfa..f7ec681d 100644 --- a/visionforge-threejs/src/main/kotlin/hep/dataforge/vision/solid/three/ThreeMaterials.kt +++ b/visionforge-threejs/src/main/kotlin/hep/dataforge/vision/solid/three/ThreeMaterials.kt @@ -2,6 +2,8 @@ package hep.dataforge.vision.solid.three import hep.dataforge.meta.* import hep.dataforge.values.ValueType +import hep.dataforge.values.int +import hep.dataforge.values.string import hep.dataforge.vision.Colors import hep.dataforge.vision.Vision import hep.dataforge.vision.solid.SolidMaterial @@ -90,7 +92,7 @@ public object ThreeMaterials { public fun MetaItem<*>.getColor(): Color { return when (this) { is MetaItem.ValueItem -> if (this.value.type == ValueType.NUMBER) { - val int = value.number.toInt() + val int = value.int Color(int) } else { Color(this.value.string)