Skip to content

Berechnung von Spielstatistiken

kubica edited this page Jul 13, 2013 · 20 revisions

General

First of all the structure of our part.

##What we get information given

##What we do We deciced to create the following classes: entity, ball, player, goalkeeper

class overview

###Entity Entity is the top class of all other classes. It contains all information, what we get (senderID, timestamp, …) It also includes the information about the total distance of an entity. ###Ball Ball inherits from the entity-class. We need the ball to calculate the nearest player and some other stuff. ###Player Player inherits from the entity-class. Every member of a team is a player. The player includes all information about a person which we discuss in the following part. ###Goalkeeper Goalkeeper is a special type of player. He needs some more information, like held shots or shots in the own goal.

Tools

##Esper Esper is an open source event stream processing (ESP) and event correlation engine (CEP).

Statistics

In general, we decided to calculate the following fundamental statistics.

Statistics for team:

* Goals
* Shots
* Shots on Goal
* Possession
* Corners
* Shot Success
* Pass Success
* (Standard Situations)

Statistics for player:

* Run Distance
* Ball Contacts
* Goals
* Shots
* Shots on Goal
* Successful Passes
* Misplaced Passes
* Ball Possession Time
* Heatmap
* (Crosses (Flanken))
* (Most Passes to)
* (Most Passes from)

Statistics for Goalkeeper:

* same like the player
* Goals against
* Shots on own Goal
* Saved Shots

Calculation

In this part we explain sample algorithm, which we need for calculation of the needed information.

##Run Distance Every player consists of two sensors – one in each of his legs. To calculate the run distance we need to take the average-position between these sensor-positions and calculate for each event what we get the distance between the events-position before and add it to his total distance.

##Ball Contacts ball contacts

First we take the position of the Ball and look from the sensor ID which is less than 1 meter away from the ball position. We doesn't take the middleposition of the player leg IDs, because we want to know which leg of the player is next to the ball. If we get multiple results we take the nearest one of them. BUT: If a player is near it's not automatically a ball contact. Therefore we look for ball hits. A ball is hit, if the accelleration of the ball is bigger than 45m/s². If we connect these both aspects we get a ball contact. There are 15000 Events per second. Thats because we decided to filter the ball contacts, that we doesn't get multiple ball contacts if there is only one contact. We take a border of 10ms between each ball contact. That means that we can only record ball contacts every 10ms, what is an approach we can take for football-games.

##Passes To calculate whether a pass is successful or not, we take the ball contacts. Now we look for the next ball contact. If the same player is on the ball, there isn't a pass. If another player is on the ball, we check the team of the player. If the player is from the same team and is not the player which was on the ball before it's a successful pass. If the player is from the other team it's not a successful pass. We also have some termination criteria, like when the game is stopped or the ball leaves the field. If the game is stopped there isn't a pass. If the ball leaves the field it's a not successful pass.

##Ball Possession Time To calculate the ball possession time per player we also need the ball contacts. We look for the first ball contact of a player and then for a pass and take the time between the first ball contact of a player and a ball contact of another player. Then we add it to player's ball possession time.

##Shot on goal shot on goal stats

To calculate a shot on the goal, we first look for a ball which is moving fast in direction of goal. We take a minimum accelleration of 55m/s² and take two events to get a vector. Now we create a linear equation and calculate whether the ball moves to the goal-area: Goal area team 1: x > 22578.5 and x < 29898.5, y = 33941.0, z < 2440.0 Goal area team 2: x > 22560.0 and x < 29880.0, y = -33968.0, z < 2440.0. If the ball does not leave the field or the direction does not changes, it's a shot on the goal.

##Heat map

example of a heat map

A heat map allows you to evaluate in which parts of the pitch a player has spent how much time. Generally this is not shown through absolute values, but relatively. This means you are able to compare the different parts of the pitch against each other, e.g. a player has been more often in this part of the pitch than in a second one. The number of equally sized tiles in which the pitch gets devided is arbitrary, but of course there are reasonable boundaries to both sides when it gets applied in practice. You neither want the grid to be too coarse nor too fine. Basically the granularity of the grid can be chosen by the user in our methods, but we set it to 13x10 tiles for our use-case.

How does the calculation work?

For every player there's a one-dimensional array in which each integer entry represents a tile of the heat map grid. While the match is going on there are events processed for the players. These always contain the current position of a particular entity on the pitch, in this case a player entity. According to the position values our algorithms calculate the respective tile and increment the corresponding entry in the array by one. In other words, we just count the number of events at times when a certain player was located in a certain tile.

What happens with these accumulated values?

When a heat map should be displayed we don't wanna use these absolute values (which continuously grow over the play time), because it's simply not necessary to distinguish between so many possible values. That's the reason why we implemented a method allowing us to scale a heat map. The user sets a maximum value according to the granularity of the values wanted and the method then scales the absolute values of the array appropriately. Yet the result is a working copy of the array so the actual array values don't get changed. Finally the visualization group can use these scaled values to assign different colors to different (ranges of) values.

Output

We decided to create a output-class with the name: GameInformation.java

##GameInformation.java This class is our connection point for all other groups, who need information from the statistic part. Here they can get all following informations:

###getActiveBallId() Returns the active Ball id.

###getBallHit(Player nearestPlayer, Ball ball) Calculates if the Ball was hit.

###getCurrentBallPossessionPlayer() Returns the current player that owns the ball.

###getCurrentBallPossessionTeam() Returns the current team that owns the ball.

###getCurrentGameTime() Returns the current relative game time in milliseconds.

###getDistanceOfNearestOpponent() Returns the distance to the next opponent of the player at the ball.

###getDistanceOfNearestTeammate() Returns the distance to the next teammate of the player at the ball.

###getDistanceOfNextNearestPlayer(boolean oppositeTeam) Returns the distance to the next player of the player at the ball.

###getEntityFromId(int id) Returns the Entity for a given id.

###getInterruptionBegin() Get the game interruption begin timestamp.

###getInterruptionEnd() Get the game interruption end timestamp.

###getLastBallLossTimeStamp() Get the relative game time in milliseconds of the last ball that was lost to the other team.

###getLastBallOutsideTimeStamp() Get the relative game time in milliseconds of the ball that is not within the game field.

###getLastBallPossessionTimeStamp()

###getLastPushedStatistics()

###getLastShotOnGoalTimeStamp()

###getNearestPlayer(Ball ball) Calculates the nearest player to the ball.

###getOpponentsInArea(int meters) Returns the number of oppenents in a area.

###getPlayerBallContacts(int id) Returns the sum of ballContacts of one player.

###getPlayerBallPossessionTime(int id) Returns the absolute ball possession time of one player for a given player id.

###getPlayerDistance(int id) Returns the absolute run distance of the player for a given playerID.

###getPlayerLastPassTimestamp(int id) Returns the timestamp of the last pass of a given player id.

###getPlayerPassesMissed(int id) Returns the absolute sum of missed passes of the player for a given playerID.

###getPlayerPassesSuccessful(int id) Returns the absolute sum of successful passes of the player for a given playerID.

###getPlayerRunningDirection(Player player) Returns the movement direction of a given player.

###getPlayersInArea(int meters, boolean oppositeTeam) Returns the number of players in a area.

###getProphet()

###getStatisticsFacade()

###getTeamBallPossessionPercentage(Team team) Get the overall time of ball possessions for a given team.

###getTeamContacts(Team team) Returns sum of all ball contacts of a given team.

###getTeammatesInArea(int meters) Returns the number of teammates in a area.

###getTeamPassQuote(int[] teamkuerzel) Returns the team pass quote for a given team.

###isPlayerLastPassSuccessful(int id) Returns the result of the last pass of a given player id.

###isPlayerOnOwnSide(Player player) Returns if the player is on his own side or opponent side.

###shotOnGoal(Ball ball, final int oldPosX, final int oldPosY, final int newPosX, final int newPosY) Calculates if the Ball moves towards the goals.