Drawing a clock is often a diagnotic in evaluating dementia. Here are some examples from tests. My idea is to use some of these inconsistent clocks as starting points, but to then add additional logic so that the clocks can actually tell time.
<head>
<style> body {padding: 0; margin: 0;} </style>
</head>
<body style="background-color:white">
<img src="sketch.jpg" width="960" height="500"/>
<br>
<a href="part1.html">part1</a>
<a href="part2.html">part2</a>
<a href="clock.html">clock</a>
<a href="debug.html">debug</a>
</body>
/*
* use p5.js to draw a clock on a 960x500 canvas
*/
function draw_clock(obj) {
// draw your own clock here based on the values of obj:
// obj.hours goes from 0-23
// obj.minutes goes from 0-59
// obj.seconds goes from 0-59
// obj.millis goes from 0-999
// obj.seconds_until_alarm is:
// < 0 if no alarm is set
// = 0 if the alarm is currently going off
// > 0 --> the number of seconds until alarm should go off
background(0);
const ballWidth = 100;
fill(255, 255, 0);
let secs = obj.seconds;
let millis = obj.millis;
let exactSeconds = secs + millis / 1000.0;
posX = map(exactSeconds, 0, 60, ballWidth/2, width-ballWidth/2);
posY = map(60, 0, 100, 0, height);
ellipse(posX, posY, ballWidth);
fill(255);
posX = map(obj.minutes, 0, 59, ballWidth/2, width-ballWidth/2);
posY = map(40, 0, 100, 0, height);
ellipse(posX, posY, ballWidth);
posX = map(obj.hours, 0, 23, ballWidth/2, width-ballWidth/2);
posY = map(20, 0, 100, 0, height);
ellipse(posX, posY, ballWidth);
}
/*
* us p5.js to draw a clock on a 960x500 canvas
*/
function draw_clock(obj) {
// draw your own clock here based on the values of obj:
// obj.hours goes from 0-23
// obj.minutes goes from 0-59
// obj.seconds goes from 0-59
// obj.millis goes from 0-999
// obj.seconds_until_alarm is:
// < 0 if no alarm is set
// = 0 if the alarm is currently going off
// > 0 --> the number of seconds until alarm should go off
let hours = obj.hours;
let minutes = obj.minutes;
let seconds = obj.seconds;
let millis = obj.millis;
let alarm = obj.seconds_until_alarm;
background(255,255,200); // beige
fill(128,100,100); // dark grey
text("Hour: " + hours, 10, 22);
text("Minute: " + minutes, 10, 42);
text("Second: " + seconds, 10, 62);
text("Millis: " + millis, 10, 82);
let hourBarWidth = map(hours, 0, 23, 0, width);
let minuteBarWidth = map(minutes, 0, 59, 0, width);
let secondBarWidth = map(seconds, 0, 59, 0, width);
let millisBarWidth = map(millis, 0, 1000, 0, width);
noStroke();
fill(40);
rect(0, 100, hourBarWidth, 50);
fill(80);
rect(0, 150, minuteBarWidth, 50);
fill(120)
rect(0, 200, secondBarWidth, 50);
fill(160)
rect(0, 250, millisBarWidth, 50);
// Make a bar which *smoothly* interpolates across 1 minute.
// We calculate a version that goes from 0...60,
// but with a fractional remainder:
let secondBarWidthChunky = map(seconds, 0, 59, 0, width);
let secondsWithFraction = seconds + (millis / 1000.0);
let secondBarWidthSmooth = map(secondsWithFraction, 0, 60, 0, width);
fill(100, 100, 200)
rect(0, 350, secondBarWidthChunky, 50);
fill(120, 120, 240)
rect(0, 400, secondBarWidthSmooth, 50);
text("Minute: " + secondsWithFraction, 200, 42);
fill(200, 100, 100)
let alarm_message = ""
if(alarm < 0) {
alarm_message = "Alarm: Not Set"
}
else if(alarm == 0) {
alarm_message = "Alarm: GOING OFF"
}
else {
let seconds_remaining = int(alarm);
alarm_message = "Alarm: will go off in " + seconds_remaining + " seconds"
}
text(alarm_message, 400, 42);
}
/*
* us p5.js to draw a clock on a 960x500 canvas
*/
/* size of square */
const s = 24
let numbers = [
// 0
[
[2, 1],
[3, 1],
[1, 2],
[4, 2],
[1, 3],
[4, 3],
[1, 4],
[4, 4],
[2, 5],
[3, 5],
],
// 1
[
[2, 2],
[3, 1],
[3, 2],
[3, 3],
[3, 4],
[3, 5]
],
// 2
[
[1, 1],
[2, 1],
[3, 1],
[4, 2],
[4, 3],
[3, 3],
[2, 4],
[1, 5],
[2, 5],
[3, 5],
[4, 5]
],
[ // 3
[1, 1],
[2, 1],
[3, 1],
[4, 2],
[3, 3],
[2, 3],
[4, 4],
[3, 5],
[2, 5],
[1, 5]
],
[ // 4
[1, 1],
[3, 1],
[1, 2],
[3, 2],
[1, 3],
[2, 3],
[3, 3],
[4, 3],
[3, 4],
[3, 5]
],
[ // 5
[1, 1],
[2, 1],
[3, 1],
[4, 1],
[1, 2],
[1, 3],
[2, 3],
[3, 3],
[4, 4],
[3, 5],
[2, 5],
[1, 5]
],
[ // 6
[2, 1],
[3, 1],
[4, 1],
[1, 2],
[1, 3],
[2, 3],
[3, 3],
[1, 4],
[4, 4],
[2, 5],
[3, 5],
], //7
[
[1, 1],
[2, 1],
[3, 1],
[4, 1],
[4, 2],
[3, 3],
[3, 4],
[3, 5],
],
[ // 8
[2, 1],
[3, 1],
[1, 2],
[4, 2],
[2, 3],
[3, 3],
[1, 4],
[4, 4],
[2, 5],
[3, 5],
],
[ // 9
[2, 1],
[3, 1],
[4, 1],
[1, 2],
[4, 2],
[2, 3],
[3, 3],
[4, 3],
[4, 4],
[4, 5]
],
]
function draw_number(num, x, y) {
/* this resets any previous translations */
resetMatrix();
translate(x, y);
var pixels = numbers[num%numbers.length];
for(var i=0; i<13; i++) {
var cur_pixel = pixels[i%pixels.length];
rect(cur_pixel[0] * s, cur_pixel[1] * s, s, s);
}
}
function draw_number_interp(frac, num1, num2, x, y) {
/* this resets any previous translations */
resetMatrix();
translate(x, y);
var pixels1 = numbers[num1%numbers.length];
var pixels2 = numbers[num2%numbers.length];
for(var i=0; i<13; i++) {
var cur_pixel1 = pixels1[i%pixels1.length];
var cur_pixel2 = pixels2[i%pixels2.length];
var pos_x = map(frac, 0.0, 1.0, cur_pixel1[0], cur_pixel2[0]);
var pos_y = map(frac, 0.0, 1.0, cur_pixel1[1], cur_pixel2[1]);
rect(pos_x * s, pos_y * s, s, s);
}
}
function digits_from_num(num) {
let digits = []
if (num < 10) {
digits.push(0);
}
else {
n1 = Math.floor(num / 10);
digits.push(n1);
}
n2 = Math.floor(num % 10);
digits.push(n2);
return digits;
}
function draw_clock(obj) {
let hour = obj.hours;
let minute = obj.minutes;
let second = obj.seconds;
let millis = obj.millis;
let alarm = obj.seconds_until_alarm;
var hour_pos = [40, height/2 - 3.5 * s];
// DEBUG CODE TO TEST HOUR ROLLOVER
// minute = minute + 35; // change based on current time
// if (minute == 60) {
// minute = 0;
// hour = 0;
// }
// is alarm going off?
if (alarm == 0) {
if (second % 2 == 0) {
background(0,0,100);
}
else {
background(100,100,0);
}
}
else {
background(50);
}
noStroke();
// is alarm going off in next 15 seconds
if (alarm > 0) {
fill(100);
rect(width-50, height-50, 40, 40);
if (alarm < 15.0) {
var box_w = map(alarm, 0, 15, width, 0);
var box_h = map(alarm, 0, 15, height, 0);
rect(width/2-box_w/2, height/2-box_h/2, box_w, box_h);
}
}
fill(255);
// HOURS
next_hour = (hour + 1) % 24;
digits1 = digits_from_num(hour);
digits2 = digits_from_num(next_hour);
if(second >= 50 && minute == 59 &&
(hour == 9 || hour == 19 || hour == 23)) {
// minute_fraction_tens = millis / 1000.0;
seconds_left = (second - 50) + millis / 1000.0;
hour_fraction_tens = seconds_left / 10.0;
}
else {
hour_fraction_tens = 0;
}
draw_number_interp(hour_fraction_tens, digits1[0], digits2[0], hour_pos[0] + 0.0 * 5 * s, hour_pos[1]);
// draw_number(digits1[0], hour_pos[0], hour_pos[1]);
if(second >= 55 && minute == 59) {
// minute_fraction_tens = millis / 1000.0;
seconds_left = (second - 55) + millis / 1000.0;
hour_fraction_ones = seconds_left / 5.0;
}
else {
hour_fraction_ones = 0;
}
draw_number_interp(hour_fraction_ones, digits1[1], digits2[1], hour_pos[0] + 1.0 * 5 * s, hour_pos[1]);
// draw_number(digits1[1], hour_pos[0] + 1.0 * 5 * s, hour_pos[1]);
// MINUTES
next_minute = (minute + 1) % 60;
digits1 = digits_from_num(minute);
digits2 = digits_from_num(next_minute);
if(second >= 58 && digits1[1] === 9) {
// minute_fraction_tens = millis / 1000.0;
seconds_left = (second - 58) + millis / 1000.0;
minute_fraction_tens = seconds_left / 2.0;
}
else {
minute_fraction_tens = 0;
}
draw_number_interp(minute_fraction_tens, digits1[0], digits2[0], hour_pos[0] + 2.5 * 5 * s, hour_pos[1]);
if(second === 59) {
minute_fraction_ones = millis / 1000.0;
}
else {
minute_fraction_ones = 0;
}
draw_number_interp(minute_fraction_ones, digits1[1], digits2[1], hour_pos[0] + 3.5 * 5 * s, hour_pos[1]);
// draw_number(digits1[1], hour_pos[0] + 3.5 * 5 * s, hour_pos[1]);
// SECONDS
next_second = (second + 1) % 60;
second_fraction = millis / 1000.0;
digits1 = digits_from_num(second);
digits2 = digits_from_num(next_second);
// print(digits1);
if(digits1[1] === 9 && millis > 500) {
second_fraction_tens = (millis - 500) / 500.0;
}
else {
second_fraction_tens = 0;
}
// draw the 10 second position
draw_number_interp(second_fraction_tens, digits1[0], digits2[0], hour_pos[0] + 5.0 * 5 * s, hour_pos[1]);
if(millis > 900) {
second_fraction_ones = (millis-900) / 100.0;
}
else {
second_fraction_ones = 0;
}
// draw the 1 second position
draw_number_interp(second_fraction_ones, digits1[1], digits2[1], hour_pos[0] + 6.0 * 5 * s, hour_pos[1]);
}
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/addons/p5.dom.js"></script>
<script language="javascript" type="text/javascript" src="z_purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="debug.js"></script>
<script language="javascript" type="text/javascript" src="clock.js"></script>
<script language="javascript" type="text/javascript" src="runner.js"></script>
</head>
<body style="background-color:white">
<div class="outer">
<div class="inner">
<div id="canvasContainer"></div>
</div>
</div>
</table>
<body style="background-color:white">
<div class="outer">
<div class="inner">
<div id="canvasContainer"></div>
</div>
<div class="inner" id="controls">
<table>
<tr>
<td>debug</td>
<td id="checkboxDebug"></td>
</tr>
<tr>
<td>hours</td>
<td id="sliderHours"></td>
<td>minutes</td>
<td id="sliderMinutes"></td>
<td>seconds</td>
<td id="sliderSeconds"></td>
<td>millis</td>
<td id="sliderMillis"></td>
</tr>
<tr>
<td>alarm</td>
<td id="checkboxAlarm"></td>
<td>alarm_secs</td>
<td id="sliderAlarm"></td>
</tr>
</table>
</div>
</div>
</table>
</body>
<br>
<a href="part1.html">part1</a>
<a href="part2.html">part2</a>
<a href="clock.html">clock</a>
<a href="debug.html">debug</a>
</body>
var DEBUG=true;
var debugCheckbox;
var hourSlider;
var minSlider;
var secSlider;
var millisSlider;
var alarmSlider;
function debug_setup() {
debugCheckbox = createCheckbox('', false);
debugCheckbox.parent("checkboxDebug")
hourSlider = createSlider(0, 23, 12);
hourSlider.parent("sliderHours")
minSlider = createSlider(0, 59, 0);
minSlider.parent("sliderMinutes")
secSlider = createSlider(0, 59, 0);
secSlider.parent("sliderSeconds")
millisSlider = createSlider(0, 999, 0);
millisSlider.parent("sliderMillis")
alarmCheckbox = createCheckbox('', false);
alarmCheckbox.parent("checkboxAlarm")
alarmSlider = createSlider(0, 60, 0);
alarmSlider.parent("sliderAlarm")
}
// Update this function to draw you own maeda clock on a 960x500 canvas
function draw_clock(obj) {
// YOUR MAIN CLOCK CODE GOES HERE
background(50); // beige
fill(200); // dark grey
textSize(40);
textAlign(CENTER, CENTER);
text("YOUR MAEDA CLOCK CODE GOES HERE", width/2, height/2);
}
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/addons/p5.dom.js"></script>
<script language="javascript" type="text/javascript" src="z_purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="maeda_clock.js"></script>
<script language="javascript" type="text/javascript" src="runner.js"></script>
</head>
<body style="background-color:white">
<div class="outer">
<div class="inner">
<div id="canvasContainer"></div>
</div>
</div>
</table>
<br>
<a href="maeda_clock.js">(source code)</a>
<a href="part1.html">part1</a>
<a href="part2.html">part2</a>
<a href="clock.html">clock</a>
<a href="debug.html">debug</a>
</body>