All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.unibo.tuprolog.ui.gui.PLPSolutionView.kt Maven / Gradle / Ivy

package it.unibo.tuprolog.ui.gui

import it.unibo.tuprolog.bdd.toDotString
import it.unibo.tuprolog.core.Term
import it.unibo.tuprolog.core.TermFormatter
import it.unibo.tuprolog.core.Var
import it.unibo.tuprolog.core.format
import it.unibo.tuprolog.solve.Solution
import it.unibo.tuprolog.solve.binaryDecisionDiagram
import it.unibo.tuprolog.solve.exception.TimeOutException
import it.unibo.tuprolog.solve.hasBinaryDecisionDiagram
import it.unibo.tuprolog.solve.probability
import javafx.fxml.FXML
import javafx.fxml.FXMLLoader
import javafx.geometry.Insets
import javafx.scene.control.Alert
import javafx.scene.control.Button
import javafx.scene.control.Label
import javafx.scene.layout.BorderPane
import javafx.scene.layout.Region
import javafx.scene.layout.VBox
import javafx.scene.paint.Paint
import javafx.scene.shape.Circle
import java.io.IOException

sealed class PLPSolutionView(private val solution: S) : VBox() {
    companion object {
        private const val FXML = "PLPSolutionView.fxml"

        private val ITEM_MARGIN = Insets(0.0, 0.0, 0.0, 55.0)

        val COLOR_YES: Paint = SolutionView.COLOR_YES
        val COLOR_NO: Paint = SolutionView.COLOR_NO
        val COLOR_HALT: Paint = SolutionView.COLOR_HALT
        val COLOR_TIMEOUT: Paint = SolutionView.COLOR_TIMEOUT

        fun of(solution: Solution): PLPSolutionView<*, *> =
            solution.whenIs(
                yes = { YesViewPLP(it) },
                no = { NoViewPLP(it) },
                halt = { HaltViewPLP(it) },
            )
    }

    protected val formatter = TermFormatter.prettyExpressions()

    init {
        val loader = FXMLLoader(PLPSolutionView::class.java.getResource(FXML))
        loader.setController(this)
        loader.setRoot(this)

        try {
            loader.load()
        } catch (e: IOException) {
            throw IllegalStateException(e)
        }
    }

    @FXML
    lateinit var led: Circle

    @FXML
    lateinit var status: Label

    @FXML
    lateinit var query: Label

    @FXML
    lateinit var probability: Label

    @FXML
    lateinit var substitutions: VBox

    @FXML
    lateinit var btnShowBinaryDecisionDiagram: Button

    @Suppress("MagicNumber")
    class YesViewPLP(solution: Solution.Yes) : PLPSolutionView, Solution.Yes>(solution) {
        init {
            status.text = "yes:"
            led.fill = COLOR_YES
            query.text = solution.solvedQuery.format(formatter)
            solution.substitution.map { it.toPair() }.forEach {
                val assignment = AssignmentView(it, formatter)
                substitutions.children.add(assignment)
                setMargin(assignment, ITEM_MARGIN)
            }

            // Show computed probability value
            probability.text = "Probability: %.2f".format(solution.probability * 100)

            // Show button for Binary Decision Diagrams, if available
            if (solution.hasBinaryDecisionDiagram) {
                btnShowBinaryDecisionDiagram.isVisible = true
                btnShowBinaryDecisionDiagram.setOnAction { this.onShowBinaryDecisionDiagramPressed() }
            } else {
                btnShowBinaryDecisionDiagram.isVisible = false
            }
        }
    }

    class NoViewPLP(solution: Solution.No) : PLPSolutionView(solution) {
        init {
            led.fill = COLOR_NO
            status.text = "no."
            query.isVisible = false
            probability.text = ""
            btnShowBinaryDecisionDiagram.isVisible = false
        }
    }

    class HaltViewPLP(solution: Solution.Halt) : PLPSolutionView(solution) {
        init {
            probability.text = ""
            btnShowBinaryDecisionDiagram.isVisible = false
            if (solution.exception is TimeOutException) {
                led.fill = COLOR_TIMEOUT
                status.text = "timeout."
                query.isVisible = false
            } else {
                led.fill = COLOR_HALT
                status.text = "halt:"
                query.text = solution.exception.message
                with(children) {
                    solution.exception.logicStackTrace.map { it.format(formatter) }.forEach {
                        val lbl = Label("at $it")
                        add(lbl)
                        setMargin(lbl, ITEM_MARGIN)
                    }
                }
            }
        }
    }

    // private fun String?.toMonospacedText(): Node {
    //     if (this == null) return Text()
    //     return Text(this).also { it.style = "-fx-font-family: monospaced" }
    // }

    fun onShowBinaryDecisionDiagramPressed() {
        solution.binaryDecisionDiagram?.let {
            val dialog = Alert(Alert.AlertType.INFORMATION)
            dialog.title = "Binary Decision Diagram"
            dialog.dialogPane.content = GraphRenderView(it.toDotString())
            dialog.dialogPane.minHeight = Region.USE_PREF_SIZE
            dialog.dialogPane.minWidth = Region.USE_PREF_SIZE
            dialog.graphic = null
            dialog.headerText = null
            dialog.showAndWait()
        }
    }

    // private fun bddToImage(bdd: BinaryDecisionDiagram<*>): Image {
    //     val outputStream = ByteArrayOutputStream()
    //     Graphviz
    //         .fromString(bdd.toDotString())
    //         .render(Format.PNG)
    //         .toOutputStream(outputStream)
    //     val inputStream = ByteArrayInputStream(outputStream.toByteArray())
    //     return Image(inputStream)
    // }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy