package org.ohmage.charts;
import org.achartengine.chart.BarChart;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.ohmage.Utilities;
import org.ohmage.charts.HistogramBase.HistogramRenderer;
import org.ohmage.loader.PromptFeedbackLoader.FeedbackItem;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.text.format.DateUtils;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
/**
* This is a histogram which can show days on the x-axis and a value on the y-axis.
* @author cketcham
*
*/
public class Histogram extends BarChart {
private static final int MAX_DAYS = 30;
transient private HistogramBase mBase;
private int mDays = MAX_DAYS;
/**
* Construct a new Histogram object with the given values.
*
* @param context
* @param renderer A renderer can be specified
* @param data must be an array and have an entry for each day. The last entry
* in the array is the value for 'today'. The second to last entry should be
* 'yesterday' etc.
* @param maxDays
*/
public Histogram(Context context, HistogramRenderer renderer, List<FeedbackItem> data, int maxDays) {
super(buildDataSet(data, maxDays), (renderer != null ? renderer : new HistogramRenderer(context)), BarChart.Type.DEFAULT);
mBase = new HistogramBase(this);
mBase.fitData();
mBase.setDateFormat("MMM d");
}
public Histogram(Context context, HistogramRenderer renderer, List<FeedbackItem> data) {
this(context, renderer, data, MAX_DAYS);
}
public Histogram(Context context, List<FeedbackItem> data) {
this(context, null, data);
}
/**
* This has the same functionality as the super class, except it calls getDateLabel
* instead of just getLabel which will format the label as a date
* {@inheritDoc}
*/
@Override
protected void drawXLabels(List<Double> xLabels, Double[] xTextLabelLocations, Canvas canvas,
Paint paint, int left, int top, int bottom, double xPixelsPerUnit, double minX,double maxX) {
mBase.drawXLabels(xLabels, xTextLabelLocations, canvas, paint, left, top, bottom, xPixelsPerUnit, minX, maxX);
}
/**
* Builds a dataset with dates as the x value and the value as the y value.
* It will parse the points and show the maximum for each day
*
* @param data
* @return dataset
*/
private static XYMultipleSeriesDataset buildDataSet(List<FeedbackItem> data, int days) {
XYMultipleSeriesDataset dataSet = new XYMultipleSeriesDataset();
XYSeries series = new XYSeries("");
Double[] values = new Double[days];
Arrays.fill(values, 0.0);
Calendar calendar = Calendar.getInstance();
Utilities.clearTime(calendar);
calendar.add(Calendar.DATE, 1);
long today = calendar.getTimeInMillis();
for(FeedbackItem item : data) {
if(item.time > today - DateUtils.DAY_IN_MILLIS * days) {
calendar.setTimeInMillis(item.time);
Utilities.clearTime(calendar);
int idx = (int) ((today - calendar.getTimeInMillis()) / DateUtils.DAY_IN_MILLIS) - 1;
values[idx] = Math.max(values[idx], item.value);
}
}
for(int i=0;i<values.length;i++) {
series.add(-i, values[i]);
}
dataSet.addSeries(series);
return dataSet;
}
/**
* Sets the number of days that will be shown for this histogram
* @param days
*/
public void setTimeRange(int days) {
mDays = days;
}
}