aboutsummaryrefslogtreecommitdiff
path: root/src/com.example.portfolio2/com/example/portfolio2/HelloApplication.java
blob: 300f6263438fbc7be83dfee6397c865c132e58a0 (plain)
  1. package com.example.portfolio2;
  2. import javafx.application.Application;
  3. import javafx.scene.Scene;
  4. import javafx.scene.control.ComboBox;
  5. import javafx.scene.control.Label;
  6. import javafx.scene.control.TextArea;
  7. import javafx.scene.layout.HBox;
  8. import javafx.scene.layout.VBox;
  9. import javafx.stage.Stage;
  10. import java.io.IOException;
  11. import java.sql.*;
  12. import java.util.ArrayList;
  13. import java.util.List;
  14. public class HelloApplication extends Application {
  15. // Initializing model, controller and database objects
  16. private Model model = new Model();
  17. private Controller con = new Controller(model,this);
  18. MyDB myDB = new MyDB();
  19. /* Below is the original implementation of the UI elements with
  20. accompanying, individual calls to setOnAction to specify functionality.
  21. Before changing to a list format,
  22. we made sure methods in controller and model
  23. were generalized to allow for the new structure seamlessly.
  24. private ComboBox<String> programCombo = new ComboBox<>();
  25. private ComboBox<String> subject1Combo = new ComboBox<>();
  26. private ComboBox<String> subject2Combo = new ComboBox<>();
  27. private ComboBox<String> electiveCombo = new ComboBox<>();
  28. private ComboBox<String> programSelect = new ComboBox<>();
  29. private ComboBox<String> subject1Select = new ComboBox<>();
  30. private ComboBox<String> subject2Select = new ComboBox<>();
  31. private ComboBox<String> electiveSelect = new ComboBox<>();
  32. private TextArea programArea = new TextArea();
  33. private TextArea subject1Area = new TextArea();
  34. private TextArea subject2Area = new TextArea();
  35. private TextArea electiveArea = new TextArea();
  36. private Label programEcts = new Label();
  37. private Label subject1Ects = new Label();
  38. private Label subject2Ects = new Label();
  39. private Label electiveEcts = new Label();
  40. private VBox program = new VBox(new Label("Program"), programCombo, programSelect, programArea, programEcts);
  41. private VBox subject1 = new VBox(new Label("Subject 1"), subject1Combo, subject1Select, subject1Area, subject1Ects);
  42. private VBox subject2 = new VBox(new Label("Subject 2"), subject2Combo, subject2Select, subject2Area, subject2Ects);
  43. private VBox elective = new VBox(new Label("Elective"), electiveCombo, electiveSelect, electiveArea, electiveEcts);
  44. */
  45. @Override
  46. public void start(Stage stage) throws IOException {
  47. // Clears old insertions into the participation table
  48. con.initialize();
  49. // Defines a list of columns based on their names.
  50. List<ActivityColumn> columns = List.of(
  51. new ActivityColumn("Program"),
  52. new ActivityColumn("Subject 1"),
  53. new ActivityColumn("Subject 2"),
  54. new ActivityColumn("Elective")
  55. );
  56. // Defines a list of subject modules
  57. List<String> subjectModules = List.of("Computer Science", "Informatik", "Astrology");
  58. // Loop for defining button funtionality for each activity column
  59. for (ActivityColumn col : columns) {
  60. col.nameLabel.setStyle("-fx-font-size: 18px; -fx-padding: 10px;"); // Styling
  61. col.ectsLabel.setStyle("-fx-font-size: 18px; -fx-padding: 10px");
  62. col.categoryCombo.setPrefSize(250, 35);
  63. col.activitySelect.setPrefSize(250, 35);
  64. col.area.setPrefWidth(250);
  65. // All boxes share the same activity logic
  66. col.activitySelect.setOnAction(event -> {
  67. con.onActivitySelected(col.categoryCombo, col.activitySelect, col.area);
  68. con.updateEcts(col.ectsLabel, col.categoryCombo);
  69. });
  70. switch (col.name) { // Switch statement handles different category boxes
  71. case "Program" -> {
  72. col.categoryCombo.getItems().addAll("HumTek", "NatBach");
  73. col.categoryCombo.setOnAction(event -> {
  74. con.onComboSelected(col.categoryCombo, col.activitySelect, col.area);
  75. });
  76. }
  77. case "Subject 1" -> { // We considered using the list for filling the box but couldn't figure it out
  78. col.categoryCombo.getItems().addAll("Computer Science", "Informatik", "Astrology");
  79. col.categoryCombo.setOnAction(event -> {
  80. con.onSubjectModuleSelected(col.categoryCombo, columns.get(2).categoryCombo, subjectModules);
  81. con.onComboSelected(col.categoryCombo, col.activitySelect, col.area);
  82. });
  83. }
  84. case "Subject 2" -> {
  85. col.categoryCombo.getItems().addAll("Computer Science", "Informatik", "Astrology");
  86. col.categoryCombo.setOnAction(event -> { // We figured we have to specify
  87. // the second column like this but reckon there's a better way.
  88. con.onSubjectModuleSelected(col.categoryCombo, columns.get(1).categoryCombo, subjectModules);
  89. con.onComboSelected(col.categoryCombo, col.activitySelect, col.area);
  90. });
  91. }
  92. case "Elective" -> {
  93. col.categoryCombo.setVisible(false); // Hide useless box
  94. con.fillElective(col.activitySelect);
  95. }
  96. }
  97. }
  98. // Define an HBox based on the columns and define the scene based on it.
  99. HBox root = new HBox(columns.get(0).asVBox(), columns.get(1).asVBox(), columns.get(2).asVBox(), columns.get(3).asVBox());
  100. Scene scene = new Scene(root, 1000, 500);
  101. stage.setTitle("Course Selector RUC: Ultimate Deluxe Edition");
  102. stage.setScene(scene);
  103. stage.show();
  104. }
  105. public static void main(String[] args) {
  106. launch();
  107. }
  108. // Class for each column of activities
  109. private class ActivityColumn {
  110. // Each column contains these elements
  111. String name;
  112. Label nameLabel;
  113. ComboBox<String> categoryCombo;
  114. ComboBox<String> activitySelect;
  115. TextArea area;
  116. Label ectsLabel;
  117. ActivityColumn(String name) {
  118. this.name = name;
  119. nameLabel = new Label(name);
  120. categoryCombo = new ComboBox<>();
  121. activitySelect = new ComboBox<>();
  122. area = new TextArea();
  123. ectsLabel = new Label();
  124. // new column, "this.name" to define and saved in the text felt,
  125. // new "nameLabel" to show visual text.
  126. // CategoryCombo creat a dropdown list
  127. // activitySelect creat one more dropdown list with Combobox, possible to choose activity.
  128. // area = new TextArea helps create a text felt to describe the chosen activity
  129. // ectsLabel = new Label shows text for ects points
  130. }
  131. VBox asVBox() {
  132. return new VBox(nameLabel, categoryCombo, activitySelect, area, ectsLabel);
  133. }
  134. }
  135. }
  136. class Controller{
  137. private Model model;
  138. private HelloApplication view; // We do this without using the view directly like this, instead passing options.
  139. void initialize() { // calls on the database
  140. model.initialize();
  141. }
  142. Controller(Model model, HelloApplication view){
  143. this.model=model; this.view=view;
  144. }
  145. void onComboSelected(ComboBox<String> combo, ComboBox<String> select, TextArea area) {
  146. select.getItems().clear(); // Clear the activity selection box
  147. area.clear(); // Clear text area
  148. select.getItems().addAll(model.selectProgram((String) combo.getValue())); // Fill activity box using model method
  149. }
  150. void onActivitySelected(ComboBox<String> combo, ComboBox<String> select, TextArea area) {
  151. addActivity((String) select.getValue(), area); // Passes the value chosen in the box
  152. updateArea(combo, area); // Updates the text area based on the category choice
  153. // users can choose from the ComboBox, string (activity) and the area would update.
  154. }
  155. void onSubjectModuleSelected(ComboBox<String> subject1, ComboBox<String> subject2, List<String> subjectModules) {
  156. // Beautiful loop we've created to remove option chosen in one subject module box from the other
  157. for (String sub : subjectModules) {
  158. if (sub.equals(subject1.getValue())) {
  159. subject2.getItems().remove(subject1.getValue());
  160. } else if (!sub.equals(subject1.getValue()) && !subject2.getItems().contains(sub)) {
  161. subject2.getItems().add(sub);
  162. }
  163. }
  164. }
  165. void addActivity(String s, TextArea textArea) { // Calls on model method to add participation in the database
  166. model.addParticipation(model.getActivityIndeks(s));
  167. }
  168. void updateArea(ComboBox combo, TextArea textArea) { // Clears the text area and adds all activity names from activities in participation
  169. textArea.clear();
  170. for(String s : model.getParticipation((String) combo.getValue())) {
  171. textArea.appendText(s + "\n");
  172. }
  173. }
  174. void updateEcts(Label ectslabel, ComboBox<String> comboBox) { // Updates the labels with the current ECTS of the program type
  175. ectslabel.setText("ECTS: "+model.getSumEcts(comboBox.getValue()));
  176. }
  177. void fillElective(ComboBox<String> electiveBox) {
  178. electiveBox.getItems().addAll(model.getAllActivities());
  179. }
  180. }
  181. class Model{ // The model handles all interactions with the database
  182. MyDB db=new MyDB();
  183. Model(){}
  184. void initialize() { // When running the program, it clears the participation database
  185. clearParticipation();
  186. }
  187. int getActivityIndeks(String name) { // Returns the integer value of the activity's index
  188. if(name ==null) return -1;
  189. ArrayList<String> result = db.query("select indeks from activity a where name is '"+name+"';", "indeks");
  190. return Integer.parseInt(result.getFirst());
  191. }
  192. void addParticipation(int activityIndex) { // Inserts the given activity into participation using the activity's index
  193. db.cmd("insert into participation values(123, "+activityIndex+");");
  194. }
  195. ArrayList<String> getParticipation(String program) { // Returns all activity names from activities currently in participation
  196. return db.query("select name from participation p inner join activity a on p.indeks = a.indeks where program is '" + program + "';", "name");
  197. }
  198. void clearParticipation() { // Removes all entries in the participation database
  199. db.cmd("delete from participation");
  200. }
  201. ArrayList<String> selectProgram(String program) { // Returns an arraylist of activities within the given program
  202. return db.query("select name from activity where program is '" + program + "';", "name");
  203. }
  204. String getSumEcts(String program){ // Returns the sum of ECTS points under the given category from the student as a string
  205. if(program==null)return "0";
  206. ArrayList<String> result = db.query("select sum(activity.ects) as total_ects,student.name from student left outer join participation on student.studid = participation.studid inner join activity on participation.indeks = activity.indeks where program is '"+program+"' group by student.studid ;", "total_ects");
  207. if (result.isEmpty()) return "0";
  208. return result.getFirst();
  209. }
  210. ArrayList<String> getAllActivities() {
  211. return db.query("select name from activity;", "name");
  212. }
  213. }
  214. class MyDB { // MyDB is all standard Database configuration that was gotten from Mads
  215. Connection conn = null;
  216. MyDB() {
  217. if (conn == null) open();
  218. }
  219. public void open() {
  220. try {
  221. String url = "jdbc:sqlite:identifier.sqlite";
  222. conn = DriverManager.getConnection(url);
  223. } catch (SQLException e) {
  224. System.out.println("cannot open");
  225. if (conn != null) close();
  226. throw new RuntimeException(e);
  227. }
  228. ;
  229. }
  230. public void close() {
  231. try {
  232. if (conn != null) conn.close();
  233. } catch (SQLException e) {
  234. throw new RuntimeException(e);
  235. }
  236. conn = null;
  237. }
  238. public void cmd(String sql) {
  239. if (conn == null) open();
  240. if (conn == null) {
  241. System.out.println("No connection");
  242. return;
  243. }
  244. Statement stmt = null;
  245. try {
  246. stmt = conn.createStatement();
  247. stmt.executeUpdate(sql);
  248. } catch (SQLException e) {
  249. System.out.println("Error in statement " + sql);
  250. throw new RuntimeException(e);
  251. }
  252. try {
  253. if (stmt != null) {
  254. stmt.close();
  255. }
  256. } catch (SQLException e) {
  257. System.out.println("Error in statement " + sql);
  258. throw new RuntimeException(e);
  259. }
  260. }
  261. public ArrayList<String> query(String query, String fld) {
  262. ArrayList<String> res = new ArrayList<>();
  263. if (conn == null) open();
  264. if (conn == null) {
  265. System.out.println("No connection");
  266. throw new RuntimeException("No connection");
  267. }
  268. Statement stmt = null;
  269. try {
  270. stmt = conn.createStatement();
  271. ResultSet rs = stmt.executeQuery(query);
  272. while (rs.next()) {
  273. String name = rs.getString(fld);
  274. res.add(name);
  275. }
  276. } catch (SQLException e) {
  277. System.out.println("Error in statement " + query + " " + fld);
  278. throw new RuntimeException(e);
  279. }
  280. try {
  281. if (stmt != null) {
  282. stmt.close();
  283. }
  284. } catch (SQLException e) {
  285. System.out.println("Error in statement " + query + " " + fld);
  286. throw new RuntimeException(e);
  287. }
  288. return res;
  289. }
  290. }