import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Scheduler2 {
private static final int MAX_OVERLAPPED_CONTENTS = 3;
public Scheduler2() {
// TODO Auto-generated constructor stub
}
public static enum Type {
start,
end
}
public static class TimeNode {
public static List<TimeNode> constructNodes(ScheduleRequest scheduleRequest, int index) {
List<TimeNode> timeNodes = new ArrayList<>(2);
timeNodes.add(new TimeNode(index, scheduleRequest.id, scheduleRequest.startTime, Type.start));
timeNodes.add(new TimeNode(index, scheduleRequest.id, scheduleRequest.endTime, Type.end));
return timeNodes;
}
private final int index;
private final String id;
private final int time;
private final Type type;
private TimeNode(int index, String id, int time, Type type) {
this.index = index;
this.id = id;
this.time = time;
this.type = type;
}
public int getIndex() {
return index;
}
public String getId() {
return id;
}
public int getTime() {
return time;
}
public Type getType() {
return type;
}
public final static Comparator<TimeNode> timeComparator = new Comparator<TimeNode>() {
public int compare(TimeNode t1, TimeNode t2) {
//TODO should compareTo do null check?
if (t1.getTime() == t2.getTime()) {
if (t1.getType() == Type.start) {
return -1;
}
else {
return 1;
}
}
return t1.getTime() - t2.getTime();
}
};
}
public static List<ScheduleRequest> schedule() {
//TODO for 1 area only now
List<ScheduleRequest> scheduleRequests = readCommercials();
if (scheduleRequests == null || scheduleRequests.size() == 0) {
return new ArrayList<ScheduleRequest>();
}
//split it into start end time
List<TimeNode> timeNodes = new LinkedList<>();
//TODO sort performance on LinkedList and ArrayList
for (int i = 0; i < scheduleRequests.size(); i++) {
if (scheduleRequests.get(i) != null) {
timeNodes.addAll(TimeNode.constructNodes(scheduleRequests.get(i), i));
}
}
//sort nodes according to time
Collections.sort(timeNodes, TimeNode.timeComparator);
List<ScheduleRequest> resultCommercials = new LinkedList<>();
List<ScheduleRequest> toRemoveCommercials = new LinkedList<>();
//TODO
//a HashMap to maintain during scan, the String is the ID and the Integer is
//the index of the Content in the Contents
Map<String, Integer> map = new HashMap<>();
//scan the sorted timeNodes
for (TimeNode node : timeNodes) {
if (node.getType() == Type.start) {
//this node represent a start time
if (map.containsKey(node.getId())) {
//id conflicts
//TODO may change remove policy here
//Remove policy: remove latest coming
toRemoveCommercials.add(scheduleRequests.get(node.getIndex()));
}
else if (map.keySet().size() == MAX_OVERLAPPED_CONTENTS){
//at current point the set of overlapped contents is oversized
//TODO may change remove policy here
toRemoveCommercials.add(scheduleRequests.get(node.getIndex()));
}
else {
//this node is selected into this point
resultCommercials.add(scheduleRequests.get(node.getIndex()));
}
}
else {
//this node represent an end time
if (map.containsKey(node.getId()) && map.get(node.getId()) == node.index) {
//the corresponded start time is actually in the map
map.remove(node.id);
}
}
}
//Output
IO.writeAds(resultCommercials);
return null;
}
public static List<ScheduleRequest> readCommercials() {
List<ScheduleRequest> list = new LinkedList<>();
ScheduleRequest ad = null;
while ((ad = IO.readAd()) != null) {
list.add(ad);
}
return list;
}
}