Skip to content
Browse files

hall of fame, twitter boostrap themes, safe display name (<25chars), …

…overall styling
  • Loading branch information...
1 parent 005a670 commit f8dd56133648d7f6ba5cfdaab494b71941ec6558 @iloire committed Mar 11, 2012
Showing with 201 additions and 64 deletions.
  1. +1 −1 config.js
  2. +31 −5 lib/modules/race.js
  3. +16 −1 lib/modules/util.js
  4. +0 −3 package.json
  5. +59 −11 public/stylesheets/style.css
  6. +1 −1 server.js
  7. +82 −31 views/index.html
  8. +11 −11 views/layout.html
View
2 config.js
@@ -7,6 +7,6 @@ exports.values={
}
,
game : {
- duration: 60 //seconds
+ duration: 10 //seconds
}
}
View
36 lib/modules/race.js
@@ -22,6 +22,21 @@ function createRace(server){
var sessions = [] //array of client id's
var scores = {}
var history = [];
+ var hall_of_fame = [];
+
+ function UpdateHallOfFame(scores, timestamp){
+
+ for (var i = 0, l = scores.length; i < l ; i++) {
+ var score = scores[i];
+ score.timestamp = timestamp;
+ hall_of_fame.push(score); //add all scores
+ };
+
+ //sort
+ util.sort(hall_of_fame, 'score', true);
+
+ return hall_of_fame.slice(0,10);
+ }
function broadcast(sessions, command, data, exception){
for (var i=0, l=sessions.length; i < l ; i++) {
@@ -48,21 +63,30 @@ function createRace(server){
var remaining = Math.floor((game_duration - elapsed) / 1000);
if (remaining<0){
//archive game
+ var timestamp = game_started.getDate() + '/' + game_started.getMonth() + '/' + game_started.getFullYear() + ' ' + game_started.getHours() + ":" + (game_started.getMinutes() > 9 ? game_started.getMinutes() : '0' + game_started.getMinutes());
if (format_scores(scores).length){
history.push({
timestamp: game_started.getTime(),
- name: game_started.getHours() + ":" + (game_started.getMinutes() > 9 ? game_started.getMinutes() : '0' + game_started.getMinutes()),
+ name: timestamp,
scores: format_scores(scores)
});
+
+ util.sort(history, 'timestamp', true);
+ history = history.slice(0,10);
+
+ hall_of_fame = UpdateHallOfFame(format_scores(scores), timestamp);
+
broadcast (sessions, 'history', history); //broadcast history
}
scores = {}; //reset
game_started = new Date(); //start game again!
broadcast (sessions, 'scores', format_scores(scores)); //reset scores in client
+ broadcast (sessions, 'hall_of_fame', hall_of_fame); //reset scores in client
+ broadcast (sessions, 'new_game', null); //flash 'new game!'
}
- else{
- broadcast (sessions, 'time', remaining); //broacast scores
- }
+ else
+ broadcast (sessions, 'time', remaining); //broacast time
+
}, 1000);
socket.on('connection', function (client) {
@@ -73,6 +97,7 @@ function createRace(server){
client.emit ('new_operation', operation.quest); //send challenge to new client
client.emit ('scores', format_scores(scores)); //send scores to new client
client.emit ('history', history); //send history
+ broadcast (sessions, 'hall_of_fame', hall_of_fame); //send hall of fame
});
client.on('solve_operation', function (data) {
@@ -81,7 +106,8 @@ function createRace(server){
client.emit ('result_operation', 1); //msg to winner
broadcast (sessions, 'result_operation', 2, client.id); //msg to rest of players. someone else won!
- scores[data.name] = (scores[data.name] || 0) + 1 //credit score to client
+ var safe_name = data.name.slice(0,25);
+ scores[safe_name] = (scores[safe_name] || 0) + 1 //credit score to client
broadcast (sessions, 'scores', format_scores(scores)); //broacast scores
//new challenge
View
17 lib/modules/util.js
@@ -6,4 +6,19 @@ function add(arr, value) {
}
arr.push(value)
}
-exports.add = add
+exports.add = add
+
+function sort (arr, property, desc){
+ function sorter(aa,bb){
+ var a = !desc ? aa : bb;
+ var b = !desc ? bb : aa;
+
+ if (typeof a[property] == "number") {
+ return (a[property] - b[property]);
+ } else {
+ return ((a[property] < b[property]) ? -1 : ((a[property] > b[property]) ? 1 : 0));
+ }
+ }
+ return arr.sort(sorter);
+};
+exports.sort = sort
View
3 package.json
@@ -1,9 +1,6 @@
{
"name": "node-myboiler",
"version": "0.0.1",
- "scripts": {
- "test": "echo '\nlaunching redis-server in background with testing config...\n'; redis-server tests/redis.conf; node tests/runall.js; kill `cat redis.pid`;rm test.rdb"
- },
"engines": {
"node": ">= 0.6.0"
},
View
70 public/stylesheets/style.css
@@ -19,11 +19,15 @@ a {
}
#time{
- font-size:3em;
+ color:yellow !important;
+ font-size:1.4em;
+ font-weight:bold;
}
#time.red{
- color:red;
+ background-color:yellow !important;
+ padding:5px;
+ color:red !important;
}
section{
@@ -37,10 +41,15 @@ span.equal{
}
input.input_player{
- font-size:9em;
+ font-size:9em;
+ width:270px;
height:140px;
- width:270px;
- vertical-align:top;
+ padding:0px;
+ margin:0px;
+ display: inline;
+ font-weight: normal;
+ line-height:normal;
+ vertical-align: top;
}
footer{
@@ -51,20 +60,59 @@ footer{
font-size:8em;
}
+.msg{
+ border-radius: 60px;
+ position:fixed;
+ text-align:center;
+ padding:20px 25px;
+}
+
+.msg-new{
+ font-size:4em;
+ background-color:yellow;
+ color:black;
+}
+
.msg-error{
font-size:2em;
- position:fixed;
background-color:red;
color:white;
- padding:10px;
- text-align:center;
}
.msg-success{
font-size:2em;
- position:fixed;
background-color:green;
color:white;
- text-align:center;
- padding:10px;
+}
+
+div.results{
+ margin-top:100px;
+}
+
+div.hall_of_fame ol li{
+ line-height:160%;
+ font-size:1.3em;
+}
+
+div.hall_of_fame .timestamp{
+ color:#c2c2c2;
+ font-size:0.7em;
+}
+
+div.scores.selected{
+ background-color:yellow;
+ color:black;
+}
+
+span.score {
+ background-color: yellow;
+ border-radius: 100px;
+ color: black;
+ text-transform: uppercase;
+ text-align: center;
+ font-size: 1.1em;
+ border-radius: 100px;
+ padding: 2px 4px;
+ border: 1px solid gray;
+ text-shadow: 0px 1px 0px black;
}
View
2 server.js
@@ -14,6 +14,6 @@ console.log("Express server listening on port %d in %s mode", app.address().port
process.on('SIGINT', function () {
app.close();
console.log();
- console.log('Shuting down server..');
+ console.log('Shutting down server..');
process.exit(0);
});
View
113 views/index.html
@@ -15,10 +15,10 @@
};
//util, print msgs --
- function print_msg (msg, style){
- $('#msg').html('<div class="msg-'+ style +'">' + msg + '</div>');
+ function print_msg (msg, style, time){
+ $('#msg').html('<div class="msg msg-'+ style +'">' + msg + '</div>');
$('#msg').fadeIn();
- setTimeout(function(){$('#msg').fadeOut()},500);
+ setTimeout(function(){$('#msg').fadeOut()},time || 500);
}
function show_error(msg){ print_msg(msg, 'error'); }
@@ -34,12 +34,12 @@
var socket = io.connect(server);
socket.on('connect',function() {
- $('#socketio').html('<span class="label label-success">socket.io connected!</label>');
+ $('#socketio').html('<span class="label label-success">connected!</label>');
socket.emit('join', { id: user_id });
});
socket.on('disconnect',function() {
- $('#socketio').html('<span class="label label-important">socket.io disconnected</label>');
+ $('#socketio').html('<span class="label label-important">disconnected</label>');
});
socket.on('time',function(time) {
@@ -60,13 +60,27 @@
socket.on('scores',function(scores) {
race.scores(sort(scores,'score', true));
+ if (scores.length){ //effect
+ $('.scores').addClass('selected');
+ setTimeout(function (){
+ $('.scores').removeClass('selected')
+ }, 200);
+ }
+ });
+
+ socket.on('hall_of_fame',function(hall_of_fame) {
+ race.hall_of_fame(sort(hall_of_fame,'score', true));
+ });
+
+ socket.on('new_game',function(result) {
+ print_msg ('new game, new score, hurry up!!', 'new', 2000);
});
socket.on('result_operation',function(result) {
if (result==1)
- print_msg ('you won!', 'success');
+ print_msg ('good!!', 'success');
else if (result==2)
- print_msg ('other player won', 'warning');
+ print_msg ('other player solved this quest faster than you!', 'warning');
else
print_msg ('nooooooooo!', 'error');
});
@@ -80,8 +94,13 @@
self.input_player1 = ko.observable();
self.scores = ko.observableArray();
self.history = ko.observableArray();
+ self.hall_of_fame = ko.observableArray();
self.time = ko.observableArray();
+ self.valid_name = ko.computed(function() {
+ return (self.name() && self.name().length>2);
+ }, self);
+
self.sendOperationResult = function() {
var data = {operation: self.input_player1(), name : self.name()};
socket.emit('solve_operation', data);
@@ -108,36 +127,68 @@
</script>
-<p>Your name: <input type="text" id="name" name="name" value="" data-bind="value: name, valueUpdate: 'afterkeydown'" /></p>
+<div class="alert alert-warning" data-bind="visible: (!valid_name())">
+ <h2>Be the faster math solver: 12 + 14 = ??</h2>
+ <h3>Play agains other player in real time! (or try to beat the top scores!)</h3>
+ <p>Please introduce your name to start playing!</p>
+</div>
+
+<p>Your name: <input maxlength="25" type="text" id="name" name="name" value="" data-bind="value: name, valueUpdate: 'afterkeydown'" /></p>
-<div class="row-fluid" style="display:none" data-bind="visible: name">
- <div class="span8 main">
+<div style="display:none" data-bind="visible: valid_name">
+ <div class="row-fluid">
+ <div class="span12 main">
<span id="operations"></span>
<span class="equal">=</span>
<input class="input_player" maxlength="4" type="text" name="player1" value="" data-bind="value: input_player1, valueUpdate: 'afterkeydown'" />
+ <div id="msg"></div>
+ </div>
+ </div>
+
+ <div class="row-fluid results">
+ <div class="span4 current_game">
+ <h3>Current game
+ <small>(ends in <span id="time" data-bind="text: time, css: { red: time() < 10 }"></span> secs)</small>
+ </h3>
+
+ <div class="scores alert alert-warning">
+ <ol data-bind="foreach: scores">
+ <li><span data-bind="text: player"></span>:
+ <span class="score" data-bind="text: score"></span>
+ </li>
+ </ol>
+ <p data-bind="visible: (scores().length==0)">Solve the math quest and be the first one to score!</p>
+ </div>
+
+ </div>
- <div id="msg"></div>
- </div>
+ <div class="span4">
+ <h3>Game history</h3>
+ <div data-bind="visible: history().length">
+ <div data-bind="foreach: history">
+ <div class="game_history alert alert-warning">
+ <h4><small>game played at: </small> <span data-bind="text: name"> </span></h4>
+ <ol data-bind="foreach: scores">
+ <li><span data-bind="text: player"></span>: <span class="score" data-bind="text: score"></span></li>
+ </ol>
+ </div>
+ </div>
+ </div>
+ </div>
- <div class="span3">
- next game in: <span id="time" data-bind="text: time, css: { red: time() < 10 }"></span> seconds.
- <h3>Current game score</h3>
- <div class="alert alert-info">
- <ol data-bind="foreach: scores">
- <li><span data-bind="text: player"></span>: <span data-bind="text: score"></span></li>
- </ol>
+ <div class="span4 hall_of_fame">
+ <h3>Hall of Fame (top scores)</h3>
+ <ol data-bind="foreach: hall_of_fame">
+ <li>
+ <strong>
+ <span data-bind="text: player"></span> <span class="score" data-bind="text: score"></span>
+ </strong>
+ <span class="timestamp">
+ (<span data-bind="text: timestamp"></span>)
+ </span>
+ </li>
+ </ol>
</div>
- <div data-bind="visible: history().length">
- <h3>Game history</h3>
- <div data-bind="foreach: history">
- <div class="game_history alert alert-warning">
- <h4><small>game played at: </small> <span data-bind="text: name"> </span></h4>
- <ol data-bind="foreach: scores">
- <li><span data-bind="text: player"></span>: <span data-bind="text: score"></span></li>
- </ol>
- </div>
- </div>
- </div>
- </div>
+ </div>
</div>
View
22 views/layout.html
@@ -2,7 +2,7 @@
<html>
<head>
<title><%= title %></title>
- <link rel='stylesheet' href='/stylesheets/bootstrap.css' />
+ <link rel='stylesheet' href='/stylesheets/bootstrap.superhero.min.css' />
<link rel='stylesheet' href='/stylesheets/style.css' />
<script src="/javascripts/jquery-1.7.1.min.js" type="text/javascript" charset="utf-8"></script>
</head>
@@ -37,16 +37,16 @@
<script src="/javascripts/knockout-2.0.0.js" type="text/javascript" charset="utf-8"></script>
</div>
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-300651-38']);
- _gaq.push(['_trackPageview']);
+ <script type="text/javascript">
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-300651-38']);
+ _gaq.push(['_trackPageview']);
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+ </script>
</body>
</html>

0 comments on commit f8dd561

Please sign in to comment.
Something went wrong with that request. Please try again.