diff options
Diffstat (limited to 'src/main/java')
4 files changed, 302 insertions, 26 deletions
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 1bb49c7..7e9a184 100644 --- a/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java +++ b/src/main/java/edu/brown/cs/student/term/DatabaseQuerier.java @@ -85,8 +85,4 @@ public class DatabaseQuerier{ 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 31bf7a3..b8ff2c9 100644 --- a/src/main/java/edu/brown/cs/student/term/Main.java +++ b/src/main/java/edu/brown/cs/student/term/Main.java @@ -13,6 +13,59 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.HashMap; +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import spark.*; +import spark.template.freemarker.FreeMarkerEngine; + + +import java.io.BufferedReader; +import java.io.InputStreamReader; + +import com.google.common.collect.ImmutableMap; + +import freemarker.template.Configuration; + +//fix +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.*; +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import spark.ExceptionHandler; +import spark.ModelAndView; +import spark.QueryParamsMap; +import spark.Request; +import spark.Response; +import spark.Route; +import spark.Filter; +import spark.Spark; +import spark.TemplateViewRoute; +import spark.template.freemarker.FreeMarkerEngine; + +import freemarker.template.Configuration; + + +import org.json.JSONObject; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; + + /** * The Main class of our project. This is where execution begins. */ @@ -44,8 +97,7 @@ public final class Main { OptionSet options = parser.parse(args); if (options.has("gui")) { - //do a gui type thing - //runSparkServer((int) options.valueOf("port")); + runSparkServer((int) options.valueOf("port")); } HashMap<String, Command> commandHashMap = new HashMap<>(); @@ -55,5 +107,78 @@ public final class Main { repl.runREPL(); } + private static FreeMarkerEngine createEngine() { + Configuration config = new Configuration(); + File templates = new File("src/main/resources/spark/template/freemarker"); + try { + config.setDirectoryForTemplateLoading(templates); + } catch (IOException ioe) { + System.out.printf("ERROR: Unable use %s for template loading.%n", + templates); + System.exit(1); + } + return new FreeMarkerEngine(config); + } + + public void runSparkServer(int port) { + Spark.port(port); + Spark.externalStaticFileLocation("src/main/resources/static"); + Spark.exception(Exception.class, new ExceptionPrinter()); + + Spark.options("/*", + (request, response) -> { + + String accessControlRequestHeaders = request + .headers("Access-Control-Request-Headers"); + if (accessControlRequestHeaders != null) { + response.header("Access-Control-Allow-Headers", + accessControlRequestHeaders); + } + + String accessControlRequestMethod = request + .headers("Access-Control-Request-Method"); + if (accessControlRequestMethod != null) { + response.header("Access-Control-Allow-Methods", + accessControlRequestMethod); + } + + return "OK"; + }); + + Spark.before((request, response) -> response.header("Access-Control-Allow-Origin", "*")); + Spark.get("/data", new DataHandler()); + } + + + private static class DataHandler implements Route { + + @Override + public Object handle(Request request, Response response) throws Exception { + String str = request.body(); + JSONObject json = new JSONObject(str); + + String startLat = json.getString("srclat"); + return "ok"; + } + } + + /** + * Display an error page when an exception occurs in the server. + * + */ + private static class ExceptionPrinter implements ExceptionHandler { + @Override + public void handle(Exception e, Request req, Response res) { + res.status(500); + StringWriter stacktrace = new StringWriter(); + try (PrintWriter pw = new PrintWriter(stacktrace)) { + pw.println("<pre>"); + e.printStackTrace(pw); + pw.println("</pre>"); + } + res.body(stacktrace.toString()); + } + } + }
\ 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 index 4c382ec..4d5755c 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,7 +1,101 @@ package edu.brown.cs.student.term.hub; +import edu.brown.cs.student.term.DatabaseQuerier; +import edu.brown.cs.student.term.repl.commands.SetupCommand; + +import java.time.Instant; +import java.util.*; + public class HubSearch { + LinkMapper mapper; + Map<Holder, Set<Holder>> followerToLeaderMap = new HashMap<>(); + + //TODO: Make this just take in a map from holder -> set of holder + public HubSearch(LinkMapper mapper){ + this.mapper = mapper; + } + + //TODO: reevaluate this basic version and tweak to customize + public Map<Holder, Double> runHubSearch(Instant start, Instant end){ + followerToLeaderMap = mapper.makeFollowerLinks(start, end); + int numHolders = followerToLeaderMap.size(); + List<Holder> holders = new ArrayList<>(followerToLeaderMap.keySet()); + double[] weights = new double[numHolders]; + double[] rank = new double[numHolders]; + double[] rankPrime = new double[numHolders]; + Arrays.fill(rankPrime, 1.0 / numHolders); + + while(!withinDistance(rank, rankPrime)){ + rank = Arrays.copyOf(rankPrime, rankPrime.length); + //calculating hub rank for ith holder + for(int i = 0; i < numHolders; i++){ + rankPrime[i] = 0; + //iterating through all holders to calculate hub rank + for(int j = 0; j < numHolders; j++){ + double weightIJ = getWeight(holders.get(i), holders.get(j), numHolders); + rankPrime[i] += (weightIJ * rank[j]); + } + } + } + + //potentially should change this to be a map from holder id => double? + Map<Holder, Double> hubRankMap = new HashMap<>(); + + for(int i = 0; i < rankPrime.length; i++){ + hubRankMap.put(holders.get(i), rankPrime[i]); + } + + return hubRankMap; + } + + private double getWeight(Holder leader, Holder follower, int numHolders){ + + //dampening factor + double damp = 0.15; + /* + In normal page rank: + links is the pages that k links to, if k links to j, then + we want to add some weight to j from k, but that + weight is diluted by the number of links that k has + in general because we don't want to count a bunch of links + from a page as highly as one targeted link from one page to another + + In Hub Search + leader = j, follower = k, if follower links to (follows) leader, + then we want to add some weight from follower to leader, + but should that weight be diluted by the number of people + who followed leader or the number of people who follower followed + --- probably the second option ;( */ + Set<Holder> peopleFollowed = followerToLeaderMap.get(follower); + int numberFollowed = peopleFollowed.size(); + + if(peopleFollowed.contains(leader)){ + return ((damp / numHolders) + (1 - damp) * (1.0 / numberFollowed)); + } else if(numberFollowed == 0){ + return ((damp / numHolders) + (1 - damp) * (1.0 / numHolders)); + } else { + return (damp / numHolders); + } + } + + private boolean withinDistance(double[] r, double[] rPrime){ + double sum = 0.0; + for(int i = 0; i < r.length; i++){ + sum += Math.pow((r[i] - rPrime[i]), 2); + } + + return sum <= 0.001; + } + + + + + + + + + /* def pageRank(pList: List[Page]): mutable.HashMap[Int, Double] = { val n = pList.length @@ -41,5 +135,14 @@ public class HubSearch { (0.15 / n) } } + + def distance(r1: Array[Double], r2: Array[Double]): Boolean = { + var sum = 0.0 + for (i <- 0 to r1.length - 1) { + sum = sum + Math.pow((r1(i) - r2(i)), 2) + } + sum <= .001 + + } */ } 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 f4ec0a7..8bc8cf9 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,7 +1,6 @@ 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; @@ -10,30 +9,23 @@ import java.util.*; public class LinkMapper { + //TODO: Review what we actually need in here //not strictly necessary but may be nice to maintain private List<List<Trade>> allTrades = new ArrayList<>(); - private Map<Holder, List<Trade>> personToTradesMap = new HashMap<>(); - private Map<Holder, List<Holder>> personToFollowers = new HashMap<>(); + private Map<Holder, Set<Holder>> followerToLeaders = new HashMap<>(); private DatabaseQuerier databaseQuerier; 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<Holder, List<Trade>> getPersonToTradesMap() { - return personToTradesMap; - } /** - * Returns the person => follower map as is, does not update it + * Returns the follower => leaders map as is, does not update it * @return person to follower map */ - public Map<Holder, List<Holder>> getPersonToFollowers() { - return personToFollowers; + public Map<Holder, Set<Holder>> getFollowerToLeaders() { + return followerToLeaders; } /** @@ -41,20 +33,17 @@ public class LinkMapper { * in the same time period * @return the newly updated link map */ - public Map<Holder, List<Holder>> makeFollowerLinks(Instant start, Instant end){ + public Map<Holder, Set<Holder>> makeFollowerLinks(Instant start, Instant end){ if(databaseQuerier != null){ try{ List<List<Trade>> allTrades = databaseQuerier.getAllTradesByStock(start, end); //reset the map to be blank - personToFollowers = new HashMap<>(); + followerToLeaders = new HashMap<>(); for(List<Trade> 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"); } @@ -62,9 +51,12 @@ public class LinkMapper { System.out.println("ERROR: No database loaded in yet"); } - return personToFollowers; + return followerToLeaders; } + + //TODO: Try to create both leader => follower and follower => leader map at once + //only if necessary tho! private void convertTradeListToFollowerMap(List<Trade> tradeList){ List<Holder> holderList = new ArrayList<>(); @@ -73,6 +65,66 @@ public class LinkMapper { holderList.add(trade.getHolder()); } + //Set<Holder> followers = new HashSet<>(holderList); + Set<Holder> encountered = new HashSet<>(); + + //[bob, george, jane, bob, mary] + for(Holder current: holderList){ + //only want to use first instance of a holder to dictate who they followed + //for instance, if the person whose at the front buys again, they probably + //didn't follow the people in between, just wanted to buy again + if(!encountered.contains(current)){ + if(followerToLeaders.containsKey(current)){ + //TODO: this probably makes it O(n^2), might want to optimize later + followerToLeaders.get(current).addAll(encountered); + } else { + Set<Holder> currentLeaders = new HashSet<>(encountered); + followerToLeaders.put(current, currentLeaders); + } + encountered.add(current); + } + } + + } + + //This code creates a leader => follower map! + /*private void convertTradeListToFollowerMap(List<Trade> tradeList){ + List<Holder> holderList = new ArrayList<>(); + + //gets in order list of people + for (Trade trade : tradeList) { + holderList.add(trade.getHolder()); + } + + Set<Holder> followers = new HashSet<>(holderList); + Set<Holder> 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 { + Set<Holder> currentFollowers = new HashSet<>(followers); + personToFollowers.put(current, currentFollowers); + } + } + } + }*/ + + + //Old version using lists of followers, allowing for duplicates + /*private void convertTradeListToFollowerMap(List<Trade> tradeList){ + List<Holder> holderList = new ArrayList<>(); + + //gets in order list of people + for (Trade trade : tradeList) { + holderList.add(trade.getHolder()); + } + Set<Holder> followers = new HashSet<>(holderList); Set<Holder> encountered = new HashSet<>(); @@ -90,5 +142,5 @@ public class LinkMapper { } } } - } + }*/ } |
