Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump to version 1.3.0-SNAPSHOT #33

Open
wants to merge 14 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 40 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,39 +20,47 @@ A comprehensive user guide is available in Russian in the [Wiki of this reposito
## Features

* Automata types
- DFA, NFA, epsilon-NFA
- PDA, n-PDA, DPDA, n-DPDA
- Register automaton
- Mealy machine, Moore machine
- Turing Machine (TM), multi-tape TM, multi-track TM, TM with registers
- Support building blocks
- DFA, NFA, epsilon-NFA
- PDA, n-PDA, DPDA, n-DPDA
- Register automaton
- Mealy machine, Moore machine
- Turing Machine (TM), multi-tape TM, multi-track TM, TM with registers
- Support building blocks
* Automaton graph editing and visualization
- State and transition addition, editing, and deletion
- State moving
- Automatically laying out automaton graph
- Group selection
- Graph pane zooming and scrolling
- Undoing and redoing performed operations
- State and transition addition, editing, and deletion
- State moving
- Automatically laying out automaton graph
- Group selection
- Graph pane zooming and scrolling
- Undoing and redoing performed operations
* State-transition table and adjacency matrix representations
- State and transition addition, editing, and deletion
- Group selection
- Undoing and redoing performed operations
* Simulation
- Instant simulation
- Step-by-state simulation
- Step-by-closure simulation
- Execution tree
- Advancing and restarting execution for individual execution states
- Freezing executions states
- Viewing execution states associated with a given state
* Transformations
- Determinization of finite automata
- Minimization of finite automata
- Conversion of regular expression to finite automata
- Elimination of epsilon-transitions
- Conversion of Mealy machine to Moore machine
- Conversion of Moore machine to Mealy machine
- Instant simulation
- Step-by-state simulation
- Step-by-closure simulation
- Execution tree
- Advancing and restarting execution for individual execution states
- Freezing executions states
- Viewing execution states associated with a given state
* Algorithms
- Determinization of finite automata
- Minimization of finite automata
- Conversion of regular expression to finite automata
- Elimination of epsilon-transitions
- Conversion of Mealy machine to Moore machine
- Conversion of Moore machine to Mealy machine
- Conversion of PDA to context-free grammar
- Hellings algorithm
* Other features
- Non determinism detection
- Epsilon-transition detection
- Problem detection
- Serialization
- Non determinism detection
- Epsilon-transition detection
- Problem detection
- Serialization
- Test panel to run the automaton on multiple inputs
- Library of automaton examples

## Architecture

Expand All @@ -77,7 +85,7 @@ This project uses Gradle build system. Here are commands for some of its most im
| `./gradlew tasks` | Displays all runnable tasks |

When running Gradle task you can specify target platform classifier with `-Pplatform={classifier}` option,
the following classifiers are supported: `win`, `linux`, `mac`, `win-x86`, `linux-aarch64`, `mac-aarch64`.
the following classifiers are supported: `win`, `linux`, `mac`, `win-x86`, `linux-aarch64`, `mac-aarch64`.

## Technologies

Expand All @@ -87,10 +95,8 @@ the following classifiers are supported: `win`, `linux`, `mac`, `win-x86`, `linu

**Build system:** Gradle

**Tests:** JUnit5, MockK
**Tests:** JUnit5, MockK, TestFX

## License

The Automata Constructor is licensed under the Apache-2.0 license, as detailed in the [LICENSE](LICENSE) file.


2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ tasks {
vendor = "spbu-se"
application = appName
appIdentifier = "automaton.constructor"
version = "1.2.1.0"
version = "1.3.0-SNAPSHOT"
licenseFile("LICENSE")
icons = icoFile
bundleJre = System.getenv("JAVA_HOME")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import automaton.constructor.model.element.*
import automaton.constructor.utils.*
import automaton.constructor.view.*
import automaton.constructor.view.automaton.AutomatonGraphView
import automaton.constructor.view.elements.vertex.AutomatonVertexView
import automaton.constructor.view.elements.transition.TransitionView
import javafx.geometry.Point2D
import javafx.scene.control.ContextMenu
import javafx.scene.input.KeyCode
import javafx.scene.input.MouseButton
import javafx.scene.shape.Line
import tornadofx.*
Expand Down Expand Up @@ -89,27 +90,7 @@ class AutomatonGraphController(automaton: Automaton, automatonViewContext: Autom
newTransitionSource = null
}
graphView.focusedProperty().onChange { if (!it) newTransitionSource = null }
graphView.setOnKeyPressed { event ->
event.consume()
if (event.code == KeyCode.DELETE && automaton.allowsModificationsByUser) {
automaton.undoRedoManager.group {
selectedElementsViews.forEach {
when (it.automatonElement) {
is AutomatonVertex -> automaton.removeVertex(it.automatonElement)
is Transition -> automaton.removeTransition(it.automatonElement)
}
}
}
clearSelection()
} else if (event.code == KeyCode.A && event.isControlDown) {
clearSelection()
selectedElementsViews.addAll(
graphView.edgeViews.values.flatMap { it.transitionViews }
.onEach { it.selected = true })
selectedElementsViews.addAll(
graphView.vertexToViewMap.values.onEach { it.selected = true })
}
}
enableShortcuts(graphView)
}

fun registerVertexView(automatonVertexView: AutomatonVertexView) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import automaton.constructor.model.action.Action
import automaton.constructor.model.action.ActionAvailability
import automaton.constructor.model.action.ActionFailedException
import automaton.constructor.model.automaton.Automaton
import automaton.constructor.model.element.AutomatonElement
import automaton.constructor.model.element.BuildingBlock
import automaton.constructor.model.element.State
import automaton.constructor.model.element.Transition
import automaton.constructor.model.element.*
import automaton.constructor.utils.I18N
import automaton.constructor.view.AutomatonElementView
import automaton.constructor.view.AutomatonViewContext
import automaton.constructor.view.automaton.AutomatonRepresentationView
import javafx.scene.control.ContextMenu
import javafx.scene.input.KeyCode
import javafx.scene.input.MouseButton
import tornadofx.*

Expand Down Expand Up @@ -118,4 +117,24 @@ open class AutomatonRepresentationController(
selectedElementsViews.onEach { it.selected = false }.clear()
lastSelectedElement = null
}
}

fun enableShortcuts(automatonView: AutomatonRepresentationView) {
automatonView.setOnKeyPressed { event ->
event.consume()
if (event.code == KeyCode.DELETE && automaton.allowsModificationsByUser) {
automaton.undoRedoManager.group {
selectedElementsViews.forEach {
when (it.automatonElement) {
is AutomatonVertex -> automaton.removeVertex(it.automatonElement)
is Transition -> automaton.removeTransition(it.automatonElement)
}
}
}
clearSelection()
} else if (event.code == KeyCode.A && event.isControlDown) {
clearSelection()
selectedElementsViews.addAll(automatonView.getAllElementsViews().onEach { it.selected = true })
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ class HellingsAlgoController(
it.rightSide.size == 1 && it.rightSide[0] is Terminal && it.rightSide[0].getSymbol() == transition.propetiesText
}
productions.forEach {
val newHellingsTransition = HellingsTransition(it.leftSide, transition.source,
val newHellingsTransition = HellingsTransition(
it.leftSide, transition.source,
transition.target, SimpleBooleanProperty(false)
)
currentTransitions.add(newHellingsTransition)
Expand All @@ -52,7 +53,8 @@ class HellingsAlgoController(
}
if (grammar.productions.any { it.leftSide == grammar.initialNonterminal && it.rightSide.isEmpty() }) {
openedAutomaton.vertices.forEach {
val newHellingsTransition = HellingsTransition(grammar.initialNonterminal, it, it,
val newHellingsTransition = HellingsTransition(
grammar.initialNonterminal, it, it,
SimpleBooleanProperty(false)
)
currentTransitions.add(newHellingsTransition)
Expand All @@ -66,10 +68,12 @@ class HellingsAlgoController(
val allTransitions = observableListOf<HellingsTransition>()
prepareForExecution(currentTransitions, allTransitions)

val hellingsAlgoExecutionWindow = find<HellingsAlgoExecutionView>(mapOf(
HellingsAlgoExecutionView::currentTransitions to currentTransitions,
HellingsAlgoExecutionView::allTransitions to allTransitions
)).apply { title = I18N.messages.getString("HellingsAlgorithm.Execution.Title") }
val hellingsAlgoExecutionWindow = find<HellingsAlgoExecutionView>(
mapOf(
HellingsAlgoExecutionView::currentTransitions to currentTransitions,
HellingsAlgoExecutionView::allTransitions to allTransitions
)
).apply { title = I18N.messages.getString("HellingsAlgorithm.Execution.Title") }
hellingsAlgoExecutionWindow.openWindow()
find<CFGView>(mapOf(CFGView::grammar to grammar)).apply {
title = I18N.messages.getString("CFGView.Title")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ sealed class AutomatonVertex(
get() = super.undoRedoProperties +
listOf(nameProperty, lastReleasePositionProperty, isInitialProperty, isFinalProperty, requiresLayoutProperty)

override fun toString() = name

companion object {
const val RADIUS = 50.0
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import automaton.constructor.model.element.AutomatonEdge
import automaton.constructor.model.element.AutomatonVertex.Companion.RADIUS
import automaton.constructor.model.element.Transition
import automaton.constructor.utils.*
import automaton.constructor.view.AutomatonVertexView.ShapeType
import automaton.constructor.view.AutomatonVertexView.ShapeType.CIRCLE
import automaton.constructor.view.AutomatonVertexView.ShapeType.SQUARE
import automaton.constructor.view.elements.vertex.AutomatonVertexView
import automaton.constructor.view.elements.vertex.AutomatonVertexView.ShapeType
import automaton.constructor.view.elements.vertex.AutomatonVertexView.ShapeType.CIRCLE
import automaton.constructor.view.elements.vertex.AutomatonVertexView.ShapeType.SQUARE
import automaton.constructor.view.elements.transition.TransitionView
import javafx.beans.binding.Bindings.isNotNull
import javafx.beans.value.ObservableBooleanValue
import javafx.beans.value.ObservableDoubleValue
Expand Down
9 changes: 7 additions & 2 deletions src/main/kotlin/automaton/constructor/view/AutomatonView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class AutomatonView(val automaton: Automaton, automatonViewContext: AutomatonVie
})
automatonTransitionTableView.controller.lastSelectedElementProperty.addListener(ChangeListener { _, _, newValue ->
settingsProperty.set(newValue?.getSettings())

})
automatonAdjacencyMatrixView.controller.lastSelectedElementProperty.addListener(ChangeListener { _, _, newValue ->
settingsProperty.set(newValue?.getSettings())
Expand All @@ -95,14 +96,18 @@ class AutomatonView(val automaton: Automaton, automatonViewContext: AutomatonVie
label {
isWrapText = true
layoutXProperty().bind([email protected]() - widthProperty() - 10.0)
maxWidthProperty().bind([email protected]() - settingsEditor.widthProperty() - 20.0)
val tabWidth = 700.0
maxWidthProperty().bind([email protected]() - tabWidth - 20.0)
maxHeight = 30.0
font = Font.font(16.0)
textProperty().bind(automaton.descriptionBinding)
visibleWhen(automaton.isOutputOfTransformationProperty.booleanBinding { it == null })
}
label {
layoutXProperty().bind([email protected]() - widthProperty() - 10.0)
layoutYProperty().bind([email protected]() - heightProperty())
layoutYProperty().bind([email protected]() - heightProperty() - 45.0)
val buttonsWidth = 700.0
maxWidthProperty().bind([email protected]() - buttonsWidth - 20.0)
font = Font.font(16.0)
textFill = Color.DARKRED
textAlignment = TextAlignment.RIGHT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import automaton.constructor.model.automaton.Automaton
import automaton.constructor.model.element.AutomatonVertex
import automaton.constructor.model.element.Transition
import automaton.constructor.utils.I18N
import automaton.constructor.view.AdjacencyMatrixTransitionView
import automaton.constructor.view.elements.transition.AdjacencyMatrixTransitionView
import automaton.constructor.view.AutomatonViewContext
import javafx.beans.property.ReadOnlyDoubleProperty
import javafx.beans.property.SimpleObjectProperty
Expand Down Expand Up @@ -66,6 +66,7 @@ class AutomatonAdjacencyMatrixView(
transitionsByVertices.removeAll { it.source == vertex }
unregisterColumn(
transitionsColumns.columns.find { it.text == vertex.name } as TableColumn<AdjacencyMatrixTransitionMap, List<Transition>>)
super.unregisterVertex(vertex)
}

override fun registerTransition(transition: Transition) {
Expand All @@ -83,7 +84,7 @@ class AutomatonAdjacencyMatrixView(
val list = this!!.transitions[transition.target]!!.value
this.transitions[transition.target]!!.set(list - transition)
}
transitionToViewMap.remove(transition)
super.unregisterTransition(transition)
}

private fun registerColumn(addedColumn: TableColumn<AdjacencyMatrixTransitionMap, List<Transition>>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import automaton.constructor.model.element.State
import automaton.constructor.utils.hoverableTooltip
import automaton.constructor.utils.subPane
import automaton.constructor.view.AutomatonEdgeView
import automaton.constructor.view.AutomatonVertexView
import automaton.constructor.view.elements.vertex.AutomatonVertexView
import automaton.constructor.view.AutomatonViewContext
import automaton.constructor.view.module.executor.executionStatesTooltip
import javafx.collections.MapChangeListener
Expand All @@ -20,11 +20,11 @@ import tornadofx.add
import tornadofx.fitToParentSize
import kotlin.collections.set

class AutomatonGraphView(val automaton: Automaton, private val automatonViewContext: AutomatonViewContext) : Pane() {
class AutomatonGraphView(val automaton: Automaton, private val automatonViewContext: AutomatonViewContext) : AutomatonRepresentationView() {
private val edgePane = subPane()
val edgeViews = mutableMapOf<Pair<AutomatonVertex, AutomatonVertex>, AutomatonEdgeView>()
val vertexToViewMap = mutableMapOf<AutomatonVertex, AutomatonVertexView>()
val controller: AutomatonGraphController = AutomatonGraphController(automaton, automatonViewContext)
override val controller: AutomatonGraphController = AutomatonGraphController(automaton, automatonViewContext)

init {
minWidth = GRAPH_PANE_INIT_SIZE.x
Expand All @@ -43,6 +43,8 @@ class AutomatonGraphView(val automaton: Automaton, private val automatonViewCont
controller.clearSelection()
}

override fun getAllElementsViews() = edgeViews.values.flatMap { it.transitionViews } + vertexToViewMap.values

private fun registerVertex(vertex: AutomatonVertex) {
val automatonVertexView = AutomatonVertexView(vertex)
controller.registerVertexView(automatonVertexView)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package automaton.constructor.view.automaton

import automaton.constructor.controller.AutomatonRepresentationController
import automaton.constructor.view.AutomatonElementView
import javafx.scene.layout.Pane

abstract class AutomatonRepresentationView: Pane() {
abstract val controller: AutomatonRepresentationController
abstract fun getAllElementsViews(): List<AutomatonElementView>
}
Loading
Loading