package metrics4Asterisk.display;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import metrics4Asterisk.metrics.CallMetric;
import metrics4Asterisk.metrics.TimeMetric;
import metrics4Asterisk.util.Constants;
import org.apache.log4j.Logger;
/**
*
* A class for the creation of a TimeMetric object for each day of the week.
*
*
* <pre>
* Example:
*
* //parse call log
* LogParser<LogMapper<CallMetric>> queueLogParser = new LogParser<LogMapper<CallMetric>>();
* // ... parsing calls omited
*
* //create the WeekDistribution and give it the queue names to use
* WeekDistribution weeks = new WeekDistribution();
* Set<String> queueNames = new HashSet<String>();
* queueNames.add("superqueue");
* weeks.setQueueNames(queueNames);
*
* //init with two Calendar objects
* weeks.init(cFromDate, cToDate);
*
* //make the summary of the week's distribution
* weeks.makeSummary(queueLogParser.getLogMapper().getMap());
*
* //ready to read the results
* </pre>
* @author Lance Stine
*/
public class WeekDistribution {
/**
* The logger for debugging this application.
*/
private Logger logger = Logger.getLogger(this.getClass());
/**
* The number of weeks that have been averaged in each of the TimeMetric fields.
*/
private int numWeeks;
/**
* The starting date and time for this distribution.
*/
private Calendar fromTime;
/**
* The ending date and time for this distribution.
*/
private Calendar toTime;
/**
* A field for the toTime coverted into milliseconds.
*/
private long toTimeLong;
/**
* This Set will contain all of the queues that are to be included in this distribution.
*/
private Set<String> queueNames;
/**
* The TimeMetric for Sunday.
*/
private TimeMetric day1TimeMetric = new TimeMetric();
/**
* The TimeMetric for Monday.
*/
private TimeMetric day2TimeMetric = new TimeMetric();
/**
* The TimeMetric for Tuesday.
*/
private TimeMetric day3TimeMetric = new TimeMetric();
/**
* The TimeMetric for Wednesday.
*/
private TimeMetric day4TimeMetric = new TimeMetric();
/**
* The TimeMetric for Thursday.
*/
private TimeMetric day5TimeMetric = new TimeMetric();
/**
* The TimeMetric for Friday.
*/
private TimeMetric day6TimeMetric = new TimeMetric();
/**
* The TimeMetric for Saturday.
*/
private TimeMetric day7TimeMetric = new TimeMetric();
/**
* The init method must be called before makeSummary. It will validate the date range of the fromTime and toTime arguments.
* If it is for less than a week or otherwise invalid then an exception will be thrown.
* A copy of the fromTime argument will be incremented by 7 until it is past the toTime argument.
* The numWeeks field will be set to the number of times that the date was incremented and
* the toTime field will become the last end of the week within the date range.
* The toTimeLong field will also be set.
* @param fromTime The date to mark the start of a seven day period
* @param toTime The end date. This date argument can't be exclusive. It has to be at least 7 days after fromDate. It will be adjusted in init.
* It will be made exclusive and adjusted to be a whole week if the date range is not a multiple of 7 days from the fromDate argument.
* @throws java.lang.Exception Thrown if the date range is invalid.
*/
public void init(final Calendar fromTime, final Calendar toTime) throws Exception {
if (logger.isDebugEnabled()) {
SimpleDateFormat sdf = new SimpleDateFormat(Constants.DATE_FORMAT);
logger.debug("init looping from " + sdf.format(fromTime.getTime()) + " to " + sdf.format(toTime.getTime()));
}
if (!fromTime.before(toTime)) {
throw new Exception("The date range is not valid.");
}
Calendar intTime = (Calendar) fromTime.clone();
intTime.add(Calendar.DATE, 7);
if (intTime.after(toTime)) {
throw new Exception("The date range is not valid. It must be at least one week.");
}
numWeeks++;
Calendar test = (Calendar) intTime.clone();
while (test.before(toTime)) {
logger.debug("looping...");
test.add(Calendar.DATE, 7);
if (test.after(toTime)) {
logger.debug("the loop is done");
break;
} else {
intTime.add(Calendar.DATE, 7);
numWeeks++;
}
}
this.fromTime = fromTime;
this.fromTime.add(Calendar.SECOND, -1); //make end date exclusinve here
this.toTime = intTime;
this.toTimeLong = this.toTime.getTimeInMillis();
setNumWeeks();
logger.debug("num weeks " + getNumWeeks());
day1TimeMetric.setNumberOfSamples(getNumWeeks());
day2TimeMetric.setNumberOfSamples(getNumWeeks());
day3TimeMetric.setNumberOfSamples(getNumWeeks());
day4TimeMetric.setNumberOfSamples(getNumWeeks());
day5TimeMetric.setNumberOfSamples(getNumWeeks());
day6TimeMetric.setNumberOfSamples(getNumWeeks());
day7TimeMetric.setNumberOfSamples(getNumWeeks());
}
/**
*
* @param map
*/
public void makeSummary(final Map<String, CallMetric> map) {
Set<String> keys = map.keySet();
Iterator<String> iter = keys.iterator();
while (iter.hasNext()) {
String key = iter.next();
CallMetric callMetric = map.get(key);
if (getQueueNames().contains(callMetric.getQueueName())) {
//only add calls in the date range
long logDateLong = callMetric.getEnterQueueTime();
if (logDateLong < this.toTimeLong) {
if (callMetric.getTalkTime() > 0l) {
addAnsToTimeMetric(logDateLong);
logger.debug("adding answred call");
} else {
addUnAnsToTimeMetric(logDateLong);
logger.debug("adding unanswered call");
}
}
} else {
logger.warn("missing queue " + callMetric.getQueueName());
}
}
}
private void setNumWeeks() {
day1TimeMetric.setNumberOfSamples(numWeeks);
day2TimeMetric.setNumberOfSamples(numWeeks);
day3TimeMetric.setNumberOfSamples(numWeeks);
day4TimeMetric.setNumberOfSamples(numWeeks);
day5TimeMetric.setNumberOfSamples(numWeeks);
day6TimeMetric.setNumberOfSamples(numWeeks);
day7TimeMetric.setNumberOfSamples(numWeeks);
}
/**
* This method will return the number of weeks that are averaged in the TimeMetric fields.
* It can be different than the number of weeks in the date range passed in init.
* @return
*/
public int getNumWeeks() {
return numWeeks;
}
/**
* this will return the correct TimeMetric object based on a weekday
* @param cal
* @return
*/
private TimeMetric getTimeMetric(int day) {
if (day == 1) {
return this.getDay1TimeMetric();
} else if (day == 2) {
return this.getDay2TimeMetric();
} else if (day == 3) {
return this.getDay3TimeMetric();
} else if (day == 4) {
return this.getDay4TimeMetric();
} else if (day == 5) {
return this.getDay5TimeMetric();
} else if (day == 6) {
return this.getDay6TimeMetric();
} else if (day == 7) {
return this.getDay7TimeMetric();
} else {
return null;
}
}
private void addAnsToTimeMetric(long milliseconds) {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(milliseconds);
int day = cal.get(Calendar.DAY_OF_WEEK);
TimeMetric timeMetric = this.getTimeMetric(day);
int hour = cal.get(Calendar.HOUR_OF_DAY);
logger.debug("retrieved timeMetirc for day " + day);
logger.debug("adding to hour " + hour);
if (hour == 0) {
timeMetric.setAnsHour0(timeMetric.getAnsHour0() + 1);
} else if (hour == 1) {
timeMetric.setAnsHour1(timeMetric.getAnsHour1() + 1);
} else if (hour == 2) {
timeMetric.setAnsHour2(timeMetric.getAnsHour2() + 1);
} else if (hour == 3) {
timeMetric.setAnsHour3(timeMetric.getAnsHour3() + 1);
} else if (hour == 4) {
timeMetric.setAnsHour4(timeMetric.getAnsHour4() + 1);
} else if (hour == 5) {
timeMetric.setAnsHour5(timeMetric.getAnsHour5() + 1);
} else if (hour == 6) {
timeMetric.setAnsHour6(timeMetric.getAnsHour6() + 1);
} else if (hour == 7) {
timeMetric.setAnsHour7(timeMetric.getAnsHour7() + 1);
} else if (hour == 8) {
timeMetric.setAnsHour8(timeMetric.getAnsHour8() + 1);
} else if (hour == 9) {
timeMetric.setAnsHour9(timeMetric.getAnsHour9() + 1);
} else if (hour == 10) {
timeMetric.setAnsHour10(timeMetric.getAnsHour10() + 1);
} else if (hour == 11) {
timeMetric.setAnsHour11(timeMetric.getAnsHour11() + 1);
} else if (hour == 12) {
timeMetric.setAnsHour12(timeMetric.getAnsHour12() + 1);
} else if (hour == 13) {
timeMetric.setAnsHour13(timeMetric.getAnsHour13() + 1);
} else if (hour == 14) {
timeMetric.setAnsHour14(timeMetric.getAnsHour14() + 1);
} else if (hour == 15) {
timeMetric.setAnsHour15(timeMetric.getAnsHour15() + 1);
} else if (hour == 16) {
timeMetric.setAnsHour16(timeMetric.getAnsHour16() + 1);
} else if (hour == 17) {
timeMetric.setAnsHour17(timeMetric.getAnsHour17() + 1);
} else if (hour == 18) {
timeMetric.setAnsHour18(timeMetric.getAnsHour18() + 1);
} else if (hour == 19) {
timeMetric.setAnsHour19(timeMetric.getAnsHour19() + 1);
} else if (hour == 20) {
timeMetric.setAnsHour20(timeMetric.getAnsHour20() + 1);
} else if (hour == 21) {
timeMetric.setAnsHour21(timeMetric.getAnsHour21() + 1);
} else if (hour == 22) {
timeMetric.setAnsHour22(timeMetric.getAnsHour22() + 1);
} else if (hour == 23) {
timeMetric.setAnsHour23(timeMetric.getAnsHour23() + 1);
} else {
logger.error("addAnsToTimeMetric(long milliseconds) hour not right " + milliseconds);
}
timeMetric.setMaxCalls(timeMetric.getMaxCalls() + 1);
}
private void addUnAnsToTimeMetric(long milliseconds) {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(milliseconds);
int hour = cal.get(Calendar.HOUR_OF_DAY);
int day = cal.get(Calendar.DAY_OF_WEEK);
TimeMetric timeMetric = this.getTimeMetric(day);
logger.debug("retrieved timeMetirc for day " + day);
logger.debug("adding to hour " + hour);
if (hour == 0) {
timeMetric.setUnansHour0(timeMetric.getUnansHour0() + 1);
} else if (hour == 1) {
timeMetric.setUnansHour1(timeMetric.getUnansHour1() + 1);
} else if (hour == 2) {
timeMetric.setUnansHour2(timeMetric.getUnansHour2() + 1);
} else if (hour == 3) {
timeMetric.setUnansHour3(timeMetric.getUnansHour3() + 1);
} else if (hour == 4) {
timeMetric.setUnansHour4(timeMetric.getUnansHour4() + 1);
} else if (hour == 5) {
timeMetric.setUnansHour5(timeMetric.getUnansHour5() + 1);
} else if (hour == 6) {
timeMetric.setUnansHour6(timeMetric.getUnansHour6() + 1);
} else if (hour == 7) {
timeMetric.setUnansHour7(timeMetric.getUnansHour7() + 1);
} else if (hour == 8) {
timeMetric.setUnansHour8(timeMetric.getUnansHour8() + 1);
} else if (hour == 9) {
timeMetric.setUnansHour9(timeMetric.getUnansHour9() + 1);
} else if (hour == 10) {
timeMetric.setUnansHour10(timeMetric.getUnansHour10() + 1);
} else if (hour == 11) {
timeMetric.setUnansHour11(timeMetric.getUnansHour11() + 1);
} else if (hour == 12) {
timeMetric.setUnansHour12(timeMetric.getUnansHour12() + 1);
} else if (hour == 13) {
timeMetric.setUnansHour13(timeMetric.getUnansHour13() + 1);
} else if (hour == 14) {
timeMetric.setUnansHour14(timeMetric.getUnansHour14() + 1);
} else if (hour == 15) {
timeMetric.setUnansHour15(timeMetric.getUnansHour15() + 1);
} else if (hour == 16) {
timeMetric.setUnansHour16(timeMetric.getUnansHour16() + 1);
} else if (hour == 17) {
timeMetric.setUnansHour17(timeMetric.getUnansHour17() + 1);
} else if (hour == 18) {
timeMetric.setUnansHour18(timeMetric.getUnansHour18() + 1);
} else if (hour == 19) {
timeMetric.setUnansHour19(timeMetric.getUnansHour19() + 1);
} else if (hour == 20) {
timeMetric.setUnansHour20(timeMetric.getUnansHour20() + 1);
} else if (hour == 21) {
timeMetric.setUnansHour21(timeMetric.getUnansHour21() + 1);
} else if (hour == 22) {
timeMetric.setUnansHour22(timeMetric.getUnansHour22() + 1);
} else if (hour == 23) {
timeMetric.setUnansHour23(timeMetric.getUnansHour23() + 1);
} else {
logger.error("addUnAnsToTimeMetric(long milliseconds) hour not right " + milliseconds);
}
timeMetric.setMaxCalls(timeMetric.getMaxCalls() + 1);
}
public TimeMetric getDay1TimeMetric() {
return day1TimeMetric;
}
public void setDay1TimeMetric(TimeMetric day1TimeMetric) {
this.day1TimeMetric = day1TimeMetric;
}
public TimeMetric getDay2TimeMetric() {
return day2TimeMetric;
}
public void setDay2TimeMetric(TimeMetric day2TimeMetric) {
this.day2TimeMetric = day2TimeMetric;
}
public TimeMetric getDay3TimeMetric() {
return day3TimeMetric;
}
public void setDay3TimeMetric(TimeMetric day3TimeMetric) {
this.day3TimeMetric = day3TimeMetric;
}
public TimeMetric getDay4TimeMetric() {
return day4TimeMetric;
}
public void setDay4TimeMetric(TimeMetric day4TimeMetric) {
this.day4TimeMetric = day4TimeMetric;
}
public TimeMetric getDay5TimeMetric() {
return day5TimeMetric;
}
public void setDay5TimeMetric(TimeMetric day5TimeMetric) {
this.day5TimeMetric = day5TimeMetric;
}
public TimeMetric getDay6TimeMetric() {
return day6TimeMetric;
}
public void setDay6TimeMetric(TimeMetric day6TimeMetric) {
this.day6TimeMetric = day6TimeMetric;
}
public TimeMetric getDay7TimeMetric() {
return day7TimeMetric;
}
public void setDay7TimeMetric(TimeMetric day7TimeMetric) {
this.day7TimeMetric = day7TimeMetric;
}
/**
* Returns the queue names that will be analyzed.
* @param queueNames
*/
public Set<String> getQueueNames() {
return queueNames;
}
/**
* Sets the queue names that will be analyzed.
* @param queueNames
*/
public void setQueueNames(Set<String> queueNames) {
this.queueNames = queueNames;
}
public Calendar getFromTime() {
return fromTime;
}
public Calendar getToTime() {
return toTime;
}
@Override
public String toString() {
StringBuilder buff = new StringBuilder();
buff.append("week day 1\n");
buff.append(day1TimeMetric.toString());
buff.append("week day 2\n");
buff.append(day2TimeMetric.toString());
buff.append("week day 3\n");
buff.append(day3TimeMetric.toString());
buff.append("week day 4\n");
buff.append(day4TimeMetric.toString());
buff.append("week day 5\n");
buff.append(day5TimeMetric.toString());
buff.append("week day 6\n");
buff.append(day6TimeMetric.toString());
buff.append("week day 7\n");
buff.append(day7TimeMetric.toString());
return buff.toString();
}
}