// ==UserScript==
// @name Time sleep prediction
// @namespace http://tampermonkey.net/
// @version 0.3
// @description Keep track of time spent on any website
// @icon https://www.iconsdb.com/icons/preview/gray/clock-10-xxl.png
// @author moony
// @match *://*/*
// @grant GM_registerMenuCommand
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_listValues
// @grant GM_deleteValue
// @grant window.onurlchange
// @license GPL-3.0
// ==/UserScript==
(function() {
'use strict';
let sleepTimeDisplay = false;
let counter = 0;
var predictionSleep
let diffTime = 0;
let CurrentDate = new Date();
let SleepingTimeArray = [];
let WakeUpTimeArray = [];
document.addEventListener("keypress", arrayTimeUpdate);
document.addEventListener("mousemove", arrayTimeUpdate);
document.addEventListener("mousedown", arrayTimeUpdate);
function arrayTimeUpdate() {
let wakeTimer = GM_getValue("wakeTimer", null);
let oldDate = GM_getValue("oldDate", null);
const minSleep = 6; const maxSleep = 24;
if (oldDate == null) { oldDate = CurrentDate.getTime(); GM_setValue("SleepingTimeArray", [8.1, 9.1, 10.1]); GM_setValue("WakeUpTimeArray", [16.1, 15.1, 14.1]); } //first time run
CurrentDate = new Date();
diffTime = CurrentDate.getTime() - oldDate;
diffTime = diffTime/(1000*60*60);
if (diffTime > minSleep && diffTime < maxSleep) {
SleepingTimeArray = GM_getValue("SleepingTimeArray", null);
WakeUpTimeArray = GM_getValue("WakeUpTimeArray", null);
if (SleepingTimeArray == null) { SleepingTimeArray = [diffTime]; } //first time store
else { SleepingTimeArray.push(diffTime); }
if (WakeUpTimeArray == null) { WakeUpTimeArray = [wakeTimer]; }
else { WakeUpTimeArray.push(wakeTimer); }
GM_setValue("SleepingTimeArray", SleepingTimeArray);
GM_setValue("WakeUpTimeArray", WakeUpTimeArray);
GM_setValue("wakeTimer", 0)
}
else if (diffTime <= minSleep) {
if (wakeTimer == null) { wakeTimer = diffTime; }
else { wakeTimer += diffTime; }
}
else { GM_setValue("wakeTimer", 0); }
GM_setValue("wakeTimer", wakeTimer);
GM_setValue("oldDate", CurrentDate.getTime());
}
function predictSleep() {
counter++
SleepingTimeArray = GM_getValue("SleepingTimeArray", null); //for read persistent storage
WakeUpTimeArray = GM_getValue("WakeUpTimeArray", null);
let index = SleepingTimeArray.length - 1;
let sum = 0;
const nsleep = SleepingTimeArray.length;
while (index > -1) {
sum += SleepingTimeArray[index];
index--;
}
const sleepAverage = sum / nsleep;
sum = 0;
index = WakeUpTimeArray.length - 1;
const nwake = WakeUpTimeArray.length;
while (index > -1) {
sum += WakeUpTimeArray[index];
index--;
}
const wakeAverage = sum / nwake;
const ratio = sleepAverage / wakeAverage
const wakeTimer = GM_getValue("wakeTimer", 0);
const predict = ratio * wakeTimer;
predictionSleep = convertHours(predict);
return predictionSleep;
}
function convertHours(predict)
{
const hours = Math.floor(predict);
let remainder = predict - hours;
remainder = remainder * 60;
const minutes = Math.floor(remainder);
remainder = remainder - minutes;
remainder = remainder * 60;
const seconds = Math.floor(remainder);
const predictionText = `${hours} hours, ${minutes} minutes and ${seconds} seconds.(${counter})`;
return predictionText;
}
function displaySleepTime() {
sleepTimeDisplay = true; GM_setValue("sleepTimeDisplay", sleepTimeDisplay);
predictionSleep = predictSleep();
let sleepTimeDiv = document.createElement("div");
let pos = GM_getValue("sleepTimeDivPos", { x: "50%", y: "50%" }); if (pos.x == "NaN" || pos.y == "NaN") pos = { x: "50%", y: "50%" };
sleepTimeDiv.style.cssText = `left: ${pos.x}; top: ${pos.y}; background-color: rgba(0,0,0,0.5); color: white; position: fixed; transform: translate(-50%, -50%); font-size: 100%; border-radius: 5px; padding: 10px; text-align: center; z-index: 9999;`;
sleepTimeDiv.innerHTML = `If you sleep now, you will WakeUp in: <span id='sleepTimeSpan'>${predictionSleep}</span>`;
document.body.appendChild(sleepTimeDiv);
let sleepTimeSpan = document.getElementById("sleepTimeSpan");
sleepTimeSpan.style.marginRight = "30px";
let closeButton = document.createElement("button");
closeButton.style.cssText = `position: absolute; top: 5px; right: 5px; background-color: rgba(0,0,0,0.5); color: white; font-size: 100%; padding: 5px 10px; border-radius: 3px; box-shadow: 0px 0px 8px rgba(0,0,0,0.1); transition: all 0.2s ease-in-out;`;
closeButton.innerHTML = "X";
closeButton.addEventListener("click", function() {
removeSleepTimeDisplay();
sleepTimeDiv.remove();
});
closeButton.addEventListener("mouseover", function() {
closeButton.style.backgroundColor = "rgba(0,0,0,0.2)";
closeButton.style.color = "white";
});
closeButton.addEventListener("mouseout", function() {
closeButton.style.backgroundColor = "rgba(0,0,0,0.5)";
closeButton.style.color = "white";
});
sleepTimeDiv.addEventListener("mousedown", function(event) {
let currentX = event.clientX - sleepTimeDiv.offsetLeft; let currentY = event.clientY - sleepTimeDiv.offsetTop;
document.addEventListener("mouseup", function() {
document.removeEventListener("mousemove", moveDiv);
let pos = { x: sleepTimeDiv.style.left, y: sleepTimeDiv.style.top }; GM_setValue("sleepTimeDivPos", pos);
});
document.addEventListener("mousemove", moveDiv);
function moveDiv(event) {
sleepTimeDiv.style.left = event.clientX - currentX + "px";
sleepTimeDiv.style.top = event.clientY - currentY + "px";
}
});
sleepTimeDiv.appendChild(closeButton);
setInterval(function() {
document.querySelector("#sleepTimeSpan").innerHTML = `${predictSleep()}`;
}, 1000);
}
function removeSleepTimeDisplay() {
if (sleepTimeDisplay) {
sleepTimeDisplay = false; GM_setValue("sleepTimeDisplay", sleepTimeDisplay);
const pos = { x: "50%", y: "50%" }; GM_setValue("sleepTimeDivPos", pos);
}
}
if (window.onurlchange === null) { console.log("URL CHANGE");
let sleepTimeDisplay = GM_getValue("sleepTimeDisplay", false);
if (sleepTimeDisplay) { displaySleepTime(); } else { removeSleepTimeDisplay();}
window.addEventListener('urlchange', (info) => { console.log("newly created"); });
}
GM_registerMenuCommand("Sleep Time", () => { if (sleepTimeDisplay) { removeSleepTimeDisplay(); } else { displaySleepTime(); }});
GM_registerMenuCommand("resetBoxPos", () => { GM_listValues((keys) => console.log(keys)); GM_deleteValue("sleepTimeDivPos"); });
})();