I’m creating a graph in php using the google graphing library to show StarCraft II APM data, and I’m having trouble thinking about the logic of it all. I’m not sure this is the best place to ask, but I’m out of options. This is a bit hard to explain so if any clarification is needed, let me know.
I have an array of keys and values. The key is the time in seconds. The value is the actions performed that second. Seconds with 0 actions are omitted by my data source.
Example:
seconds actions
1 10
3 5
4 7
7 15
etc etc
What I want to do is graph this data, showing the average actions per minute, at each second interval. Up until the first minute I would just use the available seconds that have passed.
Here is my current code
$p1_total = 0;
foreach ($p1 as $seconds => $actions) {
$p1_total = $p1_total + $actions;
$data['player1'][$seconds] = round($p1_total * 60 / $seconds);
}
However this calculates a rolling average as it goes on adding up $p1_total, what I really need is the average over the last 60 seconds at each interval.
I just cant fathom how to code this cleanly. I know I need to replace $p1_total with the count of actions from the last 60 seconds. But gathering that is whats getting me. How should I dynamically set this up without dealing with an insane amount of variables? Keep in mind my seconds aren’t every second, so I can’t just grab the last 60 entries in the array, as they might be more than 60 seconds long.
I thought about inserting values into the array to make up for the blank spots, but there is no reasonable way I can think of without skewing the average.
Or is there a way I can do this cleaner mathematically.
I appreciate everyone that can help. Please let me know if any more info would help. On the surface this feels like a really easy problem, but it really has be stumped. 🙁
You can insert zeros to make up for the blank spots, because each time that isn’t represented in the data corresponds to a second where zero actions were performed. This is probably the conceptually simplest way. You don’t need to actually insert the zeros in; what you could do is create a function which returns
$p1[$t]if it exists, otherwise 0. Then just use your function instead of accessing$p1directly. (My PHP is quite rusty, so consider this PHP-like pseudocode if necessary)Keep in mind that even though you don’t have raw data for certain seconds, there will still be a nonzero total action count for those seconds. So you should be creating a data point in the final APM array for every second, whether there were any actions performed then or not.
As for actually computing the rolling average, what you can do is iterate over the first 60 seconds and store the cumulative total in the output array:
(This would need adjusting if your raw data included an entry for zero seconds) Then after the first 60 seconds, each time you add the number of actions at a given second, subtract the number of actions performed 60 seconds earlier:
(
$tmaxwould be the highest second at which you have data, basically the length of the game.) I suppose in this latter sample,$totalno longer represents a full cumulative total, so you could rename it – but it does have to be the same variable as$totalin the previous code sample.By the way, I’m assuming
$tmaxwill never be less than 61. If you’re going to be releasing this code “into the wild” for other people to use, make sure you check for that case (just in case of an early surrender or something).