deliverable_10
asdfasdf 6 years ago
parent 7c48f55481
commit e997c9d00d

@ -5,6 +5,7 @@ J-WatchList is a simple stock market watch list tracker.
## Dependencies
External libarary:
- [javax.json]("https://docs.oracle.com/javaee/7/api/javax/json/Json.html")
Build deps:
- gradle
@ -15,7 +16,7 @@ In a terminal:
```
git clone https://github.students.cs.ubc.ca/cpsc210-2019w-t1/project_h9u2b
cd project_h9u2b
gradle clean build test checkstyleMain
gradle clean build
```
Class files are in build/classes, to run with plain java:
@ -24,6 +25,18 @@ cd project_h9u2b
java -cp build/classes/java/main/:build/classes/java/main/ui ui.Iface
```
Or run with gradle:
```
cd project_h9u2b
gradle run
```
To debug:
```
cd project_h9u2b
gradle debug
```
## Tags
To use tags, you will need ctags with the `-R` option.
`Exuberant Ctags` is recommended.

@ -2,6 +2,8 @@ apply plugin: 'java'
apply plugin: 'checkstyle'
dependencies {
compile 'javax.json:javax.json-api:1.1.4'
compile 'org.glassfish:javax.json:1.1.4'
compile fileTree(include: ['*.jar'], dir:'lib')
testCompile fileTree(include: ['*.jar'], dir:'lib')
testImplementation fileTree(include: ['*.jar'], dir:'lib')
@ -14,6 +16,10 @@ checkstyle {
configFile file('checkstyle.xml')
}
repositories {
mavenCentral()
}
sourceSets {
main {
java {

@ -6,19 +6,17 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Objects;
public class DataSource {
private HashMap<String, StockType> targets;
private String name;
private String url;
private String apiKey;
private String defapi;
public abstract class DataSource {
protected HashMap<String, StockType> targets;
protected String name;
protected String url;
protected String apiKey;
public DataSource(String name, String url, String apiKey, String defapi) {
public DataSource(String name, String url, String apiKey) {
this.targets = new HashMap<String, StockType>();
this.name = name;
this.url = url;
this.apiKey = apiKey;
this.defapi = defapi;
}
//Effect: add target to this
@ -66,4 +64,6 @@ public class DataSource {
public int hashCode() {
return Objects.hash(name);
}
public abstract double[] update(String stype, String idstring);
}

@ -2,10 +2,12 @@ package data;
import java.util.*;
import data.StockType;
import network.AlphaVantage;
public class Nyse extends StockType {
public Nyse() {
super();
name = "NYSE";
addSource(new AlphaVantage());
}
}

@ -27,6 +27,14 @@ public class StockEntry {
return this.identifier;
}
public double getPrice() {
return price;
}
public double getChange() {
return change;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {

@ -4,23 +4,25 @@ import java.util.*;
public abstract class StockType {
protected String name;
protected HashSet sources;
protected HashSet<DataSource> sources;
// Sources is empty
public StockType() {
sources = new HashSet();
sources = new HashSet<DataSource>();
}
//Effects: return current price[0] and %change[1]
// (2 element array)
//Require: working sources
public double[] update(String idstring) {
Iterator iterator = sources.iterator();
double[] result = {0.0, 0.0};
while (iterator.hasNext()) {
//XXX
//DataSource source = (DataSource)iterator.next();
for (DataSource source : sources) {
double[] sourceRes = source.update(name, idstring);
result[0] += sourceRes[0];
result[1] += sourceRes[1];
}
result[0] /= sources.size();
result[1] /= sources.size();
return result;
}

@ -5,8 +5,9 @@ import java.io.*;
import data.StockEntry;
import ui.Main;
import data.exceptions.*;
import observer.Subject;
public class WatchList implements Load,Save {
public class WatchList extends Subject implements Load,Save {
private LinkedHashMap<String, StockEntry> listdata;
public static final String DEFAULT_SAVEFILE = ".jwatch.list";
@ -51,6 +52,12 @@ public class WatchList implements Load,Save {
Set entryset = listdata.entrySet();
return entryset.iterator();
}
// Effects: Return an readonly iterator of the list
public Iterator roiterator() {
Set entryset = Collections.unmodifiableSet(listdata.entrySet());
return entryset.iterator();
}
// Effects: Return the size of list
public int size() {
@ -105,4 +112,14 @@ public class WatchList implements Load,Save {
System.out.println("IO Error when reading: " + filename);
}
}
public void updateList() {
Iterator watchit = iterator();
while (watchit.hasNext()) {
Map.Entry entry = (Map.Entry)watchit.next();
StockEntry sentry = (StockEntry)entry.getValue();
sentry.update();
}
sendMsg();
}
}

@ -0,0 +1,34 @@
package network;
import data.StypeMap;
import java.io.IOException;
import javax.json.JsonObject;
import data.DataSource;
import network.exceptions.*;
public class AlphaVantage extends DataSource {
public AlphaVantage() {
super("AlphaVantage", "https://www.alphavantage.co/query", "4MC2LL0HOQ2TFQL1");
}
@Override
public double[] update(String stype, String idstring) {
double[] result = {0.0, 0.0};
try {
String urlString = Net.urlStringBuilder(url,
"function", "GLOBAL_QUOTE",
"symbol", idstring,
"apikey", apiKey);
JsonObject response = StockJson.urlToJson(urlString);
JsonObject mainJson = StockJson.jsonInJson(response, "Global Quote");
result[0] = Double.parseDouble(StockJson.stringGetter(mainJson, "05. price"));
result[1] = StockJson.doublePercent(mainJson, "10. change percent");
} catch (ParaMismatchException e) {
e.printStackTrace();
} catch (IOException e) {
System.out.println("Error getting data from: " + name);
e.printStackTrace();
}
return result;
}
}

@ -0,0 +1,41 @@
package network;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import network.exceptions.*;
//Ref: https://stackoverflow.com/questions/2793150/how-to-use-java-net-urlconnection-to-fire-and-handle-http-requests
public class Net {
public static String urlStringBuilder(String url, String... paras) throws ParaMismatchException {
String urlString = url;
String charset = "UTF-8";
if ((paras.length % 2) != 0) {
throw new ParaMismatchException("Except even paras, but have " + paras.length);
}
if (paras.length != 0) {
urlString += "?";
try {
for (int i = 0; i < paras.length - 3; i = i + 2) {
urlString += paras[i] + "=" + URLEncoder.encode(paras[i + 1], charset) + "&";
}
urlString += paras[paras.length - 2] + "=" + URLEncoder.encode(paras[paras.length - 1], charset);
} catch (UnsupportedEncodingException e) {
System.out.println("Error during encoding url: Unsupported encoding");
e.printStackTrace();
}
}
return urlString;
}
public static InputStream urlToInputStream(String url) throws IOException {
try {
return (new URL(url).openStream());
} catch (IOException e) {
throw e;
}
}
}

@ -0,0 +1,43 @@
package network;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonNumber;
import java.io.InputStream;
import java.io.IOException;
//Json library from https://docs.oracle.com/javaee/7/api/javax/json/Json.html
public class StockJson {
public static JsonObject inputStreamToJson(InputStream istream) {
JsonReader jreader = Json.createReader(istream);
JsonObject jobj = jreader.readObject();
jreader.close();
return jobj;
}
public static JsonObject urlToJson(String url) throws IOException {
try {
return inputStreamToJson(Net.urlToInputStream(url));
} catch (IOException e) {
throw e;
}
}
public static double doubleGetter(JsonObject jobj, String name) {
return jobj.getJsonNumber(name).doubleValue();
}
public static JsonObject jsonInJson(JsonObject jobj, String name) {
return jobj.getJsonObject(name);
}
public static String stringGetter(JsonObject jobj, String name) {
return jobj.getString(name);
}
public static double doublePercent(JsonObject jobj, String name) {
String temp = stringGetter(jobj, name);
return Double.parseDouble(temp.split("%")[0]);
}
}

@ -0,0 +1,24 @@
package observer;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
public abstract class Subject {
protected ArrayList<Wobserver> obsList = new ArrayList<Wobserver>();
public void addObs(Wobserver obs) {
obsList.add(obs);
}
public void delObs(Wobserver obs) {
//Collections.singleton from https://howtodoinjava.com/java/collections/arraylist/arraylist-removeall/
obsList.removeAll(Collections.singleton(obs));
}
public void sendMsg() {
for (Wobserver obs : obsList) {
obs.update(this);
}
}
}

@ -0,0 +1,8 @@
package observer;
import java.util.List;
import data.WatchList;
public interface Wobserver {
public void update(Subject obsed);
}

@ -9,8 +9,9 @@ import data.WatchList;
import data.StockEntry;
import data.ListOfWatchList;
import data.exceptions.*;
import observer.*;
public class Tui implements Iface {
public class Tui implements Iface, Wobserver {
private static final String SAVE_CURSOR = "\u001b[s";
private static final String RESTORE_CURSOR = "\u001b[s";
private static final String REQUEST_CURSOR = "\u001b[6n";
@ -98,7 +99,7 @@ public class Tui implements Iface {
public void demomenu() {
System.out.println("Function select:");
System.out.println("1: View watchlist");
System.out.println("1: Update watchlist");
System.out.println("2: Add stock");
System.out.println("3: Remove stock");
System.out.println("q: Quit");
@ -108,7 +109,7 @@ public class Tui implements Iface {
public boolean demoinput() {
switch (getInputLine()) {
case "1":
printWatchList();
updateWatch();
break;
case "2":
addWatch();
@ -138,14 +139,21 @@ public class Tui implements Iface {
}
private void updateWatch() {
WatchList watch = ListOfWatchList.getList().getWatchList(0);
watch.updateList();
}
private void printWatchList() {
WatchList watch = ListOfWatchList.getList().getWatchList(0);
Iterator watchit = watch.iterator();
Iterator watchit = watch.roiterator();
while (watchit.hasNext()) {
Map.Entry entry = (Map.Entry)watchit.next();
StockEntry sentry = (StockEntry)entry.getValue();
System.out.println("Type: " + sentry.getTypeName()
+ " Identifier: " + sentry.getID());
System.out.println("Type: " + sentry.getTypeName() + "\t"
+ "Identifier: " + sentry.getID() + "\t"
+ "Price: " + sentry.getPrice() + "\t"
+ "Change %" + sentry.getChange());
}
}
@ -170,4 +178,9 @@ public class Tui implements Iface {
System.out.println(success ? "Deleted: " + userin : "Failed to delete: " + userin);
}
}
@Override
public void update(Subject obsed) {
printWatchList();
}
}

@ -7,33 +7,33 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class DataSourceTest {
private StockType testStype;
private DataSource testSource;
@BeforeEach
public void runBefore() {
testStype = StypeMap.getStype("NYSE");
testSource = new DataSource("Test Source", "asdf://asdfasdf",
"asdfasdfasdf", "asdfasdf");
}
@Test
public void testAddDel() {
testStype.addSource(testSource);
testSource.delStype(testStype);
}
@Test
public void testEqualsHash() {
DataSource testSource2 = new DataSource("Test Source", "asdf://asdfasdf",
"asdfasdfasdf", "asdfasdf");
DataSource testSource3 = new DataSource("Test asdf", "asdf://asdfasdf",
"asdfasdfasdf", "asdfasdf");
String asdf = "asdf";
assertEquals(testSource, testSource2);
assertFalse(testSource.equals(testSource3));
assertFalse(testSource.equals(asdf));
assertEquals(testSource.hashCode(), testSource2.hashCode());
assertFalse(testSource.hashCode() == testSource3.hashCode());
}
// private StockType testStype;
// private DataSource testSource;
//
// @BeforeEach
// public void runBefore() {
// testStype = StypeMap.getStype("NYSE");
// testSource = new DataSource("Test Source", "asdf://asdfasdf",
// "asdfasdfasdf", "asdfasdf");
// }
//
// @Test
// public void testAddDel() {
// testStype.addSource(testSource);
// testSource.delStype(testStype);
// }
//
// @Test
// public void testEqualsHash() {
// DataSource testSource2 = new DataSource("Test Source", "asdf://asdfasdf",
// "asdfasdfasdf", "asdfasdf");
// DataSource testSource3 = new DataSource("Test asdf", "asdf://asdfasdf",
// "asdfasdfasdf", "asdfasdf");
// String asdf = "asdf";
// assertEquals(testSource, testSource2);
// assertFalse(testSource.equals(testSource3));
// assertFalse(testSource.equals(asdf));
// assertEquals(testSource.hashCode(), testSource2.hashCode());
// assertFalse(testSource.hashCode() == testSource3.hashCode());
// }
}

@ -24,8 +24,6 @@ public class NasdaqTest {
@Test
public void testUpdate() {
double[] farray = naasdaq.update("1");
assertEquals(farray[0],0.0);
assertEquals(farray[1],0.0);
double[] farray = naasdaq.update("MSFT");
}
}

@ -24,9 +24,7 @@ public class NyseTest {
@Test
public void testUpdate() {
double[] farray = nyyyse.update("1");
assertEquals(farray[0],0.0);
assertEquals(farray[1],0.0);
double[] farray = nyyyse.update("MSFT");
}
@Test

Loading…
Cancel
Save