package edu.brown.cs.student.term.hub; import edu.brown.cs.student.term.DatabaseQuerier; import edu.brown.cs.student.term.profit.ProfitCalculation; import java.time.Instant; import java.sql.Date; import java.util.*; public class SuspicionRanker { DatabaseQuerier querier; public SuspicionRanker(DatabaseQuerier db) { this.querier = db; } private > V getMaxOfMap(Map map) { //Map.Entry maxEntry = Collections.max(map.entrySet(), Map.Entry.comparingByValue()); Collection values = map.values(); return Collections.max(map.values()); } private > V getMinOfMap(Map map) { Map.Entry maxEntry = Collections.min(map.entrySet(), Map.Entry.comparingByValue()); return maxEntry.getValue(); } private class SuspicionComparator implements Comparator { @Override public int compare(Holder o1, Holder o2) { if (o1.getSuspicionScore() > o2.getSuspicionScore()) { return -1; } else if (o1.getSuspicionScore() < o2.getSuspicionScore()) { return 1; } else { return 0; } } } /** * * @param start * @param end * @return */ public List getSuspicionScoreList(Instant start, Instant end) { PriorityQueue orderedSuspicion = new PriorityQueue<>(new SuspicionComparator()); List suspicionList = new ArrayList<>(); try { LinkMapper lm = new LinkMapper(querier); HubSearch hub = new HubSearch(lm); Map holderToHubScore = hub.runHubSearch(start, end); ProfitCalculation pc = new ProfitCalculation(DatabaseQuerier.getConn(), "", new Date(start.toEpochMilli()), new Date(end.toEpochMilli())); Map profitMap = pc.getProfitMap(); System.out.println(profitMap); //if the maps are empty, we abort because we have entirely incomplete data if(profitMap.isEmpty() || holderToHubScore.isEmpty()){ return new ArrayList<>(); } double profitMax = getMaxOfMap(profitMap); //if all of our values are negative, we need to flip sides so that the //biggest loser doesn't end up being the most suspicious person*/ if(profitMax <= 0) { profitMax = Math.abs(getMinOfMap(profitMap)); } //if both the min we found and max we found are 0, then we have //the special case where all the values are 0, in which case we //need to avoid dividing by 0 if(profitMax == 0){ profitMax = 1; } double hubMax = getMaxOfMap(holderToHubScore); for (Holder guy : holderToHubScore.keySet()) { double normalizedProfitScore = 0; if (profitMap.containsKey(guy.getId())) { normalizedProfitScore = profitMap.get(guy.getId()) / profitMax; } double normalizedHubScore = holderToHubScore.get(guy) / hubMax; double suspicionScore = normalizedHubScore * 0.6 + normalizedProfitScore * 0.4; guy.setSuspicionScore(suspicionScore); orderedSuspicion.add(guy); } } catch (Exception e) { e.printStackTrace(); System.out.println("ERROR: Could not connect to database querier"); } int size = orderedSuspicion.size(); for(int i = 0; i < size; i++){ suspicionList.add(orderedSuspicion.poll()); } return suspicionList; } }