2021-01-10 12:33:00 +00:00
|
|
|
let secondInterval;
|
|
|
|
let showRealTime = false;
|
2021-01-21 20:45:03 +00:00
|
|
|
let currentFormatter;
|
2021-01-10 12:33:00 +00:00
|
|
|
|
|
|
|
const utils = {
|
|
|
|
random: function(items) {
|
|
|
|
return items[~~(items.length * Math.random())];
|
|
|
|
},
|
|
|
|
|
|
|
|
oneIn: function(chance) {
|
|
|
|
return Math.floor(Math.random() * Math.floor(chance + 1)) === chance;
|
|
|
|
},
|
|
|
|
|
|
|
|
hours2Word: function(hours, minutes) {
|
|
|
|
const numbers = [
|
|
|
|
'twelve',
|
|
|
|
'one',
|
|
|
|
'two',
|
|
|
|
'three',
|
|
|
|
'four',
|
|
|
|
'five',
|
|
|
|
'six',
|
|
|
|
'seven',
|
|
|
|
'eight',
|
|
|
|
'nine',
|
|
|
|
'ten',
|
|
|
|
'eleven',
|
|
|
|
'twelve',
|
|
|
|
];
|
|
|
|
|
|
|
|
let adjustedHours = hours;
|
|
|
|
|
|
|
|
if (minutes > 40) {
|
|
|
|
adjustedHours += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (adjustedHours > 12) {
|
|
|
|
adjustedHours -= 12;
|
|
|
|
}
|
|
|
|
|
|
|
|
return numbers[adjustedHours];
|
|
|
|
},
|
|
|
|
|
|
|
|
print: function(str) {
|
|
|
|
let fontSize = 4;
|
|
|
|
const width = g.getWidth();
|
|
|
|
const height = g.getHeight() - 48;
|
|
|
|
const lines = str.split(`\n`).length;
|
|
|
|
let totalHeight;
|
|
|
|
|
|
|
|
do {
|
|
|
|
g.setFont("6x8", fontSize);
|
|
|
|
totalHeight = g.getFontHeight() * lines;
|
|
|
|
if (fontSize === 1 || (g.stringWidth(str) < width && totalHeight < height)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
fontSize--;
|
|
|
|
|
|
|
|
} while (true);
|
|
|
|
|
|
|
|
const x = width / 2;
|
|
|
|
|
|
|
|
const y = (g.getHeight() / 2) - (g.getFontHeight() * ((lines - 1) / 2));
|
|
|
|
g.drawString(str, x, y < 25 ? 24 : y);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const words = {
|
|
|
|
approx: ['\'Bout', 'About', 'Around', `Summat\nlike`, 'Near', 'Close to'],
|
|
|
|
approach: ['Nearly', `Coming\nup to`, 'Approaching', `A touch\nbefore`],
|
|
|
|
past: [`A shade\nafter`, `A whisker\nafter`, 'Just gone'],
|
2021-01-21 20:45:03 +00:00
|
|
|
quarter: ['A quarter', 'Quarter'],
|
2021-01-10 12:33:00 +00:00
|
|
|
half: ['Half', 'Half past'],
|
|
|
|
exactly: ['exactly', 'on the dot', 'o\' clock'],
|
2021-01-21 20:45:03 +00:00
|
|
|
ish: ['-ish', `\n(ish)`, `\nand change`, `\nand some`, `\nor`, `\nor\nthereabouts`]
|
2021-01-10 12:33:00 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
function switchMode() {
|
2021-01-21 20:45:03 +00:00
|
|
|
currentFormatter = null;
|
2021-01-10 12:33:00 +00:00
|
|
|
showRealTime = !showRealTime;
|
|
|
|
refreshTime();
|
|
|
|
}
|
|
|
|
|
|
|
|
function drawRealTime(date) {
|
|
|
|
const pad = (number) => `0${number}`.substr(-2);
|
|
|
|
const hours = pad(date.getHours());
|
|
|
|
const minutes = pad(date.getMinutes());
|
|
|
|
|
|
|
|
g.setFontAlign(0,1);
|
|
|
|
g.setFont("6x8", 8);
|
|
|
|
g.drawString(`${hours}:${minutes}`, g.getWidth() / 2, g.getHeight() / 2);
|
|
|
|
|
|
|
|
g.setFont("6x8", 3);
|
|
|
|
g.setFontAlign(0, -1);
|
|
|
|
g.drawString(date.toISOString().split('T')[0], g.getWidth() / 2, g.getHeight() / 2);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-01-21 20:45:03 +00:00
|
|
|
const makeApprox = (str, template) => {
|
|
|
|
let _template = template || 'approx';
|
|
|
|
if (utils.oneIn(2)) {
|
|
|
|
_template = 'approx';
|
2021-01-10 12:33:00 +00:00
|
|
|
|
2021-01-21 20:45:03 +00:00
|
|
|
if (utils.oneIn(words.approx.length)) {
|
|
|
|
const ish = utils.random(words.ish);
|
|
|
|
return `${str}${ish}`;
|
|
|
|
}
|
|
|
|
}
|
2021-01-10 12:33:00 +00:00
|
|
|
|
2021-01-21 20:45:03 +00:00
|
|
|
const approx = `${utils.random(words[_template])} `;
|
2021-01-10 12:33:00 +00:00
|
|
|
|
2021-01-21 20:45:03 +00:00
|
|
|
return `${approx}\n${str.toLowerCase()}`;
|
|
|
|
};
|
2021-01-10 12:33:00 +00:00
|
|
|
|
2021-01-21 20:45:03 +00:00
|
|
|
const formatters = {
|
|
|
|
'onTheHour': (hoursAsWord) => {
|
|
|
|
const exactly = utils.random(words.exactly);
|
2021-01-10 12:33:00 +00:00
|
|
|
|
2021-01-21 20:45:03 +00:00
|
|
|
return `${hoursAsWord}\n${exactly}`;
|
|
|
|
},
|
|
|
|
'nearTheHour': (hoursAsWord, minutes) => {
|
|
|
|
const template = (minutes < 10) ? 'past' : 'approach';
|
|
|
|
|
|
|
|
return makeApprox(hoursAsWord, template);
|
|
|
|
},
|
|
|
|
'nearQuarter': (hoursAsWord, minutes) => {
|
|
|
|
const direction = (minutes > 30) ? 'to' : 'past';
|
|
|
|
const quarter = utils.random(words.quarter);
|
|
|
|
const formatted = `${quarter} ${direction}\n${hoursAsWord}`;
|
|
|
|
|
|
|
|
return (minutes === 15 || minutes === 45) ? formatted : makeApprox(formatted);
|
|
|
|
},
|
|
|
|
'nearHalf': (hoursAsWord, minutes) => {
|
|
|
|
const half = utils.random(words.half);
|
|
|
|
const formatted = `${half}\n${hoursAsWord}`;
|
|
|
|
const template = (minutes > 30) ? 'past' : 'approach';
|
|
|
|
|
|
|
|
return (minutes === 30) ? formatted : makeApprox(formatted, template);
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
function getFormatter(hours, minutes) {
|
|
|
|
if (minutes === 0) {
|
|
|
|
return 'onTheHour';
|
|
|
|
} else if (minutes > 50 || minutes < 10) {
|
|
|
|
return 'nearTheHour';
|
|
|
|
} else if (minutes > 40|| minutes < 20) {
|
|
|
|
return 'nearQuarter';
|
|
|
|
}
|
|
|
|
|
|
|
|
return 'nearHalf';
|
|
|
|
}
|
|
|
|
|
|
|
|
function drawDumbTime(hours, minutes, formatter) {
|
|
|
|
function formatTime(hours, minutes, formatter) {
|
|
|
|
const hoursAsWord = utils.hours2Word(hours, minutes);
|
2021-01-10 12:33:00 +00:00
|
|
|
|
|
|
|
return formatter(hoursAsWord, minutes);
|
|
|
|
}
|
|
|
|
|
2021-01-21 20:45:03 +00:00
|
|
|
utils.print(formatTime(hours, minutes, formatter));
|
2021-01-10 12:33:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function cancelTimeout() {
|
|
|
|
if (secondInterval) {
|
|
|
|
clearTimeout(secondInterval);
|
|
|
|
}
|
|
|
|
|
|
|
|
secondInterval = undefined;
|
|
|
|
}
|
|
|
|
|
2021-01-21 20:45:03 +00:00
|
|
|
function refreshTime(force) {
|
|
|
|
function clearForRefresh() {
|
|
|
|
g.clearRect(0, 24, g.getWidth(), g.getHeight()-24);
|
|
|
|
g.reset();
|
|
|
|
g.setFontAlign(0,0);
|
|
|
|
}
|
2021-01-10 12:33:00 +00:00
|
|
|
|
2021-01-21 20:45:03 +00:00
|
|
|
function setRefreshInterval(time) {
|
|
|
|
const secondsTillRefresh = 60 - time.getSeconds();
|
|
|
|
secondInterval = setTimeout(refreshTime, secondsTillRefresh * 1000);
|
|
|
|
|
|
|
|
return secondInterval;
|
|
|
|
}
|
|
|
|
|
|
|
|
force = force === true;
|
|
|
|
cancelTimeout();
|
2021-01-10 12:33:00 +00:00
|
|
|
|
|
|
|
const time = new Date();
|
|
|
|
|
2021-01-21 20:45:03 +00:00
|
|
|
if (showRealTime) {
|
|
|
|
clearForRefresh();
|
|
|
|
drawRealTime(time);
|
|
|
|
return setRefreshInterval(time);
|
|
|
|
}
|
2021-01-10 12:33:00 +00:00
|
|
|
|
2021-01-21 20:45:03 +00:00
|
|
|
const hours = time.getHours();
|
|
|
|
const minutes = time.getMinutes();
|
|
|
|
const formatter = getFormatter(hours, minutes);
|
2021-01-10 12:33:00 +00:00
|
|
|
|
2021-01-21 20:45:03 +00:00
|
|
|
if (formatter !== currentFormatter) {
|
|
|
|
clearForRefresh();
|
|
|
|
currentFormatter = formatter;
|
|
|
|
drawDumbTime(hours, minutes, formatters[formatter]);
|
|
|
|
}
|
2021-01-10 12:33:00 +00:00
|
|
|
|
2021-01-21 20:45:03 +00:00
|
|
|
return setRefreshInterval(time);
|
2021-01-10 12:33:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function startClock() {
|
2024-03-04 20:34:50 +00:00
|
|
|
/*const secondsToRefresh =*/ refreshTime();
|
2021-01-10 12:33:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function addEvents() {
|
|
|
|
Bangle.on('lcdPower', (on) => {
|
|
|
|
cancelTimeout();
|
2021-01-21 20:45:03 +00:00
|
|
|
currentFormatter = null;
|
2021-01-10 12:33:00 +00:00
|
|
|
if (on) {
|
|
|
|
startClock();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-07-28 09:54:22 +00:00
|
|
|
// Show launcher when button pressed
|
|
|
|
Bangle.setUI("clockupdown", btn=>{
|
|
|
|
if (btn<0) switchMode();
|
|
|
|
if (btn>0) {
|
|
|
|
currentFormatter = null;
|
|
|
|
refreshTime();
|
|
|
|
}
|
2021-01-10 12:33:00 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function init() {
|
|
|
|
g.clear();
|
|
|
|
|
|
|
|
startClock();
|
|
|
|
Bangle.loadWidgets();
|
2021-07-28 09:54:22 +00:00
|
|
|
Bangle.drawWidgets();
|
2021-01-10 12:33:00 +00:00
|
|
|
|
|
|
|
addEvents();
|
|
|
|
}
|
|
|
|
|
2021-07-28 09:54:22 +00:00
|
|
|
init();
|