-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d8ffc5e
commit 125c422
Showing
16 changed files
with
640 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
123 changes: 123 additions & 0 deletions
123
src/main/kotlin/automaton/constructor/controller/TestsController.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
package automaton.constructor.controller | ||
|
||
import automaton.constructor.model.automaton.Automaton | ||
import automaton.constructor.model.data.MemoryUnitDescriptorData | ||
import automaton.constructor.model.data.serializersModule | ||
import automaton.constructor.model.memory.MemoryUnitDescriptor | ||
import automaton.constructor.model.module.executor.ExecutionStatus | ||
import automaton.constructor.model.module.executor.Executor | ||
import automaton.constructor.utils.I18N | ||
import automaton.constructor.utils.addOnSuccess | ||
import automaton.constructor.utils.runAsyncWithDialog | ||
import automaton.constructor.view.TestAndResult | ||
import automaton.constructor.view.TestsFragment | ||
import automaton.constructor.view.TestsResultsFragment | ||
import automaton.constructor.view.module.executor.executionLeafView | ||
import javafx.concurrent.Task | ||
import javafx.scene.control.Alert | ||
import javafx.scene.control.ButtonType | ||
import javafx.stage.FileChooser | ||
import kotlinx.serialization.Serializable | ||
import kotlinx.serialization.decodeFromString | ||
import kotlinx.serialization.encodeToString | ||
import kotlinx.serialization.json.Json | ||
import kotlinx.serialization.modules.SerializersModule | ||
import tornadofx.* | ||
import java.io.File | ||
|
||
data class Test(val input: List<MemoryUnitDescriptor>) | ||
|
||
@Serializable | ||
data class TestsForSerializing(val tests: List<List<MemoryUnitDescriptorData>>, val automatonType: String) | ||
|
||
class TestsController(val openedAutomaton: Automaton) : Controller() { | ||
var wereTestsModified = false | ||
private val formatForSerializing = Json { | ||
serializersModule = SerializersModule { | ||
prettyPrint = true | ||
include(MemoryUnitDescriptorData.serializersModule) | ||
} | ||
} | ||
fun saveTests(tests: List<Test>, uiComponent: UIComponent) { | ||
val file = chooseFile(FileChooserMode.Save) | ||
saveAsync(tests, uiComponent, file) | ||
} | ||
private fun saveAsync(tests: List<Test>, uiComponent: UIComponent, file: File): Task<Unit> { | ||
return uiComponent.runAsyncWithDialog( | ||
"Saving tests", | ||
daemon = false | ||
) { | ||
val testsForSerializing = TestsForSerializing(tests.map { test -> test.input.map { it.getData() } }, | ||
openedAutomaton::class.simpleName!!) | ||
file.writeText(formatForSerializing.encodeToString(testsForSerializing)) | ||
} addOnSuccess { | ||
wereTestsModified = false | ||
} | ||
} | ||
fun createTests() { | ||
find<TestsFragment>(mapOf(TestsFragment::controller to this)).openWindow() | ||
} | ||
private fun chooseFile(mode: FileChooserMode): File = | ||
chooseFile( | ||
filters = arrayOf(FileChooser.ExtensionFilter("1", "*.json")), | ||
mode = mode | ||
).first() | ||
fun openTests(uiComponent: UIComponent): List<Test> { | ||
val file = chooseFile(FileChooserMode.Single) | ||
return openAsync(uiComponent, file).get() | ||
} | ||
private fun openAsync(uiComponent: UIComponent, file: File): Task<List<Test>> { | ||
return uiComponent.runAsyncWithDialog( | ||
"Opening tests", | ||
daemon = false | ||
) { | ||
val deserializedTests = | ||
formatForSerializing.decodeFromString<TestsForSerializing>(file.readText()) | ||
if (deserializedTests.automatonType != openedAutomaton::class.simpleName!!) { | ||
throw RuntimeException( | ||
"Unable to load this set of tests for chosen automaton" | ||
) | ||
} | ||
deserializedTests.tests.map { test -> Test(test.map { it.createDescriptor() }) } | ||
} addOnSuccess { | ||
wereTestsModified = false | ||
} | ||
} | ||
fun runOnTests(tests: List<Test>) { | ||
val testsAndResults = mutableListOf<TestAndResult>() | ||
tests.forEach { test -> | ||
val memory = openedAutomaton.memoryDescriptors.zip(test.input).map { | ||
(descriptor, content) -> descriptor.createMemoryUnit(content) | ||
} | ||
val executor = Executor(openedAutomaton) | ||
executor.start(memory) | ||
executor.runFor() | ||
val executionResult = when (executor.status) { | ||
ExecutionStatus.ACCEPTED -> I18N.messages.getString("ExecutorController.Executor.Status.Accepted") | ||
ExecutionStatus.REJECTED -> I18N.messages.getString("ExecutorController.Executor.Status.Rejected") | ||
ExecutionStatus.FROZEN -> I18N.messages.getString("ExecutorController.Executor.Status.Frozen") | ||
ExecutionStatus.RUNNING -> I18N.messages.getString("ExecutorController.Executor.Status.Running") | ||
} | ||
val graphic = executor.acceptedExeStates.firstOrNull()?.let { executionLeafView(it) } | ||
testsAndResults.add(TestAndResult(test, executionResult, graphic)) | ||
} | ||
find<TestsResultsFragment>(mapOf(TestsResultsFragment::testsAndResults to testsAndResults)).openWindow() | ||
} | ||
|
||
fun suggestSavingChanges(tests: List<Test>, uiComponent: UIComponent): Boolean { | ||
if (!wereTestsModified) return true | ||
val result = alert( | ||
Alert.AlertType.CONFIRMATION, | ||
"Would you like to save tests?", | ||
null, | ||
ButtonType(I18N.messages.getString("Dialog.yes.button"), ButtonType.YES.buttonData), | ||
ButtonType(I18N.messages.getString("Dialog.no.button"), ButtonType.NO.buttonData), | ||
ButtonType(I18N.messages.getString("Dialog.cancel.button"), ButtonType.CANCEL.buttonData), | ||
owner = uiComponent.currentWindow, | ||
title = I18N.messages.getString("Dialog.confirmation") | ||
).result | ||
if (result.buttonData == ButtonType.YES.buttonData) | ||
saveTests(tests, uiComponent) | ||
return result.buttonData != ButtonType.CANCEL.buttonData | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
src/main/kotlin/automaton/constructor/view/ExamplesFragment.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package automaton.constructor.view | ||
|
||
import automaton.constructor.controller.FileController | ||
import javafx.beans.property.IntegerProperty | ||
import javafx.beans.property.StringProperty | ||
import javafx.scene.control.ListCell | ||
import javafx.scene.text.Text | ||
import kotlinx.serialization.Serializable | ||
import kotlinx.serialization.decodeFromString | ||
import kotlinx.serialization.encodeToString | ||
import kotlinx.serialization.json.Json | ||
import tornadofx.* | ||
import java.io.File | ||
import java.nio.file.Files | ||
import kotlin.io.path.Path | ||
|
||
@Serializable | ||
data class Example(val name: String, val description: String) | ||
|
||
class ExampleCell( | ||
private val counter: IntegerProperty, | ||
private val automatonName: StringProperty | ||
): ListCell<Example?>() { | ||
init { | ||
this.setOnMouseClicked { | ||
if (it.clickCount == 2 && this.item != null) | ||
automatonName.set(this.item!!.name) | ||
} | ||
} | ||
override fun updateItem(item: Example?, empty: Boolean) { | ||
super.updateItem(item, empty) | ||
graphic = if (item != null) { | ||
counter.set(counter.value + 1) // this whole counter thing obviously needs to be remade | ||
Text().apply { text = item.name } | ||
} else | ||
null | ||
} | ||
} | ||
|
||
class ExamplesFragment: Fragment() { | ||
val fileController: FileController by param() | ||
private val examples = mutableListOf<Example>().asObservable() | ||
init { | ||
val examplesPath = Path("${System.getProperty("user.dir")}/src/main/resources/examples/examples.json") | ||
val deserializedExamples = Json.decodeFromString<List<Example>>(examplesPath.toFile().readText()) | ||
deserializedExamples.forEach { examples.add(it) } | ||
} | ||
override val root = hbox { | ||
val examplesListView = listview(examples) | ||
val description = Text().apply { text = "Choose an example" } | ||
val counter = 0.toProperty() | ||
val automatonName = "".toProperty() | ||
examplesListView.setCellFactory { ExampleCell(counter, automatonName) } | ||
add(description) | ||
counter.addListener(ChangeListener { _, _, _ -> | ||
val selectedCellIndex = examplesListView.selectionModel.selectedIndex | ||
if (selectedCellIndex != -1) { | ||
description.text = examples[selectedCellIndex].description | ||
} | ||
}) | ||
automatonName.addListener(ChangeListener { _, _, newValue -> | ||
val automatonsPath = Path("${System.getProperty("user.dir")}/src/main/resources/examples/automatons") | ||
Files.walk(automatonsPath).forEach { | ||
if (it.toFile().name == "$newValue.atmtn") { | ||
fileController.open(it.toFile()) | ||
this@ExamplesFragment.close() | ||
} | ||
} | ||
}) | ||
} | ||
} |
Oops, something went wrong.