Tizen 2.1 base
[samples/web/ExercisePlanner.git] / js / app.timeRange.js
1 /*jslint devel: true*/
2 /*global $, ExercisePlanner: true*/
3 /**
4  *
5  */
6 (function () {
7         "use strict";
8         ExercisePlanner.prototype.checkNewTimeRange = function (start, duration, style) {
9                 console.log('ExercisePlanner_checkNewTimeRange', start, duration, style);
10                 var result = [];
11                 // check start / stop
12                 /*
13                  * deprecated if (start >= stop) { result.push({ name: 'Start time is greater or equal than
14                  * stop time.', code: 1 }); }
15                  */
16
17                 if (!start) {
18                         result.push({
19                                 name: 'Start time is not set.',
20                                 code: 2
21                         });
22                 }
23
24                 if (duration < 1 || duration > 24) {
25                         result.push({
26                                 name: 'Duration is not set properly.',
27                                 code: 2
28                         });
29                 }
30
31                 /*
32                  * deprecated if (!stop) { result.push({ name: 'Stop time is not set.', code: 3 }); }
33                  */
34                 return result;
35         };
36
37         /**
38          * Sort method for time ranges;
39          */
40         ExercisePlanner.prototype.sortTimeRanges = function () {
41                 console.log('ExercisePlanner_sortTimeRanges');
42                 this.config.timesRanges.sort(function (a, b) {
43                         return a.start - b.start;
44                 });
45         };
46
47         /**
48          * Find and return max value of nr in time ranges array;
49          * @returns {Number}
50          */
51         ExercisePlanner.prototype.getMaxNrOfTimeRange = function getMaxNrOfTimeRange() {
52                 var maxNr = -1, i, len = this.config.timesRanges.length;
53                 for (i = 0; i < len; i += 1) {
54                         if (maxNr < this.config.timesRanges[i].nr) {
55                                 maxNr = this.config.timesRanges[i].nr;
56                         }
57                 }
58                 return maxNr;
59         };
60
61         /**
62          *
63          * @param nr
64          * @returns {Boolean}
65          */
66         ExercisePlanner.prototype.getTimeRangeByNr = function getTimeRangeByNr(nr) {
67                 var result = this.config.timesRanges.filter(function (item) {
68                                 return (item.nr === nr);
69                         });
70                 return result[0];
71         };
72
73         /**
74          * Save time range
75          *
76          * @param nr
77          * @param start
78          * @param duration
79          * @param style
80          * @param enabled
81          * @returns {Boolean}
82          */
83         ExercisePlanner.prototype.saveTimeRange = function (nr, timeRange) {
84                 console.log('ExercisePlanner_saveTimeRange', nr, timeRange);
85                 var index = -1,
86                         errors = this.checkNewTimeRange(timeRange.start, timeRange.duration, timeRange.style);
87                 console.log(errors);
88
89                 // new timeRanges has nr === -1; this mean we must get max number from config
90                 if (nr === -1) {
91                         nr = this.getMaxNrOfTimeRange() + 1;
92                 } else {
93                         index = this.config.timesRanges.indexOf(this.getTimeRangeByNr(nr));
94                 }
95
96                 timeRange.nr = nr;
97
98                 if (errors.length > 0) {
99                         this.ui.showErrors(errors);
100                         return false;
101                 }
102
103                 if (index !== -1) {
104                         this.config.timesRanges[index] = timeRange;
105                 } else {
106                         this.config.timesRanges.push(timeRange);
107                 }
108
109                 this.sortTimeRanges();
110                 this.saveConfig();
111                 this.ui.fillTimesRanges(this.config.timesRanges);
112                 this.generateAlarms();
113                 this.updateGraph();
114
115                 return true;
116         };
117
118         /**
119          *
120          * @param {nymber}
121          * @returns {number}
122          */
123         ExercisePlanner.prototype.editTimeRange = function editTimeRange(nr) {
124                 var timeRange = this.getTimeRangeByNr(nr);
125
126                 if (timeRange !== undefined) {
127                         this.currentEditingTimePeriod = timeRange;
128                         this.currentEditingTimePeriodId = timeRange.nr;
129                 } else {
130                         this.currentEditingTimePeriod = {
131                                 nr: -1,
132                                 start: 10,
133                                 duration: 1,
134                                 stop: 11,
135                                 enabled: true,
136                                 style: 'everyday'
137                         };
138                         this.currentEditingTimePeriodId = -1;
139                 }
140                 return this.currentEditingTimePeriodId;
141         };
142
143         /**
144          * Delete time range by number on list
145          *
146          * @param nr
147          * @returns {Boolean}
148          */
149         ExercisePlanner.prototype.deleteTimeRange = function (nr) {
150                 console.log('ExercisePlanner_deleteTimeRange', nr);
151
152                 var index,
153                         timeRange = this.getTimeRangeByNr(nr);
154
155                 if (timeRange === undefined) {
156                         return false;
157                 }
158
159                 index = this.config.timesRanges.indexOf(timeRange);
160                 if (index === -1) {
161                         return false;
162                 }
163
164                 // delete time range from array;
165                 this.config.timesRanges.splice(index, 1);
166
167                 this.saveConfig();
168                 this.ui.fillTimesRanges(this.config.timesRanges);
169                 this.generateAlarms();
170                 // update time periods on graph;
171                 this.ui.graphSchedule.setTimeRanges(this.periodsWeekToBoolArray());
172                 this.ui.graphSchedule.refresh();
173
174                 this.updateGraph();
175                 this.showNextAlarm();
176                 return true;
177         };
178
179         /**
180          * Disable time range by number on list
181          *
182          * @param nr
183          * @returns {Boolean}
184          */
185         ExercisePlanner.prototype.disableTimeRange = function (nr) {
186                 console.log('ExercisePlanner_disableTimeRange', nr);
187                 var timeRange = this.getTimeRangeByNr(nr);
188
189                 if (timeRange === undefined) {
190                         return false;
191                 }
192
193                 timeRange.enabled = !timeRange.enabled;
194
195                 this.saveConfig();
196                 this.ui.fillTimesRanges(this.config.timesRanges);
197                 this.generateAlarms();
198                 // update time periods on graph;
199                 this.ui.graphSchedule.setTimeRanges(this.periodsWeekToBoolArray());
200                 this.ui.graphSchedule.refresh();
201
202                 this.updateGraph(this.config.currentTypeOfPeriods);
203                 this.showNextAlarm();
204                 return true;
205         };
206
207         /**
208          * Combines a overlapped time periods & delete not necesary
209          * This method modifies exisiting array in cache.
210          *
211          * @param periods
212          * @returns
213          */
214         ExercisePlanner.prototype.mergeOverlapPeriods = function mergeOverlapPeriods(periods) {
215                 var i, len = periods.length, wasOverlap = true, mergePeriod;
216
217                 periods.sort(function (a, b) {
218                         return a - b;
219                 });
220
221                 if (len < 2) {
222                         return periods;
223                 }
224
225                 while (wasOverlap) {
226                         wasOverlap = false;
227                         len = periods.length;
228                         for (i = 0; i < len - 1; i += 1) {
229                                 if (periods[i].stop > periods[i + 1].start) {
230                                         mergePeriod = $.extend({}, periods[i]);
231                                         if (mergePeriod.stop < periods[i + 1].stop) {
232                                                 mergePeriod.stop = periods[i + 1].stop;
233                                                 mergePeriod.duration = mergePeriod.stop - mergePeriod.start;
234                                         }
235                                         mergePeriod.nr = -1;
236                                         periods.splice(i, 2, mergePeriod);
237                                         wasOverlap = true;
238                                         break;
239                                 }
240                         }
241                 }
242
243                 return periods;
244         };
245
246         ExercisePlanner.prototype.mergePeriods = function mergePeriods() {
247                 console.log('ExercisePlanner_mergePeriods');
248                 var i, len, onlyEveryDay = true,
249                         ranges = this.config.timesRanges,
250                         result = {
251                                 everyday : [],
252                                 weekend: [],
253                                 workday: []
254                         };
255
256                 // checking time ranges for different to the "everyday"
257                 for (i = 0, len = ranges.length; i < len; i += 1) {
258                         if (ranges[i].style !== 'everyday') {
259                                 onlyEveryDay = false;
260                                 break;
261                         }
262                 }
263
264                 if (onlyEveryDay) {
265                         for (i = 0, len = this.config.timesRanges.length; i < len; i += 1) {
266                                 if (this.config.timesRanges[i].enabled) {
267                                         result.everyday.push(this.config.timesRanges[i]);
268                                 }
269                         }
270                 } else {
271                         // divide 'everyday' periods at workday/weekend
272                         for (i = 0, len = this.config.timesRanges.length; i < len; i += 1) {
273                                 // if time range is disabled do not append to cache;
274                                 if (this.config.timesRanges[i].enabled) {
275                                         switch (this.config.timesRanges[i].style) {
276                                         case 'everyday':
277                                                 result.workday.push(this.config.timesRanges[i]);
278                                                 result.weekend.push(this.config.timesRanges[i]);
279                                                 break;
280                                         case 'workday':
281                                                 result.workday.push(this.config.timesRanges[i]);
282                                                 break;
283                                         case 'weekend':
284                                                 result.weekend.push(this.config.timesRanges[i]);
285                                                 break;
286                                         }
287                                 }
288                         }
289                 }
290
291                 // check and correct overlaped time periods
292                 this.mergeOverlapPeriods(result.everyday);
293                 this.mergeOverlapPeriods(result.workday);
294                 this.mergeOverlapPeriods(result.weekend);
295
296                 return result;
297         };
298
299         ExercisePlanner.prototype.getSummaryAvailableTime = function getSummaryAvailableTime() {
300                 console.log('ExercisePlanner_getSummaryAvailableTime');
301                 var i, len,
302                         periods = this.cache.periodsWeek,
303                         sum = {
304                                 weekend: 0,
305                                 workday: 0,
306                                 everyday: 0
307                         };
308
309                 for (i = 0, len = periods.everyday.length; i < len; i += 1) {
310                         if (periods.everyday[i].enabled) {
311                                 sum.everyday += periods.everyday[i].duration;
312                         }
313                 }
314                 for (i = 0, len = periods.workday.length; i < len; i += 1) {
315                         if (periods.workday[i].enabled) {
316                                 sum.workday += periods.workday[i].duration;
317                         }
318                 }
319                 for (i = 0, len = periods.weekend.length; i < len; i += 1) {
320                         if (periods.weekend[i].enabled) {
321                                 sum.weekend += periods.weekend[i].duration;
322                         }
323                 }
324
325                 return sum;
326         };
327
328         ExercisePlanner.prototype.findNearestTimeRange = function (hour, ranges) {
329                 console.log('ExercisePlanner_findNearestTimeRange', hour, ranges);
330                 var nearResult,
331                         result = {
332                                 requestedHour: hour,
333                                 optimalHour: -1
334                         };
335
336                 if (!ranges.length) {
337                         return result;
338                 }
339
340                 /**
341                  * Function search ranges of time for nearest to a hour
342                  */
343                 nearResult = ranges.reduce(function (previous, element, index) {
344                         var delta = 0;
345
346                         if (element.start < hour && element.stop < hour) {
347                                 delta = hour - element.stop;
348                         }
349
350                         if (element.start > hour && element.stop > hour) {
351                                 delta = element.start - hour;
352                         }
353
354                         return (delta < previous.delta) ? { index: index, delta: delta } : previous;
355                 }, { index: -1, delta: 100 });
356
357                 if (ranges[nearResult.index].start <= hour && ranges[nearResult.index].stop >= hour) {
358                         result.optimalHour = Math.round((ranges[nearResult.index].start + ranges[nearResult.index].stop) / 2);
359                 } else {
360                         result.optimalHour = (ranges[nearResult.index].start > hour) ? ranges[nearResult.index].start : ranges[nearResult.index].stop;
361                 }
362
363                 return result;
364         };
365
366         /**
367          * Export time period to array of boolen [boolean x 24]
368          * @returns {object}
369          */
370         ExercisePlanner.prototype.periodsWeekToBoolArray = function periodsWeekToBoolArray() {
371                 var i, j, len, periods,
372                         result = {
373                                 workday: [],
374                                 weekend: []
375                         };
376
377                 // fill default result;
378                 for (i = 0; i < 24; i += 1) {
379                         result.workday[i] = false;
380                         result.weekend[i] = false;
381                 }
382
383                 // set values;
384                 periods = this.cache.periodsWeek.everyday;
385                 len = periods.length;
386                 for (i = 0; i < len; i += 1) {
387                         for (j = periods[i].start; j < periods[i].start + periods[i].duration; j += 1) {
388                                 result.workday[j] = true;
389                                 result.weekend[j] = true;
390                         }
391                 }
392
393                 // set values;
394                 periods = this.cache.periodsWeek.workday;
395                 len = periods.length;
396                 for (i = 0; i < len; i += 1) {
397                         for (j = periods[i].start; j < periods[i].start + periods[i].duration; j += 1) {
398                                 result.workday[j] = true;
399                         }
400                 }
401
402                 // set values;
403                 periods = this.cache.periodsWeek.weekend;
404                 len = periods.length;
405                 for (i = 0; i < len; i += 1) {
406                         for (j = periods[i].start; j < periods[i].start + periods[i].duration; j += 1) {
407                                 result.weekend[j] = true;
408                         }
409                 }
410                 return result;
411         };
412
413
414 }());
415