Skip to content

Instantly share code, notes, and snippets.

@lmchawla
Last active January 4, 2019 18:51
Show Gist options
  • Save lmchawla/8e9f32df89e31e6d305c09c8ee22ece4 to your computer and use it in GitHub Desktop.
Save lmchawla/8e9f32df89e31e6d305c09c8ee22ece4 to your computer and use it in GitHub Desktop.
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