/*
* Copyright 2009 Peter Karich.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* under the License.
*/
package de.timefinder.core.ui.planner;
import de.timefinder.data.algo.DataPoolSettings;
import de.timefinder.data.util.Helper;
import de.timefinder.data.Event;
import de.timefinder.data.Person;
import de.timefinder.data.Resource;
import de.timefinder.data.Role;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import javolution.util.FastMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javolution.util.FastSet;
/**
* This component lists all added events in an HTML table.
* The implemenation was quick and the result is ugly ;-)
*
* TODO I18N
*
* @author Peter Karich
*/
public class HtmlPlannerComponent {
protected Collection<Event> events = FastSet.newInstance();
private DataPoolSettings settings;
private String title;
public HtmlPlannerComponent(DataPoolSettings settings) {
this.settings = settings;
}
public HtmlPlannerComponent(DataPoolSettings settings, String title) {
this.settings = settings;
this.title = title;
}
/**
* This method adds the events. The underlying implementation
* should handle each added events collection as it comes from a
* different resource. (one resource per method call)
*/
public void addEvents(Collection<Event> events) {
this.events.addAll(events);
}
void clearEvents() {
events.clear();
}
public void initSlots(Map<Integer, List<Event>> map, List<Event> notAssigned) {
if (notAssigned == null)
notAssigned = new ArrayList();
for (Event event : events) {
if (event.getStart() < 0) {
notAssigned.add(event);
continue;
}
for (int start = event.getStart(); start < event.getEnd(); start++) {
List<Event> list = map.get(start);
if (list == null) {
list = new ArrayList<Event>();
map.put(start, list);
}
list.add(event);
}
}
}
protected void printHeader(StringBuilder sb) {
if (title != null)
sb.append("<b>" + title + "</b>");
sb.append("<thead><tr>");
sb.append("<th>");
sb.append("</th>");
for (int day = 0; day < settings.getNumberOfDays(); day++) {
sb.append("<th>");
sb.append(getDayName(day));
sb.append("</th>");
}
sb.append("</tr></thead>");
}
public String getTimeTable() {
List<Event> notAssigned = new ArrayList<Event>();
Map<Integer, List<Event>> map = new FastMap<Integer, List<Event>>();
initSlots(map, notAssigned);
StringBuilder sb = new StringBuilder();
sb.append("<table border=\"1\">");
// header of table
printHeader(sb);
// body of table
sb.append("<tbody>");
for (int timeslot = 0; timeslot < settings.getTimeslotsPerDay(); timeslot++) {
sb.append("<tr>");
sb.append("<td>");
sb.append(timeslot + 1);
for (int day = 0; day < settings.getNumberOfDays(); day++) {
sb.append("<td>");
List<Event> eventsPerSlot = map.get(timeslot + settings.getTimeslotsPerDay() * day);
if (eventsPerSlot != null)
sb.append(addTableEntry(eventsPerSlot));
sb.append("</td>");
}
sb.append("</tr>");
}
sb.append("</tbody>");
sb.append("</table>");
// footer
if (notAssigned.size() == 0) {
sb.append("<br/><br/>No unassigned events<br/>");
} else {
sb.append("<br/><br/>Unassigned events:<br/>");
for (Event event : notAssigned) {
sb.append("<div>");
sb.append(toString(event));
sb.append("</div>");
}
}
return sb.toString();
}
protected String addTableEntry(Collection<Event> eventsPerSlot) {
return Math.round(eventsPerSlot.size() * 100.0f / events.size()) + "%";
}
String getDayName(int i) {
switch (i) {
case 0:
return "Mon";
case 1:
return "Tue";
case 2:
return "Wed";
case 3:
return "Thu";
case 4:
return "Fri";
case 5:
return "Sat";
case 6:
return "Fun";
default:
return "Day" + i;
}
}
String toString(Event event) {
String str = event.getName() + "<br/>";
if (event.getLocation() != null) {
str += event.getLocation().getName() + "<br/>";
}
for (Entry<Person, Role> entry : event.getPersonsMap().entrySet()) {
if (entry.getValue() == Role.TEACHER) {
str += entry.getKey().getName() + ";";
}
}
str += "<br />";
return str;
}
public static void printWorkload(final Collection<? extends Person> personsColl, DataPoolSettings settings) {
try {
File file = File.createTempFile("timefinder.workload", "timetable.html");
FileWriter writer = new FileWriter(file);
writer.write("<html><head><title>Workload</title>");
writer.write("</head>");
writer.write("<body>");
HtmlPlannerComponent planner = new HtmlPlannerComponent(settings, "person load per slot in percent") {
@Override
protected String addTableEntry(Collection<Event> eventsPerSlot) {
int persons = 0;
// assume disjunct sets of persons
for (Event event : eventsPerSlot) {
persons += event.getPersons().size();
}
return Math.round(persons * 100.0f / personsColl.size()) + "%";// + persons + ";" + personsColl.size();
}
};
for (Person p : personsColl) {
planner.addEvents(p.getEvents());
}
writer.write(planner.getTimeTable());
writer.write("<br/><br/>");
planner = new HtmlPlannerComponent(settings, "events load per slot in percent");
for (Person p : personsColl) {
planner.addEvents(p.getEvents());
}
writer.write(planner.getTimeTable());
writer.write("</body></html>");
writer.close();
Helper.openURL(file.toURI());
} catch (IOException ex) {
new RuntimeException("Problem while writing timetable of persons!", ex);
}
}
public static void printResources(Iterator<? extends Resource> iter, DataPoolSettings settings) {
try {
File file = File.createTempFile("timefinder.resources", "timetable.html");
FileWriter writer = new FileWriter(file);
writer.write("<html><head><title>Timetable</title></head>");
writer.write("<body>");
while (iter.hasNext()) {
Resource resource = iter.next();
HtmlPlannerComponent planner = new HtmlPlannerComponent(settings, resource.getName()) {
@Override
protected String addTableEntry(Collection<Event> eventsPerSlot) {
StringBuilder sb = new StringBuilder();
for (Event event : eventsPerSlot) {
sb.append(toString(event));
sb.append("<br/>");
}
return sb.toString();
}
};
writer.write("<br/>");
planner.addEvents(resource.getEvents());
writer.write(planner.getTimeTable());
writer.write("<br/>");
writer.write("<br/>");
}
writer.write("</body></html>");
writer.close();
Helper.openURL(file.toURI());
} catch (IOException ex) {
new RuntimeException("Problem while writing timetable of persons!", ex);
}
}
}