| 
									
										
										
										
											2019-03-04 21:10:12 +00:00
										 |  |  | import loopback from 'loopback'; | 
					
						
							| 
									
										
										
										
											2017-11-03 06:17:13 -04:00
										 |  |  | import compose from 'lodash/fp/compose'; | 
					
						
							|  |  |  | import map from 'lodash/fp/map'; | 
					
						
							|  |  |  | import sortBy from 'lodash/fp/sortBy'; | 
					
						
							|  |  |  | import trans from 'lodash/fp/transform'; | 
					
						
							|  |  |  | import last from 'lodash/fp/last'; | 
					
						
							|  |  |  | import forEachRight from 'lodash/fp/forEachRight'; | 
					
						
							| 
									
										
										
										
											2019-03-04 21:10:12 +00:00
										 |  |  | import { isEmpty } from 'lodash'; | 
					
						
							| 
									
										
										
										
											2016-01-19 21:11:20 -05:00
										 |  |  | import moment from 'moment-timezone'; | 
					
						
							| 
									
										
										
										
											2019-03-04 21:10:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-10 14:52:09 -08:00
										 |  |  | import { dayCount } from '../utils/date-utils'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-03 06:17:13 -04:00
										 |  |  | const transform = trans.convert({ cap: false }); | 
					
						
							| 
									
										
										
										
											2015-12-10 14:52:09 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-03 06:17:13 -04:00
										 |  |  | const hoursBetween = 24; | 
					
						
							|  |  |  | const hoursDay = 24; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export function prepUniqueDaysByHours(cals, tz = 'UTC') { | 
					
						
							|  |  |  |   let prev = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // compose goes bottom to top (map > sortBy > transform)
 | 
					
						
							|  |  |  |   return compose( | 
					
						
							|  |  |  |     transform((data, cur, i) => { | 
					
						
							|  |  |  |       if (i < 1) { | 
					
						
							|  |  |  |         data.push(cur); | 
					
						
							|  |  |  |         prev = cur; | 
					
						
							|  |  |  |       } else if ( | 
					
						
							|  |  |  |         moment(cur) | 
					
						
							|  |  |  |           .tz(tz) | 
					
						
							| 
									
										
										
										
											2019-02-18 19:32:49 +00:00
										 |  |  |           .diff( | 
					
						
							|  |  |  |             moment(prev) | 
					
						
							|  |  |  |               .tz(tz) | 
					
						
							|  |  |  |               .startOf('day'), | 
					
						
							|  |  |  |             'hours' | 
					
						
							|  |  |  |           ) >= hoursDay | 
					
						
							| 
									
										
										
										
											2017-11-03 06:17:13 -04:00
										 |  |  |       ) { | 
					
						
							|  |  |  |         data.push(cur); | 
					
						
							|  |  |  |         prev = cur; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }, []), | 
					
						
							|  |  |  |     sortBy(e => e), | 
					
						
							| 
									
										
										
										
											2019-02-18 19:32:49 +00:00
										 |  |  |     map(ts => | 
					
						
							|  |  |  |       moment(ts) | 
					
						
							|  |  |  |         .tz(tz) | 
					
						
							|  |  |  |         .startOf('hours') | 
					
						
							|  |  |  |         .valueOf() | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-11-03 06:17:13 -04:00
										 |  |  |   )(cals); | 
					
						
							| 
									
										
										
										
											2016-02-09 09:10:18 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export function calcCurrentStreak(cals, tz = 'UTC') { | 
					
						
							| 
									
										
										
										
											2017-11-03 06:17:13 -04:00
										 |  |  |   let prev = last(cals); | 
					
						
							|  |  |  |   if ( | 
					
						
							|  |  |  |     moment() | 
					
						
							|  |  |  |       .tz(tz) | 
					
						
							|  |  |  |       .startOf('day') | 
					
						
							| 
									
										
										
										
											2019-02-18 19:32:49 +00:00
										 |  |  |       .diff(moment(prev).tz(tz), 'hours') > hoursBetween | 
					
						
							| 
									
										
										
										
											2017-11-03 06:17:13 -04:00
										 |  |  |   ) { | 
					
						
							| 
									
										
										
										
											2015-12-10 14:52:09 -08:00
										 |  |  |     return 0; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-02-09 09:10:18 -08:00
										 |  |  |   let currentStreak = 0; | 
					
						
							|  |  |  |   let streakContinues = true; | 
					
						
							| 
									
										
										
										
											2017-11-03 06:17:13 -04:00
										 |  |  |   forEachRight(cur => { | 
					
						
							|  |  |  |     if ( | 
					
						
							|  |  |  |       moment(prev) | 
					
						
							|  |  |  |         .tz(tz) | 
					
						
							|  |  |  |         .startOf('day') | 
					
						
							| 
									
										
										
										
											2019-02-18 19:32:49 +00:00
										 |  |  |         .diff(moment(cur).tz(tz), 'hours') <= hoursBetween | 
					
						
							| 
									
										
										
										
											2017-11-03 06:17:13 -04:00
										 |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2016-02-09 09:10:18 -08:00
										 |  |  |       prev = cur; | 
					
						
							|  |  |  |       currentStreak++; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       // current streak found
 | 
					
						
							|  |  |  |       streakContinues = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return streakContinues; | 
					
						
							| 
									
										
										
										
											2017-11-03 06:17:13 -04:00
										 |  |  |   })(cals); | 
					
						
							| 
									
										
										
										
											2015-12-10 14:52:09 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 09:10:18 -08:00
										 |  |  |   return currentStreak; | 
					
						
							| 
									
										
										
										
											2015-12-10 14:52:09 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 09:10:18 -08:00
										 |  |  | export function calcLongestStreak(cals, tz = 'UTC') { | 
					
						
							| 
									
										
										
										
											2015-12-10 14:52:09 -08:00
										 |  |  |   let tail = cals[0]; | 
					
						
							| 
									
										
										
										
											2019-02-18 19:32:49 +00:00
										 |  |  |   const longest = cals.reduce( | 
					
						
							|  |  |  |     (longest, head, index) => { | 
					
						
							|  |  |  |       const last = cals[index === 0 ? 0 : index - 1]; | 
					
						
							|  |  |  |       // is streak broken
 | 
					
						
							|  |  |  |       if ( | 
					
						
							|  |  |  |         moment(head) | 
					
						
							|  |  |  |           .tz(tz) | 
					
						
							|  |  |  |           .startOf('day') | 
					
						
							|  |  |  |           .diff(moment(last).tz(tz), 'hours') > hoursBetween | 
					
						
							|  |  |  |       ) { | 
					
						
							|  |  |  |         tail = head; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (dayCount(longest, tz) < dayCount([head, tail], tz)) { | 
					
						
							|  |  |  |         return [head, tail]; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return longest; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     [cals[0], cals[0]] | 
					
						
							|  |  |  |   ); | 
					
						
							| 
									
										
										
										
											2015-12-10 14:52:09 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 09:10:18 -08:00
										 |  |  |   return dayCount(longest, tz); | 
					
						
							| 
									
										
										
										
											2015-12-10 14:52:09 -08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-03-04 21:10:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | export function getUserById(id, User = loopback.getModelByType('User')) { | 
					
						
							|  |  |  |   return new Promise((resolve, reject) => | 
					
						
							|  |  |  |     User.findById(id, (err, instance) => { | 
					
						
							|  |  |  |       if (err || isEmpty(instance)) { | 
					
						
							|  |  |  |         return reject(err || 'No user instance found'); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-10-18 01:17:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-04 21:10:12 +00:00
										 |  |  |       let completedChallengeCount = 0; | 
					
						
							|  |  |  |       let completedProjectCount = 0; | 
					
						
							|  |  |  |       if ('completedChallenges' in instance) { | 
					
						
							|  |  |  |         completedChallengeCount = instance.completedChallenges.length; | 
					
						
							|  |  |  |         instance.completedChallenges.forEach(item => { | 
					
						
							|  |  |  |           if ( | 
					
						
							|  |  |  |             'challengeType' in item && | 
					
						
							|  |  |  |             (item.challengeType === 3 || item.challengeType === 4) | 
					
						
							|  |  |  |           ) { | 
					
						
							|  |  |  |             completedProjectCount++; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-10-18 01:17:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-04 21:10:12 +00:00
										 |  |  |       instance.completedChallengeCount = completedChallengeCount; | 
					
						
							|  |  |  |       instance.completedProjectCount = completedProjectCount; | 
					
						
							|  |  |  |       instance.completedCertCount = getCompletedCertCount(instance); | 
					
						
							|  |  |  |       instance.completedLegacyCertCount = getLegacyCertCount(instance); | 
					
						
							| 
									
										
										
										
											2019-10-18 01:17:37 +01:00
										 |  |  |       instance.points = | 
					
						
							|  |  |  |         (instance.progressTimestamps && instance.progressTimestamps.length) || | 
					
						
							|  |  |  |         1; | 
					
						
							| 
									
										
										
										
											2019-03-04 21:10:12 +00:00
										 |  |  |       return resolve(instance); | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function getCompletedCertCount(user) { | 
					
						
							|  |  |  |   return [ | 
					
						
							|  |  |  |     'isApisMicroservicesCert', | 
					
						
							|  |  |  |     'is2018DataVisCert', | 
					
						
							|  |  |  |     'isFrontEndLibsCert', | 
					
						
							| 
									
										
										
										
											2020-06-18 00:00:31 +09:00
										 |  |  |     'isQaCertV7', | 
					
						
							|  |  |  |     'isInfosecCertV7', | 
					
						
							| 
									
										
										
										
											2019-03-04 21:10:12 +00:00
										 |  |  |     'isJsAlgoDataStructCert', | 
					
						
							| 
									
										
										
										
											2020-02-25 00:10:32 +05:30
										 |  |  |     'isRespWebDesignCert', | 
					
						
							| 
									
										
										
										
											2020-06-18 00:00:31 +09:00
										 |  |  |     'isSciCompPyCertV7', | 
					
						
							|  |  |  |     'isDataAnalysisPyCertV7', | 
					
						
							|  |  |  |     'isMachineLearningPyCertV7' | 
					
						
							| 
									
										
										
										
											2019-03-04 21:10:12 +00:00
										 |  |  |   ].reduce((sum, key) => (user[key] ? sum + 1 : sum), 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function getLegacyCertCount(user) { | 
					
						
							| 
									
										
										
										
											2020-04-23 09:08:50 -04:00
										 |  |  |   return [ | 
					
						
							|  |  |  |     'isFrontEndCert', | 
					
						
							|  |  |  |     'isBackEndCert', | 
					
						
							|  |  |  |     'isDataVisCert', | 
					
						
							|  |  |  |     'isInfosecQaCert' | 
					
						
							|  |  |  |   ].reduce((sum, key) => (user[key] ? sum + 1 : sum), 0); | 
					
						
							| 
									
										
										
										
											2019-03-04 21:10:12 +00:00
										 |  |  | } |