Commits

Stu Kabakoff  committed ae016da

numerous bug fixes, it syncs down to the millisecond (properly this time), Chrome is fixed, sync is better.

  • Participants
  • Parent commits 59a7be5
  • Branches version2

Comments (0)

Files changed (5)

File js/PokerGame.js

 		hasFocus = false,
 		previousDimmerTimer,	
 		currentBlindIndex = -1,
+		blindTimeRemaining = 0,
 	
 	count = function() {
 		if (!countInterval) {
 		currentLevelEl = null;
 		var template = $('#templates .level')[0];
 		var binder = [ 'blinds', 'game', {selector:'.time', key:'time', fn:util.secondsToString} ];
-		var frag = util.template( template, binder, state, function(e,game,i) {
+		var frag = util.template( template, binder, state, function(el,game,i) {
 			if( game.blinds == local['break'] ) {
-				$(e).click(function(){ 
-					state.splice(i,1);
-					draw(); 
-					save();
-					if (i === currentBlindIndex) {
-						PokerRoom.endBreak(name);
+				$(el).addClass('break').click(function(){ 
+					if (hasFocus) {
+						state.splice(i,1);
+						draw(); 
+						save();
+						if (i === currentBlindIndex) {
+							PokerRoom.endBreak(name);
+						}
 					}
-				}).addClass('break');
+				});
 			}
 		} );
 		element.appendChild( frag );
 	},
 	update = function() {
 		var now = Date.now() + PokerRoom.timeOffset;
-		var milleseconds = (now-lastUpdate);
-		if ( (milleseconds > 1100 && milleseconds < 2000) || milleseconds < 900 ) {
-			// make them count at different times
+		var milliseconds = (now-lastUpdate);
+		if ( countInterval && ((blindTimeRemaining-milliseconds) % 1000) > 50 ) {
+			// end this timer and start a new one if we're off by more than 1/20 seconds
 			clearInterval(countInterval);
-			countInterval = false;
-			setTimeout( function(){ count(); }, milleseconds % 1000 );
+			countInterval = null;
+			setTimeout( function(){ count(); }, ((blindTimeRemaining-milliseconds) % 1000)  );
+		}
+		
+		if (milliseconds < 500 && currentLevelEl) {
 			return;
 		}
-		
-		var seconds = Math.floor((milleseconds+100)/1000);
 		lastUpdate = now;
 		
 		//count
 		} else {
 			blind = state[currentBlindIndex];
 			
-			while (seconds > blind.time) {
-				seconds -= blind.time;
+			while (milliseconds > blind.time) {
+				milliseconds -= blind.time;
 				blind.time = 0;
 				currentBlindIndex += 1;
 				blind = state[currentBlindIndex];
 			}
-			if (currentLevelEl != element.childNodes[currentBlindIndex]) {
+			if (previousBlindIndex != currentBlindIndex) {
 				if( currentLevelEl ) {
 					var previousLevel$ = $(currentLevelEl).removeClass('current').addClass('previous played');
 					previousDimmerTimer = setTimeout( function() {
 						previousLevel$.removeClass('previous');
 					}, 90 * 1000);
+				} else {
+					currentLevelEl = element.childNodes[currentBlindIndex];
 				}
 				
 				if (state[previousBlindIndex] && state[previousBlindIndex].blinds == local['break'] ) {
 					PokerRoom.startBreak(name);
 				}
 				currentLevelEl = element.childNodes[currentBlindIndex];
-				$(currentLevelEl).addClass('current');
+				if (currentLevelEl) {
+					$(currentLevelEl).addClass('current');
+				} else {
+					// the game is over.
+					that.remove();
+				}
 								
 				updateScroll( true, function(){ding();} );
+			} else if (!currentLevelEl) {
+				currentLevelEl = element.childNodes[currentBlindIndex];
 			}
-			blind.time -= seconds;
+			blind.time -= milliseconds;
+			blindTimeRemaining = blind.time;
 			$('.time',element.childNodes[currentBlindIndex]).html(util.secondsToString(blind.time));
 		}
 	},
 			$(element).remove();
 			clearInterval(countInterval);
 			countInterval = false;
-			PokerRoom.removeGame(this);
+			PokerRoom.removeGame(name);
 		},
 		sleep: function() {
 			clearInterval(countInterval);
 		},
 		focus: function() {
 			hasFocus = true;
+			that.wake();
 			update();
 			resize();
-			that.wake();
 			window.addEventListener( 'resize', resizeCallback, true );
 			return that;
 		},

File js/PokerRoom.js

-var FONT_SIZE = 75;
+var FONT_SIZE = 75; //text size constant.
 
 var PokerRoom = (function($) {
 	// hold games in localStorage
 	var games = {},
 		timeOffset = 0,
-		syncTimer = false,
 		bell,
 		listEl,
 		gameEl,
 		topCurtain,
 		bottomCurtain,
 		mute = true,
-		syncToken = 0,
 		currentGame,
 		onBreak = false,
 		controlsTimeout,
+		syncInProgress = false,
+		syncTimer = false,
+		syncSuspended = false,
+		syncToken = 0, //this is the syncToken for the game list
 		
-	sync = function(timer) {
+	sync = function() {
+		if (syncInProgress || syncSuspended) {
+			return;
+		}
 		clearTimeout( syncTimer );
-		
-		var sync_a = [];
-		for (var name in games) {
-			var gameSyncToken = games[name].syncToken;
-			// TODO: have this add games that have changes to send to the server
-			if (gameSyncToken) {
-				sync_a.push( {name:name, syncToken:gameSyncToken} );
+		syncInProgress = true;
+		if( currentGame ) {
+			game = games[currentGame];
+			$.post('php/games.php', {method:'sync', games:JSON.stringify([{syncToken:game.syncToken, name:game.name}]), rand:Math.random()}, function(updates) {
+				updateGames( JSON.parse(updates) );
+				syncTimer = setTimeout( function(){ sync() }, 5000 );
+				syncInProgress = false;
+			})
+		} else {
+			var syncGames = {};
+			for (var name in games) {
+				if (games[name].name ) {
+					var gameSyncToken = games[name].syncToken;
+					if (gameSyncToken && name) {
+						syncGames[name] = gameSyncToken;
+					}
+				}
+			}
+			$.post('php/games.php', {method:'sync', syncToken:syncToken, rand:Math.random()}, function(updates) {
+				updateList( JSON.parse(updates) );
+				syncTimer = setTimeout( function(){ sync() }, 5000 );
+				syncInProgress = false;
+			})
+		}
+	},
+	updateList = function( syncResult ) {
+		var serverGames = syncResult.games;
+		syncToken = syncResult.syncToken;
+		if (!serverGames.length) {
+			return;
+		}
+		for( var i=0,c=serverGames.length; i<c; i++ ) {
+			var game = serverGames[i];
+			if (games[game.name]) {
+				games[game.name].update( game );
+			} else {
+				that.add( game );
 			}
 		}
-		if (sync_a.length) {
-			$.post('php/games.php', {method:'sync', games:JSON.stringify( sync_a )}, function(updates) {
-				updates = JSON.parse(updates);
-				for( var name in updates ) {
-					var update = updates[name];
-					if (games[name]) {
-						games[name].update( update );
-					}
-				}
-				syncTimer = setTimeout( function(){ sync() }, 5000 );
-			})
-		} else {
-			syncTimer = setTimeout( function(){ sync() }, 5000 );
+
+		var games_a = [];
+		for( var game in games ) {
+			games[game].wake();
+			games_a.push(games[game]);
 		}
+		var template = $('#templates li.game')[0];
+		var bindings = ['name', {key:'element',selector:'.state'}];
+		var frag = util.template( template, bindings, games_a, function(el, game) {
+			$(el).click(function(){
+				that.showGame(game.name)
+			});
+		});
+		listEl.innerHTML = '';
+		listEl.appendChild( frag );
+		that.resume();
 	},
+	updateGames = function( updates ) {
+		for( var name in updates ) {
+			var update = updates[name];
+			if (games[name]) {
+				games[name].update( update );
+			}
+		}
+	}
 	addBreak = function(next) {
 		games[currentGame].addBreak(next);
 	},
 	keyControl = function(e) {
-		var key = ""+String.fromCharCode(e.charCode).toLowerCase();
+		var key = String.fromCharCode(e.charCode||e.which).toLowerCase();
 		switch( key ) {
 			case 'b':
 				addBreak(0);
 			if (serverTime) {
 				timeOffset = serverTime - Date.now();
 			}
-			that.listGames();
 		});
 		bell = getElementById('bell');
 		listEl = getElementById('game_list');
 		topCurtain = $('#curtains .top')[0];
 		bottomCurtain = $('#curtains .bottom')[0];
 		
-		$('#break_now').click( function(e){
+		$('#break_now')[0].addEventListener('click',/*.click(*/ function(e){
 			e.preventDefault();
 			addBreak(0);
-		});
+		}, true);
+
 		
 		$('#break_next').click( function(e){
 			e.preventDefault();
 			addBreak(1);
 		});
 		
-		document.addEventListener( 'keypress', keyControl, true );
+		document.addEventListener( 'keydown', keyControl, true );
 		document.addEventListener( 'mousemove', showControls, true );
 	});
 	
 		suspend: function() {
 			clearTimeout(syncTimer);
 			syncTimer = false;
+			syncSuspended = true;
+			return that;
+		},
+		start: function() {
+			syncSuspended = false;
+			sync();
 			return that;
 		},
 		resume: function() {
+			syncSuspended = false;
 			sync();
 			return that;
 		},
 		add: function (blindTime, blinds, p_games, name, breakLength, lastUpdate, p_syncToken) {
-			
 			if (typeof blindTime === 'object') {
 				//blind time is actually a game.
 				var o = blindTime;
 			
 			return name;
 		},
-		removeGame: function(game) {
-			delete games[game.name];
+		removeGame: function(name) {
+			delete games[name];
+			if (name === currentGame || !games[currentGame]) {
+				updateList();
+			}
 		},
 		JSON: function() {
 			return games.toString();
 		list: function() {
 			return games;
 		},
-		listGames: function() {
-			$.getJSON('php/games.php', {method:'list',syncToken:syncToken}, function(p_games) {
-				for( var name in p_games ) {
-					if( games[name] ) {
-						games[name].update(p_games[name]);
-					} else {	
-						that.add( p_games[name] );
-					}
-				}
-				var games_a = [];
-				for( var game in games ) {
-					games[game].wake();
-					games_a.push(games[game]);
-				}
-				var template = $('#templates li.game')[0];
-				var bindings = ['name', {key:'element',selector:'.state'}];
-				var frag = util.template( template, bindings, games_a, function(e, game) {
-					$(e).click(function(){that.showGame(game.name)});
-				});
-				listEl.innerHTML = '';
-				listEl.appendChild( frag );
-				currentGame = null;
-				that.resume();
-			});
-			return that;
-		},
 		move: function( newHome ) {
 			if( typeof newHome === 'string' ) {
 				newHome = getElementById( newHome );
 $(document).ready(function() {
 	
 	$('#new_game_title').val( util.randomWord() );
-	
+	PokerRoom.start();
 	//$('#asdf').click( post_game );
 	$('form').bind( 'submit', post_game )	
 });
 		}
 	},
 	secondsToString: function( sec ) {
+		sec = Math.round( sec / 1000 );
 		return Math.floor(sec/60)+':'+util.pad(sec%60,2);
 	},
 	stringToSeconds: function( time ) {
 		var time_a = time.split(':');
 		if (time_a.length > 1) {
-			return (parseInt(time_a[0],10)*60) + parseInt(time_a[1],10);
+			return ((parseInt(time_a[0],10)*60) + parseInt(time_a[1],10)) * 1000;
 		} else {
-			return parseInt(time,10);
+			return parseInt(time,10) * 1000;
 		}
 	},
 	pad: function (num, totalChars, padWith) {

File php/games.php

 		break;
 		
 	case 'sync':
-		$games = json_decode( trim($_POST['games']), true );
-		$updates = array();
-		foreach( $games as $game ) {
-			$file_name = name_to_file( $game['name'] );
-			if( file_exists( $file_name ) ) {
-				$syncToken = filemtime( $file_name );
-				if( $game['syncToken'] <  $syncToken ) {
-					$updates[$game['name']] = array(
-						'syncToken' => $syncToken,
-						'game' => get_game( $file_name )
-					);
+		if( isset( $_POST['games'] ) ) {
+			// sync specific games
+			$games = json_decode( trim($_POST['games']), true );
+			$updates = array();
+			foreach( $games as $game ) {
+				$file_name = name_to_file( $game['name'] );
+				if( file_exists( $file_name ) ) {
+					$syncToken = filemtime( $file_name );
+					if( $game['syncToken'] <  $syncToken ) {
+						$updates[$game['name']] = array(
+							'syncToken' => $syncToken,
+							'game' => get_game( $file_name )
+						);
+					}
 				}
 			}
+			echo json_encode($updates);
+		} else {
+			// sync all games
+			$game_files = glob( 'games/*' );
+			$games = array();
+			$syncToken = time();
+			foreach( $game_files as $game_file ) {
+				if( filemtime( $game_file ) > $_POST['syncToken'] ) {
+					$game_data = evaluate_game( $game_file );
+					if( $game_data ) {
+						$games[] = $game_data;
+					}
+				}
+			}
+			echo json_encode( array( 'games' => $games, 'syncToken' => $syncToken ) );
 		}
-		echo json_encode($updates);
-		break;
-		
-	case 'list':
-		//print_r(scandir('games'));
-		$game_files = glob( 'games/*' );
-		//print_r( $game_files );
-		$games = array();
-		foreach( $game_files as $game_file ) {
-			$game_data = evaluate_game( $game_file, $_POST['syncToken'] );
-			if( $game_data ) {
-				$games[$game_data['name']] = $game_data;
-			}
-		}
-		echo json_encode( $games );
 		break;
 	
 	default:
 		echo 'Please select a method. save, sync, get, list';
 }
-function evaluate_game( $file_name, $syncToken=0 ) {
+function evaluate_game( $file_name ) {
 	if( file_exists( $file_name ) ) {
 		$game_data = get_game( $file_name );
-		$now = time();
-		$countdown = $now - intVal($game_data['lastUpdate']/1000);
-		if( !$syncToken || $syncToken < filemtime( $file_name ) ) {
-			foreach( $game_data['state'] as $key => $level ) {
-				if( $level['time'] > $countdown ) {
-					$countdown = 0;
-					break;
-				} else {
-					$countdown -= $level['time'];
-				}
+		$now = time()*1000;
+		$countdown = $now - $game_data['lastUpdate'];
+		foreach( $game_data['state'] as $key => $level ) {
+			if( $level['time'] > $countdown ) {
+				$countdown = 0;
+				break;
+			} else {
+				$countdown -= $level['time'];
 			}
-			if( $countdown > 0 ) {
-				//the game is over.
-				unlink( $file_name );
-				$game_data = false;
-			} else {
-				$game_data['syncToken'] = filemtime( $file_name );
-			}
+		}
+		if( $countdown > 0 ) {
+			//the game is over.
+			unlink( $file_name );
+			$game_data = false;
 		} else {
-			$game_data = false;
+			$game_data['syncToken'] = filemtime( $file_name );
 		}
 	} else {
 		$game_data = false;