com.ess.tudarmstadt.de.sleepsense.mgraph.SleepEstimGPlotFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.ess.tudarmstadt.de.sleepsense.mgraph.SleepEstimGPlotFragment.java

Source

/* 
 * Copyright (C) 2014 TU Darmstadt, Hessen, Germany.
 * Department of Computer Science Databases and Distributed Systems
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.ess.tudarmstadt.de.sleepsense.mgraph;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map.Entry;

import android.content.Intent;
import android.graphics.Color;
import android.graphics.Paint.Align;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.ess.tudarmstadt.de.sleepsense.R;
import com.ess.tudarmstadt.de.sleepsense.database.CookTraffic;
import com.ess.tudarmstadt.de.sleepsense.database.LocalTransformationDBMS;
import com.ess.tudarmstadt.de.sleepsense.database.TrafficData;
import com.ess.tudarmstadt.de.sleepsense.systemmonitor.SensorsMeterService;
import com.ess.tudarmstadt.de.sleepsense.utils.UtilsTools;
import com.jjoe64.graphview.BarGraphView;
import com.jjoe64.graphview.CustomLabelFormatter;
import com.jjoe64.graphview.GraphView;
import com.jjoe64.graphview.GraphView.GraphViewData;
import com.jjoe64.graphview.GraphViewDataInterface;
import com.jjoe64.graphview.GraphViewSeries;
import com.jjoe64.graphview.GraphViewSeries.GraphViewSeriesStyle;
import com.jjoe64.graphview.LineGraphView;
import com.jjoe64.graphview.ValueDependentColor;

/**
 * @author HieuHa
 * 
 */
public class SleepEstimGPlotFragment extends Fragment {

    private static final String TAG = SleepEstimGPlotFragment.class.getSimpleName();
    private View rootView;

    // private ArrayList<GraphViewData> data_line;
    // private ArrayList<GraphViewData> data_bar;

    private static String sleepGrpTitle = "Sleep Pattern";
    private boolean sleepIsBar = true;

    public static final int SLEEP_THREHOLD = 26; // %

    private HashMap<Double, Integer> sleepPrbly;
    private ArrayList<TrafficData> sleepDiary;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.sleep_estim_graph_fragment, container, false);

        Log.e(TAG, ": onCreateView");

        return rootView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setHasOptionsMenu(true);

        // initialize probability
        calcPrbly();

        Button cookBtn = (Button) rootView.findViewById(R.id.cook_up);
        cookBtn.setVisibility(View.GONE);
        cookBtn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                CookTraffic mCook = new CookTraffic(getActivity().getApplicationContext());
                mCook.cookUp();
            }
        });

        Button refrBtn = (Button) rootView.findViewById(R.id.refresh_btn);
        refrBtn.setVisibility(View.GONE);
        refrBtn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                redrawCharts(getCurrentDate());
            }
        });

        Button clearDB = (Button) rootView.findViewById(R.id.clear_all);
        clearDB.setVisibility(View.GONE);
        clearDB.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // clearAllCharts();
                // clearDb();

            }
        });

        // data_line = new ArrayList<GraphViewData>();
        // data_bar = new ArrayList<GraphViewData>();

        TextView atDate = (TextView) rootView.findViewById(R.id.at_date);
        atDate.setText(getCurrentDate());

        Button backBtn = (Button) rootView.findViewById(R.id.date_back);
        backBtn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                dateBackAndForth(true);
            }
        });

        Button forthBtn = (Button) rootView.findViewById(R.id.date_next);
        forthBtn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                dateBackAndForth(false);

            }
        });

        redrawCharts(getDate(-2, getCurrentDate()));

    }

    @Override
    public void onResume() {
        super.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
    }

    private void calcPrbly() {
        sleepPrbly = new HashMap<Double, Integer>();
        LocalTransformationDBMS transformationDB = new LocalTransformationDBMS(
                getActivity().getApplicationContext());
        transformationDB.open();
        sleepDiary = transformationDB.getAllSleepData();
        transformationDB.close();

        ArrayList<Double> timeSleep = new ArrayList<Double>();
        ArrayList<Double> timeWake = new ArrayList<Double>();
        double firstSleepTime = Double.MAX_VALUE;
        double lastWakeTime = 0.0d;
        if (!sleepDiary.isEmpty()) {
            for (int i = 0; i < sleepDiary.size(); i++) {
                // populate the list of sleep time
                double aSleep = Math.floor(sleepDiary.get(i).getxValue() * 10.0) / 10.0;
                double aWake = Math.floor(sleepDiary.get(i).getyValue() * 10.0) / 10.0;
                timeSleep.add(aSleep);
                timeWake.add(aWake);

                if (aSleep < firstSleepTime)
                    firstSleepTime = aSleep;
                if (aWake > lastWakeTime)
                    lastWakeTime = aWake;
            }
        } else {
            return;
        }

        double x = firstSleepTime;
        while (x < lastWakeTime) {
            int count = 0;
            for (int j = 0; j < timeSleep.size(); j++) {
                if (x >= timeSleep.get(j)) {
                    count++;
                }
            }
            for (int z = 0; z < timeWake.size(); z++) {
                if (x >= timeWake.get(z)) {
                    count--;
                }
            }
            sleepPrbly.put(x, count);
            x = nextTenMinOf(x);
        }

        //      Log.e(TAG, sleepPrbly.toString());
    }

    private void clearAllCharts() {
        // clearChart(firstGrpTitle);
        // clearChart(secondGrpTitle);
    }

    private void clearDb() {
        // clear all DBs
        // initialize database
        LocalTransformationDBMS transformationDB = new LocalTransformationDBMS(
                getActivity().getApplicationContext());
        transformationDB.open();
        transformationDB.deleteAllTrafficRecords();
        transformationDB.close();
    }

    private void dateBackAndForth(boolean back) {
        TextView atDate = (TextView) rootView.findViewById(R.id.at_date);
        String newDate = atDate.getText().toString();
        if (back) {
            newDate = getDate(-1, atDate.getText().toString());
        } else {
            newDate = getDate(1, atDate.getText().toString());
        }

        redrawCharts(newDate);
    }

    private void redrawCharts(String newDate) {
        // update data according to date from database
        ArrayList<GraphViewData> sleep_data = updateTrafficOnDate(newDate, SensorsMeterService.sleepId);

        TextView atDate = (TextView) rootView.findViewById(R.id.at_date);
        atDate.setText(newDate);
        drawChart(sleep_data, sleepGrpTitle, R.id.sleep_pattern, sleepIsBar);

        double aSleep = 0.0d;
        double aWake = 0.0d;
        if (!sleepDiary.isEmpty()) {
            for (int i = 0; i < sleepDiary.size(); i++) {
                String aDate = sleepDiary.get(i).getTrafficDate();

                if (aDate.equals(newDate)) {
                    aSleep = Math.floor(sleepDiary.get(i).getxValue() * 10.0) / 10.0;
                    aWake = Math.floor(sleepDiary.get(i).getyValue() * 10.0) / 10.0;
                }
            }
            String nextDate = getNextDay(newDate);
            for (int j = 0; j < sleepDiary.size(); j++) {
                String nextTimeOnDb = sleepDiary.get(j).getTrafficDate();
                if (nextDate.equals(nextTimeOnDb)) {
                    double nSleep = Math.floor(sleepDiary.get(j).getxValue() * 10.0) / 10.0;
                    double nWake = Math.floor(sleepDiary.get(j).getyValue() * 10.0) / 10.0;

                    if (nSleep < 20.0) {
                        aSleep = nSleep;
                        aWake = nWake;
                        break;
                    }
                }
            }
        }
        TextView sleepTruth = (TextView) rootView.findViewById(R.id.sleep_truth_txt);
        sleepTruth.setText(new DecimalFormat("00.00").format(aSleep).replaceAll("\\,", ":") + " - "
                + new DecimalFormat("00.00").format(aWake).replaceAll("\\,", ":"));
    }

    /** get the next day after the date */
    private String getNextDay(String date) {
        Log.e(TAG, "Date:" + date);
        String nextDay = "";

        Calendar c = Calendar.getInstance();
        SimpleDateFormat sdfDate = new SimpleDateFormat("dd-MM-yyyy");
        try {
            Date now = sdfDate.parse(date);
            c.setTime(now);
            c.add(Calendar.DATE, 1);
            nextDay = sdfDate.format(c.getTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Log.e(TAG, "nextDay=" + nextDay);
        return nextDay;
    }

    private ArrayList<GraphView.GraphViewData> updateTrafficOnDate(String date, int type) {
        String nextDay = getDate(1, date);

        // initialize database
        LocalTransformationDBMS transformationDB = new LocalTransformationDBMS(
                getActivity().getApplicationContext());
        transformationDB.open();
        ArrayList<TrafficData> sensorSleepEstimate = transformationDB.getTrafficsBetweenDate(date, nextDay, type);
        // close database
        transformationDB.close();

        // initialize graph data (x-axis is time line & y-axis is value of sleep
        // in percent)
        ArrayList<GraphViewData> data = new ArrayList<GraphViewData>();

        // sensor estimate each minute - each TrafficData - the percent of sleep
        // probability
        // for 45min long with no motion from the device, so each minute add up
        // 10/4.5 percentage
        double addP = 0.0d;
        for (TrafficData t : sensorSleepEstimate) {
            if (t.getyValue() >= 0.4) // no motion
                addP += 10.0 / 4.5;
            else
                addP = 0.0;

            int slpPrbSize = sleepPrbly.size();
            double ex = 0.0d;
            for (Entry<Double, Integer> e : sleepPrbly.entrySet()) {
                if (t.getxValue() >= e.getKey() && t.getxValue() < nextTenMinOf(e.getKey())) {
                    ex = e.getValue();
                }
            }
            addP = (addP + ((ex / slpPrbSize) * 100)) / 2;

            if (addP > 100) {
                addP = 100;
            }
            // for the time range from 19.59 to 23.59 add 100 to double data
            // and for the time range from 0.00 to 10.59 add 200 to double data,
            // by that we make sure the time line begin at 19.59 and end at
            // 10.59
            // of the next day
            double x_axis = t.getxValue();
            if (t.getxValue() < 11.0)
                x_axis += 200;
            else if (t.getxValue() >= 19.59)
                x_axis += 100;

            GraphViewData x = new GraphViewData(x_axis, addP);
            data.add(x);
            //         Log.e(TAG, "y-Val=" + t.getyValue() + " --> " + addP);
        }

        return data;
    }

    /**
     * return the next 10min of time convert in double (00.00)
     * 
     * @param time
     * @return
     */
    private double nextTenMinOf(double time) {
        double x = Math.round((time + 0.10) * 100.00) / 100.00;

        if (x >= Math.floor(x) + 0.60)
            // increase by one hour if x -> minute 60
            x = Math.floor(x + 1.00);

        return x;
    }

    private void drawChart(ArrayList<GraphViewData> data_line, String title, int graphR_id, boolean isBar) {
        if (data_line.size() > 0) {
            GraphViewData[] dataList = new GraphViewData[data_line.size()];
            for (int i = 0; i < data_line.size(); i++) {
                dataList[i] = data_line.get(i);
            }
            GraphViewSeriesStyle seriesStyle = new GraphViewSeriesStyle();
            seriesStyle.setValueDependentColor(new ValueDependentColor() {
                @Override
                public int get(GraphViewDataInterface data) {
                    // the higher the more green 
                    //               return Color.rgb((int) ((75 / 255) * ((data.getY() / 50))),
                    //                     (int) (255 * (data.getY() / 100)), 50);

                    // the higher the more green (better color)
                    float hue = Float.valueOf(String.valueOf(data.getY() * 120 / SLEEP_THREHOLD));
                    return Color.HSVToColor(new float[] { hue, 1f, 0.5f });

                    // if (data.getY() > SLEEP_THREHOLD){
                    // return Color.GREEN;
                    // }
                    // else if (data.getY() > 30)
                    // return Color.YELLOW;
                    // return Color.RED;
                }
            });

            GraphViewSeries gvs_series = new GraphViewSeries("Sleep Pattern", seriesStyle, dataList);

            createGraph(title, gvs_series, graphR_id, isBar);
        } else {
            // clear Chart
            GraphViewData[] dataList = new GraphViewData[1];
            dataList[0] = new GraphViewData(0.0, 0.0);
            GraphViewSeries gvs_series = new GraphViewSeries(dataList);
            createGraph(title, gvs_series, graphR_id, isBar);
        }
    }

    private void createGraph(String graphTitle, GraphViewSeries series, final int Rid, boolean isBarChart) {
        GraphView graphView = null;

        if (isBarChart) {
            graphView = new BarGraphView(getActivity().getApplicationContext(), graphTitle);
            // ((BarGraphView) graphView).setColWidth(1.09f);
            // graphView.setVerticalLabels(new String[] { "high", "mid", "low"
            // });
            // graphView.setManualYAxisBounds(11.0d, 9.0d);
        } else {
            graphView = new LineGraphView(getActivity().getApplicationContext(), graphTitle);

        }
        // add data
        graphView.addSeries(series);
        // graphView.setScrollable(true);
        // graphView.setViewPort(0, 23);
        // optional - activate scaling / zooming
        // graphView.setScalable(true);
        // optional - legend
        // graphView.setShowLegend(true);

        graphView.setCustomLabelFormatter(new CustomLabelFormatter() {
            @Override
            public String formatLabel(double axis_value, boolean isValueX) {
                if (isValueX) {
                    // X-Axis
                    // decompose x_axis from adding up before
                    double value = axis_value;
                    if (axis_value >= 200) {
                        value = axis_value - 200;
                    } else if (axis_value >= 100)
                        value = axis_value - 100;

                    // convert (double) hour.mm to hour:mm
                    // make sure not have smth like 4:60 or 11:83 in the time frame!
                    double whole = value;
                    double fractionalPart = value % 1;
                    double integralPart = value - fractionalPart;
                    if (fractionalPart >= 0.60) {
                        whole = integralPart + 1.0d + (fractionalPart - 0.60);
                    }

                    return new DecimalFormat("00.00").format(whole).replaceAll("\\,", ":");
                } else {
                    // Y-Axis
                    return ""; //new DecimalFormat("#0.0").format(axis_value);
                }
            }
        });

        graphView.getGraphViewStyle().setNumVerticalLabels(4);
        graphView.getGraphViewStyle().setNumHorizontalLabels(0); //AUTO
        graphView.getGraphViewStyle().setTextSize(17f);
        graphView.getGraphViewStyle().setVerticalLabelsAlign(Align.CENTER);
        graphView.getGraphViewStyle().setVerticalLabelsWidth(0);
        graphView.getGraphViewStyle().setGridColor(Color.WHITE);

        LinearLayout layout = (LinearLayout) rootView.findViewById(Rid);
        layout.removeAllViews();
        layout.addView(graphView);
        rootView.postInvalidate();
        layout.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                openBig();
            }
        });

    }

    private void openBig() {
        Intent i = new Intent(this.getActivity().getApplicationContext(), SleepEstimGPlotBigActivity.class);
        String date = ((TextView) rootView.findViewById(R.id.at_date)).getText().toString();
        i.putExtra("Timy", date);
        i.putExtra("lineGraphTitle", sleepGrpTitle);
        i.putExtra("lineGraphType", SensorsMeterService.sleepId);
        i.putExtra("isFirstBarType", sleepIsBar);
        this.getActivity().startActivity(i);
    }

    /**
     * 
     * @param i
     *            0, 1 or -1
     * @return current, next or prev date on database
     */
    private String getDate(int i, String currentDate) {
        ArrayList<String> avalDate = new ArrayList<String>();
        LocalTransformationDBMS transformationDB = new LocalTransformationDBMS(
                getActivity().getApplicationContext());
        transformationDB.open();
        avalDate = transformationDB.getAllAvalDate();
        transformationDB.close();
        if (avalDate.isEmpty()) {
            Log.e(TAG, "no data available!!");
            avalDate.add(getCurrentDate());
        }
        int x = avalDate.indexOf(currentDate);

        if (i == -2) {
            Calendar c = Calendar.getInstance();
            int hour_of_day = c.get(Calendar.HOUR_OF_DAY);
            if (hour_of_day < 20 && avalDate.size() >= 2)
                return avalDate.get(avalDate.size() - 2);

            return avalDate.get(avalDate.size() - 1); // last date (special case)
        }

        if (x >= 0) {
            if (i == 1 && x < avalDate.size() - 1)
                return avalDate.get(x + i);

            if (i == -1 && x > 0)
                return avalDate.get(x + i);
        } else {
            if (i == -1) {
                return avalDate.get(avalDate.size() - 1); // last date
            }
            if (i == -1) {
                return avalDate.get(0); // last date
            }
        }

        return currentDate;

    }

    private static String getCurrentDate() {
        SimpleDateFormat sdfDate = new SimpleDateFormat("dd-MM-yyyy");
        Date now = new Date();
        String strDate = sdfDate.format(now);
        return strDate;
    }

    @Override
    public void onStop() {
        super.onStop();
    }
}