From 22538c2a68160cd7edc47d7c3bcea54f84c97b72 Mon Sep 17 00:00:00 2001 From: Julia McCauley Date: Thu, 1 Apr 2021 18:27:00 -0400 Subject: Created class outline for hub stuff, started database querier --- .../edu/brown/cs/student/term/DatabaseQuerier.java | 71 ++++++++++++++++++++++ src/main/java/edu/brown/cs/student/term/Main.java | 4 +- .../edu/brown/cs/student/term/hub/HubSearch.java | 4 ++ .../edu/brown/cs/student/term/hub/LinkMapper.java | 4 ++ .../brown/cs/student/term/hub/SuspicionRanker.java | 4 ++ .../edu/brown/cs/student/term/repl/Command.java | 6 -- .../java/edu/brown/cs/student/term/repl/REPL.java | 1 - .../brown/cs/student/term/repl/SetupCommand.java | 36 +++++++++++ .../edu/brown/cs/student/term/trade/Trade.java | 49 +++++++++++++++ 9 files changed, 170 insertions(+), 9 deletions(-) create mode 100644 src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java create mode 100644 src/main/java/edu/brown/cs/student/term/hub/HubSearch.java create mode 100644 src/main/java/edu/brown/cs/student/term/hub/LinkMapper.java create mode 100644 src/main/java/edu/brown/cs/student/term/hub/SuspicionRanker.java create mode 100644 src/main/java/edu/brown/cs/student/term/repl/SetupCommand.java create mode 100644 src/main/java/edu/brown/cs/student/term/trade/Trade.java (limited to 'src/main/java/edu/brown/cs/student') diff --git a/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java b/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java new file mode 100644 index 0000000..7818a83 --- /dev/null +++ b/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java @@ -0,0 +1,71 @@ +package edu.brown.cs.student.term; +import edu.brown.cs.student.term.trade.Trade; + +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + + +public class DatabaseQuerier{ + private static Connection conn = null; + + /** + * Makes a database querier for a particular sqlite database + * @param filename - String representing filepath of database + * @throws SQLException + * @throws ClassNotFoundException + */ + public DatabaseQuerier(String filename) throws SQLException, + ClassNotFoundException { + Class.forName("org.sqlite.JDBC"); + String urlToDB = "jdbc:sqlite:" + filename; + // AutoClosable TRY-WITH-RESOURCES ensures database connection will be closed when it is done + conn = DriverManager.getConnection(urlToDB); + } + + public static Connection getConn() { + return conn; + } + + /** + * Gets the names of all stocks in the database for the past two weeks from end date + * @param endDate - the end data for the 2 week period in unix time + * @return + * @throws SQLException + */ + public List getRecentStocks(double endDate) throws SQLException { + List stocks = new ArrayList<>(); + + PreparedStatement prep = conn.prepareStatement( + "SELECT DISTINCT stock_name FROM trades (WHERE trade_timestamp < ?)"); + + prep.setDouble(1, endDate); + ResultSet rs = prep.executeQuery(); + + while(rs.next()){ + stocks.add(rs.getString(1)); + } + + System.out.println(stocks.size()); + for (String s: stocks) { + System.out.println(s); + } + return stocks; + } + + //TODO: Fill these in + public List> getAllTradesByStock() throws SQLException { + + PreparedStatement prep = conn.prepareStatement( + ""); + return null; + } + + public List getTradeByStock() throws SQLException{ + return null; + } + + + + +} diff --git a/src/main/java/edu/brown/cs/student/term/Main.java b/src/main/java/edu/brown/cs/student/term/Main.java index c436b2e..a6a9764 100644 --- a/src/main/java/edu/brown/cs/student/term/Main.java +++ b/src/main/java/edu/brown/cs/student/term/Main.java @@ -2,6 +2,7 @@ package edu.brown.cs.student.term; import edu.brown.cs.student.term.repl.Command; import edu.brown.cs.student.term.repl.REPL; +import edu.brown.cs.student.term.repl.SetupCommand; import joptsimple.OptionParser; import joptsimple.OptionSet; @@ -45,10 +46,9 @@ public final class Main { } HashMap commandHashMap = new HashMap<>(); + commandHashMap.put("setup", new SetupCommand()); /** add commands to map here! */ REPL repl = new REPL(commandHashMap); repl.runREPL(); - - // TODO: Process commands in a REPL } } \ No newline at end of file diff --git a/src/main/java/edu/brown/cs/student/term/hub/HubSearch.java b/src/main/java/edu/brown/cs/student/term/hub/HubSearch.java new file mode 100644 index 0000000..87e723b --- /dev/null +++ b/src/main/java/edu/brown/cs/student/term/hub/HubSearch.java @@ -0,0 +1,4 @@ +package edu.brown.cs.student.term.hub; + +public class HubSearch { +} diff --git a/src/main/java/edu/brown/cs/student/term/hub/LinkMapper.java b/src/main/java/edu/brown/cs/student/term/hub/LinkMapper.java new file mode 100644 index 0000000..7cb1011 --- /dev/null +++ b/src/main/java/edu/brown/cs/student/term/hub/LinkMapper.java @@ -0,0 +1,4 @@ +package edu.brown.cs.student.term.hub; + +public class LinkMapper { +} diff --git a/src/main/java/edu/brown/cs/student/term/hub/SuspicionRanker.java b/src/main/java/edu/brown/cs/student/term/hub/SuspicionRanker.java new file mode 100644 index 0000000..a1196d8 --- /dev/null +++ b/src/main/java/edu/brown/cs/student/term/hub/SuspicionRanker.java @@ -0,0 +1,4 @@ +package edu.brown.cs.student.term.hub; + +public class SuspicionRanker { +} diff --git a/src/main/java/edu/brown/cs/student/term/repl/Command.java b/src/main/java/edu/brown/cs/student/term/repl/Command.java index f8b0b04..056c7df 100644 --- a/src/main/java/edu/brown/cs/student/term/repl/Command.java +++ b/src/main/java/edu/brown/cs/student/term/repl/Command.java @@ -10,10 +10,4 @@ public interface Command { * @param args arguments for the command */ String run(String[] args); - - /** - * Used to print command output to GUI. - * @return String representing neighbors found by NeighborsCommand and RadiusCommand commands - */ - String toString(); } diff --git a/src/main/java/edu/brown/cs/student/term/repl/REPL.java b/src/main/java/edu/brown/cs/student/term/repl/REPL.java index 0be7e3f..a1d5c23 100644 --- a/src/main/java/edu/brown/cs/student/term/repl/REPL.java +++ b/src/main/java/edu/brown/cs/student/term/repl/REPL.java @@ -1,5 +1,4 @@ package edu.brown.cs.student.term.repl; -import edu.brown.cs.student.term.repl.Command; import java.io.BufferedReader; import java.io.IOException; diff --git a/src/main/java/edu/brown/cs/student/term/repl/SetupCommand.java b/src/main/java/edu/brown/cs/student/term/repl/SetupCommand.java new file mode 100644 index 0000000..1d84f49 --- /dev/null +++ b/src/main/java/edu/brown/cs/student/term/repl/SetupCommand.java @@ -0,0 +1,36 @@ +package edu.brown.cs.student.term.repl; + +import edu.brown.cs.student.term.DatabaseQuerier; + +public class SetupCommand implements Command { + + private String error; + private static DatabaseQuerier dq; + + @Override + /** + * Sets up connection to the database + * Returns an empty string if no errors, non empty with error message otherwise + */ + public String run(String[] args) { + error = ""; + if(args.length == 1){ + try{ + dq = new DatabaseQuerier(args[0]); + } catch (Exception e) { + error = "ERROR: Could not connect to database. Ensure this is a valid database."; + System.out.println(error); + return error; + } + } else { + error = "ERROR: Incorrect number of arguments for setup command"; + System.out.println(error); + return error; + } + return error; + } + + public static DatabaseQuerier getDq() { + return dq; + } +} diff --git a/src/main/java/edu/brown/cs/student/term/trade/Trade.java b/src/main/java/edu/brown/cs/student/term/trade/Trade.java new file mode 100644 index 0000000..831f9f1 --- /dev/null +++ b/src/main/java/edu/brown/cs/student/term/trade/Trade.java @@ -0,0 +1,49 @@ +package edu.brown.cs.student.term.trade; + +public class Trade { + + private int id; + private String stock; + private boolean isBuy; + private double timestamp; + private String holder; + + public Trade(int id, String stockName, boolean buy, double ts, String holderName){ + this.id = id; + this.stock = stockName; + this.isBuy = buy; + this.timestamp = ts; + this.holder = holderName; + } + + public int getId() { + return id; + } + + public boolean isBuy() { + return isBuy; + } + + public double getTimestamp() { + return timestamp; + } + + public String getStock() { + return stock; + } + + public String getHolder() { + return holder; + } + + @Override + public String toString() { + return "Trade{" + + "id=" + id + + ", stock='" + stock + '\'' + + ", isBuy=" + isBuy + + ", timestamp=" + timestamp + + ", holder='" + holder + '\'' + + '}'; + } +} -- cgit v1.2.3-70-g09d2 From 6cf2414b421dc9270e980920978ae5aaa413c74a Mon Sep 17 00:00:00 2001 From: Julia McCauley Date: Thu, 1 Apr 2021 21:49:35 -0400 Subject: DatabaseQuerier fully functional for hub search purposes, some basic tests written --- ...rm-project-cohwille-jmccaul3-mfoiani-rhunt2.iml | 1 + data/MockTradeData.txt | 7 ++ mock_trades.sqlite3 | 0 .../edu/brown/cs/student/term/DatabaseQuerier.java | 54 +++++++--- src/main/java/edu/brown/cs/student/term/Main.java | 2 +- .../brown/cs/student/term/repl/SetupCommand.java | 36 ------- .../student/term/repl/commands/SetupCommand.java | 71 ++++++++++++ .../edu/brown/cs/student/term/trade/Trade.java | 13 ++- .../java/edu/brown/cs/student/DBQuerierTest.java | 120 +++++++++++++++++++++ 9 files changed, 247 insertions(+), 57 deletions(-) create mode 100644 mock_trades.sqlite3 delete mode 100644 src/main/java/edu/brown/cs/student/term/repl/SetupCommand.java create mode 100644 src/main/java/edu/brown/cs/student/term/repl/commands/SetupCommand.java create mode 100644 src/test/java/edu/brown/cs/student/DBQuerierTest.java (limited to 'src/main/java/edu/brown/cs/student') diff --git a/.idea/term-project-cohwille-jmccaul3-mfoiani-rhunt2.iml b/.idea/term-project-cohwille-jmccaul3-mfoiani-rhunt2.iml index e5e71fc..d624609 100644 --- a/.idea/term-project-cohwille-jmccaul3-mfoiani-rhunt2.iml +++ b/.idea/term-project-cohwille-jmccaul3-mfoiani-rhunt2.iml @@ -11,6 +11,7 @@ + diff --git a/data/MockTradeData.txt b/data/MockTradeData.txt index fac6615..35c2ee4 100644 --- a/data/MockTradeData.txt +++ b/data/MockTradeData.txt @@ -13,4 +13,11 @@ The only unintuitive bit is the is_buy column, this is dummy (binary) variable that takes on a value of 1 if the trade is a buy and a value of 0 if the trade is a sell. +**USING THE DATABASE CONNECTIONS CORRECTLY!** + +Converting from UTC Instant/unix time to an America/New_York timezone data +You want to add 5 hours to the UTC date to get the correct timezone formatted like so... +"2021-03-12T05:00:00.00Z" + +So this is in UTC, but it is equivalent to 12 am on March 3rd in NYC Time - Julia \ No newline at end of file diff --git a/mock_trades.sqlite3 b/mock_trades.sqlite3 new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java b/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java index 7818a83..2258d36 100644 --- a/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java +++ b/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java @@ -2,6 +2,7 @@ package edu.brown.cs.student.term; import edu.brown.cs.student.term.trade.Trade; import java.sql.*; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -28,41 +29,60 @@ public class DatabaseQuerier{ } /** - * Gets the names of all stocks in the database for the past two weeks from end date - * @param endDate - the end data for the 2 week period in unix time - * @return + * Gets the names of all stocks traded between start and end ddate + * @param startDate - the start date + * @param endDate - the end date + * @return a list of stock names * @throws SQLException */ - public List getRecentStocks(double endDate) throws SQLException { + public List getRecentStocks(Instant startDate, Instant endDate) throws SQLException { List stocks = new ArrayList<>(); PreparedStatement prep = conn.prepareStatement( - "SELECT DISTINCT stock_name FROM trades (WHERE trade_timestamp < ?)"); + "SELECT DISTINCT stock_name FROM trades WHERE trade_timestamp <= ? AND trade_timestamp >= ?"); - prep.setDouble(1, endDate); + prep.setLong(1, endDate.toEpochMilli()); + prep.setLong(2, startDate.toEpochMilli()); ResultSet rs = prep.executeQuery(); while(rs.next()){ stocks.add(rs.getString(1)); } - - System.out.println(stocks.size()); - for (String s: stocks) { - System.out.println(s); - } return stocks; } //TODO: Fill these in - public List> getAllTradesByStock() throws SQLException { + public List> getAllTradesByStock(Instant startDate, Instant endDate) throws SQLException { + List> allTrades = new ArrayList<>(); + List stocks = getRecentStocks(startDate, endDate); + //get the buys and sells for each stock + for(String stock: stocks){ + allTrades.add(getTradeByStock(stock, 1, startDate, endDate)); + allTrades.add(getTradeByStock(stock, 0, startDate, endDate)); + } + return allTrades; + } + + public List getTradeByStock(String stock, int isBuy, Instant startDate, Instant endDate) throws SQLException{ + List trades = new ArrayList<>(); PreparedStatement prep = conn.prepareStatement( - ""); - return null; - } + "SELECT * FROM trades WHERE (stock_name = ? AND is_buy = ?) " + + "AND (trade_timestamp <= ? AND trade_timestamp >= ?) ORDER BY trade_timestamp"); + + prep.setString(1, stock); + prep.setInt(2, isBuy); + prep.setLong(3, endDate.toEpochMilli()); + prep.setLong(4, startDate.toEpochMilli()); + ResultSet rs = prep.executeQuery(); + + while(rs.next()){ + trades.add(new Trade(rs.getInt(1), rs.getString(2), + rs.getString(3), rs.getLong(4), rs.getInt(5), + rs.getInt(6))); + } - public List getTradeByStock() throws SQLException{ - return null; + return trades; } diff --git a/src/main/java/edu/brown/cs/student/term/Main.java b/src/main/java/edu/brown/cs/student/term/Main.java index a6a9764..268a725 100644 --- a/src/main/java/edu/brown/cs/student/term/Main.java +++ b/src/main/java/edu/brown/cs/student/term/Main.java @@ -2,7 +2,7 @@ package edu.brown.cs.student.term; import edu.brown.cs.student.term.repl.Command; import edu.brown.cs.student.term.repl.REPL; -import edu.brown.cs.student.term.repl.SetupCommand; +import edu.brown.cs.student.term.repl.commands.SetupCommand; import joptsimple.OptionParser; import joptsimple.OptionSet; diff --git a/src/main/java/edu/brown/cs/student/term/repl/SetupCommand.java b/src/main/java/edu/brown/cs/student/term/repl/SetupCommand.java deleted file mode 100644 index 1d84f49..0000000 --- a/src/main/java/edu/brown/cs/student/term/repl/SetupCommand.java +++ /dev/null @@ -1,36 +0,0 @@ -package edu.brown.cs.student.term.repl; - -import edu.brown.cs.student.term.DatabaseQuerier; - -public class SetupCommand implements Command { - - private String error; - private static DatabaseQuerier dq; - - @Override - /** - * Sets up connection to the database - * Returns an empty string if no errors, non empty with error message otherwise - */ - public String run(String[] args) { - error = ""; - if(args.length == 1){ - try{ - dq = new DatabaseQuerier(args[0]); - } catch (Exception e) { - error = "ERROR: Could not connect to database. Ensure this is a valid database."; - System.out.println(error); - return error; - } - } else { - error = "ERROR: Incorrect number of arguments for setup command"; - System.out.println(error); - return error; - } - return error; - } - - public static DatabaseQuerier getDq() { - return dq; - } -} diff --git a/src/main/java/edu/brown/cs/student/term/repl/commands/SetupCommand.java b/src/main/java/edu/brown/cs/student/term/repl/commands/SetupCommand.java new file mode 100644 index 0000000..e19117c --- /dev/null +++ b/src/main/java/edu/brown/cs/student/term/repl/commands/SetupCommand.java @@ -0,0 +1,71 @@ +package edu.brown.cs.student.term.repl.commands; + +import edu.brown.cs.student.term.DatabaseQuerier; +import edu.brown.cs.student.term.repl.Command; +import edu.brown.cs.student.term.trade.Trade; + +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.List; + +public class SetupCommand implements Command { + + private String error; + private static DatabaseQuerier dq; + + @Override + /** + * Sets up connection to the database + * Returns an empty string if no errors, non empty with error message otherwise + */ + public String run(String[] args) { + error = ""; + if(args.length == 1){ + try{ + dq = new DatabaseQuerier(args[0]); + } catch (Exception e) { + error = "ERROR: Could not connect to database. Ensure this is a valid database."; + System.out.println(error); + return error; + } + } else { + error = "ERROR: Incorrect number of arguments for setup command"; + System.out.println(error); + return error; + } + + try{ + /** Just for testing purposes **/ + //12 am on 3/12 in UTC + Instant start = Instant.parse("2021-03-12T05:00:00.00Z"); + //12 am on 3/27 in UTC + Instant end = Instant.parse("2021-03-27T05:00:00.00Z"); + + System.out.println(end.toEpochMilli()); + System.out.println(start.getEpochSecond()); + + ZonedDateTime zdt = ZonedDateTime.ofInstant(start, ZoneId.of("America/New_York")); + System.out.println(zdt.toString()); + List> trades = dq.getAllTradesByStock(start, end); + + int sum = 0; + for(List t: trades){ + System.out.println(t); + sum += t.size(); + } + + System.out.println("num of trades: " + sum); + + + } catch(Exception e){ + e.printStackTrace(); + } + + return error; + } + + public static DatabaseQuerier getDq() { + return dq; + } +} diff --git a/src/main/java/edu/brown/cs/student/term/trade/Trade.java b/src/main/java/edu/brown/cs/student/term/trade/Trade.java index 831f9f1..500cc19 100644 --- a/src/main/java/edu/brown/cs/student/term/trade/Trade.java +++ b/src/main/java/edu/brown/cs/student/term/trade/Trade.java @@ -4,16 +4,18 @@ public class Trade { private int id; private String stock; - private boolean isBuy; + private int isBuy; private double timestamp; private String holder; + private int numShares; - public Trade(int id, String stockName, boolean buy, double ts, String holderName){ + public Trade(int id, String stockName, String holderName, double ts, int buy, int shares){ this.id = id; this.stock = stockName; this.isBuy = buy; this.timestamp = ts; this.holder = holderName; + this.numShares = shares; } public int getId() { @@ -21,7 +23,11 @@ public class Trade { } public boolean isBuy() { - return isBuy; + if(isBuy == 1){ + return true; + } else { + return false; + } } public double getTimestamp() { @@ -44,6 +50,7 @@ public class Trade { ", isBuy=" + isBuy + ", timestamp=" + timestamp + ", holder='" + holder + '\'' + + ", numShares=" + numShares + '}'; } } diff --git a/src/test/java/edu/brown/cs/student/DBQuerierTest.java b/src/test/java/edu/brown/cs/student/DBQuerierTest.java new file mode 100644 index 0000000..0d365ec --- /dev/null +++ b/src/test/java/edu/brown/cs/student/DBQuerierTest.java @@ -0,0 +1,120 @@ +package edu.brown.cs.student; + +import java.io.PrintStream; +import java.sql.SQLException; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +import edu.brown.cs.student.term.DatabaseQuerier; +import edu.brown.cs.student.term.repl.commands.SetupCommand; +import edu.brown.cs.student.term.trade.Trade; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class DBQuerierTest { + + /** these should span the entire mock dataset */ + //12 am on 3/11 in UTC + private Instant start = Instant.parse("2021-03-11T05:00:00.00Z"); + //12 am on 3/28 in UTC + private Instant end = Instant.parse("2021-03-28T05:00:00.00Z"); + + private DatabaseQuerier db; + + @Before + public void setUp() { + try{ + db = new DatabaseQuerier("data/mock_trades.sqlite3"); + } catch(Exception e){ + System.out.println("DBQuerier Test, couldn't connect to db???"); + } + } + + /* + * try{ + + } catch(Exception e) { + System.out.println("Error in test"); + }*/ + + @After + public void tearDown() { + db = null; + } + + @Test + public void testNonExistentStock(){ + setUp(); + try{ + List fakeStockList = db.getTradeByStock("NONO", 1, start, end); + assertTrue(fakeStockList.isEmpty()); + + } catch(Exception e) { + System.out.println("Error in test"); + } + tearDown(); + } + + @Test + public void testFlippedDates(){ + setUp(); + try{ + List gmeBadDatesList = db.getTradeByStock("GME", 1, end, start); + assertTrue(gmeBadDatesList.isEmpty()); + + } catch(Exception e) { + System.out.println("Error in test"); + } + tearDown(); + } + + @Test + public void testTradeByStockNameBuy(){ + setUp(); + try{ + List gmeBuyList = db.getTradeByStock("GME", 1, start, end); + assertEquals(gmeBuyList.size(), 6); + assertEquals(gmeBuyList.get(0).getId(), 482); + assertEquals(gmeBuyList.get(3).getId(), 149); + assertEquals(gmeBuyList.get(4).getId(), 275); + assertEquals(gmeBuyList.get(5).getId(), 30); + + + List teslaBuyList = db.getTradeByStock("TSLA", 1, start, end); + assertEquals(teslaBuyList.size(), 16); + assertEquals(teslaBuyList.get(0).getId(), 328); + assertEquals(teslaBuyList.get(7).getId(), 241); + assertEquals(teslaBuyList.get(15).getId(), 774); + + } catch(Exception e) { + System.out.println("Error in testTradeByStockName"); + } + + tearDown(); + } + + @Test + public void testTradeByNameOrdering(){ + setUp(); + + try{ + List gmeSellList = db.getTradeByStock("GME", 0, start, end); + for(int i = 1; i < gmeSellList.size(); i++){ + assertTrue(gmeSellList.get(i-1).getTimestamp() < gmeSellList.get(i).getTimestamp()); + } + + List amznBuyList = db.getTradeByStock("AMZN", 1, start, end); + for(int i = 1; i < amznBuyList.size(); i++){ + assertTrue(amznBuyList.get(i-1).getTimestamp() < amznBuyList.get(i).getTimestamp()); + } + + } catch(Exception e) { + System.out.println("Error in test"); + } + tearDown(); + } +} -- cgit v1.2.3-70-g09d2 From f8262d2aad3d50ea7a861af235d758b70d556055 Mon Sep 17 00:00:00 2001 From: Julia McCauley Date: Thu, 1 Apr 2021 22:44:43 -0400 Subject: updated database + code to include holder ids --- data/mock_trades.sqlite3 | Bin 45056 -> 49152 bytes .../edu/brown/cs/student/term/DatabaseQuerier.java | 4 +-- .../edu/brown/cs/student/term/hub/LinkMapper.java | 39 +++++++++++++++++++++ .../java/edu/brown/cs/student/term/hub/Person.java | 12 +++++++ .../edu/brown/cs/student/term/trade/Trade.java | 5 ++- .../java/edu/brown/cs/student/DBQuerierTest.java | 2 ++ 6 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 src/main/java/edu/brown/cs/student/term/hub/Person.java (limited to 'src/main/java/edu/brown/cs/student') diff --git a/data/mock_trades.sqlite3 b/data/mock_trades.sqlite3 index c9455c9..7658214 100644 Binary files a/data/mock_trades.sqlite3 and b/data/mock_trades.sqlite3 differ diff --git a/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java b/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java index 2258d36..79e8e15 100644 --- a/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java +++ b/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java @@ -6,10 +6,10 @@ import java.time.Instant; import java.util.ArrayList; import java.util.List; - public class DatabaseQuerier{ private static Connection conn = null; + //TODO: Be prepared to overhaul this to account for IDs /** * Makes a database querier for a particular sqlite database * @param filename - String representing filepath of database @@ -79,7 +79,7 @@ public class DatabaseQuerier{ while(rs.next()){ trades.add(new Trade(rs.getInt(1), rs.getString(2), rs.getString(3), rs.getLong(4), rs.getInt(5), - rs.getInt(6))); + rs.getInt(6), rs.getInt(7))); } return trades; diff --git a/src/main/java/edu/brown/cs/student/term/hub/LinkMapper.java b/src/main/java/edu/brown/cs/student/term/hub/LinkMapper.java index 7cb1011..0360bda 100644 --- a/src/main/java/edu/brown/cs/student/term/hub/LinkMapper.java +++ b/src/main/java/edu/brown/cs/student/term/hub/LinkMapper.java @@ -1,4 +1,43 @@ package edu.brown.cs.student.term.hub; +import edu.brown.cs.student.term.trade.Trade; + +import java.time.Instant; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + public class LinkMapper { + + //not strictly necessary but may be nice to maintain + private Map> personToTradesMap = new HashMap<>(); + private Map> personToFollowers = new HashMap<>(); + + public LinkMapper(){} + + /** + * Returns the person => trades map as is, does not update it + * @return person to trades map + */ + public Map> getPersonToTradesMap() { + return personToTradesMap; + } + + /** + * Returns the person => follower map as is, does not update it + * @return person to follower map + */ + public Map> getPersonToFollowers() { + return personToFollowers; + } + + /** + * The links between people and their followers who made the same trade + * in the same time period + * @return the newly updated link map + */ + public Map> makeFollowerLinks(Instant start, Instant end){ + return null; + } } diff --git a/src/main/java/edu/brown/cs/student/term/hub/Person.java b/src/main/java/edu/brown/cs/student/term/hub/Person.java new file mode 100644 index 0000000..c3d5cb3 --- /dev/null +++ b/src/main/java/edu/brown/cs/student/term/hub/Person.java @@ -0,0 +1,12 @@ +package edu.brown.cs.student.term.hub; + +public class Person { + private int id; + private String name; + + public Person(int id, String name){ + this.id = id; + this.name = name; + } + +} diff --git a/src/main/java/edu/brown/cs/student/term/trade/Trade.java b/src/main/java/edu/brown/cs/student/term/trade/Trade.java index 500cc19..8619ab1 100644 --- a/src/main/java/edu/brown/cs/student/term/trade/Trade.java +++ b/src/main/java/edu/brown/cs/student/term/trade/Trade.java @@ -8,14 +8,16 @@ public class Trade { private double timestamp; private String holder; private int numShares; + private int holderID; - public Trade(int id, String stockName, String holderName, double ts, int buy, int shares){ + public Trade(int id, String stockName, String holderName, double ts, int buy, int shares, int holderID){ this.id = id; this.stock = stockName; this.isBuy = buy; this.timestamp = ts; this.holder = holderName; this.numShares = shares; + this.holderID = holderID; } public int getId() { @@ -51,6 +53,7 @@ public class Trade { ", timestamp=" + timestamp + ", holder='" + holder + '\'' + ", numShares=" + numShares + + ", holderID=" + holderID + '}'; } } diff --git a/src/test/java/edu/brown/cs/student/DBQuerierTest.java b/src/test/java/edu/brown/cs/student/DBQuerierTest.java index 0d365ec..d813969 100644 --- a/src/test/java/edu/brown/cs/student/DBQuerierTest.java +++ b/src/test/java/edu/brown/cs/student/DBQuerierTest.java @@ -15,6 +15,7 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +//TODO: Write more tests for methods besides stock by name public class DBQuerierTest { /** these should span the entire mock dataset */ @@ -77,6 +78,7 @@ public class DBQuerierTest { setUp(); try{ List gmeBuyList = db.getTradeByStock("GME", 1, start, end); + System.out.println(gmeBuyList); assertEquals(gmeBuyList.size(), 6); assertEquals(gmeBuyList.get(0).getId(), 482); assertEquals(gmeBuyList.get(3).getId(), 149); -- cgit v1.2.3-70-g09d2 From cb79a2b3c94ef0fbfc7c1f9208b6f3027d08b4f9 Mon Sep 17 00:00:00 2001 From: Julia McCauley Date: Sun, 4 Apr 2021 21:02:43 -0400 Subject: Link mapper up and running, making map that hub search will run on --- .../edu/brown/cs/student/term/DatabaseQuerier.java | 5 +- .../java/edu/brown/cs/student/term/hub/Holder.java | 42 +++++++++++++ .../edu/brown/cs/student/term/hub/HubSearch.java | 41 ++++++++++++ .../edu/brown/cs/student/term/hub/LinkMapper.java | 73 ++++++++++++++++++---- .../java/edu/brown/cs/student/term/hub/Person.java | 12 ---- .../edu/brown/cs/student/term/trade/Trade.java | 13 ++-- .../java/edu/brown/cs/student/LinkMapperTest.java | 48 ++++++++++++++ 7 files changed, 202 insertions(+), 32 deletions(-) create mode 100644 src/main/java/edu/brown/cs/student/term/hub/Holder.java delete mode 100644 src/main/java/edu/brown/cs/student/term/hub/Person.java create mode 100644 src/test/java/edu/brown/cs/student/LinkMapperTest.java (limited to 'src/main/java/edu/brown/cs/student') diff --git a/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java b/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java index 79e8e15..1bb49c7 100644 --- a/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java +++ b/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java @@ -1,4 +1,5 @@ package edu.brown.cs.student.term; +import edu.brown.cs.student.term.hub.Holder; import edu.brown.cs.student.term.trade.Trade; import java.sql.*; @@ -78,8 +79,8 @@ public class DatabaseQuerier{ while(rs.next()){ trades.add(new Trade(rs.getInt(1), rs.getString(2), - rs.getString(3), rs.getLong(4), rs.getInt(5), - rs.getInt(6), rs.getInt(7))); + rs.getLong(4), rs.getInt(5), + rs.getInt(6), new Holder(rs.getInt(7), rs.getString(3)))); } return trades; diff --git a/src/main/java/edu/brown/cs/student/term/hub/Holder.java b/src/main/java/edu/brown/cs/student/term/hub/Holder.java new file mode 100644 index 0000000..21c0aea --- /dev/null +++ b/src/main/java/edu/brown/cs/student/term/hub/Holder.java @@ -0,0 +1,42 @@ +package edu.brown.cs.student.term.hub; + +import java.util.Objects; + +public class Holder { + private int id; + private String name; + + public Holder(int id, String name){ + this.id = id; + this.name = name; + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return "Holder{" + + "id=" + id + + ", name='" + name + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Holder holder = (Holder) o; + return id == holder.id && Objects.equals(name, holder.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } +} diff --git a/src/main/java/edu/brown/cs/student/term/hub/HubSearch.java b/src/main/java/edu/brown/cs/student/term/hub/HubSearch.java index 87e723b..4c382ec 100644 --- a/src/main/java/edu/brown/cs/student/term/hub/HubSearch.java +++ b/src/main/java/edu/brown/cs/student/term/hub/HubSearch.java @@ -1,4 +1,45 @@ package edu.brown.cs.student.term.hub; public class HubSearch { + + /* + def pageRank(pList: List[Page]): mutable.HashMap[Int, Double] = { + val n = pList.length + val weights = new Array[Double](n) + val r = new Array[Double](n) + val rPrime = Array.fill[Double](n)(1.0 / n) + + while (!distance(r, rPrime)) { + Array.copy(rPrime, 0, r, 0, n) + for (j <- 0 to n - 1) { + rPrime(j) = 0 + for (k <- 0 to n - 1) { + val wjk = getWeight(pList(j), pList(k), n) + rPrime(j) = (rPrime(j) + (wjk * r(k))) + } + } + } + + val pageRank = new mutable.HashMap[Int, Double]() + + for (i <- 0 to rPrime.length - 1) { + pageRank.put(pList(i).getID, rPrime(i)) + } + pageRank + } + + def getWeight(j: Page, k: Page, n: Int): Double = { + + val links = k.getLinks + val nk = links.size + + if (links.contains(j.getTitle.toLowerCase)) { + ((0.15 / n) + ((1 - 0.15) * (1.0 / nk))) + } else if (nk == 0) { + ((0.15 / n) + ((1 - 0.15) * (1.0 / n))) + } else { + (0.15 / n) + } + } + */ } diff --git a/src/main/java/edu/brown/cs/student/term/hub/LinkMapper.java b/src/main/java/edu/brown/cs/student/term/hub/LinkMapper.java index 0360bda..f4ec0a7 100644 --- a/src/main/java/edu/brown/cs/student/term/hub/LinkMapper.java +++ b/src/main/java/edu/brown/cs/student/term/hub/LinkMapper.java @@ -1,26 +1,30 @@ package edu.brown.cs.student.term.hub; +import edu.brown.cs.student.term.DatabaseQuerier; +import edu.brown.cs.student.term.repl.commands.SetupCommand; import edu.brown.cs.student.term.trade.Trade; +import java.sql.SQLException; import java.time.Instant; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; public class LinkMapper { //not strictly necessary but may be nice to maintain - private Map> personToTradesMap = new HashMap<>(); - private Map> personToFollowers = new HashMap<>(); + private List> allTrades = new ArrayList<>(); + private Map> personToTradesMap = new HashMap<>(); + private Map> personToFollowers = new HashMap<>(); + private DatabaseQuerier databaseQuerier; - public LinkMapper(){} + public LinkMapper(DatabaseQuerier db){ + this.databaseQuerier = db; + } /** * Returns the person => trades map as is, does not update it * @return person to trades map */ - public Map> getPersonToTradesMap() { + public Map> getPersonToTradesMap() { return personToTradesMap; } @@ -28,7 +32,7 @@ public class LinkMapper { * Returns the person => follower map as is, does not update it * @return person to follower map */ - public Map> getPersonToFollowers() { + public Map> getPersonToFollowers() { return personToFollowers; } @@ -37,7 +41,54 @@ public class LinkMapper { * in the same time period * @return the newly updated link map */ - public Map> makeFollowerLinks(Instant start, Instant end){ - return null; + public Map> makeFollowerLinks(Instant start, Instant end){ + if(databaseQuerier != null){ + try{ + List> allTrades = databaseQuerier.getAllTradesByStock(start, end); + //reset the map to be blank + personToFollowers = new HashMap<>(); + + for(List tradeList : allTrades){ + convertTradeListToFollowerMap(tradeList); + } + + //System.out.println(personToFollowers.toString()); + System.out.println("num people in map: " + personToFollowers.size()); + + } catch(SQLException e) { + System.out.println("ERROR: SQL Error while retrieving trade list"); + } + } else { + System.out.println("ERROR: No database loaded in yet"); + } + + return personToFollowers; + } + + private void convertTradeListToFollowerMap(List tradeList){ + List holderList = new ArrayList<>(); + + //gets in order list of people + for (Trade trade : tradeList) { + holderList.add(trade.getHolder()); + } + + Set followers = new HashSet<>(holderList); + Set encountered = new HashSet<>(); + + for(Holder current: holderList){ + //want to check if we've already gotten followers for this trade for this holder + if(!encountered.contains(current)){ + encountered.add(current); + followers.remove(current); + if(personToFollowers.containsKey(current)){ + //TODO: this probably makes it O(n^2), might want to optimize later + personToFollowers.get(current).addAll(followers); + } else { + List currentFollowers = new ArrayList<>(followers); + personToFollowers.put(current, currentFollowers); + } + } + } } } diff --git a/src/main/java/edu/brown/cs/student/term/hub/Person.java b/src/main/java/edu/brown/cs/student/term/hub/Person.java deleted file mode 100644 index c3d5cb3..0000000 --- a/src/main/java/edu/brown/cs/student/term/hub/Person.java +++ /dev/null @@ -1,12 +0,0 @@ -package edu.brown.cs.student.term.hub; - -public class Person { - private int id; - private String name; - - public Person(int id, String name){ - this.id = id; - this.name = name; - } - -} diff --git a/src/main/java/edu/brown/cs/student/term/trade/Trade.java b/src/main/java/edu/brown/cs/student/term/trade/Trade.java index 8619ab1..13f7ae1 100644 --- a/src/main/java/edu/brown/cs/student/term/trade/Trade.java +++ b/src/main/java/edu/brown/cs/student/term/trade/Trade.java @@ -1,23 +1,23 @@ package edu.brown.cs.student.term.trade; +import edu.brown.cs.student.term.hub.Holder; + public class Trade { private int id; private String stock; private int isBuy; private double timestamp; - private String holder; + private Holder holder; private int numShares; - private int holderID; - public Trade(int id, String stockName, String holderName, double ts, int buy, int shares, int holderID){ + public Trade(int id, String stockName, double ts, int buy, int shares, Holder holder){ this.id = id; this.stock = stockName; this.isBuy = buy; this.timestamp = ts; - this.holder = holderName; + this.holder = holder; this.numShares = shares; - this.holderID = holderID; } public int getId() { @@ -40,7 +40,7 @@ public class Trade { return stock; } - public String getHolder() { + public Holder getHolder() { return holder; } @@ -53,7 +53,6 @@ public class Trade { ", timestamp=" + timestamp + ", holder='" + holder + '\'' + ", numShares=" + numShares + - ", holderID=" + holderID + '}'; } } diff --git a/src/test/java/edu/brown/cs/student/LinkMapperTest.java b/src/test/java/edu/brown/cs/student/LinkMapperTest.java new file mode 100644 index 0000000..9b46d5e --- /dev/null +++ b/src/test/java/edu/brown/cs/student/LinkMapperTest.java @@ -0,0 +1,48 @@ +package edu.brown.cs.student; + +import edu.brown.cs.student.term.DatabaseQuerier; +import edu.brown.cs.student.term.hub.LinkMapper; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.time.Instant; + +public class LinkMapperTest { + + /** these should span the entire mock dataset */ + //12 am on 3/11 in UTC + private Instant start = Instant.parse("2021-03-11T05:00:00.00Z"); + //12 am on 3/28 in UTC + private Instant end = Instant.parse("2021-03-28T05:00:00.00Z"); + + private DatabaseQuerier db; + + @Before + public void setUp() { + try{ + db = new DatabaseQuerier("data/mock_trades.sqlite3"); + } catch(Exception e){ + System.out.println("DBQuerier Test, couldn't connect to db???"); + } + } + + /* + * try{ + + } catch(Exception e) { + System.out.println("Error in test"); + }*/ + + @After + public void tearDown() { + db = null; + } + + @Test + public void testMapper(){ + setUp(); + LinkMapper lm = new LinkMapper(db); + lm.makeFollowerLinks(start, end); + } +} -- cgit v1.2.3-70-g09d2