From 645e632dcbed3996f3e4ceedc2611aa177d4210f Mon Sep 17 00:00:00 2001 From: Matthew Cech Date: Sun, 5 May 2019 15:22:49 -0700 Subject: [PATCH] + Added command functionality base and modified command stub --- ...erBenchmark.java => CommandBenchmark.java} | 6 +- src/core/ObjectBuilderFactory.java | 50 +++++++-- src/core/benchmark/BenchmarkEntry.java | 27 +++++ src/core/benchmark/BenchmarkLog.java | 11 ++ src/core/benchmark/BenchmarkManager.java | 106 ++++++++++++++++++ src/core/benchmark/BenchmarkType.java | 17 +++ src/main/Main.java | 3 + .../DirectoryMonitor.java | 12 +- .../directoryMonitor}/MonitoredFile.java | 2 +- 9 files changed, 218 insertions(+), 16 deletions(-) rename src/commands/{CommandUserBenchmark.java => CommandBenchmark.java} (75%) create mode 100644 src/core/benchmark/BenchmarkEntry.java create mode 100644 src/core/benchmark/BenchmarkLog.java create mode 100644 src/core/benchmark/BenchmarkManager.java create mode 100644 src/core/benchmark/BenchmarkType.java rename src/utils/{ => directoryMonitor}/DirectoryMonitor.java (94%) rename src/{dataStructures => utils/directoryMonitor}/MonitoredFile.java (95%) diff --git a/src/commands/CommandUserBenchmark.java b/src/commands/CommandBenchmark.java similarity index 75% rename from src/commands/CommandUserBenchmark.java rename to src/commands/CommandBenchmark.java index f9432b7..840e9cd 100644 --- a/src/commands/CommandUserBenchmark.java +++ b/src/commands/CommandBenchmark.java @@ -10,12 +10,12 @@ import dataStructures.KittyUser; import dataStructures.Response; import dataStructures.UserInput; -public class CommandUserBenchmark extends Command +public class CommandBenchmark extends Command { - public CommandUserBenchmark(KittyRole level, KittyRating rating) { super(level, rating); } + public CommandBenchmark(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return LocStrings.Stub("UserBenchmarkInfo"); } + public String HelpText() { return LocStrings.Stub("BenchmarkInfo"); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) diff --git a/src/core/ObjectBuilderFactory.java b/src/core/ObjectBuilderFactory.java index b86a223..1c307df 100644 --- a/src/core/ObjectBuilderFactory.java +++ b/src/core/ObjectBuilderFactory.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.concurrent.Semaphore; import commands.*; +import core.benchmark.BenchmarkManager; import core.lua.PluginManager; import dataStructures.*; import net.dv8tion.jda.core.entities.Emote; @@ -42,6 +43,9 @@ public class ObjectBuilderFactory // Plugin manager private static PluginManager pluginManager; + // Userbenchmark csv manager instance + private static BenchmarkManager benchmarkManager; + // Localization classes - these are singletons, but should be initialized before almost all other // things so their inclusion in the factory is to ensure they're started at the correct time. @SuppressWarnings("unused") private static LocStrings locStrings; @@ -93,6 +97,10 @@ public class ObjectBuilderFactory } } + //////////////////////// + // Extraction Methods // + //////////////////////// + // Explicitly locks: guildCache public static KittyGuild ExtractGuild(GuildMessageReceivedEvent event) { @@ -311,16 +319,9 @@ public class ObjectBuilderFactory user.avatarID = member.getUser().getAvatarUrl(); } - // Constructs a CommandEnabler if it doesn't exist, and gets the existing one if it does. - public static CommandEnabler ConstructCommandEnabler() - { - LazyInit(); - - if(commandEnabler == null) - commandEnabler = new CommandEnabler(); - - return commandEnabler; - } + ////////////////////////// + // Construction Methods // + ////////////////////////// // Default construction of the command manager. In order to remotely resolve command enabling // and disabling, what we do is construct the commands with a localized pair that is checked against @@ -378,9 +379,22 @@ public class ObjectBuilderFactory manager.Register(LocCommands.Stub("catch"), new CommandCatch(KittyRole.General, KittyRating.Safe)); manager.Register(LocCommands.Stub("guildrolelist"), new CommandGuildRoleList(KittyRole.General, KittyRating.Safe)); + manager.Register(LocCommands.Stub("benchmark, bench"), new CommandBenchmark(KittyRole.General, KittyRating.Safe)); + return manager; } + // Constructs a CommandEnabler if it doesn't exist, and gets the existing one if it does. + public static CommandEnabler ConstructCommandEnabler() + { + LazyInit(); + + if(commandEnabler == null) + commandEnabler = new CommandEnabler(); + + return commandEnabler; + } + // Default database manager construction. It can be constructed // in different ways, and so we construct it outside of the constructor for // the factory since it doesn't have to be present / can be elsewhere. @@ -425,6 +439,21 @@ public class ObjectBuilderFactory return pluginManager; } + public static BenchmarkManager ConstructBenchmarkManager() + { + LazyInit(); + + if(benchmarkManager == null) + benchmarkManager = new BenchmarkManager(); + + return benchmarkManager; + } + + ///////////////////// + // Utility Methods // + ///////////////////// + + // Returns number of cached guilds (does not equal total users in the database, only what's in memory) public static Integer GetGuildCount() { synchronized(guildCache) { @@ -432,6 +461,7 @@ public class ObjectBuilderFactory } } + // Returns number of cached users (does not equal total users in the database, only what's in memory) public static Integer GetUserCount() { synchronized(userCache) { diff --git a/src/core/benchmark/BenchmarkEntry.java b/src/core/benchmark/BenchmarkEntry.java new file mode 100644 index 0000000..a883ae7 --- /dev/null +++ b/src/core/benchmark/BenchmarkEntry.java @@ -0,0 +1,27 @@ +package core.benchmark; + +public class BenchmarkEntry +{ + public final BenchmarkType type; + public final String partNumber; + public final String brand; + public final String model; + public final int rank; + public final float benchmark; + public final int samples; + public final String url; + + BenchmarkEntry(String input) + { + String[] row = input.split(","); + + type = BenchmarkType.valueOf(row[0]); + partNumber = row[1]; + brand = row[2]; + model = row[3]; + rank = Integer.parseInt(row[4]); + benchmark = Float.parseFloat(row[5]); + samples = Integer.parseInt(row[6]); + url = row[7]; + } +} diff --git a/src/core/benchmark/BenchmarkLog.java b/src/core/benchmark/BenchmarkLog.java new file mode 100644 index 0000000..af62ac0 --- /dev/null +++ b/src/core/benchmark/BenchmarkLog.java @@ -0,0 +1,11 @@ +package core.benchmark; + +import utils.GlobalLog; + +public class BenchmarkLog +{ + // Logging + public static void Log(String str) { GlobalLog.Log("[Benchmark] " + str); } + public static void Warn(String str) { GlobalLog.Warn("[Benchmark] " + str); } + public static void Error(String str) { GlobalLog.Error(" [Benchmark] " + str); } +} diff --git a/src/core/benchmark/BenchmarkManager.java b/src/core/benchmark/BenchmarkManager.java new file mode 100644 index 0000000..d54b75a --- /dev/null +++ b/src/core/benchmark/BenchmarkManager.java @@ -0,0 +1,106 @@ +package core.benchmark; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +import utils.FileUtils; +import utils.directoryMonitor.DirectoryMonitor; +import utils.directoryMonitor.MonitoredFile; + +// All things considered, this doesn't need to be particularly efficient since anything +// less than 10ms of search time won't be noticable to an end user really, not for +// a networked application that's not performance bound. +public class BenchmarkManager +{ + // Variables + public final String directory = "assets/userbench/"; + public final String extension = ".csv"; + public final String lineDelimiter = "\n"; + + private List raw; + private DirectoryMonitor directoryMonitor; + private boolean needsUpdate; + + // Read in all extensions + public BenchmarkManager() + { + long start = Instant.now().toEpochMilli(); + + raw = new ArrayList(); + directoryMonitor = new DirectoryMonitor(directory); + needsUpdate = false; + + RebuildLookup(); + + BenchmarkLog.Log("Took " + (Instant.now().toEpochMilli() - start) + " ms to load " + raw.size() + " entries from " + directoryMonitor.GetCurrentFiles().size() + " file" + (raw.size() > 1 ? "s" : "")); + } + + // Rebuilds the files being monitored + public void RebuildLookup() + { + synchronized(raw) + { + raw.clear(); + List files; + + synchronized(directoryMonitor) + { + files = directoryMonitor.GetCurrentFiles(); + } + + if(files != null) + { + for(MonitoredFile mf : files) + { + String contents = FileUtils.ReadContent(mf.path); + String[] lines = contents.split(lineDelimiter); + + for(int i = 1; i < lines.length; ++i) + raw.add(new BenchmarkEntry(lines[i])); + } + } + else + { + BenchmarkLog.Warn("No " + extension + " files where found in " + directory); + } + } + } + + // Search for a substring in the model name + public List FindModel(String modelSubstr) + { + long start = Instant.now().toEpochMilli(); + List matching = new ArrayList(); + String searchSubstr = modelSubstr.toLowerCase(); + + for(BenchmarkEntry e : raw) + { + String model = e.model.toLowerCase().trim(); + + if(model.contains(searchSubstr)) + matching.add(e); + } + + BenchmarkLog.Log("Searched for '" + searchSubstr + "' for "+ (Instant.now().toEpochMilli() - start) + "ms and found " + matching.size() + " entries."); + return matching; + } + + // Keeps tabs on any changes of the files. + public void Update() + { + needsUpdate = false; + directoryMonitor.Update(this::OnRescan, this::OnRescan, this::OnRescan); + + if(needsUpdate) + RebuildLookup(); + } + + // When a file is changed, handle it. + private void OnRescan(MonitoredFile file) + { + // For now, all we need is to note that something was adjusted. + if(file.path.endsWith(extension)) + needsUpdate = true; + } +} diff --git a/src/core/benchmark/BenchmarkType.java b/src/core/benchmark/BenchmarkType.java new file mode 100644 index 0000000..4ec566f --- /dev/null +++ b/src/core/benchmark/BenchmarkType.java @@ -0,0 +1,17 @@ +package core.benchmark; + +public enum BenchmarkType +{ + CPU(0), GPU(1), SSD(2), HDD(4), RAM(8), USB(16); + + private final int value; + private BenchmarkType(int value) + { + this.value = value; + } + + public int getValue() + { + return value; + } +} diff --git a/src/main/Main.java b/src/main/Main.java index aa432e0..b1c7dec 100644 --- a/src/main/Main.java +++ b/src/main/Main.java @@ -2,6 +2,7 @@ package main; import javax.security.auth.login.LoginException; import core.*; +import core.benchmark.BenchmarkManager; import core.lua.PluginManager; import core.lua.PluginUser; import dataStructures.KittyChannel; @@ -32,6 +33,7 @@ public class Main extends ListenerAdapter private static Stats stats; private static RPManager rpManager; private static PluginManager pluginManager; + private static BenchmarkManager benchmarkManager; // Main test location public static void main(String[] args) throws InterruptedException, LoginException, Exception @@ -44,6 +46,7 @@ public class Main extends ListenerAdapter stats = ObjectBuilderFactory.ConstructStats(commandManager); rpManager = ObjectBuilderFactory.ConstructRPManager(); pluginManager = ObjectBuilderFactory.ConstructPluginManager(); + benchmarkManager = ObjectBuilderFactory.ConstructBenchmarkManager(); // Bot startup kitty = new JDABuilder(AccountType.BOT).setToken(Ref.TestToken).buildBlocking(); diff --git a/src/utils/DirectoryMonitor.java b/src/utils/directoryMonitor/DirectoryMonitor.java similarity index 94% rename from src/utils/DirectoryMonitor.java rename to src/utils/directoryMonitor/DirectoryMonitor.java index 59a80e8..144665a 100644 --- a/src/utils/DirectoryMonitor.java +++ b/src/utils/directoryMonitor/DirectoryMonitor.java @@ -1,4 +1,4 @@ -package utils; +package utils.directoryMonitor; import java.io.File; import java.nio.file.Files; @@ -6,10 +6,12 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.function.Consumer; import java.util.stream.Stream; -import dataStructures.MonitoredFile; +import utils.GlobalLog; +import utils.LogFilter; // NOTE: Consider shifting internal behavior to https://docs.oracle.com/javase/tutorial/essential/io/notification.html // for external stability and support @@ -151,6 +153,12 @@ public class DirectoryMonitor Warn("There's nothing at all in a FileMonitor's target folder! Folder: " + directory); } + // Returns the current list of files the monitor is tracking in the directory. + public List GetCurrentFiles() + { + return last; + } + // Prints out an arraylist of items from a directory by path private void Print(ArrayList toPrint) { diff --git a/src/dataStructures/MonitoredFile.java b/src/utils/directoryMonitor/MonitoredFile.java similarity index 95% rename from src/dataStructures/MonitoredFile.java rename to src/utils/directoryMonitor/MonitoredFile.java index ae53ca3..f77e58f 100644 --- a/src/dataStructures/MonitoredFile.java +++ b/src/utils/directoryMonitor/MonitoredFile.java @@ -1,4 +1,4 @@ -package dataStructures; +package utils.directoryMonitor; import java.nio.file.Path;