Showing posts with label node application. Show all posts
Showing posts with label node application. Show all posts

Thursday, 25 January 2018

Node JS Football / Soccer Simulation Engine Module

Football Simulation Engine - Node Module

As previously mentioned in my blog HERE, I had been looking to design and build a football manager game, with the main purpose being to improve my JavaScript (JS) and node (Node JS) skills. I soon found there were no existing node package modules (npm) that could provide a simulated match result.

I posted on a few sites to try and see if anyone had done this before - there’s no point repeating work is there? After finding nothing specific that matched my purpose I went on ahead and built my prototypes which consisted of two random numbers and a little use of player skill to create results (see previous blog), but it didn’t really fit the bill for a football manager games back end as it didn’t take other factors into consideration.

So, I went ahead and built my own, and as of today it is now available on the npm website HERE or run 
          npm install footballsimulationengine

How does it work?
Great question, glad you asked. Basically, you provide it with two JSON strings, each its own team and requiring a specific set of JSON objects. This includes team name, players, player positions, skills and each players starting position.
Example:
{
  "name": "Team1",
  "players": [{
      "name": "Player",
      "position": "GK",
      "rating": "99",
      "skill": {
        "passing": "99",
        "shooting": "99",
        "tackling": "99",
        "saving": "99",
        "agility": "99",
        "strength": "99",
        "penalty_taking": "99",
        "jumping": "300"
      },
      "startPOS": [60,0],
      "injured": false
    }...],
  "manager": "Aiden"
}

Key things to remember:
·      Each team MUST have 11 players
·      The code currently does not check these parameters, so the skills SHOULD be between 1 and 100.
·      Except for “jumping” which is intended to be the maximum jump height of the player in centimetres.
·      Start Position should between you pitch Sizes Width and half of the pitch length. The code deals with switching their start position side. E.g if my pitch size is [120, 600], “startPOS” SHOULD BE [0-120, 0 - 300].

The other thing we will need to start a game/match is pitch size, which is shown in [width, height] where the pitch is intended to be taller than it is wide, like below.

PIC

Example Pitch JSON:
{
            "pitchWidth": 120,
            "pitchHeight": 600
}

We feed these three JSONs into the initiate function like so:

Example:
initiateGame(team1, team2, pitch).then(function(matchDetails){
  console.log(matchDetails);
}).catch(function(error){
  console.error("Error: ", error);
})

what we get back is a super larger JSON with both teams, their originPOS (so we can get them back to their original position), relativePOS (so we know where they’re heading towards), and a whole bunch of match details such as the score, number of shots and importantly, where the ball is, ball direction.

The main idea is that the game runs in iterations this allows the client using the simulation engine to change players throughout the game, set up the game in certain positions.

Playing iterations is then as simple as running that big old outputted JSON back into a play iteration function which in turn, gives an updated big old output JSON.

Example:
playIteration(matchDetails).then(function (matchDetails) {
  console.log(matchDetails);
}).catch(function(error){
  console.error("Error: ", error);
}

Example Output:
{ kickOffTeam:
   { name: 'Team1',
     players:
      [ [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object] ],
     manager: 'Aiden'
     intent: 'defend' },
  secondTeam:
   { name: 'Team2',
     players:
      [ [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object] ],
     manager: 'Joe',
     intent: 'attack' },
  pitchSize: [ 120, 600 ],
  ball:
   { position: [ 76, 314 ],
     withPlayer: true,
     Player: 'Joe Bloggs',
     withTeam: 'Team2',
     direction: 'south' },
  half: 1,
  kickOffTeamStatistics:
   { goals: 0,
     shots: 0,
     corners: 0,
     freekicks: 0,
     penalties: 0,
     fouls: 0 },
  secondTeamStatistics:
   { goals: 0,
     shots: 0,
     corners: 0,
     freekicks: 0,
     penalties: 0,
     fouls: 0 },
  iterationLog:
   [ 'Closest Player to ball: Aiden Gallagher',
     'Closest Player to ball: Joe Bloggs' ] }

An important feature here is the “iterationLog” which gives an overview of what has happened during that iteration. i.e. someone has passed the ball, someone has taken a shot, scored, freekick awarded, penalty taken, a throwin given and taken.

Finally, the last function that can be played is switch sides of the teams that are playing, i.e. after half time or if running into extra time.

Example:
startSecondHalf(matchDetails).then(function (matchDetails) {
  console.log(matchDetails);
}).catch(function(error){
  console.error("Error: ", error);
}

TL;DR / Overview:
·      Three function; initiateGame - needs two team JSONs and a Pitch Details JSON, playIteration - takes the output from initiate game and updates one movement of each player, startSecondHalf - switches the sides the players are on.
·      All three functions are return promises
·      JSON isn’t checked so make sure you’ve got it right
·      Recommended match length is 10,000 iterations.

If you’d like help setting up, have some general questions please feel free to comment below and I’ll get back to you ASAP.

Improvements:
This code is setup on a public Github which you can find HERE and I’m hoping people who use the module (if anyone) will help me improve it! You can raise issues HERE but otherwise please get in touch by email: aiden.g@live.co.uk

Visual Example:
For those who want to see, here is a youtube video of the game being used in an example I have set up. Feel free to get in touch and I can send you the "manager" setup and some instructions. 


Saturday, 7 October 2017

Deploying a Node JS application using IBM Bluemix UI

The big moment. After several weeks I had put together a dashboard for myself to include;

  • My Local Teams last two games, next game and two games after
  • Next trains from Waterloo to Winchester
  • Journey time from Hursley to Winchester
  • Last five of my home timeline tweets
  • Share prices
I also added, off the entry page;
  • Cinema time for two of my nearby cinemas
  • An old JS application I created that lets you find out how many cities you have visited.
It did what I wanted it to do, but I had to have my laptop running to view it.
My next idea was to be able to show it online whenever I wanted so I could access it as and when I liked. At first I considered using a web hosting service like 1&1 (who I have another web address with) but decided I would instead make use of the IBM Bluemix service.

IBM Bluemix has a node SDK which has a plan of £0.0424 GBP/GB-Hour.

There are a few developerWorks articles that describe deploying a node js application:

An alternative method to the command line as shown in the three examples above, is to use the bluemix User Interface. Which is what I opted for this time, having created several application using the CLI before.

 1. Create a "Cloud Foundry Apps" -> SDK for Node.js as seen in the image above.
 2. Give your application a name, select the hosting country and select "create"

 3. The application will build and then start. You need to wait for it to show as "running" at which point it will be available. In my example, this is true for the url: https://mytest012345.mybluemix.net
 4. Within the applications bluemix "Application Details" page we can go to "Overview" and "enable" continuous delivery.
 5. This creates a toolchain which include a git repo and an eclipse browser.
 6. Select the eclipse tool and we can browse the files in the editor
standard SDK for node JS project
 7. Delete the public folder
 8. Zip your own public folder as well as your dependencies such as your node modules.
 9. Right click on your project folder and select "import -> File or Zip archive" and select the zip file you just created.
 10. The zip will be unzipped and the files and directories unpackaged into the project.
 11. Replace the "package.json" with your own and replace the README.md.
 12. Update the app.js file with your path routes, variables and dependencies
//ADD YOUR VARIABLES
//var abc = require("abc");
/*eslint-env node*/
//------------------------------------------------------------------------------
// node.js starter application for Bluemix
//------------------------------------------------------------------------------
// This application uses express as its web server
// for more info, see: http://expressjs.com
var express = require('express');
// cfenv provides access to your Cloud Foundry environment
// for more info, see: https://www.npmjs.com/package/cfenv
var cfenv = require('cfenv');
// create a new express server
var app = express();
// serve the files out of ./public as our main files
app.use(express.static(__dirname + '/public'));
/*app.get(/route1, function(req, res){

}); REPEAT WITH ALL ROUTES*/
// get the app environment from Cloud Foundry
var appEnv = cfenv.getAppEnv();
// start server on the specified port and binding host
app.listen(appEnv.port, '0.0.0.0', function() {
  // print a message when the server starts listening
  console.log("server starting on " + appEnv.url);
});
 13. We now need to commit the changes we have made. On the left panel, select the "git" option and commit the changes we have just made.
The second button is a link to commit changes to our git repository
 14. We can now redeploy the application from the eclipse toolkit using the play button.
The green circle shows the application is running, if red it would indicate an error. Next to this is a play button which deploys the app, the stop button stops the application, the third button opens the application in a new tab, second from right opens the logs and the final button opens the bluemix "application overview" page.

The application should now be running again.
*I would recommend for ease and speed to follow the command line functionality described in the links presented earlier*

So... I now have my application available.

Live Dashboard
For an added extra I opened the application on my phone:
In iOS we can press the box with an arrow coming out of it and we can save the page to our home screen.
This makes it available on the home screen making for quick access.

So, the dashboard is up, I can access it and it's being hosted on Bluemix. All is good with the world and another project is complete.

Have some questions? Think you can suggest some improvements? Feel free to email me here.
Alternatively leave a comment below.