Best Android App InstaSquare Lite for full-size publication of photos in Instagram, Facebook, Twitter. Run the android application on PC. You can through the android emulator Droid4X.

root/trunk/rapidandroid/org.rapidandroid/src/org/rapidandroid/activity/chart/form/FormDataBroker.java @ 112

Revision 112, 15.6 KB (checked in by czue, 16 months ago)

Updating the form view to add zero values to the date range plots for histograms. Also re-added the legend back in and changed it to a line graph. Fixed a bug where charts crashed if there were no messages in the DB

Line 
1package org.rapidandroid.activity.chart.form;
2
3import java.util.Calendar;
4import java.util.Date;
5import java.util.Random;
6
7import org.json.JSONArray;
8import org.json.JSONException;
9import org.json.JSONObject;
10import org.rapidandroid.activity.chart.ChartBroker;
11import org.rapidandroid.activity.chart.JSONGraphData;
12import org.rapidandroid.activity.chart.ChartBroker.DateDisplayTypes;
13import org.rapidandroid.data.RapidSmsDBConstants;
14import org.rapidandroid.data.controller.ParsedDataReporter;
15import org.rapidsms.java.core.Constants;
16import org.rapidsms.java.core.model.Field;
17import org.rapidsms.java.core.model.Form;
18import org.rapidsms.java.core.model.Message;
19
20import android.app.Activity;
21import android.app.ProgressDialog;
22import android.database.Cursor;
23import android.database.sqlite.SQLiteDatabase;
24import android.util.Log;
25import android.webkit.WebView;
26
27public class FormDataBroker extends ChartBroker {
28        public static final int PLOT_ALL_MESSAGES_FOR_FORM = 0;
29        public static final int PLOT_NUMERIC_FIELD_VALUE = 1;
30        public static final int PLOT_NUMERIC_FIELD_ADDITIVE = 2;
31        public static final int PLOT_WORD_HISTOGRAM = 3;
32        public static final int PLOT_NUMERIC_FIELD_COUNT_HISTOGRAM = 4;
33
34        private Form mForm;
35        private Field fieldToPlot;
36        private int mPlotMethod;
37        private ProgressDialog mProgress;
38
39        public FormDataBroker(Activity parentActivity, WebView appView, Form form, Date startDate, Date endDate) {
40                super(parentActivity,appView,startDate,endDate);
41                mForm = form;
42                // by default, do all messages for form
43                mPlotMethod = PLOT_ALL_MESSAGES_FOR_FORM;
44
45                mVariableStrings= new String[mForm.getFields().length+1];
46                mVariableStrings[0] = "Messages over time";
47                for (int i = 1; i < mVariableStrings.length; i++) {
48                        Field f = mForm.getFields()[i-1];
49                        mVariableStrings[i] = f.getName();
50                }               
51        }
52
53        public void doLoadGraph() {
54                //mProgress = ProgressDialog.show(mAppView.getContext(), "Rendering Graph...", "Please Wait",true,false);
55                JSONGraphData allData  = null;
56               
57                if (fieldToPlot == null) {
58                        //we're going to do all messages over timereturn;
59                        allData = loadMessageOverTimeHistogram();
60                } else if (fieldToPlot.getFieldType().getItemType().equals("word")) {
61                        allData = loadHistogramFromField(); 
62                } else {
63                        allData = loadNumericLine(); 
64                        //data.put(loadNumericLine());
65                }
66                if (allData != null) {
67                        mGraphData = allData.getData();
68                        mGraphOptions = allData.getOptions();
69                } 
70                Log.d("FormDataBroker",mGraphData.toString());
71                Log.d("FormDataBroker",mGraphOptions.toString());               
72        }
73
74       
75        private JSONGraphData loadNumericLine() {
76                JSONObject result = new JSONObject();
77                SQLiteDatabase db = rawDB.getReadableDatabase();
78
79                String fieldcol = RapidSmsDBConstants.FormData.COLUMN_PREFIX
80                                + fieldToPlot.getName();
81                StringBuilder rawQuery = new StringBuilder();
82                rawQuery.append("select rapidandroid_message.time, " + fieldcol);
83                rawQuery.append(" from ");
84                rawQuery.append(RapidSmsDBConstants.FormData.TABLE_PREFIX
85                                + mForm.getPrefix());
86
87                rawQuery.append(" join rapidandroid_message on (");
88                rawQuery.append(RapidSmsDBConstants.FormData.TABLE_PREFIX
89                                + mForm.getPrefix());
90                rawQuery.append(".message_id = rapidandroid_message._id");
91                rawQuery.append(") ");
92               
93                if(mStartDate.compareTo(Constants.NULLDATE) != 0 && mEndDate.compareTo(Constants.NULLDATE) != 0) {
94                        rawQuery.append(" WHERE rapidandroid_message.time > '" + Message.SQLDateFormatter.format(mStartDate) + "' AND rapidandroid_message.time < '" + Message.SQLDateFormatter.format(mEndDate) + "' ");
95                }
96
97                rawQuery.append(" order by rapidandroid_message.time ASC");
98
99                // the string value is column 0
100                // the magnitude is column 1
101
102                Cursor cr = db.rawQuery(rawQuery.toString(), null);
103                int barCount = cr.getCount();
104
105                if (barCount == 0) {
106                        cr.close();
107                } else {
108                        Date[] xVals = new Date[barCount];
109                        int[] yVals = new int[barCount];
110                        cr.moveToFirst();
111                        int i = 0;
112                        do {
113                                try {
114                                        xVals[i] = Message.SQLDateFormatter.parse(cr.getString(0));
115                                        yVals[i] = cr.getInt(1);
116                                } catch (Exception ex) {
117
118                                }
119                                i++;
120                        } while (cr.moveToNext());
121
122                        // xaxis: { ticks: [0, [Math.PI/2, "\u03c0/2"], [Math.PI, "\u03c0"],
123                        // [Math.PI * 3/2, "3\u03c0/2"], [Math.PI * 2, "2\u03c0"]]},
124
125                        try {
126//                              result.put("label", fieldToPlot.getName());
127//                              result.put("data", prepareDateData(xVals, yVals));
128//                              result.put("label", fieldToPlot.getName());
129//                              result.put("lines", getShowTrue());
130//                              result.put("points", getShowTrue());
131//                              result.put("xaxis", getDateOptions());
132                                return new JSONGraphData(prepareDateData(xVals, yVals),loadOptionsForDateGraph(xVals, false) );
133                        } catch (Exception ex) {
134
135                        }
136                        finally {
137                                if (!cr.isClosed()) {
138                                        cr.close();
139                                }
140                        }
141                       
142                }
143                // either there was no data or something bad happened
144                return new JSONGraphData(getEmptyData(), new JSONObject());     
145        }
146
147       
148        private JSONArray getEmptyData() {
149                JSONArray toReturn = new JSONArray();
150                JSONArray innerArray = new JSONArray();
151                innerArray.put(0);
152                innerArray.put(0);
153                toReturn.put(innerArray);
154                return toReturn;
155        }
156
157        private JSONObject getDateOptions() {
158                JSONObject rootxaxis = new JSONObject();
159
160                try {
161                        rootxaxis.put("mode", "time");
162                } catch (Exception ex) {
163
164                }
165                return rootxaxis;
166        }
167
168        private JSONArray prepareDateHistogramData(DateDisplayTypes displayType, Date[] xvals, int[] yvals, String legend) throws JSONException {
169                JSONArray outerArray = new JSONArray();
170                JSONArray innerArray = new JSONArray();
171                int datalen = xvals.length;
172                Date prevVal = null;
173                for (int i = 0; i < datalen; i++) {
174                        Date thisVal = xvals[i];
175                        if (prevVal != null) {
176                                // add logic to fill in zeros
177                                Date nextInSeries = getNextValue(displayType, prevVal);
178                                while (isBefore(displayType, nextInSeries, thisVal))
179                                {
180                                        JSONArray elem = new JSONArray();
181                                        elem.put(nextInSeries.getTime());
182                                        elem.put(0);
183                                        innerArray.put(elem);
184                                        nextInSeries = getNextValue(displayType, nextInSeries);
185                                }
186                        }
187                        JSONArray elem = new JSONArray();
188                        elem.put(xvals[i].getTime());
189                        elem.put(yvals[i]);
190                        innerArray.put(elem);
191                        prevVal = thisVal;
192                }
193                JSONObject finalObj = new JSONObject();
194                finalObj.put("data", innerArray);
195                finalObj.put("label", legend);
196                outerArray.put(finalObj);
197                return outerArray;
198        }
199       
200        private JSONArray prepareDateData(Date[] xvals, int[] yvals) {
201                JSONArray outerArray = new JSONArray();
202                JSONArray innerArray = new JSONArray();
203                int datalen = xvals.length;
204                for (int i = 0; i < datalen; i++) {
205                        JSONArray elem = new JSONArray();
206                        elem.put(xvals[i].getTime());
207                        elem.put(yvals[i]);
208                        innerArray.put(elem);
209                }
210                outerArray.put(innerArray);
211                return outerArray;
212        }
213       
214        private JSONGraphData loadMessageOverTimeHistogram() {
215                SQLiteDatabase db = rawDB.getReadableDatabase();
216               
217                //Date firstDateFromForm = ParsedDataReporter.getOldestMessageDate(rawDB, mForm);
218                Date startDateToUse = mStartDate;
219//              if (firstDateFromForm.after(mStartDate)) {
220//                      // first date in the form is more recent than the start date, so just go with that.
221//                      startDateToUse = firstDateFromForm;
222//              }
223                DateDisplayTypes displayType = this.getDisplayType(startDateToUse, mEndDate);
224               
225                String legend = getLegendString(displayType);
226                String selectionArg = getSelectionString(displayType);
227               
228                StringBuilder rawQuery = new StringBuilder();
229               
230                rawQuery.append("select time, count(*) from  ");
231                rawQuery.append(RapidSmsDBConstants.FormData.TABLE_PREFIX + mForm.getPrefix());
232               
233                rawQuery.append(" join rapidandroid_message on (");
234                rawQuery.append(RapidSmsDBConstants.FormData.TABLE_PREFIX + mForm.getPrefix());
235                rawQuery.append(".message_id = rapidandroid_message._id");
236                rawQuery.append(") ");
237                if(startDateToUse.compareTo(Constants.NULLDATE) != 0 && mEndDate.compareTo(Constants.NULLDATE) != 0) {
238                        rawQuery.append(" WHERE rapidandroid_message.time > '" + Message.SQLDateFormatter.format(startDateToUse) + "' AND rapidandroid_message.time < '" + Message.SQLDateFormatter.format(mEndDate) + "' ");
239                }
240               
241                rawQuery.append(" group by ").append(selectionArg);             
242                rawQuery.append("order by ").append(selectionArg).append(" ASC");
243               
244       
245                // the X date value is column 0
246                // the y value magnitude is column 1
247
248                Cursor cr = db.rawQuery(rawQuery.toString(), null);
249                int barCount = cr.getCount();
250
251                if (barCount == 0) {
252                        db.close();
253                        cr.close();
254                } else {
255                        Date[] xVals = new Date[barCount];
256                        int[] yVals = new int[barCount];
257                        cr.moveToFirst();
258                        int i = 0;
259                        do {
260                                xVals[i] = getDate(displayType, cr.getString(0));
261                                yVals[i] = cr.getInt(1);
262                                i++;
263                        } while (cr.moveToNext());
264
265                        try {
266                                //result.put("label", fieldToPlot.getName());
267                                //result.put("data", prepareData(xVals, yVals));
268                                //result.put("bars", getShowTrue());
269                                //result.put("xaxis", getXaxisOptions(xVals));
270                                // todo
271                                return new JSONGraphData(prepareDateHistogramData(displayType, xVals, yVals, legend),loadOptionsForDateGraph(xVals, true) );
272                               
273                        } catch (Exception ex) {
274
275                        } finally {
276                                if (!cr.isClosed()) {
277                                       
278                                        cr.close();
279                                }
280                                if(db.isOpen()) {
281                                        db.close();
282                                }
283                        }
284                }
285                // either there was no data or something bad happened
286                return new JSONGraphData(getEmptyData(), new JSONObject());     
287        }
288       
289
290       
291       
292        /**
293         * Should return a two element array - the first element is the data,
294         * the second are the options
295         * @return
296         */
297        private JSONGraphData loadHistogramFromField() {
298                //JSONObject result = new JSONObject();
299                SQLiteDatabase db = rawDB.getReadableDatabase();
300
301                String fieldcol = RapidSmsDBConstants.FormData.COLUMN_PREFIX
302                                + fieldToPlot.getName();
303                StringBuilder rawQuery = new StringBuilder();
304                rawQuery.append("select " + fieldcol);
305                rawQuery.append(", count(*) from ");
306                rawQuery.append(RapidSmsDBConstants.FormData.TABLE_PREFIX
307                                + mForm.getPrefix());
308               
309                rawQuery.append(" join rapidandroid_message on (");
310                rawQuery.append(RapidSmsDBConstants.FormData.TABLE_PREFIX
311                                + mForm.getPrefix());
312                rawQuery.append(".message_id = rapidandroid_message._id");
313                rawQuery.append(") ");
314               
315                if(mStartDate.compareTo(Constants.NULLDATE) != 0 && mEndDate.compareTo(Constants.NULLDATE) != 0) {
316                        rawQuery.append(" WHERE rapidandroid_message.time > '" + Message.SQLDateFormatter.format(mStartDate) + "' AND rapidandroid_message.time < '" + Message.SQLDateFormatter.format(mEndDate) + "' ");
317                }
318
319               
320                rawQuery.append(" group by " + fieldcol);
321                rawQuery.append(" order by " + fieldcol);
322
323                // the string value is column 0
324                // the magnitude is column 1
325
326                Cursor cr = db.rawQuery(rawQuery.toString(), null);
327                int barCount = cr.getCount();
328
329                if (barCount != 0) {
330                        String[] xVals = new String[barCount];
331                        int[] yVals = new int[barCount];
332                        cr.moveToFirst();
333                        int i = 0;
334                        do {
335                                xVals[i] = cr.getString(0);
336                                yVals[i] = cr.getInt(1);
337                                i++;
338                        } while (cr.moveToNext());
339
340                        // xaxis: { ticks: [0, [Math.PI/2, "\u03c0/2"], [Math.PI, "\u03c0"],
341                        // [Math.PI * 3/2, "3\u03c0/2"], [Math.PI * 2, "2\u03c0"]]},
342
343                        try {
344                                //result.put("label", fieldToPlot.getName());
345                                //result.put("data", prepareData(xVals, yVals));
346                                //result.put("bars", getShowTrue());
347                                //result.put("xaxis", getXaxisOptions(xVals));
348                                return new JSONGraphData(prepareHistogramData(xVals, yVals),loadOptionsForHistogram(xVals) );
349                        } catch (Exception ex) {
350
351                        } finally {
352                                if (!cr.isClosed()) {
353                                        cr.close();
354                                }
355                                if(db.isOpen()) {
356                                        db.close();
357                                }
358                        }
359                }
360                // either there was no data or something bad happened
361                return new JSONGraphData(getEmptyData(), new JSONObject());
362        }
363
364        private JSONArray prepareHistogramData(String[] names, int[] counts) throws JSONException {
365                // TODO Auto-generated method stub
366                JSONArray arr = new JSONArray();
367                int datalen = names.length;
368                for (int i = 0; i < datalen; i++) {
369                       
370                        JSONObject elem = new JSONObject();
371                        // values will just be an array of length 1 with a single value
372                        JSONArray values = new JSONArray();
373                        JSONArray value = new JSONArray();
374                        value.put(i);
375                        value.put(counts[i]);
376                        values.put(value);
377                        elem.put("data", values);
378                        elem.put("bars", getShowTrue());
379                        elem.put("label", names[i]);
380                        arr.put(elem);
381                }
382                return arr;
383        }
384       
385        private JSONObject loadOptionsForDateGraph(Date[] vals, boolean displayLegend) throws JSONException {
386
387                JSONObject toReturn = new JSONObject();
388                //bars: { show: true }, points: { show: false }, xaxis: { mode: "time", timeformat:"%y/%m/%d" }
389                toReturn.put("bars", getShowFalse());
390                toReturn.put("lines", getShowTrue());
391                toReturn.put("points", getShowFalse());
392                toReturn.put("xaxis", getXaxisOptionsForDate());
393                if (displayLegend) {
394                        toReturn.put("legend", getShowTrue());
395                } 
396                return toReturn;
397        }
398       
399        private JSONObject getXaxisOptionsForDate() throws JSONException {
400                JSONObject toReturn = new JSONObject();
401                toReturn.put("mode", "time");
402                toReturn.put("timeformat", "%m/%d/%y");
403                return toReturn;
404        }
405
406        private JSONObject loadOptionsForHistogram(String[] labels) throws JSONException {
407               
408                JSONObject toReturn = new JSONObject();
409                toReturn.put("xaxis", this.getXaxisOptions(labels));
410                return toReturn;
411        }
412
413        // puts the yvalues into the json array for the given x values (defined by
414        // the array indices)
415        // so output format is [[x0,y0],[x1,y1]...etc]
416        // in reality is [[0,values[0]],[1,values[1], etc]
417        private JSONArray prepareData(int[] values) {
418                JSONArray arr = new JSONArray();
419                int datalen = values.length;
420                for (int i = 0; i < datalen; i++) {
421                        JSONArray elem = new JSONArray();
422                        elem.put(i);
423                        elem.put(values[i]);
424                        arr.put(elem);
425                }
426                return arr;
427        }
428
429        private JSONObject getXaxisOptions(String[] tickvalues) {
430                JSONObject rootxaxis = new JSONObject();
431                JSONArray arr = new JSONArray();
432                int ticklen = tickvalues.length;
433
434                for (int i = 0; i < ticklen; i++) {
435                        JSONArray elem = new JSONArray();
436                        elem.put(i);
437                        elem.put(tickvalues[i]);
438                        arr.put(elem);
439                }
440
441                try {
442                        rootxaxis.put("ticks", arr);
443                        rootxaxis.put("tickFormatter", "string");
444                } catch (Exception ex) {
445
446                }
447                return rootxaxis;
448        }
449
450        private JSONArray getRandomData() {
451                Random rand = new Random();
452                JSONArray arr = new JSONArray();
453                int priorval = rand.nextInt(100);
454                for (int i = 0; i < 100; i++) {
455                        JSONArray elem = new JSONArray();
456                        elem.put(i);
457                        if (rand.nextBoolean()) {
458                                priorval += rand.nextInt(10);
459                        } else {
460                                priorval -= rand.nextInt(10);
461                        }
462                        elem.put(priorval);
463                        arr.put(elem);
464                }
465                return arr;
466        }
467
468        private JSONObject getLineOptionsJSON() {
469                JSONObject ret = new JSONObject();
470                try {
471                        ret.put("show", true);
472                } catch (Exception ex) {
473
474                }
475                return ret;
476        }
477
478        private JSONObject getShowTrue() {
479                JSONObject ret = new JSONObject();
480                try {
481                        ret.put("show", true);
482                } catch (Exception ex) {
483
484                }
485                return ret;
486        }
487
488        private JSONObject getShowFalse() {
489                JSONObject ret = new JSONObject();
490                try {
491                        ret.put("show", false);
492                } catch (Exception ex) {
493
494                }
495                return ret;
496        }
497
498        public String getGraphTitle() {
499                return "my line baby";
500        }
501
502        /*
503         * (non-Javadoc)
504         *
505         * @see org.rapidandroid.activity.chart.ChartBroker#setVariable(int)
506         */
507
508        public void setVariable(int id) {
509                // TODO Auto-generated method stub
510                if(id == 0) {
511                        this.fieldToPlot = null;
512                } else {
513                        this.fieldToPlot = mForm.getFields()[id-1];
514                }
515                this.mGraphData = null;
516                this.mGraphOptions = null;
517        }
518/* (non-Javadoc)
519         * @see org.rapidandroid.activity.chart.ChartBroker#finishGraph()
520         */
521       
522        public String getName() {
523                return "graph_form";
524        }
525}
Note: See TracBrowser for help on using the browser.