Tizen 2.1 base
[samples/web/ExercisePlanner.git] / js / app.js
1 /*jslint browser: true, devel: true */
2 /*global tizen, $, app, localStorage, Audio, document, unlockScreen, UI */
3 var ExercisePlanner = function () {
4         "use strict";
5 };
6
7 (function () {
8         "use strict";
9
10         ExercisePlanner.prototype = {
11                 /**
12                  * Definition of time for sleep
13                  */
14                 TIME_OF_SLEEP: 8,
15
16                 /**
17                  * Definition one day in hours
18                  */
19                 ONE_DAY: 24,
20
21                 /**
22                  * Stored time of application start
23                  */
24                 applicationStartTime: new Date(),
25
26                 /**
27                  * Cofiguration data will saved for next launch;
28                  * There are default values after install;
29                  */
30                 config: {
31
32                         frequency: {
33                                 workday: 3, // 6 for test
34                                 weekend: 3
35                         },
36
37                         strength: {
38                                 workday: 1,
39                                 weekend: 1
40                         },
41
42                         /**
43                          * List of workouts;
44                          * - timeRanges:style [ everyday, weekend, workday ]; ( workday : mon-fri )
45                          */
46                         exercises: [{
47                                 name: 'bends',
48                                 enabled: true
49                         }, {
50                                 name: 'squats',
51                                 enabled: true
52                         }, {
53                                 name: 'push-ups',
54                                 enabled: false
55                         }],
56
57                         // deprecated for this version;
58                         increasingStrength: true,
59
60                         /**
61                          * Default time ranges
62                          */
63                         timesRanges: [{
64                                 nr: 0,
65                                 start: 8,
66                                 stop: 16,
67                                 duration: 8,
68                                 enabled: true,
69                                 style: 'everyday'
70                         }, {
71                                 nr: 1,
72                                 start: 18,
73                                 stop: 22,
74                                 duration: 4,
75                                 enabled: true,
76                                 style: 'weekend'
77                         }],
78
79                         nearestExercise: -1,
80
81                         count: 0,
82
83                         trainingEnabled: false
84                 },
85                 alarms: {
86                         everyday: [],
87                         workday: [],
88                         weekend: []
89                 },
90
91                 /**
92                  * Used for update GraphSchedule;
93                  * [ workday / weekend ]
94                  */
95                 currentTypeOfPeriods: 'workday',
96                 /**
97                  * Use on form to edit time period;
98                  */
99                 currentEditingTimePeriod: null,
100                 currentEditingTimePeriodId: -1,
101
102                 /**
103                  * Date when alarm will start generating
104                  */
105                 beginDate: null,
106
107                 /**
108                  * use store temporary data for alarms;
109                  */
110                 cache: {},
111
112                 /**
113                  * HTML5 audio element for play audio when alarm is called
114                  */
115                 audioOfAlert: null,
116
117                 /**
118                  * Instance of User Interface
119                  */
120                 ui: null
121         };
122
123         /**
124          * Load configuration of application
125          * (use localStorage)
126          */
127         ExercisePlanner.prototype.loadConfig = function () {
128                 console.log('ExercisePlanner_loadConfig');
129                 var configStr = localStorage.getItem('config');
130                 if (configStr) {
131                         this.config = JSON.parse(configStr);
132                 } else {
133                         this.removeAllAlarms();
134                         this.sortTimeRanges();
135                 }
136         };
137
138         /**
139          * Save configuration of application
140          * (use localStorage)
141          */
142         ExercisePlanner.prototype.saveConfig = function () {
143                 console.log('ExercisePlanner_saveConfig');
144                 localStorage.setItem('config', JSON.stringify(this.config));
145         };
146
147         ExercisePlanner.prototype.stopTraining = function () {
148                 console.log('ExercisePlanner_stopTraining');
149                 this.removeAllAlarms();
150                 this.ui.setStatusRun(this.config.trainingEnabled);
151         };
152
153         ExercisePlanner.prototype.startTraining = function () {
154                 console.log('ExercisePlanner_startTraining');
155                 this.ui.setStatusRun(this.config.trainingEnabled);
156                 this.startAlarms();
157         };
158
159         /**
160          * Toggle start/stop alarms for workouts
161          */
162         ExercisePlanner.prototype.appStartStop = function () {
163                 console.log('ExercisePlanner_appStartStop');
164                 this.config.trainingEnabled = !this.config.trainingEnabled;
165                 if (this.config.trainingEnabled) {
166                         this.startTraining();
167                 } else {
168                         this.stopTraining();
169                 }
170                 this.saveConfig();
171         };
172
173         /**
174          * Closing application with the configuration data saving
175          */
176         ExercisePlanner.prototype.exit = function () {
177                 console.log('ExercisePlanner_exit');
178                 this.saveConfig();
179                 this.stopMusic();
180                 tizen.application.getCurrentApplication().exit();
181         };
182
183         /**
184          * Sets frequency value and calculates new alarms
185          * @param value
186          */
187         ExercisePlanner.prototype.setFrequency = function (value) {
188                 console.log('ExercisePlanner_setFrequency', value);
189                 this.config.frequency[this.config.currentTypeOfPeriods] = parseInt(value, 10);
190
191                 this.saveConfig();
192                 this.generateAlarms();
193                 this.updateGraph(this.config.currentTypeOfPeriods);
194                 this.showNextAlarm();
195         };
196
197         /**
198          * Set Strength value
199          * @param value
200          */
201         ExercisePlanner.prototype.setStrength = function (value) {
202                 console.log('ExercisePlanner_setStrength', value);
203                 this.config.strength[this.config.currentTypeOfPeriods] = parseInt(value, 10);
204                 this.saveConfig();
205         };
206
207         /**
208          * Sending array of exercises to UI for update
209          */
210         ExercisePlanner.prototype.updateExercises = function () {
211                 console.log('ExercisePlanner_updateExercises');
212                 this.ui.fillExercises(this.config.exercises);
213         };
214
215         /**
216          * Sending array of time ranges to UI for update
217          * & update graph schedule
218          */
219         ExercisePlanner.prototype.updateTimesRanges = function () {
220                 console.log('ExercisePlanner_updateTimesRanges');
221
222                 this.ui.fillTimesRanges(this.config.timesRanges);
223                 this.ui.graphSchedule.updateTimeRanges();
224         };
225
226         /**
227          * Store exercises in config (and save)
228          * @param newData
229          */
230         ExercisePlanner.prototype.saveExercises = function (newData) {
231                 console.log('ExercisePlanner_saveExercises', newData);
232                 var i, l;
233
234                 if (newData) {
235                         for (i = 0, l = newData.length; i < l; i += 1) {
236                                 this.config.exercises[i].enabled = newData[i].checked;
237                         }
238                         this.generateNearestExercise();
239                         this.saveConfig();
240                 }
241         };
242
243         /**
244          * When will earliest workout
245          * and show in UI
246          */
247         ExercisePlanner.prototype.showNextAlarm = function showNextAlarm() {
248                 console.log('ExercisePlanner_showNextAlarm');
249                 var alarms,
250                         currentDate = new Date();
251
252                 if (this.alarms.everyday.length > 0) {
253                         alarms = this.alarms.everyday;
254                 } else {
255                         alarms = (this.todayIsWorkday()) ? this.alarms.workday : this.alarms.weekend;
256                 }
257
258                 alarms = alarms.filter(function (item) {
259                         return (item.getTime() > currentDate.getTime());
260                 }).sort(function (a, b) {
261                         return a.date - b.date;
262                 });
263                 console.log(alarms);
264
265                 if (this.config.nearestExercise > -1) {
266                         this.ui.showAlarmInMonitor({
267                                 alarm: alarms[0],
268                                 exerciseName: this.config.exercises[this.config.nearestExercise].name,
269                                 numberOfTimes: this.getStrength(this.config.strength.workday, this.config.count)
270                         });
271
272                         this.config.count += 1;
273                 }
274                 this.saveConfig();
275         };
276
277         /**
278          * Change type of periods [workday/weekend] and update graph
279          * @param type
280          */
281         ExercisePlanner.prototype.changeTypeOfPeriods = function changeTypeOfPeriods(type) {
282                 if (this.config.currentTypeOfPeriods !== type) {
283                         this.config.currentTypeOfPeriods = type;
284                         this.updateGraph(this.config.currentTypeOfPeriods);
285                 }
286         };
287
288         /**
289          * Check new exercise name for duplication in existings;
290          * @param name
291          * @returns
292          */
293         ExercisePlanner.prototype.checkExerciseName = function (name) {
294                 console.log('ExercisePlanner_checkExerciseName', name);
295                 var i, l;
296
297                 if (name) {
298                         for (i = 0, l = this.config.exercises.length; i < l; i += 1) {
299                                 if (this.config.exercises[i].name === name) {
300                                         return i;
301                                 }
302                         }
303                         return -1;
304                 }
305         };
306
307         /**
308          * Add new exercise sent from UI
309          * @param name
310          * @returns {Boolean}
311          */
312         ExercisePlanner.prototype.addExercise = function (name) {
313                 console.log('ExercisePlanner_addExercise', name);
314                 if (this.checkExerciseName(name) < 0) {
315                         this.config.exercises.push({
316                                 name: name,
317                                 enabled: false
318                         });
319                         this.saveConfig();
320                         this.ui.fillExercises(this.config.exercises);
321                         return true;
322                 }
323                 this.ui.showErrors({name: 'Element exists!'});
324                 return false;
325         };
326
327         /**
328          * Get number of workouts by frequency
329          * @param value
330          * @returns {number}
331          */
332         ExercisePlanner.prototype.getNumberOfWorkoutsByFrequency = function getNumberOfWorkoutsByFrequency(value) {
333                 console.log('ExercisePlanner_frequencyMap', value);
334                 var iMap = [1, 2, 4, 8, 16, 24, 150],
335                         // -- times per 24h; proportion to set periods of available time;
336                         numberOfWorkouts = iMap[value];
337
338                 return numberOfWorkouts || 2;
339         };
340
341         /**
342          * Get number of exercises in workout by strength value and optional ;
343          * @param value
344          * @param count
345          * @returns {number}
346          */
347         ExercisePlanner.prototype.getStrength = function strengthMap(value, count) {
348                 console.log('ExercisePlanner_strengthMap', value, count);
349                 var sMap = [1, 1, 2, 4, 10, 20],
350                         base = sMap[value] || 2;
351
352                 count = count || 1;
353                 return Math.round(base * (count / 10 + 1));
354         };
355
356         /**
357          * Generate name of exercise for nearest workout
358          */
359         ExercisePlanner.prototype.generateNearestExercise = function () {
360                 console.log('ExercisePlanner_generateNearestExercise');
361                 var tmp = this.config.exercises.filter(function (item) {
362                         return item.enabled;
363                 });
364                 this.config.nearestExercise = parseInt(Math.random() * tmp.length, 10);
365         };
366
367
368         /**
369          * If user want change work days this method will changing;
370          * @returns {Boolean}
371          */
372         ExercisePlanner.prototype.todayIsWorkday = function todayIsWorkday() {
373                 var day = (new Date()).getDay();
374                 return (day >= 1 && day <= 5);
375         };
376
377         /**
378          * Activate alarms in API.
379          */
380         ExercisePlanner.prototype.startAlarms = function startAlarms() {
381                 // clear old alarms;
382                 this.removeAllAlarms();
383
384                 // add new alarms
385                 this.addAlarmsAllWeek(this.alarms);
386
387                 this.generateNearestExercise();
388                 this.showNextAlarm();
389         };
390
391         /**
392          * Update Graph object
393          * @param {String} typeOfPeriods ['workday'|'weekend']
394          */
395         ExercisePlanner.prototype.updateGraph = function updateGraph(typeOfPeriods) {
396                 console.log('updateGraph');
397                 var alarms;
398                 if (!this.ui.graphSchedule) {
399                         throw {
400                                 message: 'graph schedule not exists.'
401                         };
402                 }
403
404                 typeOfPeriods = typeOfPeriods || ((this.todayIsWorkday()) ? 'workday' : 'weekend');
405                 console.log('typeOfPeriods: ', typeOfPeriods);
406
407                 if (typeOfPeriods === 'workday') {
408                         alarms = this.alarms.workday;
409                 } else {
410                         alarms = this.alarms.weekend;
411                 }
412                 if (alarms.length === 0) {
413                         alarms = this.alarms.everyday;
414                 }
415                 this.ui.graphSchedule.setTimeRanges(this.periodsWeekToBoolArray());
416                 this.ui.graphSchedule.pushTimeOfFlags(alarms);
417                 this.ui.graphSchedule.showFlags();
418         };
419
420         /**
421          * Callback function on visibility change;
422          */
423         ExercisePlanner.prototype.onVisibilityChange = function () {
424
425                 switch (document.webkitVisibilityState) {
426                 case 'visible':
427                         this.applicationStartTime = new Date();
428                         this.currentAlarm = this.findCurrentAlarm();
429                         if (this.currentAlarm.length > 0) {
430                                 this.ui.showWaitOk();
431                                 this.startMusic();
432                         }
433                         break;
434                 }
435         };
436
437         /**
438          * Turn off all alarms today
439          */
440         ExercisePlanner.prototype.todayOffAll = function todayOffAll() {
441                 // set begin date to tomorrow;
442                 this.beginDate = new Date();
443                 this.beginDate.setDate(this.beginDate.getDate() + 1);
444                 // recreate alarms;
445                 this.generateAlarms();
446                 this.exit();
447         };
448
449         // Initialize function
450         ExercisePlanner.prototype.init = function init() {
451                 var onUiInitialize = function onUiInitialize() {
452                         console.log('onUiInitialize');
453                         // register watcher on visibility change;
454                         document.addEventListener('webkitvisibilitychange', this.onVisibilityChange.bind(this));
455                         this.showNextAlarm();
456                         this.onVisibilityChange();
457                 }.bind(this);
458
459                 console.log('ExercisePlanner..init');
460                 this.selfId = tizen.application.getAppContext().appId;
461                 this.ui = new UI();
462                 this.ui.app = this;
463
464                 this.loadConfig();
465                 this.config.currentTypeOfPeriods = (this.todayIsWorkday()) ? 'workday' : 'weekend';
466
467                 this.generateAlarms();
468
469                 this.ui.initialize(onUiInitialize);
470         };
471 }());