Prof. Werner Antweiler, Ph.D.
This is exam season at UBC. I often find myself in a classroom
where there is no clock, or the clock is in a far corner where
most students will be unable to see it. To compensate for the lack
of time-keeping pieces in our classrooms, our internet-savvy generation
relies on the web to provide a solution. There are numerous clocks that
you can display, such as those on the Time and Date web site or the The Time Now web site. For example, you can find a
digital clock for Vancouver that is simple and convenient and appears as yellow numbers on a black background. Another option is available at
TheTimeNow.com.
I would like to display additional information for my students, and
I also prefer the look of an old-fashioned analog clock to show the time.
Rüdiger Appel has written a beautfiul little SVG script that shows a German railway station clock, a "Bahnhofsuhr". It is available under a free license
and I have incorporated it into my own script, which is also availble
under a free license (GPL) and is published below. If you like my clock, go to
my
exam clock to set the start and finish time of the exam, and the new window will show
the analog clock along with a dial for the elapsed and remaining exam time.
This is what it looks like:
The dial changes color as it approaches the end of the exam.
It starts out as a solid green and turns to a yellow-green
20 minutes before the end of the exam. At the 15-minute mark
it turns to yellow, and at the 10-minute mark to orange.
During the last five minutes, the dial turns to red.
An additional field provides instructions such as "START" at the beginning
and "STOP" at the end, and "WAIT" before the exam starts. During most of the
exam in progress the field shows the current time digitally. And yes,
I am on a European 00-23 time scale. The most important feature is that
the minutes left in the exam period are shown underneath the dial.
The SVG implementation of my exam dial creates a rectangular
image of 240-by-320 pixels that is suitably magnified by a factor
of two. The bulk of the code is JavaScript that updates the text
and the dial. The SVG script requires some interaction with PHP for
setting the start and finish time, provided as variables $hh0,
$mm0, $hh1, and $mm1, for hours and minutes, respectively.
The heavy lifting in the Javascript is done by the window.setInterval
and window.setTimeout functions. These are convenient ways to
make the dial and text dynamic, or to provide initial information
on start-up. Except for the Javascript, the SVG script is very
compact. The only elements that are somewhat more difficult to
understand are the path elements in SVG. To make the dial work,
the path elements need to be updated every second by calculating
the coordinates of the two end points that are moving.
Let me know if you find my exam dial and clock useful, or
if you have ideas about how to improve it.
<?xml version="1.0" encoding="utf-8"?>
<!--
exam-dial.svg
Copyright (c) 2014 Werner Antweiler
Date: 2014-12-08
Version: 1.0
Email: werner@sauder.ubc.ca
Licensed under GNU Public License terms.
-->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ev="http://www.w3.org/2001/xml-events"
version="1.1"
width="480"
height="640"
baseProfile="full"
viewBox="0 0 240 320">
<defs>
<script type="text/javascript">
<![CDATA[
window.setTimeout(function() {
var z = document.getElementById('today');
if (z) {
var now=new Date();
var dayName=new Array("Sunday","Monday","Tuesday",
"Wednesday","Thursday","Friday","Saturday");
var monName=new Array("January","February","March",
"April","May","June","July","August",
"September","October","November","December");
z.textContent=dayName[now.getDay()] + ", "
+ monName[now.getMonth()] + " " + now.getDate()
+ ", " +now.getFullYear();
}
},60);
window.setInterval(function() {
var hh0 = <?php echo $hh0; ?>;
var mm0 = <?php echo $mm0; ?>;
var hh1 = <?php echo $hh1; ?>;
var mm1 = <?php echo $mm1; ?>;
var now = new Date();
var yy = now.getFullYear();
var mm = now.getMonth();
var dd = now.getDate();
var hh = now.getHours();
var mi = now.getMinutes();
var from = new Date(yy,mm,dd,hh0,mm0,0,0);
var thru = new Date(yy,mm,dd,hh1,mm1,0,0);
var duration= (thru-from)/60/1000;
var left = (thru-now)/60/1000;
var gone = (now-from)/60/1000;
var hhmm = (hh<10?"0"+hh:hh)+":"+(mi<10?"0"+mi:mi);
notify(Math.floor(gone),Math.ceil(duration),hhmm);
if (left<0) left=0;
else if (left>duration) left=duration;
timeleft(Math.ceil(left));
advancedial((now-from)/(thru-from),Math.ceil(left));
}, 1000);
function timeleft(minutes) {
var element = document.getElementById('timeleft');
if (element) {
element.textContent=minutes;
if (minutes>100) size=52;
else if (minutes>10) size=60;
else size=72;
element.setAttribute('font-size',size);
}
}
function notify(minutes,duration,hhmm) {
element = document.getElementById('what');
if (element) {
if (minutes>=duration) { text="STOP"; color="red"; }
else if (minutes<0) { text="WAIT"; color="orange"; }
else if (minutes<=5) { text="START"; color="navy"; }
else { color="navy"; text=hhmm; }
element.textContent=text;
element.setAttribute('fill',color);
}
}
function advancedial(ratio,minutes) {
var element = document.getElementById('dial');
if (element) {
var angle=0.0;
if (ratio<0.0) { angle=0.0; }
else if (ratio>1.0) { angle=Math.PI; }
else { angle=Math.PI*ratio; }
var x0=120.0-110.0*Math.cos(angle);
var y0=120.0-110.0*Math.sin(angle);
var x1=120.0- 60.0*Math.cos(angle);
var y1=120.0- 60.0*Math.sin(angle);
var path="M10,120A110,110 0 0,1 " + x0 + "," + y0 +
"L" + x1 + "," + y1 + "A60,60 0 0,0 60,120Z";
element.setAttribute('d',path);
if (minutes<=5) color="red";
else if (minutes<=10) color="orange";
else if (minutes<=20) color="yellow";
else if (minutes<=30) color="lime";
else color="green";
var text='stroke:navy;stroke-width:2;fill:'+color;
element.setAttribute('style',text);
}
}
]]>
</script>
</defs>
<path style="fill:beige;stroke:navy;stroke-width:2;"
d="M10,120A110,110 0 0,1 230,120L180,120A60,60 0 0,0 60,120Z"/>
<path id="dial" style="fill:beige;stroke:navy;stroke-width:2;"
d="M10,120A110,110 0 0,1 230,120L180,120A60,60 0 0,0 60,120Z"/>
<text id="timeleft" x="120" y="120" font-family="Helvetica"
font-size="60" fill="navy" text-anchor="middle"></text>
<text id="timeleft" x="120" y="155" font-family="Helvetica"
font-size="30" fill="navy"
text-anchor="middle">MINUTES LEFT</text>
<rect x="10" y="180" height="30" width="220"
style="fill:white;stroke-width:1;stroke:navy;"/>
<text x="120" y="200" font-family="Helvetica" font-size="15"
fill="navy" text-anchor="middle" id="today"></text>
<rect x="10" y="230" height="80" width="220"
style="fill:beige;stroke-width:1;stroke:navy;"/>
<text x="120" y="290" font-family="Helvetica" font-size="60"
fill="navy" text-anchor="middle" id="what"></text>
</svg>
Click here to access
the SVG code, then save the file through your web browser.