First, I would like to save your valuable time before you read any further. Please check the demo hosted here, you might have to wait a couple of seconds to see the dynamic behavior on the page. If you are interested in further reading, and would like to know how this is implemented, please continue.
You can download the source code here: CricketSourceCode.
I start writing a little bit about the Cricket Scoreboard live sample. CrockInfo is a currently emerging international sports channel (just kidding...), this channel is exclusive for sports and only for sports. So they created a website to display the live commentary and match scores for India vs Australia match (Note: This match never happened, scores showed in the match are not intentional, they are just for educational purposes). Here is what the sample does.
- As of now, it is displaying a snapshot of India vs Australia match for one over (6 balls).
- It displays India batting for one over (6 balls).
- It displays Australia batting for one over (6 balls).
- It updates playing team score live (for e.g., 280/1 meaning 280 runs for one wicket).
- It updates Individual player statistics live like the number of balls played, runs made, etc.
- It updates commentary for each ball live.
- It updates Bowlers statistics live
- Last but not least, it also updates Batsman and bowlers status like who is batting…, and who is bowling…
- It broadcasts the match to all the clients connected, so doesn’t matter when you connected, it always shows the same statistics for all the clients.
The sample demonstrated above is for illustration purposes, so please don’t get into serious stuff like counting on balls left, runs needed, etc. and who is winning the game :-).
Now here comes the boring technology part, it is not really complex.., after you finished reading this article, you will say is that so simple?
Here, we are talking about so much of live updates on the web page, most of the times we do Ajax polling and partial updates on the web page to give an experience like it is updating live, but in the background, the client will keep on poking the server asking for updates. We are not doing this here. Remember we have Ryan dhal’s Nodejs expert in Push back model, wherein server can initiate the communication to client for posting messages any time when there is data, so here we are solving two problems with the old approach, there is lot of network traffic, possible inaccuracy with Ajax polling.
socket.io
I used socket.io
for implementing push back style, please check the link here for further reading. It is very simple to use, encapsulated lot of underlying technology and gave us simple to use API.
Loading socket.io
:
var io = require('socket.io');
Here is how the server pushes anything (here status object) to client, below is a broadcast message to all the clients (browsers in our context) connected.
io.sockets.emit('news', { status: message});
Here is how client consumes for the above event.
socket.on('news', function (data) {
});
The above code shows that the client is subscribed to news push backs. Whenever it receives the news push back event, it executes the associated callback, this is the core part of the sample.
Twitter Bootstrap
In order for the sample to work in all devices like mobiles, tablets and PCs, etc., I used very popular and proven Twitter Bootstrap framework and I love cyborg theme, so I used the same in my sample..
Jade Template
Stop writing lengthy HTML, and number of keystrokes, use Jade template for views (it converts to HTML when compiled). Jade is nice and easy, simple to write, saves lot of key strokes. Find the documentation here.
Set Up the Sample in Your Local Machine
1. Set up Node
The sample assumes that you have Node installed on your machine already, if not please go ahead and install it from here.
2. Download the Source Code
Download the source code from the above link and unzip it to one of the local directories. Go to the root directory of the application, then you should see the following folder structure.
2. Installing Dependencies
Here is what the package.json file looks like, it has all the required dependencies.
{
"name": "sityroute",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "~3.4.8",
"static-favicon": "~1.0.0",
"morgan": "~1.0.0",
"cookie-parser": "~1.0.1",
"body-parser": "~1.0.0",
"debug": "~0.7.4",
"jade": "~1.3.0",
"socket.io":"~0.9.16"
},
"engines": {
"node": "0.10.18"
}
}
Run the following command from the root directory of the application to install all the dependencies.
npm install
The above command installs all the dependencies mentioned in the package.json file, you should see a folder with name node_modules in the same directory which contains all the installed dependencies.
Generally, it should output something similar to below:
static-favicon@1.0.2 node_modules\static-favicon
debug@0.7.4 node_modules\debug
morgan@1.0.0 node_modules\morgan
+-- bytes@0.2.1
body-parser@1.0.1 node_modules\body-parser
+-- qs@0.6.6
+-- raw-body@1.1.3 (bytes@0.2.1)
cookie-parser@1.0.1 node_modules\cookie-parser
+-- cookie-signature@1.0.3
+-- cookie@0.1.0
socket.io@0.9.16 node_modules\socket.io
+-- base64id@0.1.0
+-- policyfile@0.0.4
+-- redis@0.7.3
+-- socket.io-client@0.9.16 (xmlhttprequest@1.4.2, uglify-js@1.2.5, ws@0.4.31, a
ctive-x-obfuscator@0.0.1)
express@3.4.8 node_modules\express
+-- methods@0.1.0
+-- merge-descriptors@0.0.1
+-- range-parser@0.0.4
+-- fresh@0.2.0
+-- buffer-crc32@0.2.1
+-- cookie-signature@1.0.1
+-- cookie@0.1.0
+-- mkdirp@0.3.5
+-- send@0.1.4 (mime@1.2.11)
+-- commander@1.3.2 (keypress@0.1.0)
+-- connect@2.12.0 (uid2@0.0.3, pause@0.0.1, qs@0.6.6, bytes@0.2.1, batch@0.5.0,
raw-body@1.1.2, negotiator@0.3.0, multiparty@2.2.0)
jade@1.3.0 node_modules\jade
+-- commander@2.1.0
+-- character-parser@1.2.0
+-- mkdirp@0.3.5
+-- monocle@1.1.51 (readdirp@0.2.5)
+-- transformers@2.1.0 (promise@2.0.0, uglify-js@2.2.5, css@1.0.8)
+-- with@3.0.0 (uglify-js@2.4.13)
+-- constantinople@2.0.0 (uglify-js@2.4.13)
Running the Application
Open command prompt (windows + R > cmd), go to the application root folder in command prompt, and run the following command:
node app.js
Open browser, and type http://localhost:3001
to see the sample running.
Code Explanation
CrockInfo page is divided into 4 sections, News, Batting, Bowling, Commentary, Ads section. Ads is out of scope for this sample. These sections are updated by server using socket.io
push backs. Each section is having a listener subscribed to one push event, news, batting, bowling, commentary, we have public/javascripts/dashboard.js file which defines all these listeners, this file will be loaded in browser context and initiates the listeners.
Client Side
var socket = io.connect(document.location.origin);
socket.on('news', function (data) {......});
socket.on("batting",function(data){ ......});
socket.on("bowling",function(data){ ......});
socket.on("clean",function(data){ .....});
Inside these listeners, we do jquery DOM manipulation to update data received from server.
Server Side
io.sockets.emit('news', { status: matches[matchIndex].name });
function postBatting(){
updateBatting(getPlayingTeam().batting,commentary[commentIndex]);
io.sockets.emit('batting',
{
batting:getPlayingTeam().batting,
animateRecord:commentary[commentIndex].order,
teamName:getPlayingTeam().name,
score : getPlayingTeamScore()
})
}
function postBowling(){
updateBowling(getPlayingTeam().bowling,commentary[commentIndex]);
io.sockets.emit('bowling',{bowling:getPlayingTeam().bowling});
}
function postCommentary(){
var currentBall = commentary[commentIndex].bowling
+ ':' + commentary[commentIndex].batting;
io.sockets.emit('commentary',{status:currentBall});
}
function postClean(){
io.sockets.emit('clean');
}
Each helper method called in one of the respective places to PostMessages to clients, before posting they do udpate total match score, individual batsman score data. Please go through the code if you are interested in how the score is calculated, how and when each commentary is fired, that should be simple enough.
If you observe the sample, it is broadcasting messages to clients for every 5 secs, first team ball after ball and then second team ball after ball. In real time, commentators might be watching the match and writing commentary to application, and whenever the application receives a new commentary, it will broadcast to all clients. But here in order to create that effect, I used matches.json file which is a back end file for the matches, teams, players.
Please continue reading here…
CodeProject