{"id":1128,"date":"2015-06-14T20:06:24","date_gmt":"2015-06-15T00:06:24","guid":{"rendered":"http:\/\/blog.agilityfeat.com\/?p=1096"},"modified":"2020-11-09T23:30:43","modified_gmt":"2020-11-09T23:30:43","slug":"real-time-game-using-pubnub","status":"publish","type":"post","link":"https:\/\/agilityfeatpanama.com\/en\/blog\/2015\/06\/real-time-game-using-pubnub\/","title":{"rendered":"A real time Lean game using PubNub"},"content":{"rendered":"<h2>Building the Penny Flipping game using Clojure, ClojureScript and PubNub<\/h2>\n<p><em>Author&#8217;s note: A portion of this post was <a href=\"http:\/\/www.pubnub.com\/blog\/syncing-state-building-a-basic-javascript-multiplayer-game\/\" target=\"_blank\" rel=\"noopener noreferrer\">also published on PubNub&#8217;s blog<\/a><\/em><\/p>\n<p>If you have ever attending a lean or agile process training, then you may have encountered a coin flipping game.  It goes by several names, including the <strong><a href=\"http:\/\/www.leansimulations.org\/2010\/11\/penny-game.html\" target=\"_blank\" rel=\"noopener noreferrer\">lean penny game<\/a><\/strong> or <strong><a href=\"http:\/\/blog.crisp.se\/2008\/09\/08\/mattiasskarin\/1220882915232\" target=\"_blank\" rel=\"noopener noreferrer\">\u00abpass the penny\u00bb<\/a><\/strong>, but they all share a similar set of rules and game play.  In short, the idea is to demonstrate lean manufacturing concepts and how they relate to project management and software development.<\/p>\n<p>It&#8217;s a timed exercise, where teams are challenged to pass a set of coins through the team, in set batch sizes, as quickly as possible, flipping the coins as they go.  The outcome is that the smaller batch size you use, the faster you complete the game.  For example, passing two coins at a time is much faster than passing 20 coins at once.  Not only do you get the first coins to your customer faster, but you also complete passing all the coins faster.<\/p>\n<p>We built an online version of this game, which allows distributed teams to play the penny flipping game.  The following video demonstrates the game and the concepts behind it, and then the rest of this blog post shows in detail how we built it using real-time data platform PubNub and Clojure.<\/p>\n<p><iframe src=\"https:\/\/player.vimeo.com\/video\/130380071\" width=\"500\" height=\"281\" style=\"max-width:500px; max-height:281px;\" frameborder=\"0\" webkitallowfullscreen mozallowfullscreen allowfullscreen><\/iframe><br clear=\"left\"\/> <\/p>\n<p><a href=\"https:\/\/vimeo.com\/130380071\">Remotely Flipped &#8211; an online version of the lean\/agile coin flipping game<\/a> from <a href=\"https:\/\/vimeo.com\/user24916355\">arinsime<\/a> on <a href=\"https:\/\/vimeo.com\">Vimeo<\/a>.<\/p>\n<p>Our team of designers and developers at AgilityFeat are experts in PubNub and other real time frameworks, so if you would like us to build a <strong><a href=\"http:\/\/www.agilityfeat.com\/realtime\" target=\"_blank\" rel=\"noopener noreferrer\">real time application<\/a><\/strong> for you, just let us know!  This particular exercise took just a few days of work, but of course most of our real time applications are much more complex.  Real time applications include communication applications, data dashboards, IoT apps, and even games like this simulation. <strong> <a href=\"http:\/\/www.agilityfeat.com\/contact\" target=\"_blank\" rel=\"noopener noreferrer\">Just contact us!<\/a><\/strong><\/p>\n<p>Now, let&#8217;s get to the detailed techie explanation of how we did it.  The rest of this blog post was written by one of our excellent developers, Germ\u00e1n Goldenstein, who also wrote all the code for this application.<\/p>\n<p>Here are the key URLs you need for our implementation and the code base:<br \/>\n&#8211; Demo deployed in Heroku: <strong><a href=\"http:\/\/remotelyflipped.com\" target=\"_blank\" rel=\"noopener noreferrer\">http:\/\/remotelyflipped.com<\/a><\/strong><br \/>\n&#8211; Code: <strong><a href=\"https:\/\/github.com\/agilityfeat\/penny-pub-react\/tree\/game\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/github.com\/agilityfeat\/penny-pub-react\/tree\/game<\/a><\/strong><\/p>\n<h2>About PubNub<\/h2>\n<p>PubNub is a commercial real time platform for publish\/subscribe messaging.  That basically means that we setup a channel on their service which any copy of our software subscribes to. That channel works like a chat room.  Any data that one of the users publishes to the channel is sent out to all the other subscribers to that channel.<\/p>\n<p><a href=\"\/wp-content\/uploads\/2015\/06\/PubNubDataSyncDataObject.png\"><img loading=\"lazy\" src=\"\/wp-content\/uploads\/2015\/06\/PubNubDataSyncDataObject-182x300.png\" alt=\"PubNubDataSyncDataObject\" width=\"182\" height=\"300\" style=\"max-width:182px; max-height:300px;\" class=\"alignleft size-medium wp-image-1115\" \/><\/a><br clear=\"left\"\/><\/p>\n<p>This is a relatively simple concept that has huge implications.  In our application, we use it to keep the data in synch across anyone looking at the coin flipping game in action.  Whenever a user passes their coins to the next player, that action needs to update all of their browsers in real-time in order to keep the game flowing smoothly.  PubNub makes it easy for us to do that.<\/p>\n<p>PubNub is not the only provider of a service like this, and there are also open source publish\/subscribe servers you can setup yourself and use for free.  However, we like using a commercial service like PubNub because they take care of all performance, scaling, and devops concerns so that we don&#8217;t have to.  All we have to do is write javascript to interface to their API&#8217;s.<\/p>\n<h2>Reviewing the flow of the \u2018Penny Flipping\u2019 game<\/h2>\n<p>1) A moderator comes to the web pages and starts a new \u00abroom\u00bb which will represent a team.  This produces a unique URL for that team.<br \/>\n2) The moderator gives that URL to everyone who should be on the team (this is done by email or chat outside of the tool).  Exactly 4 people are necessary to play the game.<br \/>\n3) Anyone with the URL is prompted to enter their name when they arrive on the page, and they are assigned an order in the team based on their arrival.<br \/>\n4) The web page shows images of virtual pennies, and a box for each person on the team with their name in it.  All the virtual pennies are in the box of the first person.<br \/>\n5) The moderator enters the number of coins for the batch size in this round, starts the game, and a timer also starts.<br \/>\n6) The first person on the team can start \u00abflipping\u00bb coins by clicking on them and moving them to a special area in the box.  When they have the right number of coins in the batch area, they can press a button to \u00abpass the coins\u00bb.  That person can then immediately start flipping more coins to put in the next batch.<br \/>\n7) The next person has now been given the first batch of coins from person #1, and they can immediately start flipping them and moving them to the queuing area in their box.  As they fill the box with the right batch size, they too can pass the coins to the next person.<br \/>\n8) For the last person, they do not pass the coins, they click a button to \u00abcomplete\u00bb that batch.<br \/>\n9) Two times are recorded for the team.  The time it took until the last person completed the first batch of coins, and the time it took until all the batches were complete.<br \/>\n10) At the end, these times are displayed on the screen, and the round is over.<br \/>\n11) The moderator will probably write these down somewhere (outside of our tool)<br \/>\n12) The moderator can then start a new round with the same team with a different batch size.  None of the statistics from the last round are saved.<\/p>\n<h2>OK, Let\u2019s get started!<\/h2>\n<p><strong>Prerequisites<\/strong><br \/>\nIn order to compile and run a Clojure project you need to have <strong><a href=\"http:\/\/leiningen.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">Leiningen<\/a><\/strong> installed. If you never had the opportunity to build an application in Clojure, we recommend you to read our post <strong><a href=\"http:\/\/www.agilityfeat.com\/blog\/2015\/03\/clojure-walking-skeleton\" target=\"_blank\" rel=\"noopener noreferrer\">\u00abHow to build a Walking Skeleton\u00bb<\/a><\/strong> where we explain how to setup a Clojure environment using <strong><a href=\"http:\/\/leiningen.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">Leiningen<\/a><\/strong>.<\/p>\n<h2>Step 1: Create a basic app with Luminus Framework<\/h2>\n<p>We used Luminus Framework, a great Framework to build apps quickly in Clojure and ClojureScript.<br \/>\nDoing this is very simple: just open a terminal and type the following line:<br \/>\n<script src=\"https:\/\/gist.github.com\/asime\/113ba3374846c4e96c21.js\"><\/script> <\/p>\n<p>This will create for us the basic structure of the application, where the Clojure and ClojureScript code are separated into two different directories. Clojure code will be under <strong>\/src<\/strong>, while Clojurescript code will be in <strong>\/src-cljs<\/strong>. Luminus comes with <strong><a href=\"http:\/\/getbootstrap.com\/\">Bootstrap<\/a><\/strong>, with the default design. We make the mockups for this project, also based on Bootstrap. You can download the mockups <strong><a href=\"https:\/\/github.com\/agilityfeat\/penny-pub-react\/tree\/game\/mockups\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a><\/strong>.<\/p>\n<p>We will focus on <strong>\/src-cljs<\/strong>, since most of the game will be developed in ClojureScript.<br \/>\nUnder <strong>\/src-cljs<\/strong> we have the file <strong><a href=\"https:\/\/github.com\/agilityfeat\/penny-pub-react\/blob\/game\/src-cljs\/penny_pub_react\/core.cljs\" target=\"_blank\" rel=\"noopener noreferrer\">core.cljs<\/a><\/strong> that we\u2019re going to use as the Presentation Layer, writing here the code of the different views and other general functions.<br \/>\nWe will create a second file called <strong><a href=\"https:\/\/github.com\/agilityfeat\/penny-pub-react\/blob\/game\/src-cljs\/penny_pub_react\/pubnub.cljs\" target=\"_blank\" rel=\"noopener noreferrer\">pubnub.cljs<\/a><\/strong> where We will write all the functions We need to interact with the <strong><a href=\"http:\/\/www.pubnub.com\/developers\/tutorials\/publish-subscribe\/\" target=\"_blank\" rel=\"noopener noreferrer\">PubNub JavaScript API<\/a><\/strong>.<\/p>\n<h2>Step 2: Include the PubNub JavaScript Library inside the HTML template file.<\/h2>\n<p>When you create a Luminus Project, It comes with a <strong>home.html<\/strong> file. The location of that file is <strong><a href=\"https:\/\/github.com\/agilityfeat\/penny-pub-react\/blob\/game\/resources\/templates\/home.html\" target=\"_blank\" rel=\"noopener noreferrer\">\/resources\/templates\/home.html<\/a><\/strong>.<br \/>\nWe\u2019re going to reuse this file, and include the PubNub JavaScript Library as follows:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/972967b12eb321b534ed.js\"><\/script><\/p>\n<p>You can include the minified version for production, and the developer version for your local dev environment.<\/p>\n<p>Also, inside the \u00abbody\u00bb tag you have to leave the header with id \u201ctop\u201d, and a div with id \u201capp\u201d.<br \/>\nReagent will use both to make a render of the navbar and the center body of the page. <\/p>\n<p>In <strong><a href=\"https:\/\/github.com\/agilityfeat\/penny-pub-react\/blob\/game\/src-cljs\/penny_pub_react\/core.cljs\" target=\"_blank\" rel=\"noopener noreferrer\">core.cljs<\/a><\/strong> you will find a function that handles the connection between these two HTML components with Reagent.<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/eed89aaa64fd1cac2952.js\"><\/script><\/p>\n<p>The div with the id \u00abapp\u00bb show the result of the function <strong>page<\/strong>. This function returns the value of <strong>pages<\/strong> which is defined as a map containing keys-values pairs relating to each component.<br \/>\nFor example, the key :home has the value [home-page], which is the component that shows the home.<br \/>\nSo, to show the component [home-page] in div \u00abapp\u00bb , we just change the session as follows:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/3a6d98cb8a9385996581.js\"><\/script><\/p>\n<h2>Step 3: New team creation process<\/h2>\n<p><strong>3.1) Homepage<\/strong><\/p>\n<p><a href=\"\/wp-content\/uploads\/2015\/06\/RemotelyFlippedHome.png\"><img loading=\"lazy\" src=\"\/wp-content\/uploads\/2015\/06\/RemotelyFlippedHome-1024x528.png\" alt=\"RemotelyFlippedHome\" width=\"510\" height=\"263\" class=\"alignleft size-large wp-image-1097\" style=\"max-width:510px; max-height:263px;\" \/><\/a><br clear=\"left\"\/><\/p>\n<p>As you can see in the screenshot above, the homepage is very simple. To create the team, the moderator enters the \u2018Team name\u2019 into the input text. When he press the \u2018Start button\u2019, the event OnClick should do the following:<\/p>\n<p>1) Make a new connection to PubNub<br \/>\n2) Make a Subscription to the new channel using the Team name as the Channel name.<br \/>\n3) Generate a new URL and show It on screen in order to the moderator can send It to the four players.<\/p>\n<p>Let\u2019s see the code of the Home page. (You can see this on github in the file <strong><a href=\"https:\/\/github.com\/agilityfeat\/penny-pub-react\/blob\/game\/src-cljs\/penny_pub_react\/core.cljs\" target=\"_blank\" rel=\"noopener noreferrer\">core.cljs<\/a><\/strong>):<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/69729eee32a2fb753860.js\"><\/script><\/p>\n<p>This is how Reagent works. Just need to write the HTML code using <strong><a href=\"https:\/\/github.com\/weavejester\/hiccup\" target=\"_blank\" rel=\"noopener noreferrer\">Hiccup<\/a><\/strong> syntax, and Reagent will convert it to real HTML code.<\/p>\n<p>The team name will be stored in an atom called \u2018team-name\u2019 defined in <strong><a href=\"https:\/\/github.com\/agilityfeat\/penny-pub-react\/blob\/game\/src-cljs\/penny_pub_react\/core.cljs\" target=\"_blank\" rel=\"noopener noreferrer\">core.cljs<\/a><\/strong> as follows:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/ebc73e183493de0a69e3.js\"><\/script><\/p>\n<p>This are the step that happens when the onClick event of the button \u2018Start Game\u2019 is fired:<\/p>\n<p>1) Generate a friendly URL (slug) using the name of the team:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/7cc41ccccb442c099d5c.js\"><\/script><\/p>\n<p>And here is the slug function:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/4b296b4ccc175a3eeb8d.js\"><\/script><\/p>\n<p>Once the slug is generated, is stored into the atom \u201cteam-slug\u201d<\/p>\n<p>2) Use an atom in order to know that we are a moderator user. <\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/1e6f4aca75fbb0a98775.js\"><\/script><\/p>\n<p>This will serve to show us some options and screens that are only for the moderator<\/p>\n<p>3) Connect to PubNub using the JavaScript API<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/1d8866930ff6abf46f68.js\"><\/script><\/p>\n<p>Now,  we start to define the functions in order to use the PubNub API, that will be created in the file <strong><a href=\"https:\/\/github.com\/agilityfeat\/penny-pub-react\/blob\/game\/src-cljs\/penny_pub_react\/pubnub.cljs\" target=\"_blank\" rel=\"noopener noreferrer\">pubnub.cljs<\/a><\/strong><\/p>\n<p>Here is the code to create the pubnub\/connect function:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/a832ac9d5c488382ded6.js\"><\/script><\/p>\n<p>In order to call the <strong>connect<\/strong> function from core.cljs we must include the namespace of pubnub.cljs into core.cljs, as follows:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/55a912d37bb390561ab9.js\"><\/script><\/p>\n<p>4) Create PubNub channel and subscribe to moderator on it<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/28598335f2753b101ee7.js\"><\/script><\/p>\n<p>This function is very important. Not only will take care of creating the channel and subscribe the moderator but also administer the values \u200b\u200bof some Atoms that will serve us for the game, such as timers and the player data.<\/p>\n<p>This is the <strong>subscribe-moderator<\/strong> function definition:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/fdd49e239591cf9e443c.js\"><\/script><\/p>\n<p>You can see the complete description of how to use the PubNub subscribe function <strong><a href=\"http:\/\/www.pubnub.com\/docs\/javascript\/api\/reference.html#subscribe\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a><\/strong>.<br \/>\nThe important thing to understand is that all PubNub functions have some callbacks:<\/p>\n<ul>\n<li><strong>presence:<\/strong> When a user joins in a channel, the callback \u00abpresence\u00bb is executed. That&#8217;s where we need to update the information the new player in the atom <strong>players<\/strong>.<\/li>\n<li><strong>message:<\/strong> When a player send any message using the PubNub function <strong>publish<\/strong> the callback \u00abmessage\u00bb is executed.<\/li>\n<li><strong>state:<\/strong> gives us the ability to add information to the newly connected user, such as a username, for example. In our case, besides a username dispatched two values more : \u00abstate_game\u00bb which is the state is the game (Waiting for players or Playing), and \u00abchannel_name \u00bb with the name of the channel. When a new player joins the channel, he consult these values \u200b\u200band be able to read the channel name.<\/li>\n<\/ul>\n<p><strong>3.2) Show the Team\u2018s URL on screen<\/strong><\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/acd1affedb546bd094cb.js\"><\/script><\/p>\n<p>As we saw above, when we change the value of <strong>:page<\/strong> in the session, another screen will be displayed. In this case <strong>:step2<\/strong>. So now we see the <strong>[step2-page]<\/strong> component.<\/p>\n<p>This page looks now like this:<\/p>\n<p><a href=\"https:\/\/agilityfeat.com\/wp-content\/uploads\/2015\/06\/teamurl.png\"><img loading=\"lazy\" src=\"\/wp-content\/uploads\/2015\/06\/teamurl-1024x534.png\" alt=\"teamurl\" width=\"510\" height=\"266\" style=\"max-width: 510px; max-height: 266px;\" class=\"alignleft size-large wp-image-1106\" \/><\/a><br clear=\"left\"\/><\/p>\n<p>On the screenshot, the name of the Team is \u201cAgilityFeat Team\u201d, and the generated URL is: <\/p>\n<p><a href=\"http:\/\/penny-pub-react.herokuapp.com\/team\/agilityfeat-team\" target=\"_blank\" rel=\"noopener noreferrer\">http:\/\/penny-pub-react.herokuapp.com\/team\/agilityfeat-team<\/a><\/p>\n<p>The code for the component [step2-page] is the following:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/2c92293a729a0f6fb22c.js\"><\/script><\/p>\n<p>Until all the four players are ready, the screen looks like the screenshot above.<br \/>\nOnly when the four players are ready to play, the component [step4-page] will display.<\/p>\n<p>In order to detect when a player is ready, we define the function <strong>p-ready?<\/strong> as follows:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/51178bac4128fb9ac42b.js\"><\/script><\/p>\n<p><strong>p-ready?<\/strong> expects the player index (from 0 to 3) as parameter, and reads the state of the player inside the atom <strong>players<\/strong>. Returns true if the state is equal to \u201cready\u201d<\/p>\n<p>Finally, we have two components showing the number of the players that are connected in the channel, and the list of them:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/c1e2b134d0baffb3baad.js\"><\/script><\/p>\n<p>The function <strong>get-total-players<\/strong> counts the number of players that are \u201cready\u201d, and completes the text \u201cX\/4 Joined\u201d, where X is the quantity of \u201cready\u201d players.<\/p>\n<p>The function <strong>get-list-players<\/strong> shows a list of players with their username.<\/p>\n<h2>Step 4: Players join the channel through the team URL<\/h2>\n<p>Each one of the Players will open a browser with the Team URL.<br \/>\nIn order to detect that a Player want to Join a team, we must detect the URL pattern and extract the slug.<\/p>\n<p>For example, if the team URL is <strong><a href=\"http:\/\/penny-pub-react.herokuapp.com\/team\/agilityfeat-team\" target=\"_blank\" rel=\"noopener noreferrer\">http:\/\/penny-pub-react.herokuapp.com\/team\/agilityfeat-team<\/a><\/strong> then we have to extract the slug part, which in this example is \u2018agilityfeat-team\u2019<br \/>\nTo do this, we have to edit \/src\/penny_pub_react\/routes\/home.clj where is all the routing configuration, using Compojure.<\/p>\n<p>Let\u2019s see the code of this file:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/54dff53a75f3826be3ad.js\"><\/script><\/p>\n<p>So we have to add a new route for the team URL. Now the code looks as follows:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/aa27769fbd9e159e5b78.js\"><\/script><\/p>\n<p>All the urls with the pattern \u201c\/team\/:team-slug\u201d will call the function <strong>team-home-page<\/strong> sending the slug part as a parameter. The function <strong>team-home-page<\/strong> use the same template than the home page.<\/p>\n<p>In order to detect this patterns and send the Player to the correct screen, we have to add the function:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/4c588a6ff80288a87efd.js\"><\/script><\/p>\n<p>The function <strong>set-page<\/strong> analyzes the value of window.location.href and verifies if the string \u2018\/team\/\u2019 matches using the indexOf.<br \/>\nIf it matches then proceed to:<br \/>\n1) connect the player to the channel <\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/c0fecf1d6b203986f2f1.js\"><\/script><\/p>\n<p>2) make the subscription (like we do before with the moderator) <\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/71fde6032e6469899c44.js\"><\/script><\/p>\n<p>3) Show the home page of team<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/75d10446e15c10dccfd1.js\"><\/script><\/p>\n<p>Let\u2019s see the <strong>pubnub\/subscribe-user<\/strong> function:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/91b16d863fc095269743.js\"><\/script><\/p>\n<p>This function is very similar to the <strong>subscribe-moderator,<\/strong> but it has many differences:<br \/>\n1) we add in this function the \u201cconnect\u201d callback. This callback will be launched when the player is connected to the channel. When that happens, the atom <strong>connected<\/strong>? will be true.<br \/>\n2) When the user joins the channel the \u201cpresence\u201d callback is fired. Here the player sets his player number using the property \u201coccupancy\u201d of the object m returned by \u00abpresence\u00bb,  which has information of the channel.<\/p>\n<p>Let\u2019s see the code of the Team home page:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/9895e0a9ccc1d8b6dce9.js\"><\/script><\/p>\n<p>The component <strong>[team-page]<\/strong> will check if the player is connected and has a player number. Until the user is connected and has assigned a number of player, the player will see the component <strong>[connecting-page]<\/strong>:<\/p>\n<p><a href=\"https:\/\/agilityfeat.com\/wp-content\/uploads\/2015\/06\/connecting.png\"><img loading=\"lazy\" src=\"\/wp-content\/uploads\/2015\/06\/connecting-1024x523.png\" alt=\"connecting\" width=\"510\" height=\"260\" style=\"max-width: 510px; max-height: 260px;\" class=\"alignleft size-large wp-image-1107\" \/><\/a><br clear=\"left\"\/><\/p>\n<p>Once the user is connected, he will see the next page. At this point, the player does not enter his name yet, so the component <strong>[step3-page]<\/strong> will be displayed as follows:<\/p>\n<p><a href=\"https:\/\/agilityfeat.com\/wp-content\/uploads\/2015\/06\/step3page.png\"><img loading=\"lazy\" src=\"\/wp-content\/uploads\/2015\/06\/step3page-1024x526.png\" alt=\"step3page\" width=\"510\" height=\"262\" style=\"max-width: 510px; max-height: 262px;\" class=\"alignleft size-large wp-image-1108\" \/><\/a><br clear=\"left\"\/><\/p>\n<p>Here is the code of the component [step3-page]:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/7487a02b69ebf71d622c.js\"><\/script><\/p>\n<p>The username is stored in the atom <strong>user-name<\/strong>. When the player press the button \u2018I\u2019m Ready\u2019, the onClick event call the function <strong>pubnub\/set-state<\/strong> which will update the information of the player. <\/p>\n<p>Let\u2019s see the <strong>set-state<\/strong> function:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/dfb7a219c3489e4ae7d4.js\"><\/script><\/p>\n<p>This function receives the JavaScript object with the user information, and send it to PubNub with the <strong><a href=\"http:\/\/www.pubnub.com\/docs\/javascript\/api\/reference.html#state\" target=\"_blank\" rel=\"noopener noreferrer\">state<\/a><\/strong> function.<\/p>\n<p>So now we have a player name, and as we saw above, now the player is going to see the <strong>[step4-page]<\/strong>, as follows:<\/p>\n<p><a href=\"https:\/\/agilityfeat.com\/wp-content\/uploads\/2015\/06\/letsflip.png\"><img loading=\"lazy\" src=\"\/wp-content\/uploads\/2015\/06\/letsflip-1024x517.png\" alt=\"letsflip\" width=\"510\" height=\"257\" style=\"max-width: 510px; max-height: 257px;\" class=\"alignleft size-large wp-image-1109\" \/><\/a><br clear=\"left\"\/><\/p>\n<p>Now, let\u2019s see the code for the component <strong>[step4-page]<\/strong>:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/698d2f4e1ada73168bf8.js\"><\/script><\/p>\n<p>The first thing that this functions do is check the value of the atom <strong>playing?<\/strong><br \/>\nThis atom stores a bool value that indicates if we are playing or not.<br \/>\nIf <strong>playing?<\/strong> is false, then the screenshot above will show up. Else, the component [step5-page] will be displayed.<\/p>\n<p>If the logged in user is the moderator, the atom <strong>moderator?<\/strong> will be true, and shows two input text to fill the total coins and batch size. Else, if the logged user is a player, only sees the message \u201cWaiting for the Moderator starts the game..\u201d.<\/p>\n<h2>Step 5: The Moderator set the values of total coins and batch size , and starts the round.<\/h2>\n<p>When the four players are ready, the moderator sees the component <strong>[step4-page]<\/strong>. Now, he is able to enter the values of total coins and the batch size, and then start the game.<\/p>\n<p>Let&#8217;s see how this screen looks:<\/p>\n<p><a href=\"https:\/\/agilityfeat.com\/wp-content\/uploads\/2015\/06\/batchsize.png\"><img loading=\"lazy\" src=\"\/wp-content\/uploads\/2015\/06\/batchsize-1024x519.png\" alt=\"batchsize\" width=\"510\" height=\"258\" style=\"max-width: 510px; max-height: 258px;\" class=\"alignleft size-large wp-image-1110\" \/><\/a><br clear=\"left\"\/><\/p>\n<p>At this time, players are waiting for the moderator start the game, and this is the screen they see:<\/p>\n<p><a href=\"https:\/\/agilityfeat.com\/wp-content\/uploads\/2015\/06\/playerswaiting.png\"><img loading=\"lazy\" src=\"\/wp-content\/uploads\/2015\/06\/playerswaiting-1024x469.png\" alt=\"playerswaiting\" width=\"510\" height=\"234\" style=\"max-width: 510px; max-height: 234px;\" class=\"alignleft size-large wp-image-1111\" \/><\/a><br clear=\"left\"\/><\/p>\n<p>Both screen are the same component: <strong>[step4-page]<\/strong><\/p>\n<p>When the moderator completes the values and press the button \u2018Start Flipping\u2019 , the function <strong>start-game<\/strong> will be executed. This function starts the game, and send a message to all the players through PubNub notifying that the game begins.<\/p>\n<p>Each player will receive this message through the \u201cmessage\u201d callback of the function <strong>subscribe-user<\/strong>, as we saw before, and then change the value of <strong>playing?<\/strong> to true. And Finally the component <strong>[step5-page]<\/strong> will be displayed.<\/p>\n<p>Let\u2019s see the code of the function <strong>start-game<\/strong><\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/e481cb919a04148286e0.js\"><\/script><\/p>\n<p>After a simple verification of the values of total icons and batch size, the function pubnub\/set-state stores this new values in the moderator information.<br \/>\nThen, restarts the timers to zero, and send the message to all the players through the function <strong>pubnub\/send-message<\/strong><\/p>\n<p>Finally, the atoms playing? change to true,  and <strong>finished?<\/strong> to false.<\/p>\n<p>What we need now is to define the function <strong>pubnub\/send-message<\/strong> as follows:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/a6bc197e5205f00f5897.js\"><\/script><\/p>\n<p>This short function use the PubNub publish function to send a message. With this function we could send any message we need in the format of any valid JSON type including objects, arrays, strings, and numbers.<\/p>\n<h2>Step 6: The game core<\/h2>\n<p>When the game starts,  the moderator sees the component <strong>[step5-game]<\/strong> as follows:<\/p>\n<p><a href=\"https:\/\/agilityfeat.com\/wp-content\/uploads\/2015\/06\/player1.png\"><img loading=\"lazy\" src=\"\/wp-content\/uploads\/2015\/06\/player1-1024x908.png\" alt=\"player1\" width=\"510\" height=\"452\" class=\"alignleft size-large wp-image-1112\" style=\"max-width: 510px; max-height: 452px;\" \/><\/a><br clear=\"left\"\/><\/p>\n<p>As you can see, the moderator is not able to move any penny. He can only views what is happening.<\/p>\n<p>However, the players screen looks a little different. They can move their coins to the next player, as follows:<\/p>\n<p><a href=\"https:\/\/agilityfeat.com\/wp-content\/uploads\/2015\/06\/player1view.png\"><img loading=\"lazy\" src=\"\/wp-content\/uploads\/2015\/06\/player1view-1024x927.png\" alt=\"player1view\" width=\"510\" height=\"462\" class=\"alignleft size-large wp-image-1113\" style=\"max-width: 510px; max-height: 462px;\" \/><\/a><br clear=\"left\"\/><\/p>\n<p>When the player selects the same amount of coins than the batch size, the \u00abRelease \u00bb button will be enabled, and the player is going to be able to send the batch to the next player.<\/p>\n<p>Let\u2019s see the code of the component <strong>[step5-page]<\/strong> which is the core of the game:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/2ea4ece5616daa08ef08.js\"><\/script><\/p>\n<p>Until the atom <strong>finished?<\/strong> is set to false, we are still playing, so the component <strong>[game]<\/strong> will be displayed.<\/p>\n<p>If <strong>finished?<\/strong> is set to true, then the component <strong>[show-results]<\/strong> will show up.<\/p>\n<p>This is how the code of the component <strong>[game]<\/strong> looks:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/edc6a001b79eb6496dac.js\"><\/script><\/p>\n<p>This component looks very simple. Shows the timers, and use another component to show each one of the players area: <strong>[draw-coin-panel]<\/strong><\/p>\n<p>This function receives the index of the player (from 0 to 3) and then prints the coins of that player.<\/p>\n<p>Let\u2019s see the code of <strong>[draw-coin-panel]<\/strong>:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/0b63e36aea235b3270d4.js\"><\/script><\/p>\n<p>This component is divided in two divs: div.coin-table and div.footer.<\/p>\n<p>The div.coin-table contains the Player\u2019s coins. As you can see, with a <strong>for<\/strong> loop statement from <strong>0 to (get-in @players [player-index :coins])<\/strong> (which is the number of coins that the player has) we draw each one of the pennies.<br \/>\nWhen the player clicks one of the coins, the coin will \u201cflip\u201d, and the atom <strong>qty-to-send<\/strong> will increase +1. If the penny was flipped before, then <strong>qty-to-send<\/strong> will decrease -1. <\/p>\n<p>The div.footer shows only for the logged player. That\u2019s why the moderator don\u2019t see It, and neither the rest of the players. Each player sees his own div.footer<br \/>\nWhen It shows, the player can see the number of selected coins, and the release button.<\/p>\n<p>The release button will be enabled only when the player select the same amount of coins than the batch size.<br \/>\nWhen the player press this button, two things will happen:<br \/>\n1) The release function will be executed<br \/>\n2) The counter <strong>qty-to-send<\/strong> will be restarted to zero.<\/p>\n<p>The release function receives two parameters: the player number, and the quantity of coins to send.<\/p>\n<p>Let\u2019s define this function as follows:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/8c63e93501a8b4546ac9.js\"><\/script><\/p>\n<p>Very simple right? The only thing this function has to do is send a message to all the players with the key \u201cstate_game\u201d and the value \u201cupdate_coins\u201d, and the callback <strong>\u201cmessage\u201d<\/strong> of the subscribe function will do the rest.<\/p>\n<h2>Step 7: Round complete! show the round times and start the new round<\/h2>\n<p>Finally, when the fourth player releases all his coins, the round is completed. The value of the atom <strong>finished?<\/strong> now is true and the component<strong> [show-results]<\/strong> will be displayed.<\/p>\n<p>All the players and moderator will see a new screen with the <strong>Overall time<\/strong> and the <strong>First Batch time<\/strong>.<\/p>\n<p>This screen looks as follows:<\/p>\n<p><a href=\"https:\/\/agilityfeat.com\/wp-content\/uploads\/2015\/06\/roundcomplete.png\"><img loading=\"lazy\" src=\"\/wp-content\/uploads\/2015\/06\/roundcomplete-1024x515.png\" alt=\"roundcomplete\" width=\"510\" height=\"256\" class=\"alignleft size-large wp-image-1114\" style=\"max-width: 510px; max-height: 256px;\" \/><\/a><br clear=\"left\"\/><\/p>\n<p>Notice that only the moderator sees the button \u201cStart new round\u201d. <\/p>\n<p>Let\u2019s see the code of this page:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/asime\/035100d93bdf6c488746.js\"><\/script><\/p>\n<p>If the value of the atom <strong>moderator?<\/strong> is true, then the first part of this component will be displayed. When the moderator press the button \u201cStart new round\u201d, the function <strong>start-game<\/strong> will be executed, and all the game starts again, with all the atoms restarted.<\/p>\n<h2>Conclusions<\/h2>\n<p>This little game was built with a specific goal in mind &#8211; demonstrating to remote teams that small batch sizes are better than large batches.  The concept applies to many industries, but in software development it shows that releasing your software in lots of small deployments is more effective than large big bang deployments.<\/p>\n<p>If you would like to play the game, check it out at:<\/p>\n<p><strong><a href=\"http:\/\/www.remotelyflipped.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">RemotelyFlipped.com<\/a><\/strong><\/p>\n<p>From a technical perspective, we hope that you have seen how we combined Clojure and PubNub to build this app and keep the data in synch across browsers.  But the technical concepts are applicable well beyond a simple coin flipping game, or games in general.  You can use these same concepts to build real time data dashboards, Internet of Things applications, communication applications, and more.<\/p>\n<p>Our team of designers and developers at AgilityFeat are experts in PubNub and other real time frameworks, so if you would like us to build a <strong><a href=\"http:\/\/www.agilityfeat.com\/realtime\" target=\"_blank\" rel=\"noopener noreferrer\">real time application<\/a><\/strong> for you, or if you have questions, just let us know! <strong><a href=\"http:\/\/www.agilityfeat.com\/contact\" target=\"_blank\" rel=\"noopener noreferrer\">We&#8217;re happy to help!<\/a><\/strong><\/p>","protected":false},"excerpt":{"rendered":"<p>Building the Penny Flipping game using Clojure, ClojureScript and PubNub Author&#8217;s note: A portion of this post was also published on PubNub&#8217;s blog If you have ever attending a lean or agile process training, then you may have encountered a coin flipping game. It goes by several names, including the lean penny game or \u00abpass [&hellip;]<\/p>","protected":false},"author":4,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":""},"categories":[116],"tags":[5,21,32,142,108,114],"jetpack_featured_media_url":"","yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v15.7 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>A real time Lean game using PubNub - AgilityFeat Panama Software Test Center<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/agilityfeatpanama.com\/en\/blog\/2015\/06\/real-time-game-using-pubnub\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"A real time Lean game using PubNub - AgilityFeat Panama Software Test Center\" \/>\n<meta property=\"og:description\" content=\"Building the Penny Flipping game using Clojure, ClojureScript and PubNub Author&#8217;s note: A portion of this post was also published on PubNub&#8217;s blog If you have ever attending a lean or agile process training, then you may have encountered a coin flipping game. It goes by several names, including the lean penny game or \u00abpass [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/agilityfeatpanama.com\/en\/blog\/2015\/06\/real-time-game-using-pubnub\/\" \/>\n<meta property=\"og:site_name\" content=\"AgilityFeat Panama Software Test Center\" \/>\n<meta property=\"article:published_time\" content=\"2015-06-15T00:06:24+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-11-09T23:30:43+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/agilityfeatpanama.com\/wp-content\/uploads\/2015\/06\/PubNubDataSyncDataObject-182x300.png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\">\n\t<meta name=\"twitter:data1\" content=\"18 minutes\">\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/34.200.113.64\/#website\",\"url\":\"https:\/\/34.200.113.64\/\",\"name\":\"AgilityFeat Panama Software Test Center\",\"description\":\"AgilityFeat Panama offers customized, multilevel web and mobile software testing for a variety of industries.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/34.200.113.64\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/agilityfeatpanama.com\/en\/blog\/2015\/06\/real-time-game-using-pubnub\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"\/wp-content\/uploads\/2015\/06\/PubNubDataSyncDataObject-182x300.png\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/agilityfeatpanama.com\/en\/blog\/2015\/06\/real-time-game-using-pubnub\/#webpage\",\"url\":\"https:\/\/agilityfeatpanama.com\/en\/blog\/2015\/06\/real-time-game-using-pubnub\/\",\"name\":\"A real time Lean game using PubNub - AgilityFeat Panama Software Test Center\",\"isPartOf\":{\"@id\":\"https:\/\/34.200.113.64\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/agilityfeatpanama.com\/en\/blog\/2015\/06\/real-time-game-using-pubnub\/#primaryimage\"},\"datePublished\":\"2015-06-15T00:06:24+00:00\",\"dateModified\":\"2020-11-09T23:30:43+00:00\",\"author\":{\"@id\":\"https:\/\/34.200.113.64\/#\/schema\/person\/c8d60d597071526db386b2b8a4afac64\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/agilityfeatpanama.com\/en\/blog\/2015\/06\/real-time-game-using-pubnub\/\"]}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/34.200.113.64\/#\/schema\/person\/c8d60d597071526db386b2b8a4afac64\",\"name\":\"arin\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/34.200.113.64\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/cc498e210512c707ed769986dd745896?s=96&d=mm&r=g\",\"caption\":\"arin\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","_links":{"self":[{"href":"https:\/\/agilityfeatpanama.com\/en\/wp-json\/wp\/v2\/posts\/1128"}],"collection":[{"href":"https:\/\/agilityfeatpanama.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/agilityfeatpanama.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/agilityfeatpanama.com\/en\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/agilityfeatpanama.com\/en\/wp-json\/wp\/v2\/comments?post=1128"}],"version-history":[{"count":1,"href":"https:\/\/agilityfeatpanama.com\/en\/wp-json\/wp\/v2\/posts\/1128\/revisions"}],"predecessor-version":[{"id":1327,"href":"https:\/\/agilityfeatpanama.com\/en\/wp-json\/wp\/v2\/posts\/1128\/revisions\/1327"}],"wp:attachment":[{"href":"https:\/\/agilityfeatpanama.com\/en\/wp-json\/wp\/v2\/media?parent=1128"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/agilityfeatpanama.com\/en\/wp-json\/wp\/v2\/categories?post=1128"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/agilityfeatpanama.com\/en\/wp-json\/wp\/v2\/tags?post=1128"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}