/** * If recently-added batting/bowling records are not reflected in statistics, run this method * @return void */ public function RecalculateStatistics() { # Gather batting stats $this->total_innings = 0; $this->all_scores = array(); $this->scores_out = array(); $this->scores_not_out = array(); $this->scores_with_balls_faced = array(); $this->balls_faced = array(); $this->batting_best = null; $this->batting_average = null; $this->batting_strike_rate = null; $this->batting_50 = 0; $this->batting_100 = 0; $this->how_out = array(); foreach ($this->batting as $batting) { /* @var $batting Batting */ if ($batting->GetHowOut() != Batting::DID_NOT_BAT) { $this->total_innings++; } if (!array_key_exists($batting->GetHowOut(), $this->how_out)) { $this->how_out[$batting->GetHowOut()] = 0; } $this->how_out[$batting->GetHowOut()]++; if (!is_null($batting->GetRuns())) { $this->all_scores[] = $batting->GetRuns(); if ($this->IsNotOut($batting->GetHowOut())) { $this->scores_not_out[] = $batting->GetRuns(); } else { $this->scores_out[] = $batting->GetRuns(); } if ($batting->GetRuns() >= 50) { $this->batting_50++; } if ($batting->GetRuns() >= 100) { $this->batting_100++; } if (is_null($this->batting_best) or $batting->GetRuns() > intval($this->batting_best) or $batting->GetRuns() == intval($this->batting_best) && $this->IsNotOut($batting->GetHowOut())) { $this->batting_best = $batting->GetRuns(); if ($this->IsNotOut($batting->GetHowOut())) { $this->batting_best .= "*"; } } if (!is_null($batting->GetBallsFaced())) { $this->scores_with_balls_faced[] = $batting->GetRuns(); $this->balls_faced[] = $batting->GetBallsFaced(); } } } $this->not_outs = array_key_exists(Batting::NOT_OUT, $this->how_out) ? $this->how_out[Batting::NOT_OUT] : 0; if (count($this->all_scores)) { # retired is not out for purpose of average $retired = array_key_exists(Batting::RETIRED, $this->how_out) ? $this->how_out[Batting::RETIRED] : 0; $retired_hurt = array_key_exists(Batting::RETIRED_HURT, $this->how_out) ? $this->how_out[Batting::RETIRED_HURT] : 0; $total_innings_for_average = $this->total_innings - $this->not_outs - $retired - $retired_hurt; if ($total_innings_for_average > 0) { $this->batting_average = round(array_sum($this->all_scores) / $total_innings_for_average, 2); } # Work out the ranges scores are in $this->WorkOutScoreSpread(); } if (count($this->scores_with_balls_faced)) { $total_balls_faced = array_sum($this->balls_faced); if ($total_balls_faced) { $this->batting_strike_rate = round(array_sum($this->scores_with_balls_faced) / $total_balls_faced * 100, 2); } } # Gather bowling stats $this->bowling_innings = 0; $this->balls = null; $this->overs = null; $this->maidens = null; $this->runs_against = null; $this->wickets_taken = 0; $this->wickets_taken_for_analysis = 0; $this->bowling_economy = null; $this->bowling_average = null; $this->bowling_strike_rate = null; $this->bowling_best = null; $best_wickets = 0; $best_runs = 0; $this->bowling_5 = 0; foreach ($this->bowling as $bowling) { /* @var $bowling Bowling */ $this->bowling_innings += 1; if (!is_null($bowling->GetOvers())) { # Initialise balls, since we now know there are some recorded if (is_null($this->balls)) { $this->balls = 0; } # Work out how many balls were bowled - have to assume 8 ball overs, even though on rare occasions that may not be the case $this->balls += StoolballStatistics::OversToBalls($bowling->GetOvers()); } if (!is_null($bowling->GetMaidens())) { # Initialise maidens now we know the stat has been recorded if (is_null($this->maidens)) { $this->maidens = 0; } # Add these maidens to total bowled $this->maidens += $bowling->GetMaidens(); } if (!is_null($bowling->GetRunsConceded())) { # Initialise runs, since we now know there are some recorded if (is_null($this->runs_against)) { $this->runs_against = 0; } # Add these runs to the total $this->runs_against += $bowling->GetRunsConceded(); } if (!is_null($bowling->GetWickets())) { $this->wickets_taken += $bowling->GetWickets(); if ($bowling->GetWickets() >= 5) { $this->bowling_5++; } # Record wickets separately for average and strike rate, because otherwise wickets recorded on batting card # with no overs recorded on bowling card distort those statistics. if (!is_null($bowling->GetRunsConceded())) { $this->wickets_taken_for_average += $bowling->GetWickets(); } if (!is_null($bowling->GetOvers())) { $this->wickets_taken_for_strike_rate += $bowling->GetWickets(); } } if (!is_null($bowling->GetWickets())) { if ($bowling->GetWickets() > $best_wickets or $bowling->GetWickets() == $best_wickets and (!is_null($bowling->GetRunsConceded()) and (is_null($best_runs) or $bowling->GetRunsConceded() < $best_runs))) { $best_wickets = $bowling->GetWickets(); $best_runs = $bowling->GetRunsConceded(); } } } if (!is_null($this->balls) and $this->balls > 0 and !is_null($this->runs_against)) { $this->overs = StoolballStatistics::BallsToOvers($this->balls); $this->bowling_economy = StoolballStatistics::BowlingEconomy($this->overs, $this->runs_against); } if ($this->wickets_taken > 0) { $this->bowling_best = "{$best_wickets}/{$best_runs}"; } if ($this->wickets_taken_for_average > 0 and !is_null($this->runs_against)) { $this->bowling_average = StoolballStatistics::BowlingAverage($this->runs_against, $this->wickets_taken_for_average); } if ($this->wickets_taken_for_strike_rate > 0 and $this->balls > 0) { $this->bowling_strike_rate = StoolballStatistics::BowlingStrikeRate($this->overs, $this->wickets_taken_for_strike_rate); } }
/** * Creates a bowling scorecard for one innings with as much data as is available * @param Match $match * @param bool $is_home_innings * @return void */ private function CreateBowlingCard(Match $match, $is_home_innings) { $overs_data = $is_home_innings ? $match->Result()->AwayOvers() : $match->Result()->HomeOvers(); $bowling_data = $is_home_innings ? $match->Result()->AwayBowling() : $match->Result()->HomeBowling(); $bowling_team = $is_home_innings ? $match->GetAwayTeam() : $match->GetHomeTeam(); # First, bowler's figures if ($bowling_data->GetCount()) { $bowling_table = new XhtmlTable(); $bowling_table->SetCaption(htmlentities($bowling_team->GetName() . "'s bowlers", ENT_QUOTES, "UTF-8", false)); $bowling_table->SetCssClass("bowling scorecard"); $over_header = new XhtmlCell(true, '<abbr title="Overs" class="small">Ov</abbr><span class="large">Overs</span>'); $over_header->SetCssClass("numeric"); $maidens_header = new XhtmlCell(true, '<abbr title="Maiden overs" class="small">Md</abbr><abbr title="Maiden overs" class="large">Mdns</abbr>'); $maidens_header->SetCssClass("numeric"); $runs_header = new XhtmlCell(true, "Runs"); $runs_header->SetCssClass("numeric"); $wickets_header = new XhtmlCell(true, '<abbr title="Wickets" class="small">Wk</abbr><abbr title="Wickets" class="large">Wkts</abbr>'); $wickets_header->SetCssClass("numeric"); $economy_header = new XhtmlCell(true, '<abbr title="Economy" class="small">Econ</abbr><span class="large">Economy</span>'); $economy_header->SetCssClass("numeric"); $average_header = new XhtmlCell(true, '<abbr title="Average" class="small">Avg</abbr><span class="large">Average</span>'); $average_header->SetCssClass("numeric"); $strike_header = new XhtmlCell(true, '<abbr title="Strike rate" class="small">S/R</abbr><span class="large">Strike rate</span>'); $strike_header->SetCssClass("numeric"); $bowling_headings = new XhtmlRow(array("Bowler", $over_header, $maidens_header, $runs_header, $wickets_header, $economy_header, $average_header, $strike_header)); $bowling_headings->SetIsHeader(true); $bowling_table->AddRow($bowling_headings); $bowling_data->ResetCounter(); while ($bowling_data->MoveNext()) { $bowling = $bowling_data->GetItem(); /* @var $bowling Bowling */ $player = new XhtmlCell(false, '<a property="schema:name" rel="schema:url" href="' . htmlentities($bowling->GetPlayer()->GetPlayerUrl(), ENT_QUOTES, "UTF-8", false) . '">' . htmlentities($bowling->GetPlayer()->GetName(), ENT_QUOTES, "UTF-8", false) . '</a>'); $player->AddCssClass("bowler"); $player->AddAttribute("typeof", "schema:Person"); $player->AddAttribute("about", $bowling->GetPlayer()->GetLinkedDataUri()); $over_data = new XhtmlCell(false, htmlentities($bowling->GetOvers(), ENT_QUOTES, "UTF-8", false)); $over_data->SetCssClass("numeric"); $maidens_data = new XhtmlCell(false, htmlentities($bowling->GetMaidens(), ENT_QUOTES, "UTF-8", false)); $maidens_data->SetCssClass("numeric"); $runs_data = new XhtmlCell(false, htmlentities($bowling->GetRunsConceded(), ENT_QUOTES, "UTF-8", false)); $runs_data->SetCssClass("numeric"); $wickets_data = new XhtmlCell(false, htmlentities($bowling->GetWickets(), ENT_QUOTES, "UTF-8", false)); $wickets_data->SetCssClass("numeric"); $economy = StoolballStatistics::BowlingEconomy($bowling->GetOvers(), $bowling->GetRunsConceded()); $economy_data = new XhtmlCell(false, is_null($economy) ? "–" : htmlentities($economy, ENT_QUOTES, "UTF-8", false)); $economy_data->SetCssClass("numeric"); $average = StoolballStatistics::BowlingAverage($bowling->GetRunsConceded(), $bowling->GetWickets()); $average_data = new XhtmlCell(false, is_null($average) ? "–" : htmlentities($average, ENT_QUOTES, "UTF-8", false)); $average_data->SetCssClass("numeric"); $strike = StoolballStatistics::BowlingStrikeRate($bowling->GetOvers(), $bowling->GetWickets()); $strike_data = new XhtmlCell(false, is_null($strike) ? "–" : htmlentities($strike, ENT_QUOTES, "UTF-8", false)); $strike_data->SetCssClass("numeric"); $bowling_row = new XhtmlRow(array($player, $over_data, $maidens_data, $runs_data, $wickets_data, $economy_data, $average_data, $strike_data)); $bowling_row->GetFirstCell()->SetCssClass("bowler"); $bowling_table->AddRow($bowling_row); } $this->AddControl($bowling_table); } # Now over-by-over if ($overs_data->GetCount()) { $overs_table = new XhtmlTable(); $overs_table->SetCaption(htmlentities($bowling_team->GetName() . "'s bowling, over-by-over", ENT_QUOTES, "UTF-8", false)); $overs_table->SetCssClass("scorecard bowling-scorecard bowling overs"); $balls_header = new XhtmlCell(true, "Balls"); $balls_header->SetCssClass("numeric"); $wides_header = new XhtmlCell(true, "Wides"); $wides_header->SetCssClass("numeric"); $no_balls_header = new XhtmlCell(true, "No balls"); $no_balls_header->SetCssClass("numeric"); $runs_in_over_header = new XhtmlCell(true, "Runs"); $runs_in_over_header->SetCssClass("numeric"); $total_header = new XhtmlCell(true, "Total"); $total_header->SetCssClass("numeric"); $overs_headings = new XhtmlRow(array("Bowler", $balls_header, $wides_header, $no_balls_header, $runs_in_over_header, $total_header)); $overs_headings->SetIsHeader(true); $overs_table->AddRow($overs_headings); $overs_data->ResetCounter(); $total = 0; while ($overs_data->MoveNext()) { $bowling = $overs_data->GetItem(); /* @var $bowling Over */ $player = new XhtmlCell(false, '<a property="schema:name" rel="schema:url" href="' . htmlentities($bowling->GetPlayer()->GetPlayerUrl(), ENT_QUOTES, "UTF-8", false) . '">' . htmlentities($bowling->GetPlayer()->GetName(), ENT_QUOTES, "UTF-8", false) . '</a>'); $player->AddCssClass("bowler"); $player->AddAttribute("typeof", "schema:Person"); $player->AddAttribute("about", $bowling->GetPlayer()->GetLinkedDataUri()); $balls_data = new XhtmlCell(false, htmlentities($bowling->GetBalls(), ENT_QUOTES, "UTF-8", false)); $balls_data->SetCssClass("numeric"); $wides_data = new XhtmlCell(false, htmlentities($bowling->GetWides(), ENT_QUOTES, "UTF-8", false)); $wides_data->SetCssClass("numeric"); $no_balls_data = new XhtmlCell(false, htmlentities($bowling->GetNoBalls(), ENT_QUOTES, "UTF-8", false)); $no_balls_data->SetCssClass("numeric"); $runs_in_over_data = new XhtmlCell(false, htmlentities($bowling->GetRunsInOver(), ENT_QUOTES, "UTF-8", false)); $runs_in_over_data->SetCssClass("numeric"); $total += $bowling->GetRunsInOver(); $total_data = new XhtmlCell(false, htmlentities($total, ENT_QUOTES, "UTF-8", false)); $total_data->SetCssClass("numeric"); $bowling_row = new XhtmlRow(array($player, $balls_data, $wides_data, $no_balls_data, $runs_in_over_data, $total_data)); $bowling_row->GetFirstCell()->SetCssClass("bowler"); $overs_table->AddRow($bowling_row); } $this->AddControl($overs_table); } }