Last active
January 4, 2019 18:51
-
-
Save lmchawla/8e9f32df89e31e6d305c09c8ee22ece4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var print = null; | |
var timers_added_today = 0; | |
moving_sum = 0; | |
looming_sum = 0; | |
var today = new Date(); | |
var key = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate(); | |
var infolog = function () { | |
//console.log | |
} | |
function curr_hours() { | |
//for experimenting with different times | |
return new Date().getHours(); | |
} | |
String.prototype.toHHMMSS = function () { | |
var sec_num = parseInt(this, 10); // don't forget the second param | |
var hours = Math.floor(sec_num / 3600); | |
var minutes = Math.floor((sec_num - (hours * 3600)) / 60); | |
var seconds = sec_num - (hours * 3600) - (minutes * 60); | |
if (hours < 10) { | |
hours = "0" + hours; | |
} | |
if (minutes < 10) { | |
minutes = "0" + minutes; | |
} | |
if (seconds < 10) { | |
seconds = "0" + seconds; | |
} | |
return hours + ':' + minutes + ':' + seconds; | |
} | |
var active = false; | |
var prev_active = false; | |
var firstload = true; | |
var prev_sum = 0; | |
function onload(rearrange) { | |
d_sum = 0; | |
w_sum = 0; | |
m_sum = 0; | |
tm_sum = 0; | |
timers_today = 0; | |
moving_sum = 0; | |
contextual_weights_max = {'Office': 4, 'General': 6, 'Focus': 5, 'Intersticies': 1.5, 'Home': 0}; | |
contextual_weights_original = {'Office': 4, 'General': 6, 'Focus': 5, 'Intersticies': 1.5, 'Home': 0}; | |
contextual_weight_sums = {'Office': 0, 'General': 0, 'Focus': 0, 'Intersticies': 0, 'Home': 0}; | |
if (today.getDay() == 0) | |
contextual_weights_max['Home'] = 10; | |
active = false; | |
var loaded = $('.taskRow').length > 0; | |
if (!loaded) | |
return; | |
if (firstload) { | |
firstload = false; | |
var tasks = $('.taskRow'); | |
var parent = null; | |
for (var i = 0; i < tasks.length; i++) { | |
var el = $(tasks[i]) | |
if (!el.hasClass('subtask')) | |
parent = $(tasks[i]).attr('id'); | |
else { | |
el.data('parent', parent); | |
$('#' + parent).data('hasChildren', true) | |
} | |
} | |
} | |
$('.taskRow').not(".subtask").each(function () { | |
star = null; | |
x = Infinity; | |
date = $(this).find('.tc_duedate'); | |
context = $($(this).find('div')[7]).text(); | |
status = $($(this).find('div')[8]).text(); | |
t = date[0].title; | |
var d = Math.max(1 / 24, 23 - curr_hours()); | |
if (t && t.length) { | |
if (t.indexOf('ago') > -1) { | |
x = 25 / 24 / 60; | |
} | |
else { | |
if (t.indexOf('In') == -1) { | |
x = 0; | |
} | |
else { | |
x = parseInt(t.split('In')[1].split('days')[0]); | |
if (context != 'Home' && x > 6) | |
x = x * 6 / 7; | |
} | |
x += d / 24; | |
} | |
} | |
else | |
star = false; | |
x = Math.max(25 / 24 / 60, x) | |
lentext = $($(this).find('div')[3]).text(); | |
lentext = lentext.split('No Length')[0]; | |
if (lentext) { | |
if (lentext.indexOf('hour') == -1) | |
len = parseFloat(lentext.split('mins')[0]) / 60; | |
else { | |
len = parseFloat(lentext.split('hour')[0]); | |
if (lentext.indexOf('mins') > -1) | |
len += parseFloat(lentext.split('hour')[1].split('mins')[0]) / 60; | |
} | |
} | |
else { | |
star = false; | |
len = null; | |
} | |
timer = $(this).find('.tc_timer>span').text(); | |
timer = timer.split('No Timer')[0]; | |
if (timer) { | |
timer = parseFloat(timer.split('h')[0]) + parseFloat(timer.split('m')[0].split('h')[1] / 60) | |
} | |
else { | |
timer = 0; | |
} | |
priority = $(this).find('.tc_priority>span').text(); | |
weight = 0; | |
thres = 24; | |
if (priority == '0 Low') | |
thres = 12; | |
if (priority == '1 Med') | |
thres = 6; | |
if (priority == '2 High') | |
thres = 3; | |
if (priority == '3 Top') | |
thres = 1; | |
if (len > 0) { | |
if (timer) | |
len -= timer; | |
if (len < 0) | |
len = 0; | |
if ($(this).hasClass('completed')) | |
len = 0; | |
if (status != 'Next Action' && status != 'Active') | |
len = 0; | |
if (x === Infinity) | |
x = Math.max(7, len / (25 / 60)) | |
weight = len / x; | |
contextual_weight_sums[context] += Math.min(weight, len); | |
if (context == 'Home') { | |
weight = len / Math.ceil(x / 7); | |
thres = 5; | |
} | |
if (x <= 1) | |
d_sum += len; | |
if (x <= 7) | |
w_sum += len; | |
if (x <= 30) | |
m_sum += len; | |
if (x <= 120) | |
tm_sum += len; | |
title = $(this).data('title') || $(this).find('.tc_title').text(); | |
$(this).data('title', title); | |
$(this).data('weight', weight); | |
$(this).data('timer', timer); | |
$(this).data('thres', thres); | |
$(this).data('len', len); | |
$(this).data('context', context); | |
$(this).data('x', Math.max(x, 0)); | |
$(this).data('target', 0); | |
$(this).data('priority', 0); | |
$(this).data('status', status); | |
if (status == 'Active') | |
active = true; | |
if (context == 'Focus') { | |
if (len > contextual_weights_original[context]) | |
alert('limit too high for' + title) | |
} | |
} | |
var star = (x <= 2 && len > 0) || weight > contextual_weights_original[context] * thres; | |
$(this).data('starred', star ? 1 : 0); | |
} | |
); | |
resort(rearrange); | |
} | |
function format(x) { | |
if (print) | |
return ''; | |
base = Math.floor(x); | |
y = x - base; | |
if (base) | |
return ' (' + base + 'h:' + (y * 60).toFixed(0) + 'm)'; | |
else | |
return ' (' + (y * 60).toFixed(0) + 'm)'; | |
} | |
function get_extra_time(time_left_updated) { | |
var ret = ''; | |
if (starred_time > 0) { | |
var red = starred_time > time_left_updated ? 'red' : 'palevioletred'; | |
ret += ('<span style=" color:' + red + '"> Minimum due today: ' + format(starred_time) + '</span>'); | |
} | |
if (time_left_extended > 0) { | |
ret += '<span style=" color: palegreen"> Extra time: ' + | |
format(time_left_extended); | |
for (var i in contextual_weights_max) { | |
if (contextual_weights_max[i] > 0) | |
ret += (' ' + i + ' : ' + format(contextual_weights_max[i])); | |
} | |
ret += '</span>'; | |
} | |
return ret | |
} | |
function timer_refersh() { | |
var now = new Date(); | |
var eod = new Date(); | |
eod.setHours(23, 59, 59, 999); | |
var time_left_updated = (eod - now) / 1000; | |
var hrs_left = time_left_updated / 3600; | |
if (moving_sum) | |
$('#tn_logo').html('<h3 style=" width:205px; background-color: #C2D9F8; color: ' + getColor(timers_added_today, moving_sum + timers_added_today, hrs_left) + ';"> ' + (moving_sum - timers_added_today).toFixed(2) + "/" + (moving_sum).toFixed(2) + ' ' + time_left_updated.toString().toHHMMSS() + '</h3>' + get_extra_time(hrs_left)); | |
} | |
function getColor(timers_added_today, moving_sum, time_left_updated) { | |
value = (timers_added_today / moving_sum) / ((24 - time_left_updated / 3600 ) / 24); | |
value = Math.min(1, value); | |
var hue = ((value) * 120).toString(10); | |
return ["hsl(", hue, ",100%,50%)"].join(""); | |
} | |
var time_left = 24; | |
var time_left_extended = 24; | |
var starred_time = 0; | |
var max_target = 12; | |
function sorter(a, b) { | |
var a_name = $(a).data('title'); | |
var b_name = $(b).data('title'); | |
var a_s = $(a).data('starred'); | |
var b_s = $(b).data('starred'); | |
var a_c = $(a).data('context'); | |
var b_c = $(b).data('context'); | |
var a_t = $(a).data('target'); | |
var b_t = $(b).data('target'); | |
var a_p = $(a).data('thres'); | |
var b_p = $(b).data('thres'); | |
var a_w = $(a).data('weight'); | |
var b_w = $(b).data('weight'); | |
var a_l = $(a).data('len'); | |
var b_l = $(b).data('len'); | |
var a_pr = $(a).data('priority'); | |
var b_pr = $(b).data('priority'); | |
var a_possible = a_l * a_p < max_target && a_l < contextual_weights_original[a_c]; | |
var b_possible = a_l * b_p < max_target && a_l < contextual_weights_original[a_c]; | |
var contextual_sort = contextual_weight_sums[b_c] / contextual_weights_max[b_c] - contextual_weight_sums[a_c] / contextual_weights_max[a_c]; | |
var output = infolog('sorting', a_name, 'VS', b_name) || b_pr - a_pr || infolog('tie on color') || | |
b_s - a_s || infolog('tie on star') || (b_s ? (a_l * a_p - b_l * b_p || | |
infolog('tie on length of starred')) : (contextual_sort || infolog('tie on context') || | |
b_t / b_p - a_t / a_p || infolog('tie on target') || | |
b_possible - a_possible || infolog('tie on can be completed today') || | |
b_w / b_p - a_w / a_p)) || infolog('tie on weight') || | |
(( a_name < b_name) ? -1 : 1) || infolog('tie on name') || $(a).attr('id') - $(b).attr('id'); | |
infolog('sorted', a_name, b_name, output); | |
return output; | |
} | |
function resort(rearrange) { | |
var rank = 0; | |
var $footer = $('.tasksFooter'); | |
var $wrapper = $('#TasksContainer>div>span'), | |
$art = $('.taskRow').not(".subtask"); | |
if (!$art.length) | |
return console.log('not ready to sort'); | |
var arr = []; | |
$wrapper.css('display', 'flex'); | |
$wrapper.css('flex-direction', 'column'); | |
var blocked = []; | |
var blocked_sundays = []; | |
time_left = (23 - curr_hours() + (60 - new Date().getMinutes()) / 60) | |
time_left_extended = time_left; | |
starred_time = 0; | |
//make scheduler | |
console.log('sorting', rearrange); | |
$art.sort(sorter) | |
.each(function () { | |
var _len = $(this).data('len'); | |
var _weight = $(this).data('weight'); | |
var _title = $(this).data('title'); | |
var _x = $(this).data('x'); | |
var _timer = $(this).data('timer') || 0; | |
var _context = $(this).data('context'); | |
if (_context == 'Home') | |
_x = _x / 7; | |
var _target_weight = _len / _x; | |
_x = Math.ceil(_x) | |
if (_target_weight > _len) | |
_target_weight = _len; | |
var _target_weight_original = _target_weight; | |
_pre_sum = 0; | |
_pre_sum_sundays = 0; | |
if (_len > 0) { | |
if (_context == 'Home') { | |
blocked_sundays.forEach(function (v) { | |
if (_x && _x > v[0] && v[1] && v[0] && _target_weight) { | |
// infolog(_target_weight, _x, v[0], (_x - v[0]), v[1], v[1] * (_x - v[0]), _title) | |
_pre = v[1] * (_x - v[0]); | |
_pre = Math.min(_pre, _target_weight * _x); | |
v[0] = v[0] + (_x - v[0]) * _pre / _target_weight; | |
_target_weight = Math.max(_target_weight - _pre / _x, 0); | |
_pre_sum_sundays += _pre / _x; | |
// infolog(_len, _pre, _len / _x, _pre_sum, _target_weight, _title); | |
} | |
}) | |
} | |
else { | |
blocked.forEach(function (v) { | |
if (_x && _x > v[0] && v[1] && v[0] && _target_weight) { | |
// infolog(_target_weight, _x, v[0], (_x - v[0]), v[1], v[1] * (_x - v[0]), _title) | |
_pre = v[1] * (_x - v[0]); | |
_pre = Math.min(_pre, _target_weight * _x); | |
v[0] = v[0] + (_x - v[0]) * _pre / _target_weight; | |
_target_weight = Math.max(_target_weight - _pre / _x, 0); | |
_pre_sum += _pre / _x; | |
// infolog(_len, _pre, _len / _x, _pre_sum, _target_weight, _title); | |
} | |
}) | |
} | |
if (_context == 'Home') { | |
blocked_sundays.push([_x, _target_weight + _pre_sum_sundays]); | |
//infolog(_len / _x, _pre_sum, _target_weight, _title); | |
moving_sum += _target_weight / 7; | |
} | |
else { | |
blocked.push([_x, _target_weight + _pre_sum]); | |
//infolog(_len / _x, _pre_sum, _target_weight, _title); | |
moving_sum += _target_weight; | |
} | |
} | |
else { | |
$(this).find('.tc_title').text(_title + format(0)); | |
} | |
timers_today += _timer; | |
if (_target_weight_original == _target_weight) | |
_target_weight = _len / $(this).data('x'); | |
if (_target_weight < 0) | |
_target_weight = 0; //never happen | |
$(this).data('target', _target_weight); | |
infolog('final targets', _title, _target_weight); | |
} | |
).each(function () { | |
var _len = $(this).data('len'); | |
var _weight = $(this).data('weight'); | |
var _title = $(this).data('title'); | |
var _thres = $(this).data('thres'); | |
var _x = $(this).data('x'); | |
var _context = $(this).data('context'); | |
var _target_weight = $(this).data('target'); | |
var _c_left = contextual_weights_max[_context]; | |
var _ctarget_left = contextual_weight_sums[_context]; | |
var _c_max = contextual_weights_original[_context]; | |
var _star = false; | |
var _status = $(this).data('status'); | |
if (_target_weight > _len) | |
_target_weight = _len; | |
if (_weight > _len) | |
_weight = _len; | |
var _target_weight_original = _target_weight; | |
if (_context == 'Focus') { | |
_target_weight = _c_left >= _len && time_left >= _len ? _len : 0; | |
_weight = _len; | |
} | |
if (_x <= 1) | |
_target_weight = _len; | |
var consumable_target_weight = _target_weight; | |
if (_x > 1) | |
consumable_target_weight = Math.max(0, Math.min(_target_weight, time_left, _c_left)); | |
var color = "white" | |
if (_target_weight_original > 0) { | |
$(this).find('.tc_title').text(_title + format(_target_weight) + format(_weight)); | |
if (consumable_target_weight < _target_weight) | |
$(this).find('.tc_title').text(_title + format(consumable_target_weight) + format(_target_weight) + format(_weight)); | |
if (_context == 'Focus') | |
$(this).find('.tc_title').text(_title + format(consumable_target_weight) + format(_target_weight_original) + format(_len)); | |
color = "#ffcccc"; //pink | |
if (_x <= 2 || _target_weight_original > _c_max * _thres || _ctarget_left > _c_max) { //things I must do urgently | |
starred_time += _target_weight_original; | |
if (_x <= 1 || _target_weight_original > _c_max * _thres || (_status = 'focus' && _x <= 2)) { | |
_star = true; | |
color = "#FF4747"; //dark-pink | |
} | |
if (_target_weight > 0) { | |
if (time_left >= _target_weight) {//things I can do by rearranging | |
color = "#FED8B1";//light orange | |
} | |
if (time_left >= _target_weight && _c_left >= _target_weight) { //things I will be able to cover today | |
color = "#ffffe0"; //bright-cream | |
if (_ctarget_left > _c_max * _thres) | |
color = "#ffeccc"; //dark cream | |
} | |
} | |
} | |
else { | |
if (_target_weight_original < 25 / 60 || _target_weight_original < _c_max * _thres) { | |
color = "#FFF5FF"; //pale-pink | |
if (_ctarget_left < _c_max * _thres || time_left_extended > 0) | |
color = "white"; | |
} | |
if (((time_left >= _target_weight && _c_left >= _target_weight) || time_left_extended > _target_weight) && _target_weight > 0) { // things that can get covered by rearranging | |
color = "#f0fcfc"; //pale-blue | |
} | |
} | |
if (time_left >= _len && _c_left >= _len && _x > 1 / 24) { // things that can get done | |
color = "palegreen"; //pale-green | |
} | |
time_left -= consumable_target_weight; | |
time_left_extended -= _target_weight; | |
contextual_weight_sums[_context] -= consumable_target_weight; | |
contextual_weights_max[_context] -= consumable_target_weight; | |
} | |
else { | |
//All low priority/future tasks here | |
var consumable_weight = _weight; | |
if (_x > 1) | |
consumable_weight = Math.max(0, Math.min(_weight, time_left, _c_left)); | |
$(this).find('.tc_title').text(_title + format(_weight)); | |
if (consumable_weight < _weight) | |
$(this).find('.tc_title').text(_title + format(consumable_weight) + format(_weight)); | |
if ((time_left >= _weight && _c_left >= _weight) || time_left_extended > _weight) { // things that can get covered by rearranging | |
color = '#FFFF99' //yellow | |
} | |
if (time_left_extended > _len || (time_left >= _len && _c_left >= _len)) { // things that can get done by rearranging | |
color = "#eafeea"; //paler-green | |
} | |
time_left -= consumable_weight; | |
time_left_extended -= _weight; | |
contextual_weight_sums[_context] -= consumable_weight; | |
contextual_weights_max[_context] -= consumable_weight; | |
} | |
if (_len <= 0) | |
color = '#f6f6f6' //palegrey | |
//can do, can cover-must cover-contextually constrained, can cover must cover, | |
// can cover by arranging must cover, can do by rearranging, must cover-cannot cover-was never possible, | |
//must cover-cannot cover, cannot cover but not dire, not even a task,already done | |
colors = { | |
'#9999ff': 10, | |
'palegreen': 2, | |
"#ffeccc": 2, //dark cream | |
"#ffffe0": 2, //bright-cream | |
"#FED8B1": 2, //light orange | |
'#FF4747': 2, //dark-pink | |
"#eafeea": 1, //paler-green | |
"#f0fcfc": 1, //pale-blue | |
'#FFFF99': 1, //paleyellow | |
"#ffcccc": 0, //pink | |
"#FFF5FF": 0, //pale-pink | |
"white": 0, | |
'#f6f6f6': -2 //grey | |
} | |
//on same day, doing nothing, task cannot change priority, only color | |
if (_status == 'Active') | |
_star = true, color = '#9999ff'; | |
$(this).data('starred', _star); | |
$(this).data("priority", colors[color]); | |
$(this).css("background-color", color); | |
var star_el = $(this).find('.cellStarSmall')[0]; | |
var previous = $(star_el).hasClass('star'); | |
if (_star != previous) | |
star_el.click(); | |
infolog('final state', _title, _context, time_left, _c_left, _target_weight, _target_weight_original, color, _x <= 1); | |
infolog('contextual_weight_sums', contextual_weights_max) | |
}); | |
subkey = location.href.split('tasks.toodledo.com/')[1]; | |
timers_today_saved = localStorage.getItem('timers_today' + key + subkey); | |
if (timers_today_saved == null) { | |
localStorage.removeItem('timers_today' + key + subkey); | |
localStorage.setItem('timers_today' + key + subkey, timers_today); | |
timers_today_saved = timers_today; | |
alert('saving new timer' + timers_today); | |
} | |
timers_added_today = timers_today - timers_today_saved; | |
if (!rearrange && prev_active == active && prev_sum == moving_sum) | |
return console.log('not fresh'); | |
prev_active = active; | |
prev_sum = moving_sum; | |
$('.taskRowDivider').hide(); | |
$('.cellSubtasks').hide(); | |
tick(); | |
if ($('span>a.cellAction').length || $('div.dd_opened').length) | |
return console.log('not rearranging doms') || window.setTimeout(resort_doms, 5 * 1000); | |
console.log('rearranging'); | |
$art.sort(sorter).each(function () { | |
infolog('final sorted list', $(this).data('title'), $(this).css("background-color"), $(this).data('starred')); | |
if (showonly && $(this).data('context') != showonly) | |
$(this).hide(); | |
else | |
$(this).show(); | |
if ($(this).data('hasChildren')) { | |
var parent_id = $(this).attr('id') | |
var children = $('div.taskRow.subtask').filter(function () { | |
return $(this).data("parent") == parent_id; | |
}); | |
children.sort(function (a, b) { | |
return $(a).attr('id') - $(b).attr('id'); | |
}); | |
if ($(this).data('status') == 'Active') { | |
for (var i = 0; i < children.length; i++) { | |
var el = $(children[i]); | |
if (el.hasClass('completed')) { | |
el.css('order', 1000); | |
} | |
else { | |
el.css('order', rank); | |
el.css("background-color", "#f0fcfc"); | |
rank += 1; | |
} | |
} | |
} | |
else { | |
children.hide(); | |
} | |
} | |
$(this).css('order', rank); | |
rank += 1; | |
}); | |
} | |
var showonly = null; | |
function cb(res) { | |
if (res) { | |
if (showonly != res.showonly) | |
setTimeout(resort_doms, 1); | |
showonly = res.showonly; | |
} | |
else | |
showonly = null; | |
console.log(showonly); | |
} | |
function tick() { | |
var data = {total_weight: moving_sum, timer: timers_added_today, isfocussed: false} | |
console.log('tick', JSON.stringify(data)) | |
// if (moving_sum && timers_added_today) | |
$.post("http://localhost:1234/tick/", data, cb); | |
// else | |
// console.log('not ticking', moving_sum, timers_added_today) | |
} | |
function resort_doms() { | |
onload(true) | |
} | |
oni = window.setInterval(onload, 5 * 1000); | |
rearri = window.setInterval(resort_doms, 30 * 1000); | |
timi = window.setInterval(timer_refersh, 1000); | |
ticki = window.setInterval(tick, 30 * 1000); | |
$(window).load(onload); | |
if (document.readyState == "complete") | |
onload(true); | |
// | |
// var vis = (function () { | |
// var stateKey, eventKey, keys = { | |
// hidden: "visibilitychange", | |
// webkitHidden: "webkitvisibilitychange", | |
// mozHidden: "mozvisibilitychange", | |
// msHidden: "msvisibilitychange" | |
// }; | |
// for (stateKey in keys) { | |
// xdcn, o9mj | |
// if (stateKey in document) { | |
// eventKey = keys[stateKey]; | |
// break; | |
// } | |
// } | |
// return function (c) { | |
// if (c) document.addEventListener(eventKey, c); | |
// return !document[stateKey]; | |
// } | |
// })(); | |
// | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment