diff options
author | Jonas Smedegaard <dr@jones.dk> | 2025-04-27 16:43:17 +0200 |
---|---|---|
committer | Jonas Smedegaard <dr@jones.dk> | 2025-04-27 16:43:22 +0200 |
commit | 8535a9ca92539bf12ec00cac7a4e47be604f0283 (patch) | |
tree | 7a1fb082d5218e18a0186d97a8ed1f7dd87fd41f /src/dk.biks.bachelorizer/dk/biks | |
parent | d104247b8bcdb2a38b680ac54e7ceb2bba155c0e (diff) |
simplify path structure
Diffstat (limited to 'src/dk.biks.bachelorizer/dk/biks')
6 files changed, 489 insertions, 0 deletions
diff --git a/src/dk.biks.bachelorizer/dk/biks/bachelorizer/Control.java b/src/dk.biks.bachelorizer/dk/biks/bachelorizer/Control.java new file mode 100644 index 0000000..b53fb9f --- /dev/null +++ b/src/dk.biks.bachelorizer/dk/biks/bachelorizer/Control.java @@ -0,0 +1,94 @@ +// SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk> +// SPDX-License-Identifier: GPL-3.0-or-later + +package dk.biks.bachelorizer; + +import java.util.List; + +import dk.biks.bachelorizer.model.GUI; +import dk.biks.bachelorizer.view.Window; + +/// Bachelorizer - Controller +public class Control{ + + /// Application model + // (declared explicitly only to silence javadoc) + private GUI model; + + /// Application view + private Window view; + + /// Parameters passed on command-line and in JNLP file + private List<String> parameters; + + /// Default constructor + /// + /// @param model Application model + /// @param view Application view + public Control(GUI model, Window view){ + this.model = model; + this.view = view; + } + + /// parse application parameters + /// + /// parse parameters as GNU-style options and arguments, + /// i.e. treat dash-prefixed words as options + /// until an optional first bare "--", + /// taking first non-option argument as name of student + /// and remaining ones as activity selections + /// + /// @param parameters Application parameters + public void setParameters(List<String> parameters) { + boolean optionsDone = false; + boolean studentAssigned = false; + for (String item : parameters) { + if (!optionsDone && item.matches("--")) { + optionsDone = true; + } else if (!item.startsWith("-")) { + if (!studentAssigned) { + model.addStudent(item); + studentAssigned = true; + showStudent(); + } else { + model.addActivity(item); + showActivities(); + } + } + } + } + + /// Enter activity + /// + /// @param s String entered + public void enterActivity(String s){ + model.addActivity(s); + view.clearActivityEntry(); + showActivities(); + } + + /// Display student + public void showStudent() { + view.setStudentName(model.getStudentName()); + } + + /// Display list of activity entries + public void showActivities() { + String toarea = ""; + for (String t : model.getActivities()) + toarea += t + "\n"; + view.setArea(toarea); + } + + /// drop last activity entry + public void delOne(){ + model.delOneActivity(); + showActivities(); + } + + /// drop all activity entries + public void delAll(){ + model.delAllActivities(); + showActivities(); + } +} diff --git a/src/dk.biks.bachelorizer/dk/biks/bachelorizer/Main.java b/src/dk.biks.bachelorizer/dk/biks/bachelorizer/Main.java new file mode 100644 index 0000000..2efd5b8 --- /dev/null +++ b/src/dk.biks.bachelorizer/dk/biks/bachelorizer/Main.java @@ -0,0 +1,90 @@ +// SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk> +// SPDX-License-Identifier: GPL-3.0-or-later + +package dk.biks.bachelorizer; + +import java.lang.UnsupportedOperationException; +import java.util.Arrays; + +/* TODO +import dk.biks.bachelorizer.view.Oneshot; +import dk.biks.bachelorizer.view.Prompt; +import dk.biks.bachelorizer.view.Pipe; +import dk.biks.bachelorizer.view.Screen; +*/ +import dk.biks.bachelorizer.view.Window; + +/// Bachelorizer - bachelor programme registrar +/// +/// Tool for registering students +/// for activities in their bachelor programme. +/// +/// Runner class spawning an interactive or non-interactive application +/// based on passed arguments +/// +/// Multi-framework MVC structure inspired by project Криптоанализатор +/// written by Александр Хмелев <akhmelev@gmail.com>. +/// +/// * v0.0.1-draft +/// * initial release, as part of delivery "Portfolio 1" +/// +/// @version 0.0.1-draft +/// @see <https://moodle.ruc.dk/mod/assign/view.php?id=523186> +/// @see <https://github.com/demologin/CryptoAnalyzerLed> +public class Main { + + /// Default constructor + /// + /// @param args command-line arguments or default demo data + public Main(final String[] args) { + + switch (uiFromArgs(args)) { + case "gui" -> { Window.main(args); } +// TODO case "tui" -> { Screen.main(args); } +// TODO case "cli" -> { Line.main(args); } + default -> { + throw new UnsupportedOperationException( + "Not yet implemented."); + } + } + } + + /// JVM entry point + /// + /// @param args command-line arguments + public static void main(String[] args) { + + // inject initial sample data unless passed as arguments + if ((args.length == 0) + || (!Arrays.stream(args).anyMatch( + s -> s != null && !s.startsWith("-"))) + ) { + args = new String[] { + "Jonas Smedegaard", + "CS-SMC2", + "CS-SMC3", + }; + } + + new Main(args); + } + + /// minimal argument parser to detect explicit UI choice + /// + /// @param args command-line arguments + /// @return choice of UI as String + public static String uiFromArgs(String[] args) { + // TODO: make "cli" the default when implemented + String defaultUI = "gui"; + + for (String arg : args) { + if (arg.matches("--(gui|tui|cli)")) { + return (arg.length() == 2) + ? defaultUI + : arg.substring(2); + } + } + + return defaultUI; + } +} diff --git a/src/dk.biks.bachelorizer/dk/biks/bachelorizer/model/Combi.java b/src/dk.biks.bachelorizer/dk/biks/bachelorizer/model/Combi.java new file mode 100644 index 0000000..371eb79 --- /dev/null +++ b/src/dk.biks.bachelorizer/dk/biks/bachelorizer/model/Combi.java @@ -0,0 +1,105 @@ +// SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk> +// SPDX-License-Identifier: GPL-3.0-or-later + +package dk.biks.bachelorizer.model; + +import java.util.Collection; +import java.util.Set; + +import com.example.portfolio3.AdjListGraph; +import com.example.portfolio3.Graph; +import com.example.portfolio3.GraphAlgorithms; +import com.example.portfolio3.MatrixGraph; +import com.example.portfolio3.Vertex; + +/// Combi - static sample dataset of course combinations +/// +/// Slurps and parses data from upstream-provided comma-separated file. +/// +/// @version 0.0.1 +/// @see <https://moodle.ruc.dk/mod/assign/view.php?id=523186> +public final class Combi { + + /// data about combinations as a Graph + private Graph g; + + /// Default constructor + /// + /// @param path path to data file + private Combi(final String path) { + + // read into temporary graph to resolve vertice count + // + // use Adjacency List Representation: + // * cheap to bootstrap (done once) + // * simple to count vertices (done once): O(1) + Graph _g = new AdjListGraph(); + GraphAlgorithms.readGraph(_g, path); + Integer _vertice_count = _g.vertices().size(); + + // read into final graph + // + // use Adjacency Matrix Representation: + // * expensive to bootstrap (done once) + // * simple to add edges but needs vertice count + // * simple to get edges (done repeatedly): O(1) + // + // TODO: avoid reading and parsing file twice + Graph g = new MatrixGraph(_vertice_count); + GraphAlgorithms.readGraph(g, path); + + // ensure the graph is connected + isConnected(g); + + GraphAlgorithms.printGraph(g); + + // release temporary variables for garbage collection + _g = null; + _vertice_count = null; + } + + /// JVM entry point + /// + /// @param args command-line arguments + public static void main(final String[] args) { + + // first argument, if provided, is the data file path; + // else use upstream named file in current directory. + String path = (args.length > 0) + ? args[0] + : "combi.txt"; + + Combi combi = new Combi(path); + } + + /// utility function to check that a graph is connected + /// + /// If check fails, throw an unchecked exception, + /// since it occurs at runtime and is unrecoverable. + /// + /// Time complexity of the operation is O(n²) + /// where n is the amount of vertices, + /// since visitDepthFirst() recurses out-edges of all vertices. + /// + /// @param g Graph to inspect + /// @throws IllegalArgumentException + /// https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html + public static void isConnected(Graph g) { + + // collect all vertices in the graph + Collection<Vertex> c = g.vertices(); + + // pick a random vertice in the graph + Vertex v = g.vertices().iterator().next(); + + // collect the set of visitable vertices + Set<Vertex> visited = GraphAlgorithms.visitDepthFirst( + g, v); + + // throw exception if not all vertices were visited + if (visited.size() != c.size()) { + throw new IllegalArgumentException( + "graph is not connected"); + } + } +} diff --git a/src/dk.biks.bachelorizer/dk/biks/bachelorizer/model/GUI.java b/src/dk.biks.bachelorizer/dk/biks/bachelorizer/model/GUI.java new file mode 100644 index 0000000..ca9bd86 --- /dev/null +++ b/src/dk.biks.bachelorizer/dk/biks/bachelorizer/model/GUI.java @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk> +// SPDX-License-Identifier: GPL-3.0-or-later + +package dk.biks.bachelorizer.model; + +import java.util.ArrayList; + +import dk.biks.bachelorizer.model.Person; + +/// Bachelorizer - GUI model +public class GUI{ + + /// Default constructor + // (declared explicitly only to silence javadoc) + public GUI(){ + } + + /// Activity list + private Person student; + + /// Activity list + private ArrayList<String> list = new ArrayList<>(); + + /// Add student + /// + /// @param name Name of student + public void addStudent(String name){ + student = new Person(name); + } + + /// Get student name + /// + /// @return name of student + public String getStudentName(){ + return student.name; + } + + /// Add activity to list + /// + /// @param s Activity to add + public void addActivity(String s){ + list.add(s); + } + + /// Get list of activities + /// + /// @return activity list + public ArrayList<String> getActivities(){ + return list; + } + + /// Delete last activity from list + public void delOneActivity(){ + if(list.size()>0) + list.remove(list.size()-1); + } + + /// Delete all activities from list + public void delAllActivities(){ + list.clear(); + } +} diff --git a/src/dk.biks.bachelorizer/dk/biks/bachelorizer/model/Person.java b/src/dk.biks.bachelorizer/dk/biks/bachelorizer/model/Person.java new file mode 100644 index 0000000..9edb7af --- /dev/null +++ b/src/dk.biks.bachelorizer/dk/biks/bachelorizer/model/Person.java @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk> +// SPDX-License-Identifier: GPL-3.0-or-later + +package dk.biks.bachelorizer.model; + +/// Bachelorizer - Person model +public class Person { + + /// Person name + public String name; + + /// Constructor + /// + /// @param name Name of person + public Person (String name) { + this.name = name; + } +} diff --git a/src/dk.biks.bachelorizer/dk/biks/bachelorizer/view/Window.java b/src/dk.biks.bachelorizer/dk/biks/bachelorizer/view/Window.java new file mode 100644 index 0000000..c75e290 --- /dev/null +++ b/src/dk.biks.bachelorizer/dk/biks/bachelorizer/view/Window.java @@ -0,0 +1,120 @@ +// SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk> +// SPDX-License-Identifier: GPL-3.0-or-later + +package dk.biks.bachelorizer.view; + +import java.util.List; +import javafx.application.Application; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; +import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; +import javafx.scene.Scene; +import javafx.stage.Stage; + +import dk.biks.bachelorizer.Control; +import dk.biks.bachelorizer.model.GUI; + +/// Bachelorizer - JavaFX Window view +// Class is final to forbid subclassing, +// because object is passed to controller during instatiation +public final class Window extends Application { // the View + + /// Default constructor + // (declared explicitly only to silence javadoc) + public Window() { + } + + /// Label styling + public static String LABEL_STYLE = + "-fx-font-weight: bold; -fx-font-size: 20;"; + + /// Application model + private GUI model = new GUI(); + + /// Application controller + private Control control = new Control(model, this); + + /// Name of student + private TextField nameEntry = new TextField(); + + /// Text entry for adding an activity + private TextField activityEntry = new TextField(); + + /// Text area for activity entries + private TextArea area = new TextArea(); + + /// Button to delete one activity + private Button delOne = new Button("Delete one"); + + /// Button to delete all activities + private Button delAll = new Button("Delete all"); + + /// Application instantiation + /// + /// @param args application parameters + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(Stage stage) { + + // pass application parameters to controller + control.setParameters(getParameters().getRaw()); + + // add listeners +// NameEntry.setOnAction(e -> control.enterName( +// activityEntry.getText())); + activityEntry.setOnAction(e -> control.enterActivity( + activityEntry.getText())); + delOne.setOnAction(e -> control.delOne()); + delAll.setOnAction(e -> control.delAll()); + + // add buttons + VBox root = new VBox(10, + ourHBox("Student", nameEntry), + ourHBox("Add activity", activityEntry), + new HBox(10, delOne, delAll), + area); + + // compose stage + Scene scene = new Scene(root, 500, 500); + stage.setTitle("JavaFX Demo"); + stage.setScene(scene); + stage.show(); + } + + /// action to apply student name + /// + /// @param s Text to apply + public void setStudentName(String s) { + nameEntry.setText(s); + } + + /// action to apply text to area + /// + /// @param s Text to apply + public void setArea(String s) { + area.setText(s); + } + + /// Button action to clear field + public void clearActivityEntry() { + activityEntry.setText(""); + } + + /// Styled HBox with label and TextField + /// + /// @param s Label string + /// @param f Text field + /// @return HBox containing styled label and text field + public HBox ourHBox(String s, TextField f) { + Label label = new Label(s+":"); + label.setStyle(LABEL_STYLE); + + return new HBox(10, label, f); + } +} |