From f7137a818b456f69b07d081bc7f825ba8a2e53d1 Mon Sep 17 00:00:00 2001 From: asdfasdf Date: Wed, 25 Sep 2019 07:41:06 -0700 Subject: [PATCH] Completed up to demo requirement --- src/main/data/Const.java | 7 ++ src/main/data/Nyse.java | 28 +++++ src/main/data/Options.java | 75 +++++++++++++ src/main/data/StockEntry.java | 27 +++++ src/main/data/StockType.java | 14 +++ src/main/data/StypeMap.java | 29 +++++ src/main/data/WatchList.java | 26 +++++ src/main/ui/Gui.java | 2 + src/main/ui/Iface.java | 17 ++- src/main/ui/IfaceFactory.java | 16 ++- src/main/ui/Main.java | 47 ++++++-- src/main/ui/Tui.java | 166 +++++++++++++++++++++++++---- src/test/placeholder/MainTest.java | 7 -- 13 files changed, 419 insertions(+), 42 deletions(-) create mode 100644 src/main/data/Const.java create mode 100644 src/main/data/Nyse.java create mode 100644 src/main/data/Options.java create mode 100644 src/main/data/StockEntry.java create mode 100644 src/main/data/StockType.java create mode 100644 src/main/data/StypeMap.java create mode 100644 src/main/data/WatchList.java delete mode 100644 src/test/placeholder/MainTest.java diff --git a/src/main/data/Const.java b/src/main/data/Const.java new file mode 100644 index 0000000..249e246 --- /dev/null +++ b/src/main/data/Const.java @@ -0,0 +1,7 @@ +package data; + +// Const for everywhere +public class Const { + public static final String PROGRAM_NAME = "J-WatchList"; + public static final String USAGE_TEXT = "Usage: Placeholder"; +} diff --git a/src/main/data/Nyse.java b/src/main/data/Nyse.java new file mode 100644 index 0000000..b5ceb31 --- /dev/null +++ b/src/main/data/Nyse.java @@ -0,0 +1,28 @@ +package data; + +import java.util.*; + +public class Nyse implements StockType { + private static final String NAME = "NYSE"; + private HashSet sources; + + public Nyse() { + sources = new HashSet(); + } + + @Override + public float[] update(String idstring) { + Iterator iterator = sources.iterator(); + float[] result = new float[2]; + while (iterator.hasNext()) { + //XXX + //DataSource source = (DataSource)iterator.next(); + } + return result; + } + + @Override + public String getName() { + return this.NAME; + } +} diff --git a/src/main/data/Options.java b/src/main/data/Options.java new file mode 100644 index 0000000..a97600b --- /dev/null +++ b/src/main/data/Options.java @@ -0,0 +1,75 @@ +package data; + +import java.util.prefs.Preferences; +import data.Const; + +public class Options { + private Preferences store; + private boolean wasEmpty; + private static final String DEF_OPTS_PATH = ""; + + public Options() { + //store = Preferences.userRoot(); + //wasEmpty = store.nodeExists(Const.PROGRAM_NAME); + //store = store.node(Const.PROGRAM_NAME); + //if (wasEmpty) { + // //load default opts from resource + // importDefPreferences(); + //} + } + + public Options(String pathname) { + store = Preferences.userRoot().node(pathname); + } + + public Options getSection(String section) { + //String path = Const.PROGRAM_NAME + "/" + section; + //Options result = new Options(path); + //return result; + return null; + } + + public void imoprtPreferences(String xmlpath) { + //XXX + System.out.println("Loaded preference from: " + + xmlpath); + } + + public void imoprtDefPreferences(String xmlpath) { + //XXX + System.out.println("Loaded default preference: "); + } + + public void exportPreferences(String xmlpath) { + //XXX + System.out.println("Exported preference from: " + + xmlpath); + } + + public void destroy() { + //XXX + // Clear config if requested or config was empty + // and is not saving + //if ((getBool(EMPTY) && getBool(NO_SAVE)) + // || getBool(CLEAR)) { + // this.store.clear(); + // } + } + + // Default all false bool pref to be safe + // Default should be imported by constructor regardless + public boolean getBool(String key) { + return this.store.getBoolean(key, false); + } + + // Default all empty string pref to be safe + // Default should be imported by constructor regardless + public String getString(String key) { + return this.store.get(key, ""); + } + + public void parseArgs(String[] args) { + //XXX + } + +} diff --git a/src/main/data/StockEntry.java b/src/main/data/StockEntry.java new file mode 100644 index 0000000..1eb8bf9 --- /dev/null +++ b/src/main/data/StockEntry.java @@ -0,0 +1,27 @@ +package data; + +public class StockEntry { + private String identifier; + private StockType stype; + private float price; + private float change; + + public StockEntry(StockType stype, String idstring) { + identifier = idstring; + this.stype = stype; + } + + public void update() { + float[] result = this.stype.update(this.identifier); + this.price = result[0]; + this.change = result[1]; + } + + public String getTypeName() { + return this.stype.getName(); + } + + public String getID() { + return this.identifier; + } +} diff --git a/src/main/data/StockType.java b/src/main/data/StockType.java new file mode 100644 index 0000000..ebc2d83 --- /dev/null +++ b/src/main/data/StockType.java @@ -0,0 +1,14 @@ +package data; + +import java.util.*; + +public interface StockType { + //Effects: return current price[0] and %change[1] + // (2 element array) + //Require: working sources + public float[] update(String idstring); + + //Effects: return name of type + //Require: working sources + public String getName(); +} diff --git a/src/main/data/StypeMap.java b/src/main/data/StypeMap.java new file mode 100644 index 0000000..890770d --- /dev/null +++ b/src/main/data/StypeMap.java @@ -0,0 +1,29 @@ +package data; + +import java.util.Set; +import java.util.Map; +import java.util.HashMap; +import java.util.Iterator; +import data.StockType; +//import data.Nyse; +//import data.Nasdaq; +//import data.Jpx; +//import data.Sse; +//import data.Hkse; + +public class StypeMap { + private HashMap smap; + + public StypeMap() { + smap = new HashMap(); + smap.put("Nyse", new Nyse()); + //smap.put("Nasdaq", new Nasdaq()); + //smap.put("Jpx", new Jpx()); + //smap.put("Sse", new Sse()); + //smap.put("Hkse", new Hkse()); + } + + public StockType getStype(String typeString) { + return smap.get(typeString); + } +} diff --git a/src/main/data/WatchList.java b/src/main/data/WatchList.java new file mode 100644 index 0000000..97dea7e --- /dev/null +++ b/src/main/data/WatchList.java @@ -0,0 +1,26 @@ +package data; + +import java.util.*; +import data.StockEntry; + +public class WatchList { + private LinkedHashMap listdata; + + public WatchList() { + this.listdata = new LinkedHashMap(); + } + + public void addStock(String target, StockType stype) { + //The only implementation yet + this.listdata.put(target, new StockEntry(stype, target)); + } + + public void delStock(String target) { + this.listdata.remove(target); + } + + public Iterator iterator() { + Set entryset = listdata.entrySet(); + return entryset.iterator(); + } +} diff --git a/src/main/ui/Gui.java b/src/main/ui/Gui.java index b7f6895..94e2da4 100644 --- a/src/main/ui/Gui.java +++ b/src/main/ui/Gui.java @@ -1,3 +1,5 @@ +package ui; + import javax.swing.*; public class Gui { diff --git a/src/main/ui/Iface.java b/src/main/ui/Iface.java index 20b2915..9672305 100644 --- a/src/main/ui/Iface.java +++ b/src/main/ui/Iface.java @@ -1,5 +1,18 @@ -//import data.Options; +package ui; -public abstract class Iface { +import data.Options; + +public interface Iface { //private Options ifaceOpts; + + //Effect: Redraw the whole interface + //Modify: This + //Require: Running thread of initialized Iface, data backend + public void redraw(); + + //Effect: Close all windows and disable all output + //Modify: This + //Require: Running thread of initialized Iface + public void destory(); + } diff --git a/src/main/ui/IfaceFactory.java b/src/main/ui/IfaceFactory.java index 77c2506..e347d52 100644 --- a/src/main/ui/IfaceFactory.java +++ b/src/main/ui/IfaceFactory.java @@ -1,7 +1,17 @@ -//import data.Options; -//import ui.Iface; +package ui; + +import data.Options; +import ui.Tui; public class IfaceFactory { - //public Iface getIface(Options IfaceOptions){ + // Produce Iface given the config + public static Iface getIface(Main mainobj) { + //uses Tui for now + return new Tui(mainobj); + } + //public static Iface getIface(Options iOpts) { + // //XXX iOpts not ready + // //uses Tui for now + // return new Tui(iOpts); //} } diff --git a/src/main/ui/Main.java b/src/main/ui/Main.java index 7c2686c..042e399 100644 --- a/src/main/ui/Main.java +++ b/src/main/ui/Main.java @@ -1,27 +1,54 @@ package ui; -import java.util.*; +import data.Const; +import data.Options; +import data.StypeMap; +import data.StockType; +import data.WatchList; +import ui.IfaceFactory; public class Main { - public static final String PROGRAM_NAME = "Num guess"; - //public static final String USAGE_TEXT = "Usage"; - private int win; - private int games; - //private Iface iface; - //private Options allOptions; + private Iface iface; + private Options allOptions; + private WatchList mainList; + private StypeMap stypeMap; //Constructor, not the java main public Main(String[] args) { //init options, it will load defaults //from resource xml - //options = new Options(); - // + allOptions = new Options(); //parse args, uses - //options.parseArgs(args); + allOptions.parseArgs(args); + stypeMap = new StypeMap(); + mainList = new WatchList(); + //initalize UI thread, options not ready + //this.Iface = IfaceFactory.getIface(allOptions.getSection("ui")); + iface = IfaceFactory.getIface(this); } // java main public static void main(String[] args) { new Main(args); } + + public WatchList getWatchList() { + //XXX volatile, threaded consideration + //instant/cached? + return this.mainList; + } + + public void addWatchStock(String target) { + //XXX Concurrency not ready + // Should add runnable to executor + // nyse only for now + StockType stype = this.stypeMap.getStype("Nyse"); + mainList.addStock(target, stype); + } + + public void delWatchStock(String target) { + //XXX Concurrency not ready + // Should add runnable to executor + mainList.delStock(target); + } } diff --git a/src/main/ui/Tui.java b/src/main/ui/Tui.java index 0e89a16..3ea0845 100644 --- a/src/main/ui/Tui.java +++ b/src/main/ui/Tui.java @@ -1,36 +1,162 @@ +package ui; + import java.util.*; -//import ui.Iface; import java.io.BufferedReader; import java.io.InputStreamReader; +import ui.Main; +import data.Const; +import data.WatchList; +import data.StockEntry; -public class Tui extends Iface { +public class Tui implements Iface { private static final String SAVE_CURSOR = "\u001b[s"; private static final String RESTORE_CURSOR = "\u001b[s"; private static final String REQUEST_CURSOR = "\u001b[6n"; - private int maxcol; private int maxrow; + private int maxcol; private BufferedReader stdin; + private Main main; + + public Tui(Main main) { + stdin = new BufferedReader(new InputStreamReader(System.in)); + getMax(); + this.main = main; + //XXX Start ui thread + demo(); + } + + public String getInputLine() { + String result; + try { + // if (stdin.ready() && (result = stdin.readLine()) != null) { + // return result; + // } else { + // return ""; + // } + result = stdin.readLine(); + return result; + } catch (Exception e) { + e.printStackTrace(); + } + return ""; + } - public Tui() { - // stdin = new BufferedReader(new InputStreamReader(System.in)); + public String readUntil(char end) { + String result = ""; + char c; + try { + while ((c = (char)stdin.read()) != end) { + result = result + String.valueOf(c); + } + } catch (Exception e) { + e.printStackTrace(); + } + return result; } - //public String getInput() { - //} + // return cursor coord as int[0]=row int[1]=colums + private int[] getCursor() { + int[] result = new int[2]; + try { + if (stdin.ready()) { + System.out.print(REQUEST_CURSOR); + stdin.skip(1); + String s = readUntil(';'); + result[0] = Integer.parseInt(s); //row + s = readUntil('R'); + result[1] = Integer.parseInt(s); //colums + } + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + private void moveCursor(int col, int row) { + System.out.print("\u001b[" + col + ";" + row + "H"); + } - //public getCursor(){ - // if (stdin.ready()) { - // System.out.print(REQUEST_CURSOR); - // stdin.skip(1); - // char c; - // while (char = (char)stdin.read() != ';') { - // row = - // } - // } - //} + private void getMax() { + System.out.print(SAVE_CURSOR); + moveCursor(9999,9999); //move cursor to impossibly big coord + int[] maxCoord = getCursor(); + maxrow = maxCoord[0]; + maxcol = maxCoord[1]; + } - //public void moveCursor(int col, int row) { - // System.out.print("\u001b["+col+";"+row+"H"); - //} + @Override + public void destory() { + //Nothing has to be done + return; + } + + @Override + public void redraw() { + //XXX Do nothing for now + return; + } + + public void demomenu() { + System.out.println("Function select:"); + System.out.println("1: View watchlist"); + System.out.println("2: Add stock"); + System.out.println("3: Remove stock"); + System.out.println("q: Quit"); + System.out.println("Enter a number or q, then press enter.\n"); + } + + public boolean demoinput() { + switch (getInputLine()) { + case "1": + printWatchList(); + break; + case "2": + addWatch(); + break; + case "3": + delWatch(); + break; + case "q": + return false; + default: + System.out.println("Invalid input, try again."); + break; + } + return true; + } + + public void demo() { + System.out.println("Welcome to " + Const.PROGRAM_NAME + "!"); + boolean cont = true; + while (cont) { + demomenu(); + cont = demoinput(); + } + System.out.println("Thank you for using " + Const.PROGRAM_NAME + "!"); + } + + + public void printWatchList() { + WatchList watch = main.getWatchList(); + Iterator watchit = watch.iterator(); + while (watchit.hasNext()) { + Map.Entry entry = (Map.Entry)watchit.next(); + StockEntry sentry = (StockEntry)entry.getValue(); + System.out.println("Type: " + sentry.getTypeName() + + " Identifier: " + sentry.getID()); + } + } + + public void addWatch() { + System.out.print("Enter your stock number and press enter: "); + String userin = getInputLine(); + main.addWatchStock(userin); + } + + public void delWatch() { + System.out.print("Enter your stock number and press enter: "); + String userin = getInputLine(); + main.delWatchStock(userin); + } } diff --git a/src/test/placeholder/MainTest.java b/src/test/placeholder/MainTest.java deleted file mode 100644 index 9fc5f55..0000000 --- a/src/test/placeholder/MainTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package placeholder; - -import static org.junit.jupiter.api.Assertions.*; - -class MainTest { - -} \ No newline at end of file