/*
* See COPYING in top-level directory.
*/
package com.monkygames.wox.health.gui;
// === java imports === //
import java.util.*;
// === chart imports === //
import org.jfree.data.time.*;
// === wox imports === //
import com.monkygames.wox.health.data.Weight;
/**
* Handles creating a TimeSeries based on the specified time frame (month, day, etc).
* @version 1.0
*/
public class DateUtil{
// ============= Class variables ============== //
private Vector<Weight> weightV;
// ============= Constructors ============== //
public DateUtil(Vector<Weight> weightV){
this.weightV = weightV;
}
// ============= Public Methods ============== //
public TimeSeries getTimeSeriesByDay(boolean isKG){
TimeSeries series = new TimeSeries("Day");
updateTimeSeries(series,isKG,false,false,true,false);
return series;
}
public TimeSeries getTimeSeriesByWeek(boolean isKG){
TimeSeries series = new TimeSeries("Week");
updateTimeSeries(series,isKG,false,false,false,true);
return series;
}
public TimeSeries getTimeSeriesByMonth(boolean isKG){
TimeSeries series = new TimeSeries("Month");
updateTimeSeries(series, isKG, false, true, false,false);
return series;
}
public TimeSeries getTimeSeriesByYear(boolean isKG){
TimeSeries series = new TimeSeries("Year");
updateTimeSeries(series, isKG, true,false,false,false);
return series;
}
// ============= Protected Methods ============== //
// ============= Private Methods ============== //
/**
* Adds the weight based on kg or pounds to the time series.
* @param isKG true if weight should be in kg and false if pounds.
* @param ts the time series to add the data to.
* @param tp the time of the day to add.
* @param w the weight to be added.
**/
private void addWeight(boolean isKG, TimeSeries ts, RegularTimePeriod tp, Weight w){
if(isKG){
ts.addOrUpdate(tp,w.weightInkg);
}else{
ts.addOrUpdate(tp,w.getPounds());
}
}
public void updateTimeSeries(TimeSeries series, boolean isKG, boolean isYear, boolean isMonth, boolean isDay, boolean isWeek){
Vector<Category> categoryV = new Vector<Category>();
Category category = new Category();
for(int i = 0; i < weightV.size(); i++){
Weight w = weightV.elementAt(i);
Date date = new Date(w.date);
Item item = new Item(w,date);
// need to sort into months
boolean isAdded = false;
if(isMonth){
for(int j = 0; j < categoryV.size(); j++){
Category cat = categoryV.elementAt(j);
if(cat.isSameYear(date) && cat.isSameMonth(date)){
cat.itemsV.add(item);
isAdded = true;
break;
}
}
}else if(isYear){
for(int j = 0; j < categoryV.size(); j++){
Category cat = categoryV.elementAt(j);
if(cat.isSameYear(date)){
cat.itemsV.add(item);
isAdded = true;
break;
}
}
}else if(isDay){
for(int j = categoryV.size()-1 ; j >= 0; j--){
Category cat = categoryV.elementAt(j);
if(cat.isSameYear(date) && cat.isSameMonth(date) && cat.isSameDay(date)){
cat.itemsV.add(item);
isAdded = true;
break;
}
}
}else if(isWeek){
for(int j = categoryV.size()-1 ; j >= 0; j--){
Category cat = categoryV.elementAt(j);
if(cat.isSameYear(date) && cat.isSameMonth(date) && cat.isSameWeek(date)){
cat.itemsV.add(item);
isAdded = true;
break;
}
}
}
if(!isAdded){
Category cat = new Category();
cat.itemsV.add(item);
categoryV.add(cat);
}
}
// done sorting
// now start adding
for(int i = 0; i < categoryV.size(); i++){
Category cat = categoryV.elementAt(i);
if(isMonth){
series.addOrUpdate(new Month(cat.getDate()),cat.getAverage(isKG));
}else if(isYear){
series.addOrUpdate(new Year(cat.getDate()),cat.getAverage(isKG));
}else if(isDay){
series.addOrUpdate(new Day(cat.getDate()),cat.getAverage(isKG));
}else if(isWeek){
series.addOrUpdate(new Week(cat.getDate()),cat.getAverage(isKG));
}
}
}
// ============= Implemented Methods ============== //
// ============= Extended Methods ============== //
// ============= Internal Classes ============== //
protected class Category{
public Vector <Item> itemsV;
public Category(){
itemsV = new Vector<Item>();
}
/**
* Returns the first date in this category.
**/
public Date getDate(){
return itemsV.elementAt(0).date;
}
/**
* Returns the average of all the items in this category.
* @param isKG true if weight is in kg and false if in pounds.
* @return the average.
**/
public float getAverage(boolean isKG){
float result = 0f;
for(int i = 0; i < itemsV.size(); i++){
if(isKG){
result += itemsV.elementAt(i).w.weightInkg/itemsV.size();
}else{
result += itemsV.elementAt(i).w.getPounds()/itemsV.size();
}
}
return result;
}
/**
* Checks if the date and the items in this category have the same year.
* @param date the date to check.
* @return true if the same year and false otherwise.
**/
public boolean isSameYear(Date date){
return isSameField(date,Calendar.YEAR);
}
public boolean isSameMonth(Date date){
return isSameField(date,Calendar.MONTH);
}
public boolean isSameWeek(Date date){
return isSameField(date,Calendar.WEEK_OF_YEAR);
}
public boolean isSameDay(Date date){
return isSameField(date,Calendar.DAY_OF_MONTH);
}
/**
* Returns true if the dates have the same field.
* @param date the date to check against the first element in this category.
* @param field the field to check against like Calendar.MONTH
* @return true if the date has the same field and false otherwise.
**/
public boolean isSameField(Date date, int field){
if(itemsV.size() > 0){
Calendar cal = getCal(itemsV.elementAt(0).date);
Calendar cal2 = getCal(date);
int fieldResult = cal.get(field);
int field2Result = cal2.get(field);
if(fieldResult == field2Result){
return true;
}
}
return false;
}
private Calendar getCal(Date date){
Calendar cal = Calendar.getInstance();
cal.setTime(date);
return cal;
}
}
protected class Item{
public Weight w;
public Date date;
public Item(Weight w, Date date){
this.w = w;
this.date = date;
}
}
// ============= Static Methods ============== //
}
/*
* Local variables:
* c-indent-level: 4
* c-basic-offset: 4
* End:
*
* vim: ts=8 sts=4 sw=4 noexpandtab
*/