Photographing Chess Clock

Discussion of anything and everything relating to chess playing software and machines.

Moderators: hgm, Rebel, chrisw

User avatar
GONeill
Posts: 87
Joined: Sun Jun 15, 2014 6:40 am
Location: New Zealand
Full name: Graham O'Neill

Re: Photographing Chess Clock

Post by GONeill »

That's much better, thanks! I hadn't realised there was a Webcam.loaded value.

I've made a few more changes, such as showing the colours in red and playing a sound when time is up. And a personal preference for me was that any key should swap the clocks rather than dividing the keyboard in two, so I changed the KeyHit function (as well as tidying it up slightly for editing the time). I also preferred to have a button for taking back moves.

Code: Select all

<!doctype html>

<html lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<title>Chess Clock</title>
	<style type="text/css">
		body &#123; font-family&#58; Helvetica, sans-serif; &#125;
		h2, h3 &#123; margin-top&#58;0; &#125;
		form &#123; margin-top&#58; 15px; &#125;
		form > input &#123; margin-right&#58; 15px; &#125;
	</style>
</head>
<body>
<div align="center">
<table cellpadding="10"><tr><td>
	<h2>Life image&#58;</h2>
	<div id="my_camera"></div>
</td><td valign="top">
	<h1>Webcam Chess Clock</h1>
	<p><b>Start times, in seconds&#58;</b></p>
	<ul>
		<li>Sudden death&#58; basetime, e.g. 600</li>
		<li>Fischer&#58; basetime+inc, e.g. 120+10</li>
		<li>Bronstein&#58; basetime-deadtime, e.g. 300-10</li>
		<li>Classical&#58; basetime/moves, e.g. 300/40</li>
	</ul>
	<p>Space bar stops the clocks.</p>
</td><td>
	<div id="results"><div style="border&#58;1px;background&#58;#cccccc;padding&#58;20px;">Your captured image will appear here...</div></div>
</td></tr></table>
	
	<!-- First, include the Webcam.js JavaScript Library -->
	<script type="text/javascript" src="./webcam2.js"></script>
	
	<!-- Configure a few settings and attach camera -->
	<script language="JavaScript">
		// =======================================
		var FLIP = false;
		var LNAME = 'White';
		var RNAME = 'Black';
		var snd = new Audio&#40;"TimeUp.wav");
		// =======================================
		Webcam.set&#40;&#123;
			width&#58; 320,
			height&#58; 240,
			crop_height&#58; 150,
			crop_width&#58; 320,
			flip_horiz&#58; FLIP,
			image_format&#58; 'jpeg',
			jpeg_quality&#58; 90
		&#125;);
		Webcam.attach&#40; '#my_camera' );
	</script>
	
	<!-- A button for taking snaps -->
	<form>
		<input type=button value="Take Snapshot" onClick="take_snapshot&#40;)">
		Start time&#58; <input type=text value="3600" id="starttime">
		<input type=button value="Reset Clocks" onClick="SetClock&#40;)">
		<input type=button value="Swap Players" onClick="Swap&#40;)">
		<input type=button value="Take Back" onClick="AdjustCount&#40;)">
		<input type=button value="<<" onClick="GoTo&#40;0&#41;">
		<input type=button value="<" onClick="GoTo&#40;-1&#41;">
		<input type=button value=">" onClick="GoTo&#40;1&#41;">
		<input type=button value=">>" onClick="GoTo&#40;9999&#41;">
	</form>

	<p id="key" style="background&#58;#8080FF;"></p>

	<table cellpadding="10" border="1"><tr>
		<td id="player1" style="font-size&#58;75px;" align="center">
		<script>document.write&#40;LNAME&#41;;</script></td>
		<td id="movenr"  style="font-size&#58;75px;" align="center" width="15%">0</td>
		<td id="player2" style="font-size&#58;75px; "align="center">
		<script>document.write&#40;RNAME&#41;;</script></td>
	</tr><tr>
		<td id="clock1" style="font-size&#58;150px;" align="right" width="50%" colspan="2"></td>
		<td id="clock2" style="font-size&#58;150px;" align="right" width="50%"></td>
	</tr></table>
</div>

	<!-- Code to handle taking the snapshot and displaying it locally -->
	<script language="JavaScript">
		var images = new Array&#40;);
		var nrOfImages = 0;
		var times = new Array&#40;);
		var active = 0, ticks = 0;
		var deadTime = 0, session = 0, nr = 0;
		var current = 0;
		times&#91;1&#93; = times&#91;2&#93; = 36000;
		times&#91;3&#93; = times&#91;4&#93; = times&#91;5&#93; = times&#91;6&#93; = times&#91;9&#93; = 0;
		DisplayTime&#40;1, times&#91;1&#93;);
		DisplayTime&#40;2, times&#91;2&#93;);

		window.addEventListener&#40;"keydown", KeyHit, false&#41;;

		var timer = setTimeout&#40;"Clock&#40;);", 100&#41;;

		function Display&#40;n&#41; &#123;
			document.getElementById&#40;'results').innerHTML = 
				'<h2>Captured image ' + n + '&#58;</h2>' + 
				'<img src="'+images&#91;n&#93;+'"/>';
		&#125;

		function take_snapshot&#40;) &#123;
			if&#40;Webcam.loaded&#41; &#123;
				// take snapshot and get image data
				Webcam.snap&#40; function&#40;data_uri&#41; &#123;
					// display results in page
					document.getElementById&#40;'results').innerHTML = 
						'<h2>Captured image&#58;</h2>' + 
						'<img src="'+data_uri+'"/>';
					current = nrOfImages;
					images&#91;nrOfImages++&#93; = data_uri; // save the snapshot
				&#125; );
			&#125;
		&#125;
			
		function SecToTime&#40;t&#41; &#123;
			var s = 0; if&#40;t<0&#41; &#123; s = 1; t = -t; &#125;
			t = &#40;t - t%10&#41;/10;
			var sec = t % 60; t = &#40;t - sec&#41;/60; if&#40;sec < 10&#41; sec = '0' + sec;
			var min = t % 60; t = &#40;t - min&#41;/60; if&#40;min < 10&#41; min = '0' + min;
			return s ? '-' + min + '&#58;' + sec &#58; t + '&#58;' + min + '&#58;' + sec;
		&#125;

		function DisplayTime&#40;n, t&#41; &#123;
			if&#40;t < 0&#41; document.getElementById&#40;"clock" + n&#41;.style.background = "red";
			if&#40;t == -1&#41; snd.play&#40;);
			document.getElementById&#40;"clock" + n&#41;.innerHTML = SecToTime&#40;t&#41;;
		&#125;

		function Clock&#40;) &#123;
			if&#40;active&#41; &#123;
				if&#40;--deadTime < 0&#41; times&#91;active&#93;--;
				if&#40;&#40;times&#91;active&#93;+1&#41;%10 == 0&#41; DisplayTime&#40;active, times&#91;active&#93;);
			&#125;
			ticks++; timer = setTimeout&#40;"Clock&#40;);", 100&#41;;
		&#125;

		var lastActive = 0;

		function Switch&#40;side&#41; &#123;
			if&#40;side == active&#41; return;
			if&#40;active&#41; &#123;
				if&#40;times&#91;active&#93; < 0&#41; document.getElementById&#40;"clock" + active&#41;.style.color = "red"; else
				                      document.getElementById&#40;"clock" + active&#41;.style.color = "black";
				document.getElementById&#40;"clock" + active&#41;.style.background = "white";
				if&#40;Webcam.loaded&#41; take_snapshot&#40;); else
				document.getElementById&#40;"results").innerHTML =
					'<div style="background&#58;#FF0000;border&#58;1px;padding&#58;20px">Webcam not available</div>';
			&#125;
			active = side;
			if&#40;active&#41; &#123;
				if&#40;active != lastActive&#41; &#123;
					session--; document.getElementById&#40;"movenr").innerHTML = 1 + ++nr >> 1;
					times&#91;active&#93; += times&#91;active+2&#93;; // Fischer increment
				&#125;
				if&#40;session == 0&#41; &#123; session = times&#91;9&#93;; times&#91;1&#93; += times&#91;7&#93;; times&#91;2&#93; += times&#91;8&#93;; &#125; 
				lastActive = active;
				document.getElementById&#40;"clock" + active&#41;.style.color = "white";
				document.getElementById&#40;"clock" + active&#41;.style.background = "black";
				deadTime = times&#91;active+4&#93;; // Bronstein delay
				DisplayTime&#40;active, times&#91;active&#93;);
			&#125;
		&#125;

		var digit = '1234567890-+/';
		var lastKey = 0;

		function KeyHit&#40;ev&#41; &#123;
			var c = ev.key;
			if&#40;!active&#41; &#123;
				// for typing start time
				if&#40;digit.search&#40;c&#41; >= 0 || c == 'Shift' || c == 'Backspace' || c == 'Delete' || c == 'ArrowLeft' || c == 'ArrowRight') return;
				if&#40;c == 'Enter') &#123;
					SetClock&#40;);
					ev.preventDefault&#40;);
					return;
				&#125;
			&#125;
			lastKey = ticks;
			if&#40;c == ' ') Switch&#40;0&#41;; else
			if&#40;active <= 1&#41; Switch&#40;2&#41;; else
			if&#40;active == 2&#41; Switch&#40;1&#41;;
			ev.preventDefault&#40;);
		&#125;

		function GoTo&#40;n&#41; &#123;
			if&#40;Webcam.loaded&#41; &#123;
				if&#40;!n&#41; current = n; else if&#40;n == 9999&#41; current = nrOfImages - 1; else current += n;
				if&#40;current < 0&#41; current = 0; else if &#40;current >= nrOfImages&#41; current = nrOfImages - 1;
				Display&#40;current&#41;;
			&#125;
		&#125;

		function SetClock&#40;) &#123;
			var newTime = document.getElementById&#40;"starttime").value;
			if&#40;active || ticks - lastKey < 2&#41; return;
			times&#91;1&#93; = times&#91;2&#93; = times&#91;7&#93; = times&#91;8&#93; = 10*parseInt&#40;newTime&#41;;
			times&#91;3&#93; = times&#91;4&#93; = times&#91;5&#93; = times&#91;6&#93; = 0; times&#91;9&#93; = -1;
			var s = newTime.split&#40;'+');
			if&#40;s.length > 1&#41; times&#91;3&#93; = times&#91;4&#93; = 10*parseInt&#40;s&#91;1&#93;);
			s = newTime.split&#40;'-');
			if&#40;s.length > 1&#41; times&#91;5&#93; = times&#91;6&#93; = 10*parseInt&#40;s&#91;1&#93;);
			s = newTime.split&#40;'/');
			if&#40;s.length > 1&#41; times&#91;9&#93; = 2*parseInt&#40;s&#91;1&#93;);
			nrOfImages = current = nr = 0;
			session = times&#91;9&#93; + 1;
			document.getElementById&#40;"clock" + 1&#41;.style.color = "black";
			document.getElementById&#40;"clock" + 2&#41;.style.color = "black";
			DisplayTime&#40;1, times&#91;1&#93;); DisplayTime&#40;2, times&#91;2&#93;);
			times&#91;1&#93; -= times&#91;3&#93;; times&#91;2&#93; -= times&#91;4&#93;;
			document.getElementById&#40;"movenr").innerHTML = 1;
		&#125;

		function Swap&#40;) &#123;
			var h = times&#91;1&#93;; times&#91;1&#93; = times&#91;2&#93;; times&#91;2&#93; = h;
			var side = active; Switch&#40;0&#41;;
			h = document.getElementById&#40;"player1").innerHTML;
			document.getElementById&#40;"player1").innerHTML = document.getElementById&#40;"player2").innerHTML;
			document.getElementById&#40;"player2").innerHTML = h;
			DisplayTime&#40;1, times&#91;1&#93;); DisplayTime&#40;2, times&#91;2&#93;);
			if&#40;side&#41; &#123; lastActive = 3 -side; Switch&#40;3 - side&#41;; &#125; else Switch&#40;side&#41;;
		&#125;

		function AdjustCount&#40;) &#123;
			if&#40;nr < 2&#41; return;
			nr -= 2; session += 2;
			document.getElementById&#40;"movenr").innerHTML = 1 + nr >> 1;
		&#125;
	</script>
	
</body>
</html>
User avatar
hgm
Posts: 27836
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Photographing Chess Clock

Post by hgm »

What still is a bit annoying to me in Bronstein TC mode is that during the dead time there is no feedback at all howmuch time you still have left before the clock starts running down. I am not sure how this could be solved. I can display times[active] + deadTime whenever the latter is > 0. But then an upredictable amount of time will disappear from your clock when you press it while still in dead time.

I could of course slowly change the background color from green via yellow to red as the dead time runs out, always keeping times[active] in the display as I do now.
Jesse Gersenson
Posts: 593
Joined: Sat Aug 20, 2011 9:43 am

Re: Photographing Chess Clock

Post by Jesse Gersenson »

Add a count-down timer and make it 40-60% the size of the main clock.
Or, there could be maybe 7 vertical lines which disappear, one at a time.
User avatar
GONeill
Posts: 87
Joined: Sun Jun 15, 2014 6:40 am
Location: New Zealand
Full name: Graham O'Neill

Re: Photographing Chess Clock

Post by GONeill »

I wasn't keen on the colour change idea as it causes problems for the colour blind, and the problem with adding another clock is the amount of screen space used (especially if your laptop has a small display). So how about this version? I've added a progress bar type display for the countdown.

In Firefox pressing the spacebar after clicking on a button repeated that button's action so I've added focus() calls to prevent this. And I also found there were problems with the clocks and move counter if sides were swapped so I think I've fixed that too.

Code: Select all

<!doctype html>
<html lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<title>Chess Clock</title>
	<style type="text/css">
		body &#123; font-family&#58; Helvetica, sans-serif; &#125;
		table &#123;position&#58; relative;&#125;
		h2, h3 &#123; margin-top&#58;0; &#125;
		form &#123; margin-top&#58; 15px; &#125;
		form > input &#123; margin-right&#58; 15px; &#125;
		#bronbar &#123;position&#58;absolute; padding&#58;0px; height&#58;6px; bottom&#58;3px; width&#58;0px;&#125;
	</style>
</head>
<body>
<div align="center">
<table cellpadding="10"><tr><td>
	<h2>Live image&#58;</h2>
	<div id="my_camera"></div>
</td><td valign="top">
	<h1>Webcam Chess Clock</h1>
	<p><b>Start times, in seconds&#58;</b></p>
	<ul>
		<li>Sudden death&#58; basetime, e.g. 600</li>
		<li>Fischer&#58; basetime+inc, e.g. 120+10</li>
		<li>Bronstein&#58; basetime-deadtime, e.g. 300-10</li>
		<li>Classical&#58; basetime/moves, e.g. 300/40</li>
	</ul>
	<p>Space bar stops the clocks.</p>
</td><td>
	<div id="results"><div style="border&#58;1px;background&#58;#cccccc;padding&#58;20px;">Your captured image will appear here...</div></div>
</td></tr></table>

	<!-- First, include the Webcam.js JavaScript Library -->
	<script type="text/javascript" src="./webcam2.js"></script>

	<!-- Configure a few settings and attach camera -->
	<script language="JavaScript">
		// =======================================
		var FLIP = false;
		var LNAME = 'White';
		var RNAME = 'Black';
		var COLTIME = 'red';    // or 'black';
		var COLBRON = 'green';  // or 'black';
		var SNDFILE = new Audio&#40;"TimeUp.wav");	// or 'none';
		// =======================================
		Webcam.set&#40;&#123;
			width&#58; 320,
			height&#58; 240,
			crop_height&#58; 150,
			crop_width&#58; 320,
			flip_horiz&#58; FLIP,
			image_format&#58; 'jpeg',
			jpeg_quality&#58; 90
		&#125;);
		Webcam.attach&#40; '#my_camera' );
	</script>

	<!-- A button for taking snaps -->
	<form>
		<input type=button value="Take Snapshot" onClick="take_snapshot&#40;)">
		Start time&#58; <input type=text value="3600" id="starttime">
		<input type=button value="Reset Clocks" onClick="SetClock&#40;)">
		<input type=button value="Swap Players" onClick="Swap&#40;)">
		<input type=button value="Take Back" onClick="AdjustCount&#40;)">
		<input type=button value="<<" onClick="GoTo&#40;0&#41;">
		<input type=button value="<" onClick="GoTo&#40;-1&#41;">
		<input type=button value=">" onClick="GoTo&#40;1&#41;">
		<input type=button value=">>" onClick="GoTo&#40;9999&#41;">
	</form>

	<p id="key" style="background&#58;#8080FF;"></p>

	<table cellpadding="10" border="1"><tr>
		<td id="player1" style="font-size&#58;75px;" align="center"></td>
		<td id="movenr"  style="font-size&#58;75px;" align="center" width="15%">0</td>
		<td id="player2" style="font-size&#58;75px; "align="center"></td>
	</tr><tr>
		<td id="clock1" style="font-size&#58;150px;" align="right" width="50%" colspan="2"></td>
		<td id="clock2" style="font-size&#58;150px;" align="right" width="50%"></td>
	</tr><tr id="bronstein" style="height&#58;7px; display&#58;none;">
		<td style="padding&#58;0px;" colspan="3"><div id="bronbar"></div></td>
	</tr></table>
</div>

	<!-- Code to handle taking the snapshot and displaying it locally -->
	<script language="JavaScript">
		document.getElementById&#40;'player1').innerHTML = LNAME;
		document.getElementById&#40;'player2').innerHTML = RNAME;
		var images = new Array&#40;);
		var nrOfImages = 0;
		var times = new Array&#40;);
		var active = 0, ticks = 0;
		var deadTime = 0, session = 0, nr = 0;
		var current = 0;
		times&#91;1&#93; = times&#91;2&#93; = 36000;
		times&#91;3&#93; = times&#91;4&#93; = times&#91;5&#93; = times&#91;6&#93; = times&#91;9&#93; = 0;
		DisplayTime&#40;1, times&#91;1&#93;);
		DisplayTime&#40;2, times&#91;2&#93;);

		window.addEventListener&#40;"keydown", KeyHit, false&#41;;

		var timer = setTimeout&#40;"Clock&#40;);", 100&#41;;

		function Display&#40;n&#41; &#123;
			document.getElementById&#40;'results').innerHTML =
				'<h2>Captured image ' + n + '&#58;</h2>' +
				'<img src="'+images&#91;n&#93;+'"/>';
		&#125;

		function cursor_pos&#40;) &#123;
			document.getElementById&#40;'starttime').focus&#40;);
		&#125;

		function take_snapshot&#40;) &#123;
			if&#40;Webcam.loaded&#41; &#123;
				// take snapshot and get image data
				Webcam.snap&#40; function&#40;data_uri&#41; &#123;
					// display results in page
					document.getElementById&#40;'results').innerHTML =
						'<h2>Captured image&#58;</h2>' +
						'<img src="'+data_uri+'"/>';
					current = nrOfImages;
					images&#91;nrOfImages++&#93; = data_uri; // save the snapshot
				&#125; );
			&#125;
			cursor_pos&#40;);
		&#125;

		function SecToTime&#40;t&#41; &#123;
			var s = 0; if&#40;t<0&#41; &#123; s = 1; t = -t; &#125;
			t = &#40;t - t%10&#41;/10;
			var sec = t % 60; t = &#40;t - sec&#41;/60; if&#40;sec < 10&#41; sec = '0' + sec;
			var min = t % 60; t = &#40;t - min&#41;/60; if&#40;min < 10&#41; min = '0' + min;
			return s ? '-' + min + '&#58;' + sec &#58; t + '&#58;' + min + '&#58;' + sec;
		&#125;

		function DisplayTime&#40;n, t&#41; &#123;
			if&#40;active&#41; &#123;
				if&#40;t < 0&#41; document.getElementById&#40;"clock" + n&#41;.style.background = COLTIME;
				if&#40;t == -1 && SNDFILE !== 'none') SNDFILE.play&#40;);
			&#125;
			document.getElementById&#40;"clock" + n&#41;.innerHTML = SecToTime&#40;t&#41;;
		&#125;

		function Clock&#40;) &#123;
			if&#40;active&#41; &#123;
				if&#40;--deadTime < 0&#41; times&#91;active&#93;--; else
					document.getElementById&#40;'bronbar').style.width = &#40;deadTime*99/times&#91;active+4&#93;)+'%';
				if&#40;&#40;times&#91;active&#93;+1&#41;%10 == 0&#41; DisplayTime&#40;active, times&#91;active&#93;);
			&#125;
			ticks++; timer = setTimeout&#40;"Clock&#40;);", 100&#41;;
		&#125;

		var lastActive = 0;

		function Switch&#40;side&#41; &#123;
			if&#40;side == active&#41; return;
			if&#40;active&#41; &#123;
				if&#40;times&#91;active&#93; < 0&#41; document.getElementById&#40;"clock" + active&#41;.style.color = COLTIME;
								else  document.getElementById&#40;"clock" + active&#41;.style.color = "black";
				document.getElementById&#40;"clock" + active&#41;.style.background = "white";
				if&#40;Webcam.loaded&#41; take_snapshot&#40;); else
				document.getElementById&#40;"results").innerHTML =
					'<div style="background&#58;#FF0000;border&#58;1px;padding&#58;20px">Webcam not available</div>';
			&#125;
			active = side;
			if&#40;active&#41; &#123;
				if&#40;active != lastActive&#41; &#123;
					session--;
					document.getElementById&#40;"movenr").innerHTML = 1 + ++nr >> 1;
					times&#91;active&#93; += times&#91;active+2&#93;; // Fischer increment
				&#125;
				if&#40;session == 0&#41; &#123; session = times&#91;9&#93;; times&#91;1&#93; += times&#91;7&#93;; times&#91;2&#93; += times&#91;8&#93;; &#125;
				lastActive = active;
				document.getElementById&#40;"clock" + active&#41;.style.color = "white";
				document.getElementById&#40;"clock" + active&#41;.style.background = "black";
				deadTime = times&#91;active+4&#93;; // Bronstein delay
				DisplayTime&#40;active, times&#91;active&#93;);
			&#125;
		&#125;

		var digit = '1234567890-+/';
		var lastKey = 0;

		function KeyHit&#40;ev&#41; &#123;
			var c = ev.key;
			if&#40;!active&#41; &#123;
				// for typing start time
				if&#40;digit.search&#40;c&#41; >= 0 || c == 'Shift' || c == 'Home' || c == 'End' || c == 'Backspace' || c == 'Delete' || c == 'ArrowLeft' || c == 'ArrowRight') return;
				if&#40;c == 'Enter') &#123;
					SetClock&#40;);
					ev.preventDefault&#40;);
					return;
				&#125;
			&#125;
			lastKey = ticks;
			if&#40;c == ' ') Switch&#40;0&#41;; else
			if&#40;active == 0 && lastActive > 0&#41; Switch&#40;lastActive&#41;; else
			if&#40;active <= 1&#41; Switch&#40;2&#41;; else
			if&#40;active == 2&#41; Switch&#40;1&#41;;
			ev.preventDefault&#40;);
		&#125;

		function GoTo&#40;n&#41; &#123;
			if&#40;Webcam.loaded&#41; &#123;
				if&#40;!n&#41; current = n; else if&#40;n == 9999&#41; current = nrOfImages - 1; else current += n;
				if&#40;current < 0&#41; current = 0; else if &#40;current >= nrOfImages&#41; current = nrOfImages - 1;
				Display&#40;current&#41;;
			&#125;
			cursor_pos&#40;);
		&#125;

		function SetClock&#40;) &#123;
			if&#40;active || ticks - lastKey < 2&#41; return;
			var newTime = document.getElementById&#40;"starttime").value;
			times&#91;1&#93; = times&#91;2&#93; = times&#91;7&#93; = times&#91;8&#93; = 10*parseInt&#40;newTime&#41;;
			times&#91;3&#93; = times&#91;4&#93; = times&#91;5&#93; = times&#91;6&#93; = 0;
			times&#91;9&#93; = -1;
			var s = newTime.split&#40;'+');
			if&#40;s.length > 1&#41; times&#91;3&#93; = times&#91;4&#93; = 10*parseInt&#40;s&#91;1&#93;);
			s = newTime.split&#40;'-');
			if&#40;s.length > 1&#41; &#123;
				times&#91;5&#93; = times&#91;6&#93; = 10*parseInt&#40;s&#91;1&#93;);
				document.getElementById&#40;'bronstein').style.display = 'table-row';
				document.getElementById&#40;'bronbar').style.width = '0px';
				document.getElementById&#40;'bronbar').style.background = COLBRON;
			&#125; else
				document.getElementById&#40;'bronstein').style.display = 'none';
			s = newTime.split&#40;'/');
			if&#40;s.length > 1&#41; times&#91;9&#93; = 2*parseInt&#40;s&#91;1&#93;);
			nrOfImages = current = nr = 0;
			session = times&#91;9&#93; + 1;
			document.getElementById&#40;"clock" + 1&#41;.style.color = "black";
			document.getElementById&#40;"clock" + 2&#41;.style.color = "black";
			DisplayTime&#40;1, times&#91;1&#93;); DisplayTime&#40;2, times&#91;2&#93;);
			times&#91;1&#93; -= times&#91;3&#93;; times&#91;2&#93; -= times&#91;4&#93;;
			document.getElementById&#40;"movenr").innerHTML = 0;
			lastActive = 0;
			cursor_pos&#40;);
		&#125;

		function Swap&#40;) &#123;
			var h, ob1, ob2, side;
			h = times&#91;1&#93;; times&#91;1&#93; = times&#91;2&#93;; times&#91;2&#93; = h;
			side = active; Switch&#40;0&#41;;
			ob1 = document.getElementById&#40;'player1'); ob2 = document.getElementById&#40;'player2');
			h = ob1.innerHTML; ob1.innerHTML = ob2.innerHTML; ob2.innerHTML = h;
			ob1 = document.getElementById&#40;'clock1'); ob2 = document.getElementById&#40;'clock2');
			h = ob1.style.color; ob1.style.color = ob2.style.color; ob2.style.color = h;
			h = ob1.style.background; ob1.style.background = ob2.style.background; ob2.style.background = h;
			DisplayTime&#40;1, times&#91;1&#93;); DisplayTime&#40;2, times&#91;2&#93;);
			if&#40;side&#41; &#123;
				lastActive = 3 - side;
				Switch&#40;3 - side&#41;;
			&#125; else &#123;
				if&#40;lastActive == 1&#41; lastActive=2; else
				if&#40;lastActive == 2&#41; lastActive=1;
				Switch&#40;side&#41;;
			&#125;
			cursor_pos&#40;);
		&#125;

		function AdjustCount&#40;) &#123;
			if&#40;nr < 2&#41; return;
			nr -= 2; session += 2;
			document.getElementById&#40;"movenr").innerHTML = 1 + nr >> 1;
			cursor_pos&#40;);
		&#125;
	</script>

</body>
</html>
Henk
Posts: 7221
Joined: Mon May 27, 2013 10:31 am

Re: Photographing Chess Clock

Post by Henk »

I wonder what they did two hundred years ago when there were no chess clocks and players were thinking too long. Did they get a warning ?
User avatar
GONeill
Posts: 87
Joined: Sun Jun 15, 2014 6:40 am
Location: New Zealand
Full name: Graham O'Neill

Re: Photographing Chess Clock

Post by GONeill »

I had another look and did some tidying up. Also it now starts the clock for White first.

I'm not planning on doing any more on this now!

clock.html

Code: Select all

<!doctype html> 
<html lang="en"> 

<head>
	<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
	<title>Chess Clock</title> 
	<style type="text/css">
		body &#123; font-family&#58; Helvetica, sans-serif; &#125;
		table &#123;position&#58; relative;&#125;
		h2, h3 &#123; margin-top&#58;0; &#125;
		form &#123; margin-top&#58; 15px; &#125;
		form > input &#123; margin-right&#58; 15px; &#125;
		#bronbar &#123;position&#58;absolute; padding&#58;0px; height&#58;10px; bottom&#58;4px; width&#58;0px;&#125;
	</style> 
</head>

<body>
<div align="center"> 
	<table cellpadding="10">
		<tr>
			<td> 
				<h2>Live image&#58;</h2> 
				<div id="my_camera"></div>
			</td>
			<td valign="top"> 
				<h1>Webcam Chess Clock</h1> 
				<p><b>Start times, in seconds&#58;</b></p> 
				<ul>
					<li>Sudden death&#58; basetime, e.g. 600</li> 
					<li>Fischer&#58; basetime+inc, e.g. 120+10</li> 
					<li>Bronstein&#58; basetime-deadtime, e.g. 300-10</li> 
					<li>Classical&#58; basetime/moves, e.g. 300/40</li> 
				</ul>
				<p>Space bar stops the clocks.</p> 
			</td>
			<td> 
				<div id="results">
					<div style="border&#58;1px;background&#58;#cccccc;padding&#58;20px;">Your
						captured image will appear here...</div>
				</div>
			</td>
		</tr>
	</table>

<!-- First, include the Webcam.js JavaScript Library -->
	<script src="./webcam2.js" type="text/javascript"></script> 

<!-- Configure a few settings and attach camera -->
	<script language="JavaScript">
		// =======================================
		var FLIP = false;       // or true;
		var LNAME = 'White';
		var RNAME = 'Black';
		var COLTIME = 'red';    // or 'black';
		var COLBRON = 'green';  // or 'black';
		var SNDFILE = new Audio&#40;"TimeUp.wav");	// or 'none';
		// =======================================
		Webcam.set&#40;&#123;
			width&#58; 320,
			height&#58; 240,
			crop_width&#58; 320,
			crop_height&#58; 0,
			flip_horiz&#58; FLIP,
			image_format&#58; 'jpeg',
			jpeg_quality&#58; 90
		&#125;);
		Webcam.attach&#40; '#my_camera' );
	</script> 

	<form>
		<input type=button value="Take Snapshot" onClick="TakeSnapshot&#40;)">
		Start time&#58;
		<input type=text value="3600" id="starttime">
		<input type=button value="Reset Clocks" onClick="SetClock&#40;)">
		<input type=button value="Swap Players" onClick="Swap&#40;)">
		<input type=button value="Take Back" onClick="AdjustCount&#40;)">
		<input type=button value="<<" onClick="GoTo&#40;0&#41;">
		<input type=button value="<"  onClick="GoTo&#40;-1&#41;">
		<input type=button value=">"  onClick="GoTo&#40;1&#41;">
		<input type=button value=">>" onClick="GoTo&#40;9999&#41;">
	</form>

	<p id="key" style="background&#58;#8080FF;"></p>

	<table border="1" cellpadding="10">
		<tr>
			<td id="player1" align="center" style="font-size&#58;75px;"></td>
			<td id="movDisplay" align="center" style="font-size&#58;75px;" width="15%">0</td>
			<td id="player2" align="center" style="font-size&#58;75px;"></td>
		</tr>
		<tr>
			<td id="clock1" align="right" colspan="2" style="font-size&#58;150px;" width="50%"></td>
			<td id="clock2" align="right" style="font-size&#58;150px;" width="50%"></td>
		</tr>
		<tr id="bronstein" style="height&#58;11px; display&#58;none;">
			<td colspan="3" style="padding&#58;0px;">
				<div id="bronbar"></div>
			</td>
		</tr>
	</table>
</div>

<script language="JavaScript">
	var active = 0, lastActive = 0, white = 1;
	var movSession = 0, movCount = 0;
	var deadTime = 0, ticks = 0, lastKey = 0;
	var images = new Array&#40;);
	var nrOfImages = 0, currImage = 0;
	var times = new Array&#40;);
	times&#91;1&#93; = times&#91;2&#93; = 36000;   // Clocks
	times&#91;3&#93; = times&#91;4&#93; = 0;       // Fischer allowances
	times&#91;5&#93; = times&#91;6&#93; = 0;       // Bronstein allowances
	times&#91;7&#93; = 0;                  // Saved basetime for basetime/moves
	times&#91;8&#93; = 0;                  // Saved moves for basetime/moves

	document.getElementById&#40;'player1').innerHTML = LNAME;
	document.getElementById&#40;'player2').innerHTML = RNAME;
	DisplayTime&#40;1&#41;;
	DisplayTime&#40;2&#41;;

	window.addEventListener&#40;"keydown", KeyHit, false&#41;;

	var timer = setTimeout&#40;"Clock&#40;);", 100&#41;;

	function cursor_pos&#40;) &#123;
		document.getElementById&#40;'starttime').focus&#40;);
	&#125;

	<!--------------- WebCam functions --------------->
	function GoTo&#40;n&#41; &#123;
		if&#40;Webcam.loaded && nrOfImages > 0&#41; &#123;
			if&#40;n==0&#41; currImage=1;
			else if&#40;n==9999&#41; currImage=nrOfImages;
			else &#123;
				currImage += n;
				if&#40;currImage < 1&#41; currImage = 1; else if&#40;currImage > nrOfImages&#41; currImage = nrOfImages;
			&#125;
			document.getElementById&#40;'results').innerHTML =
				'<h2>Captured image ' + currImage + '&#58;</h2>' +
				'<img src="'+images&#91;currImage&#93;+'"/>';
		&#125;
		cursor_pos&#40;);
	&#125;

	function TakeSnapshot&#40;) &#123;
		if&#40;Webcam.loaded&#41; &#123;
			// take snapshot and get image data
			Webcam.snap&#40; function&#40;data_uri&#41; &#123;
				// display results in page
				document.getElementById&#40;'results').innerHTML =
					'<h2>Captured image&#58;</h2>' +
					'<img src="'+data_uri+'"/>';
				currImage = ++nrOfImages;
				images&#91;nrOfImages&#93; = data_uri; // save the snapshot
			&#125; );
		&#125;
		cursor_pos&#40;);
	&#125;

	<!--------------- System timer functions --------------->
	function Clock&#40;) &#123;
		if&#40;active&#41; &#123;
			if&#40;--deadTime < 0&#41; times&#91;active&#93;--; else
				document.getElementById&#40;'bronbar').style.width = &#40;deadTime*99/times&#91;active+4&#93;)+'%';
			if&#40;&#40;times&#91;active&#93;+1&#41;%10 == 0&#41; DisplayTime&#40;active&#41;;
		&#125;
		ticks++; timer = setTimeout&#40;"Clock&#40;);", 100&#41;;
	&#125;

	function KeyHit&#40;ev&#41; &#123;
		var c = ev.key;
		var digit = '1234567890-+/';
		if&#40;!active&#41; &#123;
			// for typing start time
			if&#40;digit.search&#40;c&#41; >= 0 || c == 'Shift' || c == 'Home' || c == 'End' || c == 'Backspace' || c == 'Delete' || c == 'ArrowLeft' || c == 'ArrowRight') return;
			if&#40;c == 'Enter') &#123;
				SetClock&#40;);
				ev.preventDefault&#40;);
				return;
			&#125;
		&#125;
		lastKey = ticks;
		if&#40;c == ' ') &#123;
			SetPlayer&#40;0&#41;;
		&#125; else if&#40;!active&#41; &#123;
			if&#40;lastActive&#41; SetPlayer&#40;lastActive&#41;; else SetPlayer&#40;white&#41;;
		&#125; else
			SetPlayer&#40;3 - active&#41;;
		ev.preventDefault&#40;);
	&#125;

	<!--------------- Chess clock functions --------------->
	function SecToTime&#40;t&#41; &#123;
		var s = 0; if&#40;t<0&#41; &#123; s = 1; t = -t; &#125;
		t = &#40;t - t%10&#41;/10;
		var sec = t % 60; t = &#40;t - sec&#41;/60; if&#40;sec < 10&#41; sec = '0' + sec;
		var min = t % 60; t = &#40;t - min&#41;/60; if&#40;min < 10&#41; min = '0' + min;
		return s ? '-' + min + '&#58;' + sec &#58; t + '&#58;' + min + '&#58;' + sec;
	&#125;

	function DisplayTime&#40;n&#41; &#123;
		if&#40;active&#41; &#123;
			if&#40;times&#91;n&#93; < 0&#41; document.getElementById&#40;"clock" + n&#41;.style.background = COLTIME;
			            else document.getElementById&#40;"clock" + n&#41;.style.background = "black";
			if&#40;times&#91;n&#93; == -1 && SNDFILE !== 'none') SNDFILE.play&#40;);
		&#125;
		document.getElementById&#40;"clock" + n&#41;.innerHTML = SecToTime&#40;times&#91;n&#93;);
	&#125;

	function SetPlayer&#40;n&#41; &#123;
		if&#40;n == active&#41; return;
		if&#40;active&#41; &#123;
			if&#40;times&#91;active&#93; < 0&#41; document.getElementById&#40;"clock" + active&#41;.style.color = COLTIME;
								  else document.getElementById&#40;"clock" + active&#41;.style.color = "black";
			document.getElementById&#40;"clock" + active&#41;.style.background = "white";
			if&#40;n&#41; &#123;
				if&#40;Webcam.loaded&#41; TakeSnapshot&#40;);
				else document.getElementById&#40;"results").innerHTML =
					'<div style="background&#58;#FF0000;border&#58;1px;padding&#58;20px">Webcam not available</div>';
				if&#40;active==white&#41; document.getElementById&#40;"movDisplay").innerHTML = ++movCount;
			&#125;
		&#125;
		active = n;
		if&#40;active&#41; &#123;
			if&#40;active != lastActive&#41; &#123;
				movSession--;
				times&#91;active&#93; += times&#91;active+2&#93;; // Fischer increment
				deadTime = times&#91;active+4&#93;;       // Bronstein delay
			&#125;
			if&#40;movSession == 0&#41; &#123;
				movSession = times&#91;8&#93;;
				if&#40;times&#91;7&#93;) &#123;
					times&#91;1&#93; += times&#91;7&#93;;
					times&#91;2&#93; += times&#91;7&#93;;
					document.getElementById&#40;"clock" + 1&#41;.innerHTML = SecToTime&#40;times&#91;1&#93;);
					document.getElementById&#40;"clock" + 2&#41;.innerHTML = SecToTime&#40;times&#91;2&#93;);
				&#125;
			&#125;
			lastActive = active;
			document.getElementById&#40;"clock" + active&#41;.style.color = "white";
			DisplayTime&#40;active&#41;;
		&#125;
	&#125;

	function Swap&#40;) &#123;
		var saveAct, h, ob1, ob2;
		saveAct = active;
		SetPlayer&#40;0&#41;;
		h = times&#91;1&#93;; times&#91;1&#93; = times&#91;2&#93;; times&#91;2&#93; = h;
		ob1 = document.getElementById&#40;'player1'); ob2 = document.getElementById&#40;'player2');
		h = ob1.innerHTML; ob1.innerHTML = ob2.innerHTML; ob2.innerHTML = h;
		ob1 = document.getElementById&#40;'clock1'); ob2 = document.getElementById&#40;'clock2');
		h = ob1.style.color; ob1.style.color = ob2.style.color; ob2.style.color = h;
		h = ob1.style.background; ob1.style.background = ob2.style.background; ob2.style.background = h;
		DisplayTime&#40;1&#41;; DisplayTime&#40;2&#41;;
		white = 3 - white;
		if&#40;lastActive&#41; lastActive = 3 - lastActive;
		if&#40;saveAct&#41; SetPlayer&#40;3 - saveAct&#41;;
		cursor_pos&#40;);
	&#125;

	function SetClock&#40;) &#123;
		if&#40;active || ticks - lastKey < 2&#41; return;
		var newTime = document.getElementById&#40;"starttime").value;
		times&#91;1&#93; = times&#91;2&#93; = times&#91;7&#93; = 10*parseInt&#40;newTime&#41;;
		times&#91;3&#93; = times&#91;4&#93; = times&#91;5&#93; = times&#91;6&#93; = 0;
		times&#91;8&#93; = -1;
		nrOfImages = currImage = movCount = lastActive = deadTime = 0;
		var s = newTime.split&#40;'+');
		if&#40;s.length > 1&#41; times&#91;3&#93; = times&#91;4&#93; = 10*parseInt&#40;s&#91;1&#93;);
		s = newTime.split&#40;'-');
		if&#40;s.length > 1&#41; &#123;
			deadTime = times&#91;5&#93; = times&#91;6&#93; = 10*parseInt&#40;s&#91;1&#93;);
			document.getElementById&#40;'bronstein').style.display = 'table-row';
			document.getElementById&#40;'bronbar').style.width = '0px';
			document.getElementById&#40;'bronbar').style.background = COLBRON;
		&#125; else
			document.getElementById&#40;'bronstein').style.display = 'none';
		s = newTime.split&#40;'/');
		if&#40;s.length > 1&#41; times&#91;8&#93; = 2*parseInt&#40;s&#91;1&#93;);
		movSession = times&#91;8&#93; + 1;
		document.getElementById&#40;"clock" + 1&#41;.style.color = "black";
		document.getElementById&#40;"clock" + 2&#41;.style.color = "black";
		DisplayTime&#40;1&#41;; DisplayTime&#40;2&#41;;
		document.getElementById&#40;"movDisplay").innerHTML = 0;
		document.getElementById&#40;"results").innerHTML =
			'<div style="border&#58;1px;background&#58;#cccccc;padding&#58;20px;">Your	captured image will appear here...</div>';
		cursor_pos&#40;);
	&#125;

	function AdjustCount&#40;) &#123;
		if&#40;movCount < 2&#41; return;
		document.getElementById&#40;"movDisplay").innerHTML = --movCount;
		movSession += 2;
		cursor_pos&#40;);
	&#125;
</script> 
</body>

</html>