-
Notifications
You must be signed in to change notification settings - Fork 479
[H1410101] iP #555
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
[H1410101] iP #555
Changes from 12 commits
28ad2b8
ed6d4d2
afe47af
4ccdfbe
b2749c3
696361d
cfbfbac
1209ca0
8d970a2
17a2cc2
3ef9980
ac0962c
e2e6f0c
09eb837
021f2e1
26f5425
5218357
84540d8
347cb97
76f3604
13fa8fb
493a117
50839b0
901f2c7
bb8638f
a40bfab
d305a5a
3fd5f4e
3c32b3c
66ff7aa
f91fbe1
7b0e464
6ceecdd
77825cb
f10b024
e351a0f
6e2d091
0a08fda
7e1f6f6
030f583
cb5ae6c
f2798ae
9a5badd
976c574
fa5cdf8
4893ea7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| package catbot; | ||
|
|
||
| import catbot.internal.CommandMap; | ||
| import catbot.internal.CommandPattern; | ||
| import catbot.internal.NamedParameterMap; | ||
| import catbot.io.CatbotConsoleIO; | ||
| import catbot.io.ErrorIndicatorIo; | ||
| import catbot.io.UserIo; | ||
| import catbot.task.Task; | ||
| import catbot.task.TaskList; | ||
|
|
||
| import java.util.Objects; | ||
| import java.util.Optional; | ||
| import java.util.function.BiConsumer; | ||
| import java.util.function.BiFunction; | ||
| import java.util.function.Consumer; | ||
|
|
||
| public class CatBot { | ||
|
|
||
| private static final CommandMap commands = new CommandMap(); | ||
| static final UserIo io = new CatbotConsoleIO(); | ||
| private static final TaskList taskList = new TaskList("Tasks.txt"); | ||
| static { | ||
| addSupportedCommandsToCommandMap(); | ||
| } | ||
|
|
||
| private static void addSupportedCommandsToCommandMap() { | ||
| CommandPattern<Integer> integerPattern = CatBotCommandPatterns.getIntegerPatternGenerator() | ||
| .generate(io::indicateInvalidInteger); | ||
| CommandPattern<NamedParameterMap> slashPattern = CatBotCommandPatterns.getSlashPatternGenerator() | ||
| .generate(CatBotCommandPatterns.NO_DEFAULT); | ||
|
|
||
| commands.setDefaultCommand(io::indicateInvalidCommand) | ||
| .addCommand("bye", args -> io.cleanup()) | ||
| .addCommand("list", args -> io.printTaskList(taskList)); | ||
|
|
||
| // User modifying existing tasks (through IntegerPattern, and Index) | ||
| BiConsumer<String, Consumer<Integer>> runIfValidIndexElseIndicateError = | ||
| (args, lambda) -> integerPattern.ifParsableElseDefault(args, | ||
| integer -> taskList.ifValidIndexElse(integer, | ||
| lambda, | ||
| invalidIndex -> io.indicateInvalidIndex(invalidIndex, taskList.getIndexBounds()) | ||
| )); | ||
|
|
||
| //noinspection SpellCheckingInspection | ||
| commands.addCommand("mark", | ||
| string -> runIfValidIndexElseIndicateError.accept(string, | ||
| validIndex -> { | ||
| taskList.markTask(validIndex-1); | ||
| io.printTaskModified(taskList, validIndex); | ||
| } | ||
| ) | ||
| ) | ||
| .addCommand("unmark", | ||
| string -> runIfValidIndexElseIndicateError.accept(string, | ||
| validIndex -> { | ||
| taskList.unmarkTask(validIndex-1); | ||
| io.printTaskModified(taskList, validIndex); | ||
| } | ||
| ) | ||
| ) | ||
| .addCommand("delete", | ||
| string -> runIfValidIndexElseIndicateError.accept(string, | ||
| validIndex -> io.printTaskDeleted(taskList.removeTask(validIndex-1)) | ||
| ) | ||
| ); | ||
|
|
||
| // User creating new tasks (with SlashPattern) | ||
|
|
||
| BiConsumer<String, BiFunction<NamedParameterMap, BiConsumer<ErrorIndicatorIo.InvalidState, NamedParameterMap>, Optional<Task>>> | ||
|
||
| createTaskIfValidElseWarn = (args, bifunction) -> slashPattern.ifParsableElseDefault(args, | ||
| namedParameterMap -> bifunction.apply( | ||
| namedParameterMap, | ||
| io::indicateArgumentInvalid | ||
| ).ifPresent(task -> { | ||
| taskList.addTask(task); | ||
| io.printTaskAdded(taskList); | ||
| }) | ||
| ); | ||
|
|
||
| commands.addCommand("todo", | ||
| args -> createTaskIfValidElseWarn.accept(args, Task.Todo::createIfValidElse) | ||
| ) | ||
| .addCommand("event", | ||
| args -> createTaskIfValidElseWarn.accept(args, Task.Event::createIfValidElse) | ||
| ) | ||
| .addCommand("deadline", | ||
| args -> createTaskIfValidElseWarn.accept(args, Task.Deadline::createIfValidElse) | ||
| ) | ||
| ; | ||
|
|
||
| } | ||
|
||
|
|
||
| public static void main(String[] args) { | ||
| UserIo.CommandArgument commandArgument; | ||
| io.initialize(); | ||
| do { | ||
| commandArgument = io.getNextCommand(); | ||
| commands.run(commandArgument.getCommand(), commandArgument.getArgument()); | ||
| } while (!Objects.equals(commandArgument.getCommand(), "bye")); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| package catbot; | ||
|
|
||
| import catbot.internal.CommandPattern; | ||
| import catbot.internal.CommandPatternGenerator; | ||
| import catbot.internal.NamedParameterMap; | ||
|
|
||
| import java.util.function.Consumer; | ||
|
|
||
| public class CatBotCommandPatterns { | ||
|
||
|
|
||
| public static final Consumer<String> NO_DEFAULT = new Consumer<String>() { | ||
| @Override | ||
| public void accept(String s) { | ||
| assert false; //SHOULD NOT BE CALLED | ||
| } | ||
| }; | ||
|
|
||
| //region Integer Pattern | ||
| public static CommandPatternGenerator<Integer> getIntegerPatternGenerator() { | ||
| return integerPatternGenerator; | ||
| } | ||
| private static final IntegerPatternGenerator integerPatternGenerator = new IntegerPatternGenerator(); | ||
| private static class IntegerPatternGenerator implements CommandPatternGenerator<Integer> { | ||
|
|
||
| @Override | ||
| public CommandPattern<Integer> generate(Consumer<String> invalidInput) { | ||
| return new CommandPattern<Integer>() { | ||
| @Override | ||
| public void ifParsableElseDefault(String args, Consumer<Integer> consumer) { | ||
| try { | ||
| consumer.accept(Integer.parseInt(args)); | ||
| } catch (NumberFormatException nfe) { | ||
| invalidInput.accept(args); | ||
| } | ||
| } | ||
| }; | ||
| } | ||
| } | ||
| //endregion | ||
|
|
||
| //region Slash Arguments Pattern | ||
| private static final SlashArgumentPatternGenerator slashPatternGenerator = new SlashArgumentPatternGenerator(); | ||
|
||
| public static CommandPatternGenerator<NamedParameterMap> getSlashPatternGenerator() { | ||
| return slashPatternGenerator; | ||
| } | ||
|
|
||
| private static class SlashArgumentPatternGenerator implements CommandPatternGenerator<NamedParameterMap> { | ||
|
|
||
| @Override | ||
| public CommandPattern<NamedParameterMap> generate(Consumer<String> ignored) { | ||
| return new CommandPattern<NamedParameterMap>() { | ||
|
|
||
| private final Parser slashParser = Parser.by("/", true); | ||
| @Override | ||
| public void ifParsableElseDefault(String args, Consumer<NamedParameterMap> consumer) { | ||
| consumer.accept(slashParser.parse(args)); | ||
| } | ||
| }; | ||
| } | ||
| } | ||
| //endregion | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| package catbot; | ||
|
|
||
| import catbot.internal.NamedParameterMap; | ||
|
|
||
| import java.util.Arrays; | ||
|
|
||
| public class Parser { | ||
|
|
||
| private final String delimiter; | ||
| private final boolean emptyArgument; | ||
|
|
||
| //region Constructor | ||
|
|
||
| private Parser(String delimiter, boolean emptyArgument) { | ||
| this.delimiter = delimiter; | ||
| this.emptyArgument = emptyArgument; | ||
| } | ||
|
|
||
| public static Parser by(String delimiter) { | ||
| return by(delimiter, false); | ||
| } | ||
|
|
||
| public static Parser by(String delimiter, boolean emptyArgument) { | ||
|
||
| if (delimiter == null || delimiter.isEmpty()) { | ||
| return new SingleParser(); | ||
| } else { | ||
| return new Parser(delimiter, emptyArgument); | ||
| } | ||
| } | ||
| //endregion | ||
|
|
||
| public static class SingleParser extends Parser { | ||
|
|
||
| private SingleParser() { | ||
| super(null, false); | ||
| } | ||
|
|
||
| @Override | ||
| public NamedParameterMap parse(String s) { | ||
| NamedParameterMap cmdArgs = new NamedParameterMap(); | ||
| parseCmdArg(s, cmdArgs); | ||
| return cmdArgs; | ||
| } | ||
| } | ||
|
|
||
| public NamedParameterMap parse(String s) { | ||
| NamedParameterMap cmdArgs = new NamedParameterMap(); | ||
| String[] arr = s.split(delimiter); | ||
| parseCmdArg(arr[0], cmdArgs, this.emptyArgument); | ||
| Arrays.stream(arr).skip(1).forEach(segment -> parseCmdArg(segment, cmdArgs)); | ||
| return cmdArgs; | ||
| } | ||
|
|
||
| //region Internal Helpers | ||
|
|
||
| /** | ||
| * Split string into one pair of command + argument based on the first whitespace. | ||
| * @param s string containing both command and argument, in that order | ||
| * @param map to store the mapping between command and argument | ||
| */ | ||
| private static void parseCmdArg(String s, NamedParameterMap map) { | ||
| String[] cmdArg = s.split("\\s", 2); | ||
|
||
| if (cmdArg.length == 2) { | ||
| map.addNamedParameter(cmdArg[0].trim(), cmdArg[1].trim()); | ||
| } else { | ||
| map.addNamedParameter(cmdArg[0].trim(), ""); | ||
| } | ||
| } | ||
|
|
||
| private static void parseCmdArg(String s, NamedParameterMap map, boolean emptyArgument) { | ||
| if (emptyArgument) { | ||
| map.addNamedParameter("", s.trim()); | ||
| } else { | ||
| parseCmdArg(s, map); | ||
| } | ||
| } | ||
|
||
|
|
||
| //endregion | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| package catbot.internal; | ||
|
|
||
| public interface Command { | ||
|
|
||
| public void run(String args); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package catbot.internal; | ||
|
|
||
| import java.util.HashMap; | ||
|
|
||
| public class CommandMap { | ||
|
|
||
| private final HashMap<String, Command> commandMap = new HashMap<>(); | ||
| private Command defaultCommand; | ||
| //endregion | ||
|
|
||
| public CommandMap addCommand(String invocation, Command lambda) { | ||
| commandMap.put(invocation, lambda); | ||
| return this; | ||
| } | ||
|
|
||
| public CommandMap setDefaultCommand(Command defaultCommand) { | ||
| this.defaultCommand = defaultCommand; | ||
| return this; | ||
| } | ||
|
|
||
| public void run(String s, String args) { | ||
| commandMap.getOrDefault(s, defaultCommand).run(args); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package catbot.internal; | ||
|
|
||
| import java.util.function.Consumer; | ||
|
|
||
| public abstract class CommandPattern<T> { | ||
|
|
||
| protected Consumer<String> invalidCommandInput; | ||
|
|
||
| public abstract void ifParsableElseDefault(String args, Consumer<T> consumer); | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package catbot.internal; | ||
|
|
||
| import java.util.function.Consumer; | ||
|
|
||
| public interface CommandPatternGenerator<T> { | ||
| public CommandPattern<T> generate(Consumer<String> invalidInput); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| package catbot.internal; | ||
|
|
||
| import java.util.HashMap; | ||
| import java.util.Set; | ||
|
|
||
| public class NamedParameterMap { | ||
|
|
||
| private HashMap<String, String> parameters; | ||
|
|
||
| public NamedParameterMap() { | ||
| parameters = new HashMap<>(); | ||
| } | ||
|
|
||
| public boolean containsKey(String key) { | ||
| return parameters.containsKey(key); | ||
| } | ||
|
|
||
| public void moveToNewKey(String oldKey, String newKey) { | ||
| if (!parameters.containsKey(newKey) && parameters.containsKey(oldKey)) { | ||
| parameters.put(newKey, parameters.get(oldKey)); | ||
| parameters.remove(oldKey); | ||
| } | ||
| } | ||
|
|
||
| public Set<String> keySet() { | ||
| return parameters.keySet(); | ||
| } | ||
|
|
||
| public String get(String key) { | ||
| return parameters.get(key); | ||
| } | ||
|
|
||
| public NamedParameterMap addNamedParameter(String parameterName, String parameterValue) { | ||
| parameters.put(parameterName, parameterValue); | ||
| return this; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like how you name the variables in a greater explanatory sense