-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMenus.java
396 lines (371 loc) · 20.7 KB
/
Menus.java
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
import java.lang.Math;
import java.io.File;
import java.io.PrintWriter;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.io.IOException;
import java.util.InputMismatchException;
import java.util.ArrayList;
import CustomExceptions.*;
import Entities.*;
/**
* COMP90041, Sem1, 2023: Final Project
* @author Jule Valendo Halim
* student id: 1425567
* student email: [email protected]
*
* Contains the menus needed and executes user inputs based on replies to main menu
*/
public class Menus {
private Audit audit;
private enum possibleInputs {JUDGE,J,RUN,R,AUDIT,A,QUIT,Q};
//Constructors
/**
* Default constructor for Menus, initializes an Audit
*/
public Menus() {
audit = new Audit();
}
//Public Methods
/**
* Prints the help menu, terminating the program
* Executed under conditions in which incorrect arguments are provided or a scenario file is not found
*/
public void helpMenu() { //shows help menu
System.out.println("RescueBot - COMP90041 - Final Project");
System.out.println("");
System.out.println("Usage: java RescueBot [arguments]");
System.out.println("");
System.out.println("Arguments:");
System.out.printf("-s or --scenarios\tOptional: path to scenario file\n");
System.out.printf("-h or --help\t\tOptional: Print Help (this message) and exit\n");
System.out.printf("-l or --log\t\tOptional: path to data log file\n");
System.exit(0);
}
/**
* Returns a string of user input on main menu
* @param scanner Scanner used to get user input
* @return Returns a string of user input if valid
*/
public String mainMenu(Scanner scanner) {
String inputString;
int errorOrNot = 0;
while (true) { //loops until valid user input provided
if (errorOrNot == 0) {
System.out.println("Please enter one of the following commands to continue:");
}
System.out.println("- judge scenarios: [judge] or [j]");
System.out.println("- run simulations with the in-built decision algorithm: [run] or [r]");
System.out.println("- show audit from history: [audit] or [a]");
System.out.println("- quit the program: [quit] or [q]");
System.out.print("> ");
try {
inputString = scanner.nextLine();
boolean correctInput = false;
for (possibleInputs i: possibleInputs.values()) {
if (i.name().equalsIgnoreCase(inputString)) {
correctInput = true;
}
}
if (inputString.isEmpty()) {
throw new InputMismatchException();
}
if (correctInput) {
break;
}
errorOrNot = 1;
System.out.println("Invalid command! Please enter one of the following commands to continue:");
} catch (InputMismatchException e) {
System.out.println("Invalid command! Please enter one of the following commands to continue:");
continue;
}
}
return inputString;
}
/**
* Executes the command from the user input obtained from main menu
* @param userInput User input to execute command as given by user
* @param scenarioList List of scenarios to execute commands on
* @param logFile File to be written to if user consented or a bot run is performed
* @param scanner Used to get user input
* @param containsScenario Indcates whether a scenario is provided
* @param logFileProvided Indicates whether a log file is provided
* @param logFileExists Indicates if a log file exists if provided
* @param rescueList Passes RescueList object to perform certain methods
* @throws InvalidInputException Thrown when user inputs an incorrect data type
* @throws InputMismatchException Occurs when parsing produces an error
*/
public void menuCommandsExecute(String userInput, ArrayList < Scenario > scenarioList, File logFile, Scanner scanner, boolean containsScenario, boolean logFileProvided, boolean logFileExists, RescueList rescueList) {
Judge judge = new Judge();
ArrayList < Scenario > tempJudgeScenarioList=scenarioList;
Randomizer randomizer = new Randomizer();
if(!containsScenario){
RescueList randomRescueList = new RescueList();
randomRescueList.randomizedScenarios(randomizer.scenarioGenerator(0));
tempJudgeScenarioList = randomRescueList.getScenarioList();
} else if(containsScenario){
tempJudgeScenarioList = scenarioList;
}
String userConsent = null;
int errorOrNot = 0;
if (userInput.equalsIgnoreCase("judge") || userInput.equalsIgnoreCase("j")) {
boolean yesOrNoProvided = false;
while (!yesOrNoProvided) { //loops until user consents or doesn't consent
try {
if (errorOrNot == 0) {
System.out.println("Do you consent to have your decisions saved to a file? (yes/no)"); //checks for user consent to save file
System.out.print("> ");
}
userConsent = scanner.next();
if (userConsent.equalsIgnoreCase("yes") || userConsent.equalsIgnoreCase("no")) {
yesOrNoProvided = true;
} else {
throw new InvalidInputException("Invalid response! Do you consent to have your decisions saved to a file? (yes/no)");
}
} catch (InvalidInputException e) {
System.out.println(e.getMessage());
System.out.print("> ");
errorOrNot = 1;
}
}
judge.judgeScenario(userConsent, tempJudgeScenarioList, logFile, scanner, judge, logFileProvided, logFileExists, containsScenario); //lets user judge
}
if (userInput.equalsIgnoreCase("run") || userInput.equalsIgnoreCase("r")) { //performs a bot algorithm
ArrayList < Scenario > tempScenarioList = scenarioList;
int howMany=0; //checks how many scenarios run, executes only if no scenario is provided
if (containsScenario) {
tempScenarioList = scenarioList;
}
if (!containsScenario) { //executes only if no scenarios provided
while (true) {
try {
System.out.println("How many scenarios should be run?");
System.out.print("> ");
howMany = Integer.parseInt(scanner.nextLine());
if (howMany < 1) {
throw new InputMismatchException();
}
break;
} catch (InputMismatchException e) { //executes if wrong data type passed
System.out.print("Invalid input! ");
} catch (NumberFormatException e){ //executes if parsing into int fails
System.out.print("Invalid input! ");
}
}
RescueList tempRescueList = new RescueList();
Randomizer tempRandomizer = new Randomizer();
tempRescueList.randomizedScenarios(tempRandomizer.scenarioGenerator(howMany)); //creates a randomized scenario to judge
tempScenarioList = tempRescueList.getScenarioList();
}
judge.botJudge(tempScenarioList, logFile, judge, logFileProvided, logFileExists);
thatsAll(scanner, false); //shows message, asking user for input of enter
}
if (userInput.equalsIgnoreCase("audit") || userInput.equalsIgnoreCase("a")) {
performAudit(logFile,logFileProvided,logFileExists,audit,scanner);
}
if (userInput.equalsIgnoreCase("quit") || userInput.equalsIgnoreCase("q")) {
System.exit(0);
}
}
/**
* Prints the message asking the user to press enter to return to main menu
* Executes when certain actions have finished being performed, or there is no history to audit from a log file
* @param scanner Scanner used to get user input
* @param hasNoHistory Indicates if method is executed due to no history
*/
public void thatsAll(Scanner scanner, boolean hasNoHistory) {
while (true) {
try {
if (!hasNoHistory) { //if method called from not having any history
System.out.println("That's all. Press Enter to return to main menu.");
} else if (hasNoHistory) { //method called from any other condition
System.out.println("No history found. Press enter to return to main menu.");
}
System.out.print("> ");
scanner.nextLine();
break;
} catch (Exception e) {
System.out.print("Invalid input! ");
continue;
}
}
}
//Private Methods
/**
* Performs an audit on a log file, printing out the audit if any exists
* @param logFile File to read audits from
* @param logFileProvided Indicates if user provided a log file
* @param logFileExists Indicates if user-provided log file
* @param scanner Used to get user input
* @throws Exception Thrown when an exception occur in the logFIle, which should never happen
*/
private void performAudit(File logFile, boolean logFileProvided, boolean logFileExists, Audit audit, Scanner scanner) {
audit.checkIfLogExists(logFileProvided, logFileExists); //check if logFile provided by user but doesn't exist
Scanner fileScanner = null;
try {
fileScanner = new Scanner(logFile);
} catch (FileNotFoundException e) {
System.out.println("error in scanning logFile");
} catch (Exception e) {
System.out.println("some other error");
}
boolean userRead = false;
ArrayList < String > botAuditList = new ArrayList < String > ();
ArrayList < String > userAuditList = new ArrayList < String > ();
int userHowManyRuns = 0;
int botHowManyRuns = 0;
int totalBotScenarios = 0;
int totalBotAge = 0;
int totalBotEntities = 0;
int totalUserScenarios = 0;
int totalUserAge = 0;
int totalUserEntities = 0;
while (fileScanner.hasNextLine()) { //iterating through every line
try {
String currentRead = fileScanner.nextLine();
String[] currentReadSplit = currentRead.split(":", -1);
ArrayList < String > currentReadingList = new ArrayList < String > ();
for (String field: currentReadSplit) {
if (field.toLowerCase().contains("useraudit".toLowerCase())) {
userRead = true; //means currently read log is an user log
userHowManyRuns += 1;
} else if (field.toLowerCase().contains("botaudit".toLowerCase())) {
userRead = false; //means currently read log is a bot log
botHowManyRuns += 1;
}
if (field.toLowerCase().contains("age//".toLowerCase())) {
int startAge = field.indexOf("AGE//") + "AGE//".length(); //gets total age of humans for an audit
int endAge = field.indexOf("//", startAge);
int startEntity = field.indexOf("TOTAL-HUMANS//") + "TOTAL-HUMANS//".length(); //gets total number of humans for an audit
int endEntity = field.indexOf("//", startEntity);
int startScenario = field.indexOf("SCENARIOS//") + "SCENARIOS//".length(); //gets number of scenarios run in an audit
int endScenario = field.indexOf("//", startScenario);
if (userRead) { //adds to user audit if comes from user log
totalUserAge += Integer.parseInt(field.substring(startAge, endAge));
totalUserEntities += Integer.parseInt(field.substring(startEntity, endEntity));
totalUserScenarios += Integer.parseInt(field.substring(startScenario, endScenario));
}
if (!userRead) { //adds to bot audit if comes from bot log
totalBotAge += Integer.parseInt(field.substring(startAge, endAge));
totalBotEntities += Integer.parseInt(field.substring(startEntity, endEntity));
totalBotScenarios += Integer.parseInt(field.substring(startScenario, endScenario));
}
}
}
int logLength=5;
if (currentReadSplit.length == logLength) { //length of a row that contains characteristic information
if (userRead) { //accesses which list depending on whose log it is
currentReadingList = userAuditList;
} else if (!userRead) { //accesses which list depending on whose log it is
currentReadingList = botAuditList;
}
boolean inListOrNot = false;
//indexes of where information is from the log file
int indexOfProperty = 0;
int numeratorShift = 2;
int denominatorShift = 4;
int denominatorInArray = 2;
for (int i = 0; i < currentReadingList.size(); i++) { //checks if a characteristic has already been added to log
if (currentReadSplit[0].equalsIgnoreCase(currentReadingList.get(i))) {
inListOrNot = true;
indexOfProperty = i;
break;
}
}
if (!inListOrNot) { //executes if characteristic was not read before
if (userRead) { //runs depending on user or bot log, updating values as necessary
userAuditList.add(currentReadSplit[0]);
userAuditList.add(currentReadSplit[numeratorShift]);
userAuditList.add(currentReadSplit[denominatorShift]);
}
if (!userRead) { //runs depending on user or bot log, updating values as necessary
botAuditList.add(currentReadSplit[0]);
botAuditList.add(currentReadSplit[numeratorShift]);
botAuditList.add(currentReadSplit[denominatorShift]);
}
} else if (inListOrNot) { //executes if characteristic was read before
if (userRead) { //runs depending on user or bot log, updating values as necessary
int numerator = Integer.parseInt(userAuditList.get(indexOfProperty + 1));
int denominator = Integer.parseInt(userAuditList.get(indexOfProperty + denominatorInArray));
int addNumerator = Integer.parseInt(currentReadSplit[numeratorShift]);
int addDenominator = Integer.parseInt(currentReadSplit[denominatorShift]);
int newNumerator = numerator + addNumerator;
int newDenominator = denominator + addDenominator;
userAuditList.set(indexOfProperty + 1, String.valueOf(newNumerator));
userAuditList.set(indexOfProperty + denominatorInArray, String.valueOf(newDenominator));
} else if (!userRead) { //runs depending on user or bot log, updating values as necessary
int numerator = Integer.parseInt(botAuditList.get(indexOfProperty + 1));
int denominator = Integer.parseInt(botAuditList.get(indexOfProperty + denominatorInArray));
int addNumerator = Integer.parseInt(currentReadSplit[numeratorShift]);
int addDenominator = Integer.parseInt(currentReadSplit[denominatorShift]);
int newNumerator = numerator + addNumerator;
int newDenominator = denominator + addDenominator;
botAuditList.set(indexOfProperty + 1, String.valueOf(newNumerator));
botAuditList.set(indexOfProperty + denominatorInArray, String.valueOf(newDenominator));
}
}
}
} catch (Exception e) {
System.out.println("an exception occured in reading logFile"); //exception handling if there is an error in reading log file that is not caused by non-existent log
continue;
}
}
fileScanner.close();
if (userAuditList.isEmpty() && botAuditList.isEmpty()) {
thatsAll(scanner, true);
}
if (!(botAuditList.isEmpty())) {
printBotAudit(totalBotScenarios, botHowManyRuns, totalBotAge, totalBotEntities, botAuditList, audit, userAuditList);
}
if (!(userAuditList.isEmpty())) {
printUserAudit(totalUserScenarios, userHowManyRuns, totalUserAge, totalUserEntities, userAuditList, audit);
}
if (!(userAuditList.isEmpty() && botAuditList.isEmpty())) {
thatsAll(scanner, false);
}
}
/**
* Prints the user audit if a user audit exists
* @param totalUserScenarios Total number of scenarios in user audits
* @param totalUserAge Total age of humans surviving in all user audits saved
* @param totalUserEntities Total number of humans surviving in all user audits saved
* @param userAuditList List of characteristics saved, including surivial rates for each characteristics
* @param audit Audit used to execute methods related to printing statistics
*/
private void printUserAudit(int totalUserScenarios, int userHowManyRuns, int totalUserAge, int totalUserEntities, ArrayList < String > userAuditList, Audit audit){
System.out.println("======================================");
System.out.println("# User Audit");
System.out.println("======================================");
System.out.printf("- %% SAVED AFTER %d RUNS%n", totalUserScenarios);
audit.printAudit(userAuditList, userHowManyRuns, true);
double totalUserAgeDouble = totalUserAge;
double totalUserEntitiesDouble = totalUserEntities;
double avgAge = Math.ceil((totalUserAgeDouble / totalUserEntitiesDouble) * 100) / 100.0; //rounds the age up
System.out.println("--");
System.out.printf("average age: %.2f%n", avgAge);
}
/**
* Prints the bot audit if a bot audit exists
* @param totalBotScenarios Total number of scenarios in bot audits
* @param totalBotAge Total age of humans surviving in all bot audits saved
* @param totalBotEntities Total number of humans surviving in all bot audits saved
* @param botAuditList List of characteristics saved, including surivial rates for each characteristics
* @param audit Audit used to execute methods related to printing statistics
* @param userAuditList Used to check if user audit is empty, and whether to print a new line
*/
private void printBotAudit(int totalBotScenarios, int botHowManyRuns, int totalBotAge, int totalBotEntities, ArrayList < String > botAuditList, Audit audit, ArrayList < String > userAuditList){
System.out.println("======================================");
System.out.println("# Algorithm Audit");
System.out.println("======================================");
System.out.printf("- %% SAVED AFTER %d RUNS%n", totalBotScenarios);
double totalBotAgeDouble = totalBotAge;
double totalBotEntitiesDouble = totalBotEntities;
audit.printAudit(botAuditList, botHowManyRuns, true);
double avgAge = Math.ceil((totalBotAgeDouble / totalBotEntitiesDouble) * 100) / 100.0; //rounds the age up
System.out.println("--");
System.out.printf("average age: %.2f%n", avgAge);
if (!(userAuditList.isEmpty())) { //prints a space only if an algorithm audit will also be printed
System.out.println("");
}
}
}