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