├── .gitignore ├── JSONsimple ├── .gitkeep └── json-simple-1.1.1.jar ├── JavaFX ├── .gitkeep └── lib │ ├── .gitkeep │ ├── javafx-swt.jar │ ├── javafx.base.jar │ ├── javafx.controls.jar │ ├── javafx.fxml.jar │ ├── javafx.graphics.jar │ ├── javafx.media.jar │ ├── javafx.properties │ ├── javafx.swing.jar │ ├── javafx.web.jar │ └── src.zip ├── README.md ├── input.json ├── out └── production │ └── project-13-design │ ├── JavaFxApplication.iml │ ├── META-INF │ └── project-13-design.kotlin_module │ └── sample │ ├── main.css │ └── main.html ├── project-13-design.iml └── src ├── JavaFxApplication.iml ├── controllers ├── AlertHelper.java ├── MainController.java ├── ProjectOverviewController.java ├── ProjectScheduleController.java ├── dashboardController.java ├── editMemberController.java ├── milestonesController.java ├── newMemberController.java ├── riskMatrixController.java └── userInfoController.java ├── fxml-files ├── contactUs.fxml ├── dashboard.fxml ├── editMember.fxml ├── milestones.fxml ├── newMember.fxml ├── projectOverview.fxml ├── projectSchedule.fxml ├── riskMatrix.fxml └── userInfo.fxml ├── id_generator └── GeneratorMain.java ├── json_reader_writer ├── JsonReader.java └── JsonWriter.java ├── member_manager ├── Member.java ├── Milestone.java ├── Planner.java ├── RiskMatrix.java ├── Schedule.java └── Timesheet.java └── sample ├── Main.java └── main.css /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /out/ 3 | .out/ 4 | *.iml 5 | /test.json -------------------------------------------------------------------------------- /JSONsimple/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brother-Blue/Mini-Project-Team-programming/4eb7caac477e12bc9e1783ba69332aa6cd2c9eb5/JSONsimple/.gitkeep -------------------------------------------------------------------------------- /JSONsimple/json-simple-1.1.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brother-Blue/Mini-Project-Team-programming/4eb7caac477e12bc9e1783ba69332aa6cd2c9eb5/JSONsimple/json-simple-1.1.1.jar -------------------------------------------------------------------------------- /JavaFX/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brother-Blue/Mini-Project-Team-programming/4eb7caac477e12bc9e1783ba69332aa6cd2c9eb5/JavaFX/.gitkeep -------------------------------------------------------------------------------- /JavaFX/lib/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brother-Blue/Mini-Project-Team-programming/4eb7caac477e12bc9e1783ba69332aa6cd2c9eb5/JavaFX/lib/.gitkeep -------------------------------------------------------------------------------- /JavaFX/lib/javafx-swt.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brother-Blue/Mini-Project-Team-programming/4eb7caac477e12bc9e1783ba69332aa6cd2c9eb5/JavaFX/lib/javafx-swt.jar -------------------------------------------------------------------------------- /JavaFX/lib/javafx.base.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brother-Blue/Mini-Project-Team-programming/4eb7caac477e12bc9e1783ba69332aa6cd2c9eb5/JavaFX/lib/javafx.base.jar -------------------------------------------------------------------------------- /JavaFX/lib/javafx.controls.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brother-Blue/Mini-Project-Team-programming/4eb7caac477e12bc9e1783ba69332aa6cd2c9eb5/JavaFX/lib/javafx.controls.jar -------------------------------------------------------------------------------- /JavaFX/lib/javafx.fxml.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brother-Blue/Mini-Project-Team-programming/4eb7caac477e12bc9e1783ba69332aa6cd2c9eb5/JavaFX/lib/javafx.fxml.jar -------------------------------------------------------------------------------- /JavaFX/lib/javafx.graphics.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brother-Blue/Mini-Project-Team-programming/4eb7caac477e12bc9e1783ba69332aa6cd2c9eb5/JavaFX/lib/javafx.graphics.jar -------------------------------------------------------------------------------- /JavaFX/lib/javafx.media.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brother-Blue/Mini-Project-Team-programming/4eb7caac477e12bc9e1783ba69332aa6cd2c9eb5/JavaFX/lib/javafx.media.jar -------------------------------------------------------------------------------- /JavaFX/lib/javafx.properties: -------------------------------------------------------------------------------- 1 | javafx.version=11.0.2 2 | javafx.runtime.version=11.0.2+1 3 | javafx.runtime.build=1 4 | -------------------------------------------------------------------------------- /JavaFX/lib/javafx.swing.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brother-Blue/Mini-Project-Team-programming/4eb7caac477e12bc9e1783ba69332aa6cd2c9eb5/JavaFX/lib/javafx.swing.jar -------------------------------------------------------------------------------- /JavaFX/lib/javafx.web.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brother-Blue/Mini-Project-Team-programming/4eb7caac477e12bc9e1783ba69332aa6cd2c9eb5/JavaFX/lib/javafx.web.jar -------------------------------------------------------------------------------- /JavaFX/lib/src.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brother-Blue/Mini-Project-Team-programming/4eb7caac477e12bc9e1783ba69332aa6cd2c9eb5/JavaFX/lib/src.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Project description 2 | Software tool to manage a software project. 3 | * Use data from our project. 4 | * The demo should be pre-loaded with actual data generated during the development of the project itself. 5 | * (input file) will be specified/stored via a JSON file or any other convenient format/technology. 6 | * The structure and content of the input is up to the imagination of the project group. 7 | * Each project group member should have a unique number (i.e., member ID) to be used in search functionality. 8 | 9 | # Features 10 | * [ ] Earned Value (EV)should be calculated at intervals of 2 weeks. 11 | * [ ] Schedule Variance (SV)should be calculated at intervals of 2 weeks. 12 | * [ ] Cost Variance (CV)should be calculated at intervals of 2 weeks. 13 | * [ ] Risk Matrixshould indicate the risk = impact x likelihood. 14 | * [ ] Project Scheduleindicating activity, start week and end week. 15 | * [ ] Time spent on the project per team member. 16 | * [ ] The system should be able to search by team member to show the time spent by the member. 17 | * [ ] The system should be able to search by team member to show the work products where (s)he has participated. 18 | 19 | # Other files 20 | [Trello](https://trello.com/b/e9JXYcHB/group-13)
21 | [Time spent](https://docs.google.com/spreadsheets/d/11prYMzwm3u-r01q-JYTA9KiewqtteWdSsmUbRfXNwww/edit#gid=634347005)
22 | [Role description](https://docs.google.com/document/d/195QX52F8_163NgF6ZDA371yS6VPNdnxj2ce9t3elpsw/edit)
23 | [Role schedule](https://docs.google.com/spreadsheets/d/11prYMzwm3u-r01q-JYTA9KiewqtteWdSsmUbRfXNwww/edit#gid=1063704) 24 | # Authors 25 | * Altug Altetmek 26 | * Christian O'Neill 27 | * Clementne Jensen 28 | * Hjalmar Thunberg 29 | * Hugo Hempel 30 | * Linus Ivarsson 31 | * Linus Åberg 32 | 33 | -------------------------------------------------------------------------------- /input.json: -------------------------------------------------------------------------------- 1 | 2 | 3 | { 4 | "endDate": "2020-01-10", 5 | "members": [ 6 | { 7 | "firstName": "Hjalmar", 8 | "lastName": "Thunberg", 9 | "ID": "18619", 10 | "salary": "250.0" 11 | }, 12 | { 13 | "firstName": "Altug", 14 | "lastName": "Altetmek", 15 | "ID": "14587", 16 | "salary": "210.0" 17 | }, 18 | { 19 | "firstName": "Christian", 20 | "lastName": "O'Neill", 21 | "ID": "23787", 22 | "salary": "145.0" 23 | }, 24 | { 25 | "firstName": "Clementine", 26 | "lastName": "Jensen", 27 | "ID": "26162", 28 | "salary": "220.0" 29 | }, 30 | { 31 | "firstName": "Hugo", 32 | "lastName": "Hempel", 33 | "ID": "13209", 34 | "salary": "250.0" 35 | }, 36 | { 37 | "firstName": "Linus", 38 | "lastName": "Ivarsson", 39 | "ID": "14975", 40 | "salary": "150.0" 41 | }, 42 | { 43 | "firstName": "Linus", 44 | "lastName": "Åberg", 45 | "ID": "17004", 46 | "salary": "280.0" 47 | } 48 | ], 49 | "riskMatrix": [ 50 | { 51 | "riskName": "Json files become corrupted \nand all data is lost", 52 | "unlikely": "Severe", 53 | "veryLikely": "Catastrophic", 54 | "possible": "Catastrophic" 55 | }, 56 | { 57 | "riskName": "Developer corrupts the \ndata on purpose", 58 | "unlikely": "Moderate", 59 | "veryLikely": "Catastrophic", 60 | "possible": "Catastrophic" 61 | }, 62 | { 63 | "riskName": "Software not matching \nthe requirements", 64 | "unlikely": "Moderate", 65 | "veryLikely": "Catastrophic", 66 | "possible": "Severe" 67 | }, 68 | { 69 | "riskName": "User finds the UI \ncomplicated to use", 70 | "unlikely": "Low", 71 | "veryLikely": "Catastrophic", 72 | "possible": "Moderate" 73 | }, 74 | { 75 | "riskName": "Developer dies", 76 | "unlikely": "Low", 77 | "veryLikely": "Catastrophic", 78 | "possible": "Moderate" 79 | }, 80 | { 81 | "riskName": "Bugs after release", 82 | "unlikely": "Moderate", 83 | "veryLikely": "Severe", 84 | "possible": "Severe" 85 | }, 86 | { 87 | "riskName": "GitLab crashes and team can’t function in a collaborative way", 88 | "unlikely": "Moderate", 89 | "veryLikely": "Severe", 90 | "possible": "Severe" 91 | }, 92 | { 93 | "riskName": "Hardware malfunction", 94 | "unlikely": "Low", 95 | "veryLikely": "Severe", 96 | "possible": "Moderate" 97 | }, 98 | { 99 | "riskName": "Miscommunication between developers", 100 | "unlikely": "Low", 101 | "veryLikely": "Severe", 102 | "possible": "Moderate" 103 | }, 104 | { 105 | "riskName": "Developer drops out", 106 | "unlikely": "Low", 107 | "veryLikely": "Severe", 108 | "possible": "Moderate" 109 | }, 110 | { 111 | "riskName": "User does not understand the language of the software", 112 | "unlikely": "Low", 113 | "veryLikely": "Moderate", 114 | "possible": "Low" 115 | } 116 | ], 117 | "projectName": "Project 13", 118 | "timesheet": [ 119 | { 120 | "week": "1", 121 | "hoursWorked": { 122 | "26162": "11", 123 | "17004": "4", 124 | "13209": "4", 125 | "14587": "2", 126 | "18619": "8", 127 | "23787": "7", 128 | "14975": "5" 129 | }, 130 | "percentComplete" : "0.05" 131 | }, 132 | { 133 | "week": "2", 134 | "hoursWorked": { 135 | "26162": "17", 136 | "17004": "1", 137 | "13209": "2", 138 | "14587": "11", 139 | "18619": "12", 140 | "23787": "12", 141 | "14975": "2" 142 | }, 143 | "percentComplete" : "0.11" 144 | }, 145 | { 146 | "week": "3", 147 | "hoursWorked": { 148 | "26162": "17", 149 | "17004": "20", 150 | "13209": "12", 151 | "14587": "14", 152 | "18619": "15", 153 | "23787": "11", 154 | "14975": "20" 155 | }, 156 | "percentComplete" : "0.18" 157 | }, 158 | { 159 | "week": "4", 160 | "hoursWorked": { 161 | "26162": "2", 162 | "17004": "14", 163 | "13209": "4", 164 | "14587": "1", 165 | "18619": "4", 166 | "23787": "27", 167 | "14975": "23" 168 | }, 169 | "percentComplete" : "0.41" 170 | }, 171 | { 172 | "week": "5", 173 | "hoursWorked": { 174 | "26162": "0", 175 | "17004": "0", 176 | "13209": "0", 177 | "14587": "0", 178 | "18619": "0", 179 | "23787": "8", 180 | "14975": "0" 181 | }, 182 | "percentComplete" : "0.64" 183 | }, 184 | { 185 | "week": "6", 186 | "hoursWorked": { 187 | "26162": "0", 188 | "17004": "0", 189 | "13209": "0", 190 | "14587": "0", 191 | "18619": "0", 192 | "23787": "2", 193 | "14975": "0" 194 | }, 195 | "percentComplete" : "0.85" 196 | }, 197 | { 198 | "week": "7", 199 | "hoursWorked": { 200 | "26162": "0", 201 | "17004": "0", 202 | "13209": "0", 203 | "14587": "0", 204 | "18619": "0", 205 | "23787": "0", 206 | "14975": "0" 207 | }, 208 | "percentComplete" : "0.87" 209 | }, 210 | { 211 | "week": "8", 212 | "hoursWorked": { 213 | "26162": "0", 214 | "17004": "0", 215 | "13209": "0", 216 | "14587": "0", 217 | "18619": "0", 218 | "23787": "7", 219 | "14975": "0" 220 | }, 221 | "percentComplete" : "0.89" 222 | }, 223 | { 224 | "week": "9", 225 | "hoursWorked": { 226 | "26162": "0", 227 | "17004": "0", 228 | "13209": "0", 229 | "14587": "0", 230 | "18619": "0", 231 | "23787": "0", 232 | "14975": "0" 233 | }, 234 | "percentComplete" : "0.0" 235 | }, 236 | { 237 | "week": "10", 238 | "hoursWorked": { 239 | "26162": "0", 240 | "17004": "0", 241 | "13209": "0", 242 | "14587": "0", 243 | "18619": "0", 244 | "23787": "0", 245 | "14975": "0" 246 | }, 247 | "percentComplete" : "1.0" 248 | } 249 | ], 250 | "milestones": [ 251 | { 252 | "actualEndDate": "2019-11-14", 253 | "milestoneName": "Planning Meetings", 254 | "milestoneDescription": "Group got together and planned the week", 255 | "startDate": "2019-11-11", 256 | "plannedEndDate": "2019-11-15", 257 | "hoursPerMember": { 258 | "26162": "3.0", 259 | "17004": "3.0", 260 | "13209": "3.0", 261 | "14587": "3.0", 262 | "18619": "3.0", 263 | "23787": "3.0", 264 | "14975": "3.0" 265 | } 266 | }, 267 | { 268 | "actualEndDate": "2019-12-22", 269 | "milestoneName": "Create FXML files", 270 | "milestoneDescription": "Create and complete all FXML files", 271 | "startDate": "2019-11-22", 272 | "plannedEndDate": "2019-11-15", 273 | "hoursPerMember": { 274 | "26162": "19.0", 275 | "17004": "0.0", 276 | "13209": "10.0", 277 | "14587": "0.0", 278 | "18619": "0.0", 279 | "23787": "9.0", 280 | "14975": "16.0" 281 | } 282 | }, 283 | { 284 | "actualEndDate": "2019-11-15", 285 | "milestoneName": "Class diagram", 286 | "milestoneDescription": "Creating a complete class diagram over our software", 287 | "startDate": "2019-11-13", 288 | "plannedEndDate": "2019-11-15", 289 | "hoursPerMember": { 290 | "26162": "2.0", 291 | "17004": "0.0", 292 | "13209": "0.0", 293 | "14587": "0.0", 294 | "18619": "3.0", 295 | "23787": "8.0", 296 | "14975": "2.0" 297 | } 298 | }, 299 | { 300 | "actualEndDate": "2019-12-22", 301 | "milestoneName": "Create Controllers", 302 | "milestoneDescription": "Creating all controllers classes for our interface", 303 | "startDate": "2019-11-22", 304 | "plannedEndDate": "2019-11-27", 305 | "hoursPerMember": { 306 | "26162": "18.0", 307 | "17004": "0.0", 308 | "13209": "10.0", 309 | "14587": "0.0", 310 | "18619": "0.0", 311 | "23787": "18.0", 312 | "14975": "18.0" 313 | } 314 | }, 315 | { 316 | "actualEndDate": "2020-01-10", 317 | "milestoneName": "Develop methods", 318 | "milestoneDescription": "Complete all methods for the software", 319 | "startDate": "2019-11-18", 320 | "plannedEndDate": "2020-01-10", 321 | "hoursPerMember": { 322 | "26162": "10.0", 323 | "17004": "18.0", 324 | "13209": "11.0", 325 | "14587": "10.0", 326 | "18619": "17.0", 327 | "23787": "14.0", 328 | "14975": "8.0" 329 | } 330 | }, 331 | { 332 | "actualEndDate": "2019-12-22", 333 | "milestoneName": "Implement JSON", 334 | "milestoneDescription": "Create JSON reader, writer and input files", 335 | "startDate": "2019-11-25", 336 | "plannedEndDate": "2019-11-15", 337 | "hoursPerMember": { 338 | "26162": "0.0", 339 | "17004": "14.0", 340 | "13209": "0.0", 341 | "14587": "20.0", 342 | "18619": "17.0", 343 | "23787": "5.0", 344 | "14975": "4.0" 345 | } 346 | }, 347 | { 348 | "actualEndDate": "2020-01-09", 349 | "milestoneName": "Finish coding", 350 | "milestoneDescription": "Complete the entire code for the entire software", 351 | "startDate": "2019-11-25", 352 | "plannedEndDate": "2019-01-10", 353 | "hoursPerMember": { 354 | "26162": "6.0", 355 | "17004": "14.0", 356 | "13209": "11.0", 357 | "14587": "15.0", 358 | "18619": "10.0", 359 | "23787": "16.0", 360 | "14975": "8.0" 361 | } 362 | }, 363 | { 364 | "actualEndDate": "2020-01-10", 365 | "milestoneName": "Final report", 366 | "milestoneDescription": "Write the final report for our course", 367 | "startDate": "2019-12-17", 368 | "plannedEndDate": "2020-01-17", 369 | "hoursPerMember": { 370 | "26162": "8.0", 371 | "17004": "8.0", 372 | "13209": "8.0", 373 | "14587": "8.0", 374 | "18619": "8.0", 375 | "23787": "8.0", 376 | "14975": "8.0" 377 | } 378 | }, 379 | { 380 | "actualEndDate": "2020-01-10", 381 | "milestoneName": "Create executable", 382 | "milestoneDescription": "Create a executable program of our software", 383 | "startDate": "2019-12-17", 384 | "plannedEndDate": "2020-01-10", 385 | "hoursPerMember": { 386 | "26162": "0.0", 387 | "17004": "4.0", 388 | "13209": "0.0", 389 | "14587": "0.0", 390 | "18619": "0.0", 391 | "23787": "0.0", 392 | "14975": "0.0" 393 | } 394 | }, 395 | { 396 | "actualEndDate": "2019-12-01", 397 | "milestoneName": "Migration to JavaFX", 398 | "milestoneDescription": "Move our Java based project to a new one and migrate it to JavaFX", 399 | "startDate": "2019-11-18", 400 | "plannedEndDate": "2019-11-29", 401 | "hoursPerMember": { 402 | "26162": "6.0", 403 | "17004": "0.0", 404 | "13209": "0.0", 405 | "14587": "0.0", 406 | "18619": "0.0", 407 | "23787": "1.0", 408 | "14975": "1.0" 409 | } 410 | } 411 | ], 412 | "startDate": "2019-11-08", 413 | "budget": "43000.0" 414 | } 415 | 416 | -------------------------------------------------------------------------------- /out/production/project-13-design/JavaFxApplication.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /out/production/project-13-design/META-INF/project-13-design.kotlin_module: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /out/production/project-13-design/sample/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | height: 100%; 3 | width: 100%; 4 | background-image: linear-gradient(to bottom right, #b4b4b4, #4bb4bb); 5 | background-repeat: no-repeat; 6 | } 7 | 8 | .main-bar { 9 | font-size: 3em; 10 | color: #3e3e3e; 11 | text-shadow: 3px 2px 5px #4bb4bb; 12 | float: left; 13 | padding-bottom: 25px; 14 | margin-bottom: 30px; 15 | } 16 | 17 | .id-search-bar { 18 | float: left; 19 | padding-top: 50px; 20 | } 21 | 22 | .about-member { 23 | float: right; 24 | padding-top: 50px; 25 | } 26 | 27 | * { 28 | box-sizing: border-box; 29 | } 30 | 31 | form.id-search-form input[type=text]{ 32 | padding: 10px; 33 | font-size: 15px; 34 | border: 1px solid gray; 35 | float: left; 36 | width: 40%; 37 | background: #b4b4b4; 38 | } 39 | 40 | form.id-search-form button { 41 | float: left; 42 | padding: 10px; 43 | background: #4bb4bb; 44 | color: white; 45 | border: 1px solid gray; 46 | border-left: none; 47 | cursor: pointer; 48 | } 49 | 50 | form.id-search-form button:hover { 51 | background-color: #44a4aa; 52 | } 53 | 54 | form.id-search-form::after { 55 | content: ""; 56 | clear: both; 57 | display: table; 58 | } 59 | 60 | .member-table-display { 61 | width: 80%; 62 | box-shadow: 8px 8px 3px rgba(0, 0, 0, 0.25); 63 | } 64 | 65 | .about-member { 66 | padding-right: 20px; 67 | height: 450px; 68 | overflow: auto; 69 | box-shadow: -8px 8px 3px rgba(0, 0, 0, 0.25); 70 | } 71 | 72 | .personIcon { 73 | width: 100px; 74 | } 75 | 76 | .search-bar-dropdown { 77 | padding: 0; 78 | margin-bottom: 35px; 79 | width: 80%; 80 | background: #4bb4bb; 81 | border-top: none; 82 | box-shadow: 2px 2px 1px rgba(0, 0, 0, 0.25); 83 | } 84 | 85 | .search-bar-dropdown button { 86 | width: 100%; 87 | text-align: center; 88 | padding: 5px; 89 | color: white; 90 | border: 1px solid gray; 91 | border-top: none; 92 | } 93 | 94 | .dropdown-menu { 95 | border-bottom: 2px solid #bbbbbb; 96 | } -------------------------------------------------------------------------------- /out/production/project-13-design/sample/main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Group 13 Project 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
G.13 Project Manager
18 | 19 | 97 | 98 |
99 | Yo face here 100 |
101 |

About #Member#

102 | 103 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

104 |
105 |
106 | 107 | -------------------------------------------------------------------------------- /project-13-design.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/JavaFxApplication.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/controllers/AlertHelper.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import javafx.scene.control.Alert; 4 | import javafx.stage.Window; 5 | 6 | public class AlertHelper { 7 | 8 | public static void showAlert(Alert.AlertType alertType, Window owner, String title, String message) { 9 | Alert alert = new Alert(alertType); 10 | alert.setTitle(title); 11 | alert.setHeaderText(null); 12 | alert.setContentText(message); 13 | alert.initOwner(owner); 14 | alert.show(); 15 | } 16 | } -------------------------------------------------------------------------------- /src/controllers/MainController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import id_generator.GeneratorMain; 4 | import javafx.scene.chart.*; 5 | import javafx.scene.control.*; 6 | import javafx.scene.text.Text; 7 | import json_reader_writer.JsonReader; 8 | import member_manager.Member; 9 | import member_manager.Milestone; 10 | import member_manager.Planner; 11 | import javafx.collections.FXCollections; 12 | import javafx.collections.ObservableList; 13 | import javafx.event.ActionEvent; 14 | import javafx.fxml.FXML; 15 | import javafx.fxml.FXMLLoader; 16 | import javafx.scene.Node; 17 | import javafx.scene.Parent; 18 | import javafx.scene.Scene; 19 | import javafx.stage.Stage; 20 | import javafx.stage.Window; 21 | 22 | import java.io.IOException; 23 | import java.util.ArrayList; 24 | 25 | public class MainController { 26 | 27 | static Planner planner; 28 | 29 | // This code is for all back buttons that go back to the dashboard. 30 | @FXML 31 | public void back(ActionEvent event) throws IOException { 32 | 33 | Parent backMemberParent = FXMLLoader.load(getClass().getResource("../fxml-files/dashboard.fxml")); 34 | Scene backMemberScene = new Scene(backMemberParent); 35 | 36 | Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow(); 37 | 38 | window.setScene(backMemberScene); 39 | window.show(); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/controllers/ProjectOverviewController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import javafx.beans.property.ObjectProperty; 4 | import javafx.collections.FXCollections; 5 | import javafx.collections.ObservableList; 6 | import javafx.event.ActionEvent; 7 | import javafx.fxml.FXML; 8 | import javafx.fxml.FXMLLoader; 9 | import javafx.fxml.Initializable; 10 | import javafx.scene.Node; 11 | import javafx.scene.Parent; 12 | import javafx.scene.Scene; 13 | import javafx.scene.chart.*; 14 | import javafx.scene.control.*; 15 | import javafx.stage.Stage; 16 | import javafx.stage.Window; 17 | import javafx.util.Duration; 18 | import member_manager.Member; 19 | 20 | import java.io.IOException; 21 | import java.net.URL; 22 | import java.util.ArrayList; 23 | import java.util.ResourceBundle; 24 | 25 | public class ProjectOverviewController extends MainController implements Initializable { 26 | 27 | @FXML 28 | private ComboBox calculatorDropdown; 29 | @FXML 30 | private ComboBox weekSelectionDropdown; 31 | @FXML 32 | private TextField calcResult; 33 | @FXML 34 | private TextArea calcFormula; 35 | @FXML 36 | private TextArea calcDescrip; 37 | @FXML 38 | private AreaChart areaChart; 39 | @FXML 40 | private CategoryAxis xAxis; 41 | @FXML 42 | private NumberAxis yAxis; 43 | @FXML 44 | private Button searchButton; 45 | 46 | private int weekSelected = 1; 47 | 48 | public void riskMatrixView(ActionEvent event) throws IOException { 49 | Parent riskMatrixMemberParent = FXMLLoader.load(getClass().getResource("../fxml-files/riskMatrix.fxml")); 50 | Scene riskMatrixMemberScene = new Scene(riskMatrixMemberParent); 51 | 52 | Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow(); 53 | 54 | window.setScene(riskMatrixMemberScene); 55 | window.show(); 56 | } 57 | 58 | public void projectScheduleView(ActionEvent event) throws IOException{ 59 | Parent projectScheduleParent = FXMLLoader.load(getClass().getResource("../fxml-files/projectSchedule.fxml")); 60 | Scene projectScheduleScene = new Scene(projectScheduleParent); 61 | 62 | Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow(); 63 | 64 | window.setScene(projectScheduleScene); 65 | window.show(); 66 | } 67 | 68 | public void weekSelected() { 69 | weekSelected = Integer.parseInt(weekSelectionDropdown.getValue().toString().substring(5)); 70 | calcSelection(); 71 | } 72 | 73 | @Override 74 | public void initialize(URL url, ResourceBundle resourceBundle) { 75 | 76 | ObservableList calcOptions = FXCollections.observableArrayList(); 77 | calcOptions.addAll("Planned Value (PV)", "Earned Value (EV)", "Actual Cost (AC)", 78 | "Budget at Completion (BAC)", "Schedule Variance (SV)", 79 | "Schedule Performance Index (SPI)", "Cost Variance (CV)", 80 | "Cost Performance Index (CPI)"); 81 | 82 | ObservableList weekOptions = FXCollections.observableArrayList(); 83 | weekOptions.addAll("Week 1", "Week 2", "Week 3", "Week 4", "Week 5", "Week 6", "Week 7", "Week 8", "Week 9"); 84 | 85 | weekSelectionDropdown.setItems(weekOptions); 86 | calculatorDropdown.setItems(calcOptions); 87 | 88 | xAxis.setAnimated(false); 89 | yAxis.setAnimated(false); 90 | } 91 | 92 | public void calcSelection() { 93 | Window owner = calculatorDropdown.getScene().getWindow(); 94 | String selection = calculatorDropdown.getValue().toString(); 95 | 96 | if (selection == null){ 97 | AlertHelper.showAlert(Alert.AlertType.ERROR, owner, "Error", "Please select an option"); 98 | } else if (selection == "Planned Value (PV)"){ 99 | plannedValue(); 100 | } else if (selection == "Earned Value (EV)"){ 101 | earnedValue(); 102 | } else if (selection == "Actual Cost (AC)") { 103 | actualCost(); 104 | } else if (selection == "Budget at Completion (BAC)") { 105 | budgetAtCompl(); 106 | } else if (selection == "Schedule Variance (SV)") { 107 | scheduleVariance(); 108 | } else if (selection == "Schedule Performance Index (SPI)") { 109 | schedulePerfIndex(); 110 | } else if (selection == "Cost Variance (CV)") { 111 | costVariance(); 112 | } else if (selection == "Cost Performance Index (CPI)"){ 113 | costPerfIndex(); 114 | } 115 | } 116 | 117 | public void plannedValue(){ 118 | searchButton.setDisable(true); 119 | ArrayList results = planner.calcPv(); 120 | XYChart.Series pvSeries = new XYChart.Series(); 121 | areaChart.getData().clear(); 122 | 123 | calcDescrip.setText("Planned value is the relation between the amount of days a current milestone has been worked on and the current budget. " + 124 | "The current days are measured from when the milestone started up to the current day."); //calcWeek - 1 brings the graph value thats displayed ti the correct value. 125 | calcResult.setText("Current week: " + weekSelected + ", Planned Value: " + results.get(Integer.valueOf(weekSelected)-1) + "SEK\n"); 126 | calcFormula.setText("Planned Value = Days worked / Total days worked (Expected)"); 127 | 128 | pvSeries.setName("PV Values"); 129 | xAxis.setLabel("Week"); 130 | yAxis.setLabel("Amount (SEK)"); 131 | 132 | for (int i = 0; i < results.size(); i++) { 133 | pvSeries.getData().add(new XYChart.Data(Integer.toString(i+1), results.get(i))); 134 | } 135 | areaChart.getData().add(pvSeries); 136 | } 137 | public void earnedValue(){ 138 | ArrayList results = planner.calcEv(); 139 | searchButton.setDisable(true); 140 | XYChart.Series evSeries = new XYChart.Series(); 141 | areaChart.getData().clear(); 142 | 143 | calcDescrip.setText("Expenditures that should have been realised given the actual technical project progress (based on\n" + 144 | "the expenditure plan) (From lecture slides)"); 145 | calcResult.setText("Current week: " + weekSelected + ", Earned Value: " + results.get(Integer.valueOf(weekSelected)-1) + "SEK\n"); 146 | calcFormula.setText("Percentage of Project Complete * Project Budget"); 147 | 148 | evSeries.setName("Earned Value"); 149 | xAxis.setLabel("Week"); 150 | yAxis.setLabel("Amount (SEK)"); 151 | 152 | for (int i = 0; i < results.size(); i++) { 153 | evSeries.getData().add(new XYChart.Data(Integer.toString(i+1), results.get(i))); 154 | } 155 | 156 | areaChart.getData().add(evSeries); 157 | 158 | } 159 | public void actualCost(){ 160 | ArrayList results = planner.calcActualCost(); 161 | searchButton.setDisable(true); 162 | XYChart.Series acSeries = new XYChart.Series(); 163 | areaChart.getData().clear(); 164 | 165 | double actual = 0; 166 | for (int i = 0; i < results.size(); i++) { 167 | actual = actual + results.get(i); 168 | } 169 | 170 | calcDescrip.setText("Actual Cost is how much was paid at a certain period of time. \n(In our case costs is only salary).\nTotal final costs: " + actual + "sek"); 171 | calcResult.setText("Current week: " + weekSelected + ", Actual Cost: " + results.get(Integer.valueOf(weekSelected)-1) + "SEK\n"); 172 | calcFormula.setText("Actual Cost = Budget - Costs."); 173 | 174 | acSeries.setName("Actual Costs"); 175 | xAxis.setLabel("Week"); 176 | yAxis.setLabel("Amount (SEK)"); 177 | 178 | for (int i = 0; i < results.size(); i++) { 179 | acSeries.getData().add(new XYChart.Data(Integer.toString(i+1), results.get(i))); 180 | } 181 | 182 | areaChart.getData().add(acSeries); 183 | 184 | } 185 | public void budgetAtCompl(){ 186 | ArrayList results = planner.calcBAC(); 187 | searchButton.setDisable(true); 188 | XYChart.Series bacSeries = new XYChart.Series(); 189 | areaChart.getData().clear(); 190 | 191 | calcDescrip.setText("Shows the current budget at the completion of every work week"); 192 | calcResult.setText("Current week: " + weekSelected + ", BAC: " + results.get(Integer.valueOf(weekSelected)-1) + "SEK\n"); 193 | calcFormula.setText("Current Budget - Weekly Costs"); 194 | 195 | bacSeries.setName("Budget at Completion - (Week)"); 196 | xAxis.setLabel("Week"); 197 | yAxis.setLabel("Amount (SEK)"); 198 | 199 | for (int i = 0; i < results.size(); i++) { 200 | bacSeries.getData().add(new XYChart.Data(Integer.toString(i+1), results.get(i))); 201 | } 202 | 203 | areaChart.getData().add(bacSeries); 204 | } 205 | public void scheduleVariance(){ 206 | ArrayList results = planner.calcSv(); 207 | searchButton.setDisable(true); 208 | XYChart.Series svSeries = new XYChart.Series(); 209 | areaChart.getData().clear(); 210 | 211 | calcDescrip.setText("Difference between planned expenditures and earned value (From lecture slides)"); 212 | calcResult.setText("Current week: " + weekSelected + ", Schedule Variance: " + results.get(Integer.valueOf(weekSelected)-1) + "SEK\n"); 213 | calcFormula.setText("EV – PV"); 214 | 215 | svSeries.setName("Scheduled Variance"); 216 | xAxis.setLabel("Week"); 217 | yAxis.setLabel("Amount (SEK)"); 218 | 219 | for (int i = 0; i < results.size(); i++) { 220 | svSeries.getData().add(new XYChart.Data(Integer.toString(i+1), results.get(i))); 221 | System.out.println(results.get(i)); 222 | } 223 | 224 | areaChart.getData().add(svSeries); 225 | 226 | } 227 | public void schedulePerfIndex(){ 228 | ArrayList results = planner.calcSPI(); 229 | searchButton.setDisable(true); 230 | XYChart.Series spiSeries = new XYChart.Series(); 231 | areaChart.getData().clear(); 232 | 233 | calcDescrip.setText("The ratio of Earned Value (EV) over Planned Value (PV)"); 234 | calcResult.setText("Current week: " + weekSelected + ", SPI: " + Math.round(results.get(Integer.valueOf(weekSelected)-1)*100.0000)/100.0000); 235 | calcFormula.setText("(EV / PV)*100"); 236 | 237 | spiSeries.setName("Scheduled Performance Index"); 238 | xAxis.setLabel("Week"); 239 | yAxis.setLabel("Index"); 240 | 241 | for (int i = 0; i < results.size(); i++) { 242 | spiSeries.getData().add(new XYChart.Data(Integer.toString(i+1), results.get(i))); 243 | } 244 | 245 | areaChart.getData().add(spiSeries); 246 | } 247 | public void costVariance(){ 248 | ArrayList results = planner.calcCv(); 249 | searchButton.setDisable(true); 250 | XYChart.Series cvSeries = new XYChart.Series(); 251 | areaChart.getData().clear(); 252 | 253 | calcDescrip.setText("Difference between actual expenditures and earned value (From lecture slides)"); 254 | calcResult.setText("Current week: " + weekSelected + ", Cost Variance: " + results.get(Integer.valueOf(weekSelected)-1) + "SEK\n"); 255 | calcFormula.setText("EV – AV"); 256 | 257 | cvSeries.setName("Cost Variance"); 258 | xAxis.setLabel("Week"); 259 | yAxis.setLabel("Amount (SEK)"); 260 | 261 | for (int i = 0; i < results.size(); i++) { 262 | cvSeries.getData().add(new XYChart.Data(Integer.toString(i+1), results.get(i))); 263 | } 264 | 265 | areaChart.getData().add(cvSeries); 266 | } 267 | public void costPerfIndex(){ 268 | ArrayList results = planner.calcCPI(); 269 | searchButton.setDisable(true); 270 | XYChart.Series cpiSeries = new XYChart.Series(); 271 | areaChart.getData().clear(); 272 | 273 | calcDescrip.setText("The ratio of Earned Value (EV) over Actual Cost (AC)"); 274 | calcResult.setText("Current week: " + weekSelected + ", CPI: " + Math.round(results.get(Integer.valueOf(weekSelected)-1)*100.0000)/100.0000); 275 | calcFormula.setText("(EV / AC)"); 276 | 277 | cpiSeries.setName("Cost Performance Index"); 278 | xAxis.setLabel("Week"); 279 | yAxis.setLabel("Index"); 280 | 281 | for (int i = 0; i < results.size(); i++) { 282 | cpiSeries.getData().add(new XYChart.Data(Integer.toString(i+1), results.get(i))); 283 | 284 | } 285 | 286 | areaChart.getData().add(cpiSeries); 287 | } 288 | 289 | public void enableSearch(ActionEvent actionEvent) { 290 | searchButton.setDisable(false); 291 | } 292 | } 293 | 294 | -------------------------------------------------------------------------------- /src/controllers/ProjectScheduleController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import javafx.beans.Observable; 4 | import javafx.beans.property.SimpleStringProperty; 5 | import javafx.collections.FXCollections; 6 | import javafx.collections.ObservableList; 7 | import javafx.event.ActionEvent; 8 | import javafx.fxml.FXML; 9 | import javafx.fxml.FXMLLoader; 10 | import javafx.fxml.Initializable; 11 | import javafx.scene.Node; 12 | import javafx.scene.Parent; 13 | import javafx.scene.Scene; 14 | import javafx.scene.chart.*; 15 | import javafx.scene.control.*; 16 | import javafx.scene.control.cell.PropertyValueFactory; 17 | import javafx.scene.layout.HBox; 18 | import javafx.scene.text.Text; 19 | import javafx.stage.Stage; 20 | import javafx.stage.Window; 21 | import member_manager.Member; 22 | import member_manager.Schedule; 23 | 24 | import java.io.IOException; 25 | import java.net.URL; 26 | import java.time.LocalDate; 27 | import java.time.Month; 28 | import java.util.ArrayList; 29 | import java.util.ResourceBundle; 30 | 31 | public class ProjectScheduleController extends MainController implements Initializable { 32 | 33 | @FXML 34 | private Text headline; 35 | @FXML 36 | private TableView tableView; 37 | @FXML 38 | private TableColumn id; 39 | @FXML 40 | private TableColumn task; 41 | @FXML 42 | private TableColumn startDate; 43 | @FXML 44 | private TableColumn finishDate; 45 | @FXML 46 | private TableColumn duration; 47 | @FXML 48 | private TableColumn resources; 49 | 50 | @FXML 51 | public void backProject(ActionEvent event) throws IOException { 52 | 53 | Parent backProjectMemberParent = FXMLLoader.load(getClass().getResource("../fxml-files/projectOverview.fxml")); 54 | Scene backProjectMemberScene = new Scene(backProjectMemberParent); 55 | 56 | Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow(); 57 | 58 | window.setScene(backProjectMemberScene); 59 | window.show(); 60 | } 61 | 62 | @FXML 63 | public void loadAnalysis(ActionEvent event) throws IOException { 64 | 65 | id.setCellValueFactory(new PropertyValueFactory("id")); 66 | task.setCellValueFactory(new PropertyValueFactory("task")); 67 | startDate.setCellValueFactory(new PropertyValueFactory("startDate")); 68 | finishDate.setCellValueFactory(new PropertyValueFactory("finishDate")); 69 | duration.setCellValueFactory(new PropertyValueFactory("duration")); 70 | resources.setCellValueFactory(new PropertyValueFactory("resources")); 71 | 72 | headline.setText("Analysis"); 73 | 74 | tableView.setItems(getAnalysis()); 75 | } 76 | 77 | @FXML 78 | public void loadUI(ActionEvent event) throws IOException { 79 | 80 | id.setCellValueFactory(new PropertyValueFactory("id")); 81 | task.setCellValueFactory(new PropertyValueFactory("task")); 82 | startDate.setCellValueFactory(new PropertyValueFactory("startDate")); 83 | finishDate.setCellValueFactory(new PropertyValueFactory("finishDate")); 84 | duration.setCellValueFactory(new PropertyValueFactory("duration")); 85 | resources.setCellValueFactory(new PropertyValueFactory("resources")); 86 | 87 | headline.setText("UI Design"); 88 | 89 | tableView.setItems(getUIDesign()); 90 | } 91 | 92 | @FXML 93 | public void loadDevelopment(ActionEvent event) throws IOException { 94 | id.setCellValueFactory(new PropertyValueFactory("id")); 95 | task.setCellValueFactory(new PropertyValueFactory("task")); 96 | startDate.setCellValueFactory(new PropertyValueFactory("startDate")); 97 | finishDate.setCellValueFactory(new PropertyValueFactory("finishDate")); 98 | duration.setCellValueFactory(new PropertyValueFactory("duration")); 99 | resources.setCellValueFactory(new PropertyValueFactory("resources")); 100 | 101 | headline.setText("Development"); 102 | 103 | tableView.setItems(getDevelopment()); 104 | } 105 | 106 | @FXML 107 | public void loadCompletion(ActionEvent event) throws IOException { 108 | id.setCellValueFactory(new PropertyValueFactory("id")); 109 | task.setCellValueFactory(new PropertyValueFactory("task")); 110 | startDate.setCellValueFactory(new PropertyValueFactory("startDate")); 111 | finishDate.setCellValueFactory(new PropertyValueFactory("finishDate")); 112 | duration.setCellValueFactory(new PropertyValueFactory("duration")); 113 | resources.setCellValueFactory(new PropertyValueFactory("resources")); 114 | 115 | headline.setText("Completion"); 116 | 117 | tableView.setItems(getCompletion()); 118 | } 119 | 120 | @Override 121 | public void initialize(URL url, ResourceBundle resourceBundle) { 122 | 123 | id.setCellValueFactory(new PropertyValueFactory("id")); 124 | task.setCellValueFactory(new PropertyValueFactory("task")); 125 | startDate.setCellValueFactory(new PropertyValueFactory("startDate")); 126 | finishDate.setCellValueFactory(new PropertyValueFactory("finishDate")); 127 | duration.setCellValueFactory(new PropertyValueFactory("duration")); 128 | resources.setCellValueFactory(new PropertyValueFactory("resources")); 129 | 130 | headline.setText("Analysis"); 131 | 132 | tableView.setItems(getAnalysis()); 133 | } 134 | 135 | public ObservableList getAnalysis(){ 136 | ObservableList analysis = FXCollections.observableArrayList(); 137 | 138 | analysis.add(new Schedule("1", "Analysis", LocalDate.of(2019, Month.NOVEMBER, 04), 139 | LocalDate.of(2019, Month.NOVEMBER, 17), "13 days", 140 | "Clementine, Hugo, Linus I, Linus Å, Christian, Altug, Hjalmar")); 141 | 142 | analysis.add(new Schedule("2", "Planning Meetings", LocalDate.of(2019, Month.NOVEMBER, 11), 143 | LocalDate.of(2019, Month.NOVEMBER, 14), "4 days", 144 | "Clementine, Hugo, Linus I, Linus Å, Christian, Altug, Hjalmar")); 145 | 146 | analysis.add(new Schedule("3", "Create Class Diagram", LocalDate.of(2019, Month.NOVEMBER, 13), 147 | LocalDate.of(2019, Month.NOVEMBER, 15), "3 days", 148 | "Christian, Linus I, Clementine, Hjalmar")); 149 | 150 | analysis.add(new Schedule("4", "Analysis Finished", LocalDate.of(2019, Month.NOVEMBER, 17), 151 | LocalDate.of(2019, Month.NOVEMBER, 19), "1 day", "")); 152 | 153 | return analysis; 154 | } 155 | 156 | public ObservableList getUIDesign(){ 157 | 158 | ObservableList UIDesign = FXCollections.observableArrayList(); 159 | 160 | UIDesign.add(new Schedule("5", "UI Design", LocalDate.of(2019, Month.NOVEMBER, 18), 161 | LocalDate.of(2019, Month.DECEMBER, 22), "35 days", 162 | "Clementine, Hugo, Linus I, Christian")); 163 | 164 | UIDesign.add(new Schedule("6", "Migration to JavaFX", LocalDate.of(2019, Month.NOVEMBER, 18), 165 | LocalDate.of(2019, Month.DECEMBER, 01), "14 days", 166 | "Clementine, Linus I, Christian")); 167 | 168 | UIDesign.add(new Schedule("7", "Create FXML Files", LocalDate.of(2019, Month.NOVEMBER, 22), 169 | LocalDate.of(2019, Month.DECEMBER, 22), "29 days", 170 | "Christian, Linus I, Clementine, Hjalmar")); 171 | 172 | UIDesign.add(new Schedule("8", "Create Controllers", LocalDate.of(2019, Month.NOVEMBER, 22), 173 | LocalDate.of(2019, Month.DECEMBER, 22), "29 day", 174 | "Cleemntine, Linus I, Christian, Hugo")); 175 | 176 | UIDesign.add(new Schedule("9", "UI Design Finished", LocalDate.of(2019, Month.DECEMBER, 22), 177 | LocalDate.of(2019, Month.DECEMBER, 22), "1 day", "")); 178 | 179 | return UIDesign; 180 | } 181 | 182 | public ObservableList getDevelopment(){ 183 | 184 | ObservableList development = FXCollections.observableArrayList(); 185 | 186 | development.add(new Schedule("10", "Development", LocalDate.of(2019, Month.NOVEMBER, 18), 187 | LocalDate.of(2020, Month.JANUARY, 10), "54 days", 188 | "Clementine, Hugo, Linus I, Linus Å, Christian, Altug, Hjalmar")); 189 | 190 | development.add(new Schedule("11", "Develop Methods", LocalDate.of(2019, Month.NOVEMBER, 18), 191 | LocalDate.of(2020, Month.JANUARY, 10), "54 days", 192 | "Clementine, Hugo, Linus I, Linus Å, Christian, Altug, Hjalmar")); 193 | 194 | development.add(new Schedule("12", "Implement Json", LocalDate.of(2019, Month.NOVEMBER, 25), 195 | LocalDate.of(2019, Month.DECEMBER, 07), "13 days", 196 | "Linus Å, Christian, Altug, Hjalmar")); 197 | 198 | development.add(new Schedule("13", "Finish Coding", LocalDate.of(2019, Month.NOVEMBER, 25), 199 | LocalDate.of(2020, Month.JANUARY, 10), "54 days", 200 | "Clementine, Hugo, Linus I, Linus Å, Christian, Altug, Hjalmar")); 201 | 202 | development.add(new Schedule("14", "Development Finished", LocalDate.of(2020, Month.JANUARY, 10), 203 | LocalDate.of(2020, Month.JANUARY, 10), "1 day", "")); 204 | 205 | return development; 206 | } 207 | 208 | public ObservableList getCompletion(){ 209 | 210 | ObservableList completion = FXCollections.observableArrayList(); 211 | 212 | completion.add(new Schedule("15", "Completion", LocalDate.of(2019, Month.DECEMBER, 17), 213 | LocalDate.of(2020, Month.JANUARY, 10), "25 days", 214 | "Clementine, Hugo, Linus I, Linus Å, Christian, Altug, Hjalmar")); 215 | 216 | completion.add(new Schedule("16", "Create Executable", LocalDate.of(2020, Month.JANUARY, 07), 217 | LocalDate.of(2020, Month.JANUARY, 10), "4 days", 218 | "Hugo, Linus Å ")); 219 | 220 | completion.add(new Schedule("17", "Final Report", LocalDate.of(2019, Month.DECEMBER, 17), 221 | LocalDate.of(2020, Month.JANUARY, 10), "25 days", 222 | "Clementine, Hugo, Linus I, Linus Å, Christian, Altug, Hjalmar")); 223 | 224 | return completion; 225 | } 226 | 227 | } 228 | 229 | -------------------------------------------------------------------------------- /src/controllers/dashboardController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import javafx.event.ActionEvent; 4 | import javafx.fxml.FXML; 5 | import javafx.fxml.FXMLLoader; 6 | import javafx.scene.Node; 7 | import javafx.scene.Parent; 8 | import javafx.scene.Scene; 9 | import javafx.scene.control.Button; 10 | import javafx.stage.Stage; 11 | import json_reader_writer.JsonReader; 12 | import json_reader_writer.JsonWriter; 13 | import member_manager.Planner; 14 | 15 | import java.io.IOException; 16 | 17 | public class dashboardController extends MainController { 18 | 19 | @FXML 20 | private Button exitApp; 21 | @FXML 22 | private Button saveDataButton; 23 | @FXML 24 | private Button loadDataButton; 25 | @FXML 26 | private Button projectOverviewButton; 27 | @FXML 28 | private Button newMilestoneButton; 29 | @FXML 30 | private Button viewMemberButton; 31 | @FXML 32 | private Button newMemberButton; 33 | 34 | private static boolean loaded = false; 35 | 36 | public void initialize() { 37 | if (!loaded) { 38 | saveDataButton.setDisable(true); 39 | projectOverviewButton.setDisable(true); 40 | newMilestoneButton.setDisable(true); 41 | viewMemberButton.setDisable(true); 42 | newMemberButton.setDisable(true); 43 | } else { 44 | loadButtons(); 45 | } 46 | } 47 | 48 | public void loadButtons() { 49 | saveDataButton.setDisable(false); 50 | projectOverviewButton.setDisable(false); 51 | newMilestoneButton.setDisable(false); 52 | viewMemberButton.setDisable(false); 53 | newMemberButton.setDisable(false); 54 | } 55 | 56 | public void addMember(ActionEvent event) throws IOException { 57 | 58 | Parent addMemberParent = FXMLLoader.load(getClass().getResource("../fxml-files/newMember.fxml")); 59 | Scene addMemberScene = new Scene(addMemberParent); 60 | 61 | Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow(); 62 | 63 | window.setScene(addMemberScene); 64 | window.show(); 65 | } 66 | 67 | public void viewMember(ActionEvent event) throws IOException { 68 | 69 | Parent viewMemberParent = FXMLLoader.load(getClass().getResource("../fxml-files/userInfo.fxml")); 70 | Scene viewMemberScene = new Scene(viewMemberParent); 71 | 72 | Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow(); 73 | 74 | window.setScene(viewMemberScene); 75 | window.show(); 76 | } 77 | @FXML 78 | public void projectOverview(ActionEvent event) throws IOException{ 79 | 80 | Parent projectMemberParent = FXMLLoader.load(getClass().getResource("../fxml-files/projectOverview.fxml")); 81 | Scene projectMemberScene = new Scene(projectMemberParent); 82 | 83 | Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow(); 84 | 85 | window.setScene(projectMemberScene); 86 | window.show(); 87 | 88 | } 89 | 90 | public void contactUs(ActionEvent event) throws IOException{ 91 | Parent contactUsParent = FXMLLoader.load(getClass().getResource("../fxml-files/contactUs.fxml")); 92 | Scene contactUsScene = new Scene(contactUsParent); 93 | 94 | Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow(); 95 | 96 | window.setScene(contactUsScene); 97 | window.show(); 98 | } 99 | 100 | 101 | public void newMilestone(ActionEvent event) throws IOException { 102 | 103 | Parent milestoneMemberParent = FXMLLoader.load(getClass().getResource("../fxml-files/milestones.fxml")); 104 | Scene milestoneMemberScene = new Scene(milestoneMemberParent); 105 | 106 | Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow(); 107 | 108 | window.setScene(milestoneMemberScene); 109 | window.show(); 110 | } 111 | 112 | public void loadData(){ 113 | JsonReader reader = new JsonReader(); 114 | planner = reader.loadPlanner(); 115 | loaded = true; 116 | loadButtons(); 117 | } 118 | public void saveState(){ 119 | JsonWriter writer = new JsonWriter(); 120 | writer.savePlanner(planner); 121 | } 122 | 123 | public void exit(){ 124 | Stage stage = (Stage) exitApp.getScene().getWindow(); 125 | stage.close(); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/controllers/editMemberController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | 4 | import id_generator.GeneratorMain; 5 | import javafx.collections.FXCollections; 6 | import javafx.collections.ObservableList; 7 | import javafx.event.ActionEvent; 8 | import javafx.fxml.FXML; 9 | import javafx.fxml.FXMLLoader; 10 | import javafx.scene.Node; 11 | import javafx.scene.Parent; 12 | import javafx.scene.Scene; 13 | import javafx.scene.control.Alert; 14 | import javafx.scene.control.Button; 15 | import javafx.scene.control.ComboBox; 16 | import javafx.scene.control.TextField; 17 | import javafx.stage.Stage; 18 | import javafx.stage.Window; 19 | import member_manager.Member; 20 | 21 | import java.io.IOException; 22 | 23 | public class editMemberController extends MainController { 24 | @FXML 25 | private ComboBox memberIdDropdown; 26 | @FXML 27 | private TextField searchForID; 28 | @FXML 29 | private Button saveButton; 30 | @FXML 31 | private TextField updateName; 32 | @FXML 33 | private TextField updateLastName; 34 | @FXML 35 | private TextField updateSalary; 36 | @FXML 37 | private TextField updatedFirstName; 38 | @FXML 39 | private TextField updatedLastName; 40 | @FXML 41 | private TextField updatedSalary; 42 | @FXML 43 | private TextField showID; 44 | 45 | //Checks for valid ID and updates member information. 46 | public void saveInfo(ActionEvent actionEvent) { 47 | int searchedID = 0; 48 | boolean IDValid = true; 49 | Window owner = saveButton.getScene().getWindow(); 50 | 51 | if (searchForID.getText().isEmpty()) { 52 | AlertHelper.showAlert(Alert.AlertType.INFORMATION, owner, "Info", "Search field must be filled in!"); 53 | System.out.println("Search failed (Empty search)."); 54 | IDValid = false; 55 | } else if (!GeneratorMain.isParsable(searchForID.getText())) { 56 | AlertHelper.showAlert(Alert.AlertType.ERROR, owner, "Error", "ID's must be 5-digit integers!"); 57 | System.out.println("Search failed (Invalid ID format, non-number characters)."); 58 | IDValid = false; 59 | } else if (Integer.parseInt(searchForID.getText()) > 99999) { 60 | AlertHelper.showAlert(Alert.AlertType.WARNING, owner, "Error", "ID's are positive 5-digit integers!"); 61 | System.out.println("Search failed (Invalid ID format, more than 5 digits"); 62 | IDValid = false; 63 | } else if (Integer.parseInt(searchForID.getText()) < 10000) { 64 | AlertHelper.showAlert(Alert.AlertType.WARNING, owner, "Error", "ID's are positive 5-digit integers!"); 65 | System.out.println("Search failed (Invalid ID format, less than 5 digits OR negative input)."); 66 | IDValid = false; 67 | 68 | } else if (GeneratorMain.isParsable(searchForID.getText())) { 69 | searchedID = Integer.parseInt(searchForID.getText()); 70 | 71 | for (Member member : planner.members) { 72 | if (searchedID == member.getId()) { 73 | if (IDValid) { 74 | if (updateName.getText().isEmpty()) { 75 | //keeps same firstname if no new name is entered 76 | } else { 77 | member.setFirstName(updateName.getText()); 78 | } 79 | if (updateLastName.getText().isEmpty()) { 80 | //keeps same lastname if no new lastname is entered 81 | } else { 82 | member.setLastName(updateLastName.getText()); 83 | } 84 | if (updateSalary.getText().isEmpty()) { 85 | //keeps same salary if no new salary is entered 86 | } else { 87 | double updatedSalary = Double.parseDouble(updateSalary.getText()); 88 | member.setSalary(updatedSalary); 89 | } 90 | //Sets updated information to "Updated member information" textfields and clears input-textfields. 91 | showID.setText(Integer.toString(member.getId())); 92 | updatedFirstName.setText(member.getFirstName()); 93 | updatedLastName.setText(member.getLastName()); 94 | updatedSalary.setText(String.valueOf(member.getSalary())); 95 | updateName.clear(); 96 | updateLastName.clear(); 97 | updateSalary.clear(); 98 | 99 | } 100 | } 101 | } 102 | } 103 | } 104 | 105 | public void initialize (){ 106 | ObservableList memberDropdownItems = FXCollections.observableArrayList(); 107 | for (Member member : planner.members) { 108 | memberDropdownItems.add(Integer.toString(member.getId()) + " : " + member.getFirstName() + " " + member.getLastName()); 109 | } 110 | memberIdDropdown.setItems(memberDropdownItems); 111 | } 112 | 113 | public void setText (ActionEvent actionEvent){ 114 | searchForID.setText(memberIdDropdown.getValue().toString().substring(0, 5)); 115 | } 116 | 117 | 118 | @Override 119 | public void back (ActionEvent event) throws IOException { 120 | 121 | Parent backMemberParent = FXMLLoader.load(getClass().getResource("../fxml-files/userInfo.fxml")); 122 | Scene backMemberScene = new Scene(backMemberParent); 123 | 124 | Stage window = (Stage) ((Node) event.getSource()).getScene().getWindow(); 125 | 126 | window.setScene(backMemberScene); 127 | window.show(); 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /src/controllers/milestonesController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import javafx.event.ActionEvent; 4 | import javafx.fxml.FXML; 5 | import javafx.scene.control.DatePicker; 6 | import javafx.scene.control.TextField; 7 | import member_manager.Member; 8 | import member_manager.Milestone; 9 | 10 | import java.util.ArrayList; 11 | 12 | public class milestonesController extends MainController { 13 | 14 | @FXML 15 | private TextField milestoneNameRegister; 16 | @FXML 17 | private TextField milestoneDescripRegister; 18 | @FXML 19 | private TextField milestoneMemberRegister; 20 | @FXML 21 | private DatePicker startDateRegister; 22 | @FXML 23 | private DatePicker endDateRegister; 24 | 25 | 26 | @FXML 27 | public void registerMilestone(ActionEvent event) { 28 | milestoneMemberRegister.getText(); 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/controllers/newMemberController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import id_generator.GeneratorMain; 4 | import javafx.event.ActionEvent; 5 | import javafx.fxml.FXML; 6 | import javafx.scene.control.Alert; 7 | import javafx.scene.control.Button; 8 | import javafx.scene.control.TextField; 9 | import javafx.stage.Window; 10 | import json_reader_writer.JsonReader; 11 | import json_reader_writer.JsonWriter; 12 | import member_manager.Member; 13 | import member_manager.Planner; 14 | 15 | public class newMemberController extends MainController { 16 | 17 | @FXML 18 | private TextField firstNameRegister; 19 | @FXML 20 | private TextField lastNameRegister; 21 | @FXML 22 | private TextField dobRegister; 23 | @FXML 24 | private TextField salaryRegister; 25 | @FXML 26 | private Button registerButton; 27 | 28 | 29 | 30 | public void registerMember(ActionEvent event) throws NumberFormatException { 31 | Window owner = registerButton.getScene().getWindow(); //setup the popup 32 | boolean success = true; 33 | 34 | if (firstNameRegister.getText().isEmpty()) { //checks if first name field is empty 35 | AlertHelper.showAlert(Alert.AlertType.ERROR, owner, "Error", "First name field can not be empty!"); 36 | System.out.println("First name field failed."); 37 | success = false; 38 | 39 | } if (lastNameRegister.getText().isEmpty()) { //checks if last name field is empty 40 | AlertHelper.showAlert(Alert.AlertType.ERROR, owner, "Error", "Last name field can not be empty!"); 41 | System.out.println("Last name field failed."); 42 | success = false; 43 | } if (GeneratorMain.isParsable(dobRegister.getText())) { //checks if birthday field valid but < 0 or > 991231 44 | int tempInt = Integer.parseInt(dobRegister.getText()); 45 | if (tempInt <= 0) { 46 | AlertHelper.showAlert(Alert.AlertType.ERROR, owner, "Error", "Age can not be less than 0!"); 47 | System.out.println("Birthday field failed (negative input)."); 48 | success = false; 49 | } else if (tempInt > 20181212) { //The highest accepted value as of the day implemented. 50 | AlertHelper.showAlert(Alert.AlertType.ERROR, owner, "Error", "Please follow the appropriate format YYMMDD!"); 51 | System.out.println("Birthday field failed (input exceeds max accepted input)."); 52 | success = false; 53 | } 54 | } if (!GeneratorMain.isParsable(dobRegister.getText())) { //checks if birthday field is empty or invalid 55 | AlertHelper.showAlert(Alert.AlertType.ERROR, owner, "Error", "Please follow the appropriate format YYMMDD!"); 56 | System.out.println("Birthday field failed (invalid input)."); 57 | success = false; 58 | } if (GeneratorMain.isParsable(salaryRegister.getText())) { 59 | double tempSalary = Double.parseDouble(salaryRegister.getText()); 60 | if (tempSalary < 80) { 61 | AlertHelper.showAlert(Alert.AlertType.ERROR, owner, "Error", "Salary must be at least minimum wage! (Currently 80SEK)"); 62 | System.out.println("Salary field failed (invalid salary amount)."); 63 | success = false; 64 | } 65 | } if (!GeneratorMain.isParsable(salaryRegister.getText()) || salaryRegister.getText().isEmpty()) { 66 | AlertHelper.showAlert(Alert.AlertType.ERROR, owner, "Error", "Salary must be a number greater than minimum wage (80SEK)."); 67 | System.out.println("Salary field failed (invalid salary input)."); 68 | success = false; 69 | } else { 70 | int genID = GeneratorMain.generateID(firstNameRegister.getText(), lastNameRegister.getText(), Integer.parseInt(dobRegister.getText())); 71 | System.out.println("ABOVE TEXT IS JUST CONSOLE DEBUGGING FOR ID GEN. IF NO TEXT FOLLOWS THEN NO MEMBER WAS CREATED."); 72 | for (Member member : MainController.planner.members) { 73 | if (genID == member.getId()) { 74 | AlertHelper.showAlert(Alert.AlertType.ERROR, owner, "Error", "User with ID: " + genID + " already exists. Please proceed to the contact page if you believe this is an error."); 75 | success = false; 76 | } 77 | } 78 | } 79 | 80 | if (success) { 81 | AlertHelper.showAlert(Alert.AlertType.CONFIRMATION, owner, "Success", "Member successfully registered! \n" + firstNameRegister.getText() + "'s generated ID is: " + GeneratorMain.generateID(firstNameRegister.getText(), lastNameRegister.getText(), Integer.parseInt(dobRegister.getText()))); 82 | System.out.println("Member registration successful."); 83 | //Add the member to the Planner 84 | planner.addMember(firstNameRegister.getText(), lastNameRegister.getText(), Integer.parseInt(dobRegister.getText()), Double.parseDouble(salaryRegister.getText())); 85 | System.out.println(firstNameRegister.getText() + " was added to the planner."); 86 | System.out.println(planner.members); 87 | 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/controllers/riskMatrixController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import javafx.event.ActionEvent; 4 | import javafx.event.Event; 5 | import javafx.fxml.FXML; 6 | import javafx.fxml.FXMLLoader; 7 | import javafx.scene.Node; 8 | import javafx.scene.Parent; 9 | import javafx.scene.Scene; 10 | import javafx.scene.layout.AnchorPane; 11 | import javafx.stage.Stage; 12 | import json_reader_writer.JsonReader; 13 | import member_manager.RiskMatrix; 14 | 15 | import java.awt.*; 16 | import java.io.IOException; 17 | import java.util.ArrayList; 18 | 19 | public class riskMatrixController extends MainController { 20 | 21 | @FXML 22 | private javafx.scene.control.Label e11; 23 | @FXML 24 | private javafx.scene.control.Label e12; 25 | @FXML 26 | private javafx.scene.control.Label e13; 27 | @FXML 28 | private javafx.scene.control.Label e14; 29 | @FXML 30 | private javafx.scene.control.Label e15; 31 | @FXML 32 | private javafx.scene.control.Label l22; 33 | @FXML 34 | private javafx.scene.control.Label l23; 35 | @FXML 36 | private javafx.scene.control.Label l21; 37 | @FXML 38 | private javafx.scene.control.Label l24; 39 | @FXML 40 | private javafx.scene.control.Label l25; 41 | @FXML 42 | private javafx.scene.control.Label l32; 43 | @FXML 44 | private javafx.scene.control.Label l34; 45 | @FXML 46 | private javafx.scene.control.Label l44; 47 | @FXML 48 | private javafx.scene.control.Label l33; 49 | @FXML 50 | private javafx.scene.control.Label l45; 51 | @FXML 52 | private javafx.scene.control.Label l31; 53 | @FXML 54 | private javafx.scene.control.Label l42; 55 | @FXML 56 | private javafx.scene.control.Label l43; 57 | @FXML 58 | private javafx.scene.control.Label l41; 59 | 60 | @FXML 61 | public void visualRisks() { 62 | JsonReader jsonReader = new JsonReader(); 63 | ArrayList risks; 64 | risks = jsonReader.loadRiskMatrix(); 65 | e11.setText(risks.get(0).getRiskName()); 66 | l21.setText(risks.get(0).getVeryLikely()); 67 | l31.setText(risks.get(0).getPossible()); 68 | l41.setText(risks.get(0).getUnlikely()); 69 | 70 | e12.setText(risks.get(1).getRiskName()); 71 | l22.setText(risks.get(1).getVeryLikely()); 72 | l32.setText(risks.get(1).getPossible()); 73 | l42.setText(risks.get(1).getUnlikely()); 74 | 75 | e13.setText(risks.get(2).getRiskName()); 76 | l23.setText(risks.get(2).getVeryLikely()); 77 | l33.setText(risks.get(2).getPossible()); 78 | l43.setText(risks.get(2).getUnlikely()); 79 | 80 | e14.setText(risks.get(3).getRiskName()); 81 | l24.setText(risks.get(3).getVeryLikely()); 82 | l34.setText(risks.get(3).getPossible()); 83 | l44.setText(risks.get(3).getUnlikely()); 84 | 85 | e15.setText(risks.get(4).getRiskName()); 86 | l25.setText(risks.get(4).getVeryLikely()); 87 | l45.setText(risks.get(4).getUnlikely()); 88 | l34.setText(risks.get(4).getPossible()); 89 | 90 | 91 | 92 | 93 | } 94 | 95 | public void initialize () { 96 | visualRisks(); 97 | } 98 | 99 | @Override 100 | public void back(ActionEvent event) throws IOException { 101 | 102 | Parent backMemberParent = FXMLLoader.load(getClass().getResource("../fxml-files/projectOverview.fxml")); 103 | Scene backMemberScene = new Scene(backMemberParent); 104 | 105 | 106 | Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow(); 107 | 108 | window.setScene(backMemberScene); 109 | window.show(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/controllers/userInfoController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import id_generator.GeneratorMain; 4 | import javafx.collections.FXCollections; 5 | import javafx.collections.ObservableList; 6 | import javafx.event.ActionEvent; 7 | import javafx.fxml.FXML; 8 | import javafx.fxml.FXMLLoader; 9 | import javafx.scene.Node; 10 | import javafx.scene.Parent; 11 | import javafx.scene.Scene; 12 | import javafx.scene.chart.*; 13 | import javafx.scene.control.*; 14 | import javafx.scene.text.Text; 15 | import javafx.stage.Stage; 16 | import javafx.stage.Window; 17 | import javafx.util.Duration; 18 | import member_manager.Member; 19 | 20 | import java.io.IOException; 21 | import java.util.ArrayList; 22 | 23 | public class userInfoController extends MainController { 24 | @FXML 25 | private NumberAxis yAxis; 26 | @FXML 27 | private CategoryAxis xAxis; 28 | @FXML 29 | private BarChart barChart; 30 | @FXML 31 | private TextField searchForID; 32 | @FXML 33 | private Button searchForIDButton; 34 | @FXML 35 | private Button showHours; 36 | @FXML 37 | private Button showSalary; 38 | @FXML 39 | private Button submitButton; 40 | @FXML 41 | private Text revealName; 42 | @FXML 43 | private Text revealID; 44 | @FXML 45 | private Text userInfoDescription; 46 | @FXML 47 | private PieChart pieChart; 48 | @FXML 49 | private ComboBox compareUserDropdown; 50 | @FXML 51 | private ComboBox compareHoursSalaryDropdown; 52 | @FXML 53 | private ComboBox memberIdDropdown; 54 | 55 | public void initialize() { 56 | ObservableList memberDropdownItems = FXCollections.observableArrayList(); 57 | for (Member member : planner.members) { 58 | memberDropdownItems.add(Integer.toString(member.getId()) + " : " + member.getFirstName() + " " + member.getLastName()); 59 | } 60 | memberIdDropdown.setItems(memberDropdownItems); 61 | } 62 | 63 | public void setText(ActionEvent actionEvent) { 64 | searchForID.setText(memberIdDropdown.getValue().toString().substring(0, 5)); 65 | search(); 66 | } 67 | 68 | public void search() { 69 | 70 | Window owner = searchForIDButton.getScene().getWindow(); 71 | int searchedID = 0; 72 | boolean IDValid = true; 73 | boolean IDFound = false; 74 | 75 | if (searchForID.getText().isEmpty()) { 76 | AlertHelper.showAlert(Alert.AlertType.INFORMATION, owner, "Info", "Search field must be filled in!"); 77 | System.out.println("Search failed (Empty search)."); 78 | IDValid = false; 79 | } else if (GeneratorMain.isParsable(searchForID.getText())) { 80 | searchedID = Integer.parseInt(searchForID.getText()); 81 | 82 | ObservableList optionsIds = FXCollections.observableArrayList(); 83 | for (Member member : planner.members) { 84 | if (member.getId() != Integer.parseInt(searchForID.getText())) { 85 | optionsIds.add((member.getId()) + " : " + member.getFirstName() + " " + member.getLastName().substring(0, 1) + "."); 86 | } 87 | } 88 | compareUserDropdown.setItems(optionsIds); 89 | 90 | ObservableList optionsHoursSalary = FXCollections.observableArrayList(); 91 | optionsHoursSalary.add("Hours"); 92 | optionsHoursSalary.add("Salaries"); 93 | compareHoursSalaryDropdown.setItems(optionsHoursSalary); 94 | 95 | if (Integer.parseInt(searchForID.getText()) < 10000) { 96 | AlertHelper.showAlert(Alert.AlertType.WARNING, owner, "Error", "ID's are positive 5-digit integers!"); 97 | System.out.println("Search failed (Invalid ID format, less than 5 digits OR negative input)."); 98 | IDValid = false; 99 | } else if (Integer.parseInt(searchForID.getText()) > 99999) { 100 | AlertHelper.showAlert(Alert.AlertType.WARNING, owner, "Error", "ID's are positive 5-digit integers!"); 101 | System.out.println("Search failed (Invalid ID format, more than 5 digits"); 102 | IDValid = false; 103 | } 104 | } else { 105 | if (!GeneratorMain.isParsable(searchForID.getText())) { 106 | AlertHelper.showAlert(Alert.AlertType.ERROR, owner, "Error", "ID's must be 5-digit integers!"); 107 | System.out.println("Search failed (Invalid ID format, non-number characters)."); 108 | IDValid = false; 109 | } 110 | } 111 | if (IDValid) { 112 | //Input the team member's information into the page 113 | System.out.println(">> Debugger"); 114 | System.out.println(planner.members); 115 | 116 | String memberName = ""; 117 | for (Member member : planner.members) { 118 | System.out.println(member.getId()); 119 | if (searchedID == member.getId()) { 120 | IDFound = true; 121 | memberName = member.getFirstName().concat(" ").concat(member.getLastName()); 122 | } 123 | } 124 | 125 | if (IDFound) { 126 | revealName.setText(memberName); 127 | revealID.setText(Integer.toString(searchedID)); 128 | System.out.println("Name set to: " + memberName); 129 | System.out.println("ID set to: " + searchedID); 130 | 131 | showHours.setDisable(false); 132 | showSalary.setDisable(false); 133 | submitButton.setDisable(false); 134 | searchForIDButton.setDisable(false); 135 | compareHoursSalaryDropdown.setDisable(false); 136 | compareUserDropdown.setDisable(false); 137 | 138 | userInfoDescription.setText("Milestones worked on by " + memberName + ":\n" + 139 | planner.getMilestonesWorkedOn(searchedID).toString().substring(1, planner.getMilestonesWorkedOn(searchedID).toString().length() -1)); 140 | } else { 141 | AlertHelper.showAlert(Alert.AlertType.INFORMATION, owner, "Error", "Member ID does not yet exist."); 142 | } 143 | } 144 | } 145 | 146 | public void editMember(ActionEvent event) throws IOException{ 147 | 148 | Parent editMemberParent = FXMLLoader.load(getClass().getResource("../fxml-files/editMember.fxml")); 149 | Scene editMemberScene = new Scene(editMemberParent); 150 | 151 | Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow(); 152 | 153 | window.setScene(editMemberScene); 154 | window.show(); 155 | 156 | } 157 | 158 | public String getName() { 159 | int ID = 0; 160 | if (GeneratorMain.isParsable(searchForID.getText())) { 161 | ID = Integer.parseInt(searchForID.getText()); 162 | } 163 | String name = ""; 164 | 165 | for (Member member : planner.members) { 166 | if (ID == member.getId()) { 167 | name = member.getFirstName() + " " + member.getLastName(); 168 | } 169 | } 170 | return name; 171 | } 172 | 173 | public void showHours(ActionEvent event) throws IOException { 174 | //draw pie chart 175 | pieChart.getData().clear(); 176 | 177 | ObservableList chartData = FXCollections.observableArrayList(); 178 | 179 | for (Member member : planner.members) { 180 | int hours = (int) planner.getAllHoursForMember(member.getId()); 181 | String memberID = member.getFirstName() + ": " + hours + " hours"; 182 | chartData.add(new PieChart.Data(memberID, hours)); 183 | } 184 | 185 | pieChart.setLabelsVisible(false); 186 | pieChart.setLegendVisible(false); 187 | pieChart.setTitle("Hours worked"); 188 | pieChart.setData(chartData); 189 | 190 | pieChart.getData().stream().forEach(data -> { 191 | Tooltip valuesToolTip = new Tooltip(); 192 | valuesToolTip.setText(data.getName()); 193 | Tooltip.install(data.getNode(), valuesToolTip); 194 | valuesToolTip.setShowDelay(Duration.ZERO); 195 | }); 196 | 197 | //draw graph 198 | String name = getName(); 199 | barChart.setTitle("Hours worked by: " + name); 200 | xAxis.setLabel("Week"); 201 | yAxis.setLabel("Hours"); 202 | 203 | barChart.getData().clear(); 204 | barChart.autosize(); 205 | 206 | XYChart.Series dataSeries = new XYChart.Series(); 207 | dataSeries.setName("Hours Worked"); 208 | 209 | double totalHours = 0; 210 | 211 | for (Member member : planner.members) { 212 | totalHours = totalHours + planner.getAllHoursForMember(member.getId()); 213 | } 214 | 215 | double avgHours = Math.round(totalHours / planner.members.size()); 216 | 217 | for (Integer week : planner.timesheet.keySet()) { 218 | double hoursWorked = 0; 219 | hoursWorked = planner.getWeeklyHoursForMember(week, Integer.parseInt(searchForID.getText())); 220 | dataSeries.getData().add(new XYChart.Data<>(Integer.toString(week), hoursWorked)); 221 | } 222 | 223 | xAxis.setAnimated(false); 224 | yAxis.setAnimated(false); 225 | barChart.getData().add(dataSeries); 226 | 227 | //add in info 228 | userInfoDescription.setText(name + "'s total hours are " + planner.getAllHoursForMember(Integer.parseInt(searchForID.getText())) + " hours. Compared to the total group average of " + avgHours + "."); 229 | } 230 | 231 | public void showSalary(ActionEvent event) throws IOException { 232 | 233 | //do pieChart 234 | pieChart.getData().clear(); 235 | 236 | ObservableList chartData = FXCollections.observableArrayList(); 237 | 238 | double totalSalary = 0; 239 | for (Member member : planner.members) { 240 | totalSalary = member.getSalary() * planner.getAllHoursForMember(member.getId()); 241 | String memberID = member.getFirstName() + ": " + totalSalary + " SEK"; 242 | chartData.add(new PieChart.Data(memberID, totalSalary)); 243 | } 244 | 245 | pieChart.setLabelsVisible(false); 246 | pieChart.setLegendVisible(true); 247 | pieChart.setTitle("Salary Earned"); 248 | pieChart.setData(chartData); 249 | 250 | pieChart.getData().stream().forEach(data -> { 251 | Tooltip valuesToolTip = new Tooltip(); 252 | valuesToolTip.setText(data.getName()); 253 | Tooltip.install(data.getNode(), valuesToolTip); 254 | valuesToolTip.setShowDelay(Duration.ZERO); 255 | }); 256 | 257 | //Do barChart 258 | String name = getName(); 259 | barChart.setTitle("Salaries earned by: " + name); 260 | xAxis.setLabel("Week"); 261 | yAxis.setLabel("Amount (SEK)"); 262 | 263 | barChart.getData().clear(); 264 | barChart.autosize(); 265 | 266 | XYChart.Series dataSeries = new XYChart.Series(); 267 | dataSeries.setName("Salary Earned"); 268 | 269 | double total = 0; 270 | for (Integer week : planner.timesheet.keySet()) { 271 | total = planner.getWeeklySalaryForMember(week, Integer.parseInt(searchForID.getText())); 272 | dataSeries.getData().add(new XYChart.Data<>(Integer.toString(week), total)); 273 | } 274 | 275 | xAxis.setAnimated(false); 276 | yAxis.setAnimated(false); 277 | barChart.getData().add(dataSeries); 278 | 279 | double avgSalary = 0; 280 | for (Member member : planner.members) { 281 | avgSalary = Math.round((avgSalary + (planner.getTotalSalaryForMember(member.getId()))) / planner.members.size()); 282 | } 283 | 284 | //add in info 285 | userInfoDescription.setText(name + "'s total salary is " + planner.getTotalSalaryForMember(Integer.parseInt(searchForID.getText())) + "sek. Compared to the total group average of " + avgSalary + "."); 286 | } 287 | 288 | public void compareUsers(ActionEvent actionEvent) { 289 | int firstID = Integer.parseInt(searchForID.getText()); 290 | String secondID = (String) compareUserDropdown.getValue(); 291 | int compareID = Integer.parseInt(secondID.substring(0, 5)); 292 | String compareType = (String) compareHoursSalaryDropdown.getValue(); 293 | 294 | System.out.println(firstID + ", " + secondID); //debuggers 295 | System.out.println(firstID + ", " + compareID); 296 | 297 | Member member1 = null; 298 | Member member2 = null; 299 | 300 | for (Member member : planner.members) { 301 | if (member.getId() == firstID) { 302 | member1 = member; 303 | } else if (member.getId() == compareID) { 304 | member2 = member; 305 | } 306 | } 307 | 308 | System.out.println(member1); 309 | System.out.println(member2); 310 | 311 | //draw piechart for both members. 312 | pieChart.getData().clear(); 313 | pieChart.autosize(); 314 | 315 | //lists for hours pie chart 316 | ObservableList hoursMembers = FXCollections.observableArrayList(); 317 | 318 | hoursMembers.add(new PieChart.Data(member1.getFirstName(), planner.getAllHoursForMember(member1.getId()))); 319 | hoursMembers.add(new PieChart.Data(member2.getFirstName(), planner.getAllHoursForMember(member2.getId()))); 320 | 321 | //lists for salaries pie chart 322 | ObservableList salaryMembers = FXCollections.observableArrayList(); 323 | 324 | salaryMembers.add(new PieChart.Data(member1.getFirstName(), planner.getTotalSalaryForMember(member1.getId()))); 325 | salaryMembers.add(new PieChart.Data(member2.getFirstName(), planner.getTotalSalaryForMember(member2.getId()))); 326 | 327 | //data series for hours bar chart 328 | XYChart.Series hoursSeriesMember1 = new XYChart.Series(); 329 | hoursSeriesMember1.setName(member1.getFirstName()); 330 | XYChart.Series hoursSeriesMember2 = new XYChart.Series(); 331 | hoursSeriesMember2.setName(member2.getFirstName()); 332 | XYChart.Series salarySeriesMember1 = new XYChart.Series(); 333 | salarySeriesMember1.setName(member1.getFirstName()); 334 | XYChart.Series salarySeriesMember2 = new XYChart.Series(); 335 | salarySeriesMember2.setName(member2.getFirstName()); 336 | 337 | for (Integer week : planner.timesheet.keySet()) { 338 | hoursSeriesMember1.getData().add(new XYChart.Data<>(Integer.toString(week), planner.getWeeklyHoursForMember(week, member1.getId()))); 339 | salarySeriesMember1.getData().add(new XYChart.Data<>(Integer.toString(week), planner.getWeeklySalaryForMember(week, member1.getId()))); 340 | hoursSeriesMember2.getData().add(new XYChart.Data<>(Integer.toString(week), planner.getWeeklyHoursForMember(week, member2.getId()))); 341 | salarySeriesMember2.getData().add(new XYChart.Data<>(Integer.toString(week), planner.getWeeklySalaryForMember(week, member2.getId()))); 342 | } 343 | 344 | //draw graphs 345 | if (!compareType.isEmpty()) { 346 | if (compareType.equalsIgnoreCase("hours")) { 347 | pieChart.getData().clear(); 348 | pieChart.setLegendVisible(true); 349 | pieChart.setLabelsVisible(false); 350 | pieChart.setTitle("Compared Hours"); 351 | pieChart.setData(hoursMembers); 352 | 353 | pieChart.getData().stream().forEach(data -> { 354 | Tooltip valuesToolTip = new Tooltip(); 355 | valuesToolTip.setText(data.getName() + "\n" + data.getPieValue() + " hours"); 356 | Tooltip.install(data.getNode(), valuesToolTip); 357 | valuesToolTip.setShowDelay(Duration.ZERO); 358 | }); 359 | 360 | barChart.getData().clear(); 361 | barChart.autosize(); 362 | xAxis.setAnimated(false); 363 | yAxis.setAnimated(false); 364 | barChart.setTitle("Compared Hours"); 365 | barChart.getData().addAll(hoursSeriesMember1, hoursSeriesMember2); 366 | 367 | userInfoDescription.setText(member1.getFirstName() + "'s total hours worked are " + planner.getAllHoursForMember(member1.getId()) + 368 | "\nWhile " + member2.getFirstName() + "'s total hours worked are " + planner.getAllHoursForMember(member2.getId()) + "."); 369 | } 370 | if (compareType.equalsIgnoreCase("salaries")) { 371 | pieChart.getData().clear(); 372 | pieChart.setLegendVisible(true); 373 | pieChart.setLabelsVisible(false); 374 | pieChart.setTitle("Compared Salaries"); 375 | pieChart.setData(salaryMembers); 376 | 377 | pieChart.getData().stream().forEach(data -> { 378 | Tooltip valuesToolTip = new Tooltip(); 379 | valuesToolTip.setText(data.getName() + "\n" + data.getPieValue() + "SEK"); 380 | Tooltip.install(data.getNode(), valuesToolTip); 381 | valuesToolTip.setShowDelay(Duration.ZERO); 382 | }); 383 | 384 | barChart.getData().clear(); 385 | barChart.autosize(); 386 | xAxis.setAnimated(false); 387 | yAxis.setAnimated(false); 388 | barChart.setTitle("Compared Salaries"); 389 | barChart.getData().addAll(salarySeriesMember1, salarySeriesMember2); 390 | 391 | userInfoDescription.setText(member1.getFirstName() + "'s total earned salary is " + planner.getTotalSalaryForMember(member1.getId()) + "SEK" + 392 | "\nWhereas " + member2.getFirstName() + "'s total earned salary is " + planner.getTotalSalaryForMember(member2.getId()) + "SEK."); 393 | } 394 | } 395 | } 396 | } 397 | -------------------------------------------------------------------------------- /src/fxml-files/contactUs.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 38 | 39 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 39 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 59 | 64 | 69 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/fxml-files/editMember.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/fxml-files/milestones.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 32 | 33 | 34 | 35 | 36 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/fxml-files/newMember.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 20 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/fxml-files/projectOverview.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |