package com.google.sps.utilities;

import com.google.common.collect.Sets;
import com.google.sps.data.Event;
import com.google.sps.data.User;
import com.google.sps.data.VolunteeringOpportunity;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class EventRanker {
  /**
   * Sorts events based on each event's score. Breaks ties with the event's date; the more recent
   * event will be ranked higher. Makes the assumption that all events are NOT in the past.
   *
   * @param user The user for whom the events are ranked
   * @param unrankedEvents A {@link Set} of events that need to be ranked
   * @return A {@link List} of events that is ranked according to each element's score
   */
  public static List<Event> rankEvents(User user, Set<Event> unrankedEvents) {
    List<Event> rankedEvents = new ArrayList<>(unrankedEvents);
    Collections.sort(
        rankedEvents,
        (Event event1, Event event2) -> {
          int comparison = getEventScore(user, event1).compareTo(getEventScore(user, event2));
          if (comparison == 0) {
            comparison = event2.getDate().compareTo(event1.getDate());
          }
          return comparison;
        });
    Collections.reverse(rankedEvents);
    return rankedEvents;
  }

  private static Integer getEventScore(User user, Event event) {
    Set<String> interestsAndSkills = new HashSet<>(user.getInterests());
    interestsAndSkills.addAll(user.getSkills());
    Set<String> labelsAndSkills = new HashSet<>(event.getLabels());
    for (VolunteeringOpportunity opportunity : event.getOpportunities()) {
      labelsAndSkills.addAll(opportunity.getRequiredSkills());
    }
    return Sets.intersection(interestsAndSkills, labelsAndSkills).size();
  }
}

@@ -244,16 +244,42 @@
 ctions;%0A
+import java.util.HashMap;%0A
 import j
@@ -336,19 +336,141 @@
 va.util.
-Set
+Map;%0Aimport java.util.Set;%0Aimport java.util.function.Function;%0Aimport java.util.stream.Collectors;%0Aimport org.javatuples.Pair
 ;%0A%0Apubli
@@ -761,29 +761,123 @@
  @param 
-unrankedEvent
+directMatches A %7B@link Set%7D of events that need to be ranked; direct event maches%0A   * @param similarMatche
 s A %7B@li
@@ -912,24 +912,47 @@
 to be ranked
+; similar event matches
 %0A   * @retur
@@ -1098,25 +1098,88 @@
 nt%3E 
-unrankedEvents) %7B
+events) %7B%0A    Map%3CEvent, Double%3E eventScoreMap = getEventScoreMap(user, events);
 %0A   
@@ -1226,22 +1226,30 @@
 t%3C%3E(
-unrankedEvents
+eventScoreMap.keySet()
 );%0A 
@@ -1360,20 +1360,17 @@
 rison = 
-getE
+e
 ventScor
@@ -1366,31 +1366,32 @@
 = eventScore
-(user, 
+Map.get(
 event1).comp
@@ -1396,20 +1396,17 @@
 mpareTo(
-getE
+e
 ventScor
@@ -1406,23 +1406,24 @@
 entScore
-(user, 
+Map.get(
 event2))
@@ -1671,15 +1671,26 @@
 tic 
-Integer
+Map%3CEvent, Double%3E
  get
@@ -1699,16 +1699,19 @@
 entScore
+Map
 (User us
@@ -1718,27 +1718,33 @@
 er, 
+Set%3C
 Event
+%3E
  event
+s
 ) %7B%0A    
 Set%3C
@@ -1743,330 +1743,480 @@
     
-Set%3CString%3E interestsAndSkills = new HashSet%3C%3E(user.getInterests());%0A    interestsAndSkills.addAll(user.getSkills());%0A    Set%3CString%3E labelsAndSkills = new HashSet%3C%3E(event.getLabels());%0A    for (Volu
+List%3CSet%3CPair%3CEvent, Integer%3E%3E%3E allEvents =%0A        new GetLabelCategories().getEventRelevancy(events, user);%0A    Set%3CPair%3CEvent, Integer%3E%3E directEventPairs = allEvents.get(0);%0A    Set%3CPair%3CEvent, Integer%3E%3E similarEventPairs = allEvents.get(1);%0A%0A    Map%3CEvent, Double%3E eventScoreMap = new HashMap%3C%3E();%0A    for (Pair%3CEvent, I
 nte
+g
 er
-ingOpportunity opportunity : event.getOpportunities()) %7B%0A      labelsAndSkills.addAll(opportunity.getRequiredSkills
+%3E eventRelevancyPair : directEventPairs) %7B%0A      eventScoreMap.put(eventRelevancyPair.getValue0(), new Double(eventRelevancyPair.getValue1
 ())
+)
 ;%0A  
@@ -2227,76 +2227,201 @@
     
-return Sets.intersection(interestsAndSkills, labelsAndSkills).size()
+for (Pair%3CEvent, Integer%3E eventRelevancyPair : similarEventPairs) %7B%0A      eventScoreMap.put(eventRelevancyPair.getValue0(), 0.7 * eventRelevancyPair.getValue1());%0A    %7D%0A    return eventScoreMap
 ;%0A  

Connect event ranker