This is a personal blog, postings on this site are my own and don’t necessarily represent IBM’s positions, strategies or opinions.
I blog about some of my day to day work findings in integration, programming and project competitions. I also blog about personal projects such as painting, the allotment, robot building, node modules or the history of IT.
1. Pick your two teams and click select teams. Hint: If you don't pick any teams or only pick one, just click "select teams" and it'll randomly pick two teams.
This dynamically generates 11 selection boxes with each countries squad displayed in each box, ready to pick your team. You will also need to select your formation or it won't work!
2. Pick your players. Not sure who to pick? Just click random select and it will pick a formation. This will fill in each position with either a Goalkeeper, a Defender, a Midfielder or a Forward depending on the formation and the players preferred position.
Hint: Not all player of a certain type will be put in their best position i.e. an RB in a CB position!
3. Hit simulate match. After you hit "Simulate Match" you'll see a screen with all the players selected and the positions they were put in. At which point you can either do a "Quick Match" which simulates the match with updates to the statistics or you can "Watch Match" which will give a graphical view.
2 Years ago I published my first node package module (npm) in npmjs to allow football match results to be simulated. Yesterday I uploaded the latest version FootballSimulationEngine-v3.0.1 which can be installed by running: npm install footballsimulationengine
What's New?
startPOS and relativePOS have changed
The biggest - and breaking - change was to update the arrays used to track where players currently are on the pitch (startPOS) and where players are moving towards (relativePOS). These were not very descriptive and resulted in several GitHub issues so they have been changed to better reflect what they do. "startPOS" is now "currentPOS", "relativePOS" is now "intentPOS".
"currentPOS": [340,0],
"fitness": 100,
"injured": false,
"originPOS": [340,0],
"intentPOS": [340,0],
Tests tests tests
I have been reading more and more about the importance of tests and clean code, in fact its been prominent on this blog:
As described, I have added lots and lots of tests into the code making it more readable, easier to make code changes, has led to variables and functions being named more accurately. The result is 143 passing (199ms) tests and roughly 55% test coverage.
55.88% Statements1401/2507
44.32% Branches655/1478
82.13% Functions170/207
53.14% Lines1227/2309
Penalty Position - Corner and Freekicks
Players no longer form an arbitary collection of bodies at a set location for freekicks and corners, instead they now gather in the penalty box which is a defined dimension on the pitch. This makes corner taking more realistic and improves goal opportunities from corners.
Identifiers
Previously, the current ball holder and the team they were playing were matched against their names for certain logic. i.e. can the player kick the ball? First, we need to know if that player has the ball. Now each match, player and team are given an identification number during initiation.
{
"matchID": "78883930303030001",
"kickOffTeam": {
"teamID": "78883930303030002",
"name": "ThisTeam",
"rating": 88,
"players": [
{
"playerID": "78883930303030100",
Red Cards
Players who get red cards will no longer be part of the playing action. This is shown by current position being set to ['NP', 'NP'] which means 'Not Playing'. If the current position is set the player will not be targeted for passing and will not make any movements.
Skill Rating Utilization
Player skills are better utilised including to make shots on or off target depending on their skill against a random number generation i.e. players with shooting skill of 40 will be less likely to shoot on target than players with shooting skill of 70. This is also applied for saving shots that are in the box with the skills of the goalkeeper determining if the ball is 'saved' or not when in reach.
Future iterations will take this further for more sophistication. If you have any thoughts for how to do this be sure to raise an issue in GitHub.
Player Stats Improvements
Player statistics from during the game have been greatly improved with statistics for fouls, passes, shots and tackles. This will improve reporting of player information.
If there are others that can/should be added, raise an issue in GitHub.
'goals':0,
'shots': {
'total':0,
'on':0,
'off':0
},
'cards': {
'yellow':0,
'red':0
},
'passes': {
'total':0,
'on':0,
'off':0
},
'tackles': {
'total':0,
'on':0,
'off':0,
'fouls':0
}
Conclusion
There are still some improvements to be made, to player movement (which still isn't quite there), passing statistics, intelligence of decisions being made and whole lotta tests to be added. I'll be blogging soon about how I've used this latest version to simulate the 2019/2020 season to showcase how the engine can be used to simulate a season for a football manager game.
Let me know what you think, either in the comments, or by raising an issue on Github or emailing me on aiden.g@live.co.uk! Happy footballing!
The football simulation engine node module has been available for just over a year now and has a couple of hundred downloads, and an interaction of a fair few people via GitHub. Part of that interaction has led to requests for changes to be made to the modules functions to either make the game easier to control or alter.
Whilst making the changes other issues were thrown up such as the ball not continuing to move with the players when they were in possession, and in other cases the ball remaining in the players control after it had been kicked. The new versions - specifically version 2.2.1 - resolves these issues and provides a much better and more reliable output.
Refactoring
The first big change was the removal of the async module. Two reasons for this were that a) it didn’t need it, b) I’ve grown a distaste for dependencies in my NodeJS programs. On top of this there were changes to allow for the latest node version to be used which included using let, const instead of var which good practice dictates and the general removal of promises which were also not necessary.
General input from https://github.com/dashersw has been instrumental which has included improving error throwing as well as removing repetition. As such the code has been regularly reduced or made easier to understand with game examples now available.
Testing
Part of my own journey has been to begin looking at Test Driven Development (TDD). Unfortunately, I could only apply it in this module retrospectively but will be adding test cases for all new functionality before I code it in future.
For now, I have added testing for the three main exported functions and testing of validation of input. This is because it is where users are most likely to get stuck. My new goal is also to raise tests around whatever issues come through. One example is https://github.com/GallagherAiden/footballSimulationEngine/issues/33 where tests were added to validate the “ClosestPlayer” functions.
Adding tests has improved the game, because it has caught a number of interesting ‘perks’ of the code written where tests that should have passed actually failed. Which is good, as it shows TDD in action.
Finally, part of the testing now includes End to End testing through Match Simulation of varying team ratings which shows expected results for teams of different skills.
New Functionality
After a review of the games being played there were a few obvious changes that could be made. Allowing more tackleswas one such whereby players rarely were able to take the ball off each other before, this has now changed and with it comes an improved risk of players committing fouls.
The greatest new functionality was to stop the ball moving instantaneously, instead the ball moves over a period of iterations. This includes an x, y and z movement which factors in the height of the ball against the height of another player. This has allowed even greater play by introducing interception of the ball as it moves.
Another big new function to the simulation was in the calculation of offside and the beginnings of some simple player marking. Other improvements have been possible with the ball movement change which includes; direction of player movementso players attack in the right direction, and better passing to stop players constantly passing to the keeper.
Finally, the way shots were taken, calculated and checked for so that own goals are awarded to the correct teams and shots occur over time. This has also led to an improvement of the ability for keepers to save shots as the ball enters their area.
Finally, a player fitness parameter has been added however this has no impact on the game currently and is merely additional information for people using the simulation engine as a manger game. This also includes an action parameter for each player which allows the move performed by each player determined by the simulator to be overridden.
Fixes
There have been a number of little fixes such as elimination of incorrect reporting of player possession of the ball. Changes have been made so that the closest player to ball or a position now gives a more accurate output.
Players now move with the ball at their feetwhich was quite a major bug in previous versions.
The changes made have had a massive impact on game play which you can see on the video I created for the latest version.
There are other changes coming in version 3 which looks to make the iteration json read better and make it more accessible. Other possibilities will be the removal of players from game play e.g. by red or yellow cards and the ability for team rating and other skills and fitness to have a greater impact on individual player performance.
With the World Cup upon us, this year being hosted in Russia I decided to take the hard work I did in making a football simulation engine: available here and discussed in this blog and put it to good use in a real life scenario.
What better way to test the module and see if it is anywhere near accurate then to simulate each result in the 2018 World Cup. At the same time I've been ironing out some issues and we are - at the time of writing - onto version 2.0.1 and the modules working a charm.
I have decided to host the nodeJS application on IBM Cloud, which gives 255MB free nodeJS deployment especially for this type of development work. Whilst it wouldn't be enough to handle Sky Sports Super 6 traffic, it should be enough for the numbers I'm expecting over the World Cup.
First pick your two teams (I've gone for Tunisia vs England) and click select teams. Hint: If you don't pick any teams or only pick one, just click "select teams" and it'll randomly pick two teams.
Select your team
This dynamically generates 11 selection boxes with each countries squad displayed in each box, ready to pick your team. You will also need to select your formation or it won't work!
pick your players
Not sure who to pick? Just click random select and it will pick a formation. This will fill in each position with either a Goalkeeper, a Defender, a Midfielder or a Forward depending on the formation and the players preferred position. Hint: Not all player of a certain type will be put in their best position i.e. an RB in a CB position!
After you hit "Simulate Match" you'll see a screen with all the players selected and the positions they were put in. At which point you can either do a "Quick Match" which simulates the match with updates to the statistics or you can "Watch Match" which will give a graphical view. Hint: Mobile Phones should be held in landscape mode
Ready to Play
Watch Match
Quick Match
Best of three has it. Tunisia will win 1 - 0.
Let's hope not
Let me know how you get on via email or comments below.
I recently created a football simulation engine for npm which I talked about here.
I also posted a youtube video of me demonstrating the code, and after some interest I thought I would upload the helper code I used in order to visualise the match!
## Install
1. Download the project onto your system ({dir})
2. cd {dir}
3. run ``npm install``
---
## Run the Game
1. load your team into the {dir}/teams directory (you can use an existing team as an example)
2. in '{dir}/server.js' change either
```
readFile("teams/team1.json").then(function (team1) {
```
to your newly created .json file i.e.
```
readFile("teams/myTeam.json").then(function (team1) {
```
3. Set the pitch size by changing the ``pitchWidth`` and ``pitchHeight`` in '{dir}/server.js'
*Note: Any changes will need changes made to the start positions of the players*
4. run ``npm start``
5. Go To ``http://localhost:1442/match.html``
---
## Playing A Match
1. Press ``start match``
- This starts a new match where the pitch size is displayed on the screen and the players are in their correct positions.
2. Press ``play match``
- This runs '10' iterations, moving the players and give iteration logs for each iteration.
i.e. `Iteration 50: Closest Player to ball: Louise Johnson,Closest Player to ball: Aiden Smith`
3. Press ``play match`` until the iterations reach 5,000
- We can make this quicker by changing the number of iterations per "play" in {dir}/public/js/match.js
```
function getMatch() { var iterations = 10; for (i = 0; i < iterations; i++) { movePlayers("/movePlayers"); }
}
```
to
```
function getMatch() { var iterations = X; for (i = 0; i < iterations; i++) { movePlayers("/movePlayers"); }
}
```
where X is the number of iterations to do at a time.
4. Press ``start second half``
- This flips the players to opposite sides
5. Press ``play match`` until the iterations reach 10,000
6. Record the results
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 sitesto
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 todayit
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:
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.
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.
·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 HEREbut
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.