Jump to content

User:IPLRecordsUpdateBot/Version 1.0 source/StatsUpdateFunctions.php

From Wikipedia, the free encyclopedia
<?php

require 'translate.php';
include 'CricinfoDataParser.php';

# HELPER FUNCTIONS FOR THE STAT UPDATE FUNCTIONS

function SUF_generatePlayerSortNameLink($name, $uri = '', $flag = false) {
    # Generates a {{sortname}} template from a Cricinfo player name, optionally with a flag of that player's country
    global $CricinfoPlayerNameTranslationTable;

    # If the unique ID from the URI given exists in the table, use it, otherwise use the name
    preg_match('%/content(?:/.*?)?/player/(\d+)\.html$%', $uri, $idMatch);
    $index = isset($CricinfoPlayerNameTranslationTable[@$idMatch[1]]) ? $idMatch[1] : $name;

    $playerdata = @$CricinfoPlayerNameTranslationTable[$index];

    if ( ! $playerdata ) {
        throw new Exception("Player name does not exist in translation table: {$name}");
    }

    $result = "{{sortname|1={$playerdata['first']}|2={$playerdata['last']}"
              . (@$playerdata['page'] ? "|3={$playerdata['page']}" : '') . (@$playerdata['sort'] ? "|4={$playerdata['sort']}" : '') . "}}";

    if ( $flag && isset($playerdata['country']) ) {
        $result = "{{flagicon|{$playerdata['country']}}} " . $result;
    }

    return $result;
}

function SUF_generateTeamNameLink($name) {
    # Generates a {{Cr-IPL}} template from a Cricinfo short team name or an actual team name
    global $CricinfoTeamNameTranslationTable;
    $teamdata = @$CricinfoTeamNameTranslationTable[$name];

    if ( ! $teamdata ) {
        throw new Exception("Team name does not exist in translation table: {$name}");
    }

    return "{{Cr-IPL|{$teamdata['alias']}}}";
}

function SUF_getPlayerCurrentTeam($name) {
    # Return the current team of a player from its Cricinfo name
    global $CricinfoPlayerNameTranslationTable;
    return $CricinfoPlayerNameTranslationTable[$name]['team'];
}

function SUF_generateGroundNameLink($uri) {
    # Generate wikitext consisting of the ground name and location from a Cricinfo profile page URI
    global $CricinfoGroundNameTranslationTable;

    preg_match('%/content(?:/.*?)?/ground/(\d+)\.html$%', $uri, $idMatch);
    $id = $idMatch[1];
    $grounddata = @$CricinfoGroundNameTranslationTable[$id];

    if ( ! $grounddata ) {
        throw new Exception("Ground ID not found in translation table: {$id}");
    }

    return "'''[[{$grounddata['location']}]]''' – [[{$grounddata['name']}]]";
}

function SUF_generateWikiTableRow($data) {
    # Generates a wiki text table row from the function's arguments
    return '| ' . implode(' || ', func_get_args());
}

function SUF_encodeWikiTemplates($text) {
    # Replaces characters in templates which conflict with table and header syntax, with HTML entities
    $text = preg_replace_callback('/\{\{(?:[^\{\}]++|(?<!\{)\{|\}(?!\})|(?R))*?\}\}/u',
                                function($match) {
                                    return str_replace(['&', '|', '!', '='], ['&amp;', '&#124;', '&#33;', '&#61;'], $match[0]);
                                } , $text);
    return $text;
}

# Regular expression to capture the body of a wikitext table
# Note that newlines in the header region of a table are not allowed as setting the s modifier globally causes unexpected results
$wikiTableBodyRegex = '/^\{\|.*?\n(?:(?:\!|\|\-).*?\n)*\|\-.*?\n((?:\|\-?(?s).*?(?-s)\n)*?)\|\}/mu';

# The default limit (maximum number of rows to be returned from the parsed data) for all functions
$defaultLimit = 5;

# Load the match results (they are requuired by some of the functions)
# The results of earlier seasons are stored locally in old_match_results.json to reduce time and server load. Only the current season's results need to be fetched.
$matchResultsParser = new CricinfoDataParser();
$matchResultsParser->load('http://stats.espncricinfo.com/indian-premier-league-2013/engine/records/team/match_results.html?id=2013;trophy=117;type=season');
if ( $matchResultsParser->loadFailed ) {
    $currentMatchResults = [];
}
else {
    $currentMatchResults = $matchResultsParser->parse(
        0,
        [ 'C_TEAM1', 'C_TEAM2', 'C_WINNER', 'C_MARGIN', 'C_GROUND', 'C_MATCH_DATE', 'C_SCORECARD' ],
        true
    );
}

$MatchResults = array_merge(
    json_decode(file_get_contents('old_match_results.json'), true),
    $currentMatchResults
);
unset($matchResultsParser, $currentMatchResults);


$StatsUpdateFunctions = [

    # ---------- STATS UPDATE FUNCTIONS START HERE ----------

    # This uses PHP 5.3 syntax, older versions need to use create_function()
    # Not using data-sort-value attributes as sort keys for now, as HTML5 is not supported by some browsers. Use the sorting templates instead.
    # Functions should return true on success, false on failure.


    # TEAM RECORDS

    'TEAM_HIGHEST_TOTALS'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n===Highest totals===", strpos($PageText, "\n==Team records=="));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: TEAM_HIGHEST_TOTALS', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/team/highest_innings_totals.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_TEAM', 'C_SCORE', 'C_OVERS', 'C_RUN_RATE', 'C_INNINGS', 6 => 'C_OPPOSITION', 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_SCORE', 'C_RUN_RATE', 'C_DATE' ],
            CricinfoDataParser::SORT_DESCENDING
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                '{{ntsh|{{#expr:' . (explode('/', $row['C_SCORE'])[0] + 1) . '+1/' . (((strpos($row['C_SCORE'], '/') !== false) ? explode('/', $row['C_SCORE'])[1] : 10) + 1) . '}}}}' . "'''{$row['C_SCORE']}'''",  # Add 1 to both runs and wickets in the sort key to avoid a division by zero
                'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_TEAM']),
                'style="text-align:left"|' . SUF_generateTeamNameLink(preg_replace('/^v /i', '', $row['C_OPPOSITION'])),
                $row['C_OVERS'],
                $row['C_RUN_RATE'],
                $row['C_INNINGS'],
                '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        # Since the table body regex catches the newline before the ending "|}", add it to the replacement string to avoid breaking the table syntax

        return true;
    },


    'TEAM_LOWEST_TOTALS'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n===Lowest totals===", strpos($PageText, "\n==Team records=="));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: TEAM_LOWEST_TOTALS', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.cricinfo.com/ipl2009/engine/records/team/lowest_innings_totals.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_TEAM', 'C_SCORE', 'C_OVERS', 'C_RUN_RATE', 'C_INNINGS', 6 => 'C_OPPOSITION', 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_SCORE', 'C_RUN_RATE', 'C_DATE' ],
            CricinfoDataParser::SORT_ASCENDING,
            [ 'C_DATE' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                '{{ntsh|{{#expr:' . (explode('/', $row['C_SCORE'])[0] + 1) . '+1/' . (((strpos($row['C_SCORE'], '/') !== false) ? explode('/', $row['C_SCORE'])[1] : 10) + 1) . '}}}}' . "'''{$row['C_SCORE']}'''",
                'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_TEAM']),
                'style="text-align:left"|' . SUF_generateTeamNameLink(preg_replace('/^v /i', '', $row['C_OPPOSITION'])),
                $row['C_OVERS'],
                $row['C_RUN_RATE'],
                $row['C_INNINGS'],
                '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;

    },


    'TEAM_HIGHEST_MATCH_AGGREGATES'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit, $MatchResults;

        $tablePosition = strpos($PageText, "\n===Highest match aggregates===", strpos($PageText, "\n==Team records=="));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: TEAM_HIGHEST_MATCH_AGGREGATES', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/team/highest_match_aggregates.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_TEAM1', 'C_TEAM2', 'C_RUNS', 'C_WICKETS', 'C_OVERS', 'C_RUN_RATE', 7 => 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_RUNS', 'C_RUN_RATE', 'C_WICKETS', 'C_DATE' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_WICKETS' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {

            # Find the result of the match to determine the winner
            preg_match('%engine/match/(\d+)\.html$%', $row['C_SCORECARD:href'], $idMatch);
            $thisMatchResult = array_filter($MatchResults,
                                            function($result) use ($idMatch) {
                                                return preg_match('%engine/match/' . preg_quote($idMatch[1], '%') . '\.html$%', $result['C_SCORECARD:href']);
                                            });
            $thisMatchResult = $thisMatchResult[array_keys($thisMatchResult)[0]];
            # Trigger a warning if a tied match is found (since super over results are not given, winner and loser columns may be mismatched in the result)
            if ( $thisMatchResult['C_WINNER'] == 'tied' ) {
                trigger_error("Tied match found when attempting to determine winner (scorecard URI: {$thisMatchResult['C_SCORECARD:href']}), winner and loser columns may be mismatched", E_USER_WARNING);
            }

            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_RUNS']}'''",
                'style="text-align:left"|' . SUF_generateTeamNameLink( ($thisMatchResult['C_WINNER'] == $row['C_TEAM1']) ? $row['C_TEAM1'] : $row['C_TEAM2'] ),
                'style="text-align:left"|' . SUF_generateTeamNameLink( ($thisMatchResult['C_WINNER'] == $row['C_TEAM1']) ? $row['C_TEAM2'] : $row['C_TEAM1'] ),
                $row['C_OVERS'],
                $row['C_RUN_RATE'],
                $row['C_WICKETS'],
                '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
            );
        }

        $tablePosition = strpos($PageText, "\n===Highest match aggregates===", strpos($PageText, "\n==Team records=="));
        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'TEAM_LOWEST_MATCH_AGGREGATES'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit, $MatchResults;

        $tablePosition = strpos($PageText, "\n===Lowest match aggregates===", strpos($PageText, "\n==Team records=="));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: TEAM_LOWEST_MATCH_AGGREGATES', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.cricinfo.com/ipl2009/engine/records/team/lowest_match_aggregates.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_TEAM1', 'C_TEAM2', 'C_RUNS', 'C_WICKETS', 'C_OVERS', 'C_RUN_RATE', 7 => 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_RUNS', 'C_RUN_RATE', 'C_WICKETS', 'C_DATE' ],
            CricinfoDataParser::SORT_ASCENDING,
            [ 'C_WICKETS', 'C_DATE' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            preg_match('%engine/match/(\d+)\.html$%', $row['C_SCORECARD:href'], $idMatch);
            $thisMatchResult = array_filter($MatchResults,
                                            function($result) use ($idMatch) {
                                                return preg_match('%engine/match/' . preg_quote($idMatch[1], '%') . '\.html$%', $result['C_SCORECARD:href']);
                                            });
            $thisMatchResult = $thisMatchResult[array_keys($thisMatchResult)[0]];
            if ( $thisMatchResult['C_WINNER'] == 'tied' ) {
                trigger_error("Tied match found when attempting to determine winner (scorecard URI: {$thisMatchResult['C_SCORECARD:href']}), winner and loser columns may be mismatched", E_USER_WARNING);
            }

            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_RUNS']}'''",
                'style="text-align:left"|' . SUF_generateTeamNameLink( ($thisMatchResult['C_WINNER'] == $row['C_TEAM1']) ? $row['C_TEAM1'] : $row['C_TEAM2'] ),
                'style="text-align:left"|' . SUF_generateTeamNameLink( ($thisMatchResult['C_WINNER'] == $row['C_TEAM1']) ? $row['C_TEAM2'] : $row['C_TEAM1'] ),
                $row['C_OVERS'],
                $row['C_RUN_RATE'],
                $row['C_WICKETS'],
                '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'TEAM_LARGEST_VICTORIES'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.cricinfo.com/ipl2009/engine/records/team/largest_margins.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResults = [];

        $parseResults['runs'] = $parser->parse(
            0,
            [ 'C_WINNER', 'C_MARGIN', 'C_TARGET', 4 => 'C_OPPOSITION', 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_MARGIN', 'C_TARGET', 'C_DATE' ],
            CricinfoDataParser::SORT_DESCENDING
        );

        $parseResults['wickets'] = $parser->parse(
            1,
            [ 'C_WINNER', 'C_MARGIN', 'C_BALLS_REMAINING', 'C_TARGET', 'C_OVERS', 6 => 'C_OPPOSITION', 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_MARGIN', 'C_TARGET', 'C_BALLS_REMAINING', 'C_DATE' ],
            CricinfoDataParser::SORT_DESCENDING
        );

        $parseResults['balls_remaining'] = $parser->parse(
            2,
            [ 'C_WINNER', 'C_MARGIN', 'C_BALLS_REMAINING', 'C_TARGET', 'C_OVERS', 7 => 'C_OPPOSITION', 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_BALLS_REMAINING', 'C_TARGET', 'C_MARGIN', 'C_DATE' ],
            CricinfoDataParser::SORT_DESCENDING
        );


        foreach ( $parseResults as $parseKey => $parseResult ) {
            switch ( $parseKey ) {

                case 'runs':
                    $tablePosition = strpos($PageText, "\n====By runs====", strpos($PageText, "\n===Largest victories===", strpos($PageText, "\n==Team records==")));
                    if ( $tablePosition === false ) {
                        trigger_error('Cannot find section header for function: TEAM_LARGEST_VICTORIES (runs)', E_USER_WARNING);
                        return false;
                    }

                    $newTableRows = [];
                    foreach ( $parseResult as $row ) {
                        $newTableRows[] = SUF_generateWikiTableRow(
                            "'''{{nts|" . ((int) $row['C_MARGIN']) . '}} run' . (($row['C_MARGIN'] > 1) ? 's' : '') . "'''",
                            'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_WINNER']),
                            $row['C_TARGET'],
                            'style="text-align:left"|' . SUF_generateTeamNameLink(preg_replace('/^v /i', '', $row['C_OPPOSITION'])),
                            '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                            'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                            "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
                        );
                    }

                    preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

                    $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
                    break;

                case 'wickets':
                    $tablePosition = strpos($PageText, "\n====By wickets====", strpos($PageText, "\n===Largest victories===", strpos($PageText, "\n==Team records==")));
                    if ( $tablePosition === false ) {
                        trigger_error('Cannot find section header for function: TEAM_LARGEST_VICTORIES (wickets)', E_USER_WARNING);
                        return false;
                    }

                    $newTableRows = [];
                    foreach ( $parseResult as $row ) {
                        $newTableRows[] = SUF_generateWikiTableRow(
                            "'''{{nts|" . ((int) $row['C_MARGIN']) . '}} wicket' . (($row['C_MARGIN'] > 1) ? 's' : '') . "'''",
                            'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_WINNER']),
                            $row['C_TARGET'],
                            $row['C_BALLS_REMAINING'],
                            $row['C_OVERS'],
                            'style="text-align:left"|' . SUF_generateTeamNameLink(preg_replace('/^v /i', '', $row['C_OPPOSITION'])),
                            '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                            'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                            "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
                        );
                    }

                    preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

                    $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
                    break;

                case 'balls_remaining':
                    $tablePosition = strpos($PageText, "\n====By balls remaining====", strpos($PageText, "\n===Largest victories===", strpos($PageText, "\n==Team records==")));
                    if ( $tablePosition === false ) {
                        trigger_error('Cannot find section header for function: TEAM_LARGEST_VICTORIES (balls_remaining)', E_USER_WARNING);
                        return false;
                    }

                    $newTableRows = [];
                    foreach ( $parseResult as $row ) {
                        $newTableRows[] = SUF_generateWikiTableRow(
                            "'''{$row['C_BALLS_REMAINING']}'''",
                            'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_WINNER']),
                            $row['C_TARGET'],
                            '{{nts|' . ((int) $row['C_MARGIN']) . '}} wickets',
                            $row['C_OVERS'],
                            'style="text-align:left"|' . SUF_generateTeamNameLink(preg_replace('/^v /i', '', $row['C_OPPOSITION'])),
                            '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                            'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                            "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
                        );
                    }

                    preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

                    $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
                    break;

            }
        }

        return true;
    },


    'TEAM_SMALLEST_VICTORIES'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.cricinfo.com/ipl2009/engine/records/team/smallest_margins.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResults = [];

        $parseResults['runs'] = $parser->parse(
            0,
            [ 'C_WINNER', 'C_MARGIN', 'C_TARGET', 4 => 'C_OPPOSITION', 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_MARGIN', 'C_TARGET', 'C_DATE' ],
            CricinfoDataParser::SORT_ASCENDING,
            [ 'C_DATE' ]
        );

        $parseResults['wickets'] = $parser->parse(
            1,
            [ 'C_WINNER', 'C_MARGIN', 'C_BALLS_REMAINING', 'C_TARGET', 'C_OVERS', 6 => 'C_OPPOSITION', 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_MARGIN', 'C_TARGET', 'C_BALLS_REMAINING', 'C_DATE' ],
            CricinfoDataParser::SORT_ASCENDING,
            [ 'C_DATE' ]
        );

        $parseResults['balls_remaining'] = $parser->parse(
            2,
            [ 'C_WINNER', 'C_MARGIN', 'C_BALLS_REMAINING', 'C_TARGET', 'C_OVERS', 7 => 'C_OPPOSITION', 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_BALLS_REMAINING', 'C_TARGET', 'C_MARGIN', 'C_DATE' ],
            CricinfoDataParser::SORT_ASCENDING,
            [ 'C_DATE' ]
        );


        foreach ( $parseResults as $parseKey => $parseResult ) {
            switch ( $parseKey ) {

                case 'runs':
                    $tablePosition = strpos($PageText, "\n====By runs====", strpos($PageText, "\n===Smallest victories===", strpos($PageText, "\n==Team records==")));
                    if ( $tablePosition === false ) {
                        trigger_error('Cannot find section header for function: TEAM_SMALLEST_VICTORIES (runs)', E_USER_WARNING);
                        return false;
                    }

                    $newTableRows = [];
                    foreach ( $parseResult as $row ) {
                        $newTableRows[] = SUF_generateWikiTableRow(
                            "'''{{nts|" . ((int) $row['C_MARGIN']) . '}} run' . (($row['C_MARGIN'] > 1) ? 's' : '') . "'''",
                            'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_WINNER']),
                            $row['C_TARGET'],
                            'style="text-align:left"|' . SUF_generateTeamNameLink(preg_replace('/^v /i', '', $row['C_OPPOSITION'])),
                            '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                            'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                            "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
                        );
                    }

                    preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

                    $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
                    break;

                case 'wickets':
                    $tablePosition = strpos($PageText, "\n====By wickets====", strpos($PageText, "\n===Smallest victories===", strpos($PageText, "\n==Team records==")));
                    if ( $tablePosition === false ) {
                        trigger_error('Cannot find section header for function: TEAM_SMALLEST_VICTORIES (wickets)', E_USER_WARNING);
                        return false;
                    }

                    $newTableRows = [];
                    foreach ( $parseResult as $row ) {
                        $newTableRows[] = SUF_generateWikiTableRow(
                            "'''{{nts|" . ((int) $row['C_MARGIN']) . '}} wicket' . (($row['C_MARGIN'] > 1) ? 's' : '') . "'''",
                            'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_WINNER']),
                            $row['C_TARGET'],
                            $row['C_BALLS_REMAINING'],
                            $row['C_OVERS'],
                            'style="text-align:left"|' . SUF_generateTeamNameLink(preg_replace('/^v /i', '', $row['C_OPPOSITION'])),
                            '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                            'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                            "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
                        );
                    }

                    preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

                    $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
                    break;

                case 'balls_remaining':
                    $tablePosition = strpos($PageText, "\n====By balls remaining====", strpos($PageText, "\n===Smallest victories===", strpos($PageText, "\n==Team records==")));
                    if ( $tablePosition === false ) {
                        trigger_error('Cannot find section header for function: TEAM_SMALLEST_VICTORIES (balls_remaining)', E_USER_WARNING);
                        return false;
                    }

                    $newTableRows = [];
                    foreach ( $parseResult as $row ) {
                        $newTableRows[] = SUF_generateWikiTableRow(
                            "'''{$row['C_BALLS_REMAINING']}'''",
                            'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_WINNER']),
                            $row['C_TARGET'],
                            '{{nts|' . ((int) $row['C_MARGIN']) . '}} wickets',
                            $row['C_OVERS'],
                            'style="text-align:left"|' . SUF_generateTeamNameLink(preg_replace('/^v /i', '', $row['C_OPPOSITION'])),
                            '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                            'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                            "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
                        );
                    }

                    preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

                    $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
                    break;

            }
        }

        return true;
    },


    # INDIVIDUAL RECORDS (BATTING)

    'BATTING_MOST_RUNS'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Most runs====", strpos($PageText, "\n===Batting Records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: BATTING_MOST_RUNS', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/batting/most_runs_career.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_SPAN', 'C_MATCHES', 'C_INNINGS', 'C_NOT_OUT', 'C_RUNS', 'C_HIGH_SCORE', 'C_AVERAGE', 'C_BALLS', 'C_STRIKE_RATE', 'C_100', 'C_50', 'C_0', 'C_4', 'C_6' ],
            true,
            $defaultLimit,
            [ 'C_RUNS', 'C_AVERAGE', 'C_STRIKE_RATE', 'C_HIGH_SCORE', 'C_100', 'C_50', 'C_6', 'C_4', 'C_NAME' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_RUNS']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . (@SUF_getPlayerCurrentTeam($row['C_NAME']) ? SUF_generateTeamNameLink(SUF_getPlayerCurrentTeam($row['C_NAME'])) : ''),
                str_replace('-', '&#8211;', $row['C_SPAN']),  # Replace hyphen with en-dash
                $row['C_MATCHES'],
                $row['C_INNINGS'],
                $row['C_BALLS'],
                $row['C_STRIKE_RATE'],
                $row['C_AVERAGE'],
                '{{nts|' . ((int) $row['C_HIGH_SCORE']) . '}}' . ((strpos($row['C_HIGH_SCORE'], '*') !== false) ? '*' : ''),
                $row['C_100'],
                $row['C_50'],
                $row['C_4'],
                $row['C_6']
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'BATTING_BEST_STRIKE_RATE'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Best strike rate====", strpos($PageText, "\n===Batting Records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: BATTING_BEST_STRIKE_RATE', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/batting/highest_career_strike_rate.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_SPAN', 'C_MATCHES', 'C_INNINGS', 'C_NOT_OUT', 'C_RUNS', 'C_HIGH_SCORE', 'C_AVERAGE', 'C_BALLS', 'C_STRIKE_RATE', 'C_100', 'C_50', 'C_0', 'C_4', 'C_6' ],
            true,
            $defaultLimit,
            [ 'C_STRIKE_RATE', 'C_RUNS', 'C_AVERAGE', 'C_HIGH_SCORE', 'C_100', 'C_50', 'C_6', 'C_4', 'C_NAME' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME' ],
            function($row) {
                return $row['C_BALLS'] >= 125;
            }
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_STRIKE_RATE']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . (@SUF_getPlayerCurrentTeam($row['C_NAME']) ? SUF_generateTeamNameLink(SUF_getPlayerCurrentTeam($row['C_NAME'])) : ''),
                str_replace('-', '&#8211;', $row['C_SPAN']),
                $row['C_MATCHES'],
                $row['C_INNINGS'],
                $row['C_RUNS'],
                $row['C_BALLS'],
                $row['C_AVERAGE'],
                '{{nts|' . ((int) $row['C_HIGH_SCORE']) . '}}' . ((strpos($row['C_HIGH_SCORE'], '*') !== false) ? '*' : ''),
                $row['C_100'],
                $row['C_50'],
                $row['C_4'],
                $row['C_6']
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'BATTING_BEST_AVERAGE'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Best average====", strpos($PageText, "\n===Batting Records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: BATTING_BEST_AVERAGE', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2010/engine/records/batting/highest_career_batting_average.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_SPAN', 'C_MATCHES', 'C_INNINGS', 'C_NOT_OUT', 'C_RUNS', 'C_HIGH_SCORE', 'C_AVERAGE', 'C_BALLS', 'C_STRIKE_RATE', 'C_100', 'C_50', 'C_0', 'C_4', 'C_6' ],
            true,
            $defaultLimit,
            [ 'C_AVERAGE', 'C_RUNS', 'C_STRIKE_RATE', 'C_HIGH_SCORE', 'C_100', 'C_50', 'C_6', 'C_4', 'C_NAME' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME' ],
            function($row) {
                return $row['C_INNINGS'] >= 10;
            }
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_AVERAGE']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . (@SUF_getPlayerCurrentTeam($row['C_NAME']) ? SUF_generateTeamNameLink(SUF_getPlayerCurrentTeam($row['C_NAME'])) : ''),
                str_replace('-', '&#8211;', $row['C_SPAN']),
                $row['C_MATCHES'],
                $row['C_INNINGS'],
                $row['C_RUNS'],
                $row['C_BALLS'],
                $row['C_STRIKE_RATE'],
                '{{nts|' . ((int) $row['C_HIGH_SCORE']) . '}}' . ((strpos($row['C_HIGH_SCORE'], '*') !== false) ? '*' : ''),
                $row['C_100'],
                $row['C_50'],
                $row['C_4'],
                $row['C_6']
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'BATTING_HIGHEST_SCORE'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Highest score====", strpos($PageText, "\n===Batting Records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: BATTING_HIGHEST_SCORE', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/batting/most_runs_innings.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_RUNS', 'C_BALLS', 'C_4', 'C_6', 'C_STRIKE_RATE', 7 => 'C_TEAM', 'C_OPPOSITION', 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_RUNS', 'C_STRIKE_RATE', 'C_6', 'C_4', 'C_NAME', 'C_DATE' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{{nts|" . ((int) $row['C_RUNS']) . '}}' . ((strpos($row['C_RUNS'], '*') !== false) ? '*' : '') . "'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_TEAM']),
                'style="text-align:left"|' . SUF_generateTeamNameLink(preg_replace('/^v /i', '', $row['C_OPPOSITION'])),
                $row['C_BALLS'],
                $row['C_STRIKE_RATE'],
                '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'BATTING_MOST_RUNS_SERIES'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Most runs in a series====", strpos($PageText, "\n===Batting Records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: BATTING_MOST_RUNS_SERIES', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/batting/most_runs_series.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_MATCHES', 'C_INNINGS', 'C_NOT_OUT', 'C_RUNS', 'C_HIGH_SCORE', 'C_AVERAGE', 'C_BALLS', 'C_STRIKE_RATE', 'C_100', 'C_50', 'C_0', 'C_4', 'C_6' ],
            true,
            $defaultLimit,
            [ 'C_RUNS', 'C_AVERAGE', 'C_STRIKE_RATE', 'C_HIGH_SCORE', 'C_100', 'C_50', 'C_6', 'C_4', 'C_NAME' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {

            # Get the player's team and the year
            preg_match('/^\(([\w\d\s]++)\) - .*, (\d{4}(?:\/\d{2})?)$/u', $row['NOTE'], $noteMatch);
            $row['C_TEAM'] = $noteMatch[1];
            $row['C_YEAR'] = $noteMatch[2];
            if ( $row['C_YEAR'] == '2007/08' ) {
                $row['C_YEAR'] = 2008;
            }
            if ( $row['C_YEAR'] == '2009/10' ) {
                $row['C_YEAR'] = 2010;
            }

            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_RUNS']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_TEAM']),
                "[[{$row['C_YEAR']} Indian Premier League|{$row['C_YEAR']}]]",
                $row['C_MATCHES'],
                $row['C_INNINGS'],
                $row['C_BALLS'],
                $row['C_STRIKE_RATE'],
                $row['C_AVERAGE'],
                '{{nts|' . ((int) $row['C_HIGH_SCORE']) . '}}' . ((strpos($row['C_HIGH_SCORE'], '*') !== false) ? '*' : ''),
                $row['C_100'],
                $row['C_50'],
                $row['C_4'],
                $row['C_6']
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'BATTING_MOST_SIXES'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Most sixes====", strpos($PageText, "\n===Batting Records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: BATTING_MOST_SIXES', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/batting/most_sixes_career.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_SPAN', 'C_MATCHES', 'C_INNINGS', 'C_NOT_OUT', 'C_RUNS', 'C_HIGH_SCORE', 'C_AVERAGE', 'C_BALLS', 'C_STRIKE_RATE', 'C_100', 'C_50', 'C_0', 'C_4', 'C_6' ],
            true,
            $defaultLimit,
            [ 'C_6', 'C_RUNS', 'C_AVERAGE', 'C_STRIKE_RATE', 'C_HIGH_SCORE', 'C_100', 'C_50', 'C_4', 'C_NAME' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_6']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . (@SUF_getPlayerCurrentTeam($row['C_NAME']) ? SUF_generateTeamNameLink(SUF_getPlayerCurrentTeam($row['C_NAME'])) : ''),
                str_replace('-', '&#8211;', $row['C_SPAN']),
                $row['C_MATCHES'],
                $row['C_INNINGS'],
                $row['C_RUNS'],
                $row['C_BALLS'],
                $row['C_4']
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'BATTING_MOST_RUNS_BOUNDARIES_INNINGS'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Most runs from boundaries in an innings====", strpos($PageText, "\n===Batting Records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: BATTING_MOST_RUNS_BOUNDARIES_INNINGS', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/batting/most_runs_from_fours_sixes_innings.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_RUNS', 'C_BALLS', 'C_4', 'C_6', 'C_4+6', 'C_STRIKE_RATE', 8 => 'C_TEAM', 'C_OPPOSITION', 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_4+6', 'C_6', 'C_4', 'C_RUNS', 'C_STRIKE_RATE', 'C_NAME', 'C_DATE' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_4+6']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_TEAM']),
                'style="text-align:left"|' . SUF_generateTeamNameLink(preg_replace('/^v /i', '', $row['C_OPPOSITION'])),
                $row['C_4'],
                $row['C_6'],
                '{{nts|' . ((int) $row['C_RUNS']) . '}}' . ((strpos($row['C_RUNS'], '*') !== false) ? '*' : ''),
                $row['C_BALLS'],
                '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    # INDIVIDUAL RECORDS (BOWLING)

    'BOWLING_MOST_WICKETS'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Most wickets====", strpos($PageText, "\n===Bowling Records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: BOWLING_MOST_WICKETS', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/bowling/most_wickets_career.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_SPAN', 'C_MATCHES', 'C_INNINGS', 'C_OVERS', 'C_MAIDENS', 'C_RUNS', 'C_WICKETS', 'C_BEST_BOWLING', 'C_AVERAGE', 'C_ECONOMY_RATE', 'C_STRIKE_RATE', 'C_4_WICKETS', 'C_5_WICKETS' ],
            true,
            $defaultLimit,
            [ 'C_WICKETS', 'C_ECONOMY_RATE', 'C_AVERAGE', 'C_STRIKE_RATE', 'C_BEST_BOWLING', 'C_5_WICKETS', 'C_4_WICKETS', 'C_NAME' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME', 'C_ECONOMY_RATE', 'C_STRIKE_RATE', 'C_AVERAGE' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_WICKETS']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . (SUF_getPlayerCurrentTeam($row['C_NAME']) ? SUF_generateTeamNameLink(SUF_getPlayerCurrentTeam($row['C_NAME'])) : ''),
                str_replace('-', '&#8211;', $row['C_SPAN']),
                $row['C_MATCHES'],
                $row['C_INNINGS'],
                $row['C_OVERS'],
                $row['C_MAIDENS'],
                $row['C_RUNS'],
                '{{ntsh|{{#expr:' . (explode('/', $row['C_BEST_BOWLING'])[0] + 1) . '+1/' . (explode('/', $row['C_BEST_BOWLING'])[1] + 1) . '}}}}' . $row['C_BEST_BOWLING'],
                $row['C_AVERAGE'],
                $row['C_ECONOMY_RATE'],
                $row['C_STRIKE_RATE']
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'BOWLING_BEST_STRIKE_RATE'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Best strike rates====", strpos($PageText, "\n===Bowling Records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: BOWLING_BEST_STRIKE_RATE', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.cricinfo.com/ipl2009/engine/records/bowling/best_career_strike_rate.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_SPAN', 'C_MATCHES', 'C_OVERS', 'C_MAIDENS', 'C_RUNS', 'C_WICKETS', 'C_BEST_BOWLING', 'C_AVERAGE', 'C_ECONOMY_RATE', 'C_STRIKE_RATE', 'C_4_WICKETS', 'C_5_WICKETS' ],
            true,
            $defaultLimit,
            [ 'C_STRIKE_RATE', 'C_WICKETS', 'C_ECONOMY_RATE', 'C_AVERAGE', 'C_BEST_BOWLING', 'C_5_WICKETS', 'C_4_WICKETS', 'C_NAME' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME', 'C_ECONOMY_RATE', 'C_STRIKE_RATE', 'C_AVERAGE' ],
            function($row) {
                return (explode('.', $row['C_OVERS'])[0] * 6) + explode('.', $row['C_OVERS'])[1] >= 250;  # Mimimun 250 balls
            }
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_STRIKE_RATE']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . (@SUF_getPlayerCurrentTeam($row['C_NAME']) ? SUF_generateTeamNameLink(SUF_getPlayerCurrentTeam($row['C_NAME'])) : ''),
                str_replace('-', '&#8211;', $row['C_SPAN']),
                $row['C_MATCHES'],
                $row['C_OVERS'],
                $row['C_MAIDENS'],
                $row['C_RUNS'],
                $row['C_WICKETS'],
                '{{ntsh|{{#expr:' . (explode('/', $row['C_BEST_BOWLING'])[0] + 1) . '+1/' . (explode('/', $row['C_BEST_BOWLING'])[1] + 1) . '}}}}' . $row['C_BEST_BOWLING'],
                $row['C_AVERAGE'],
                $row['C_ECONOMY_RATE']
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'BOWLING_BEST_AVERAGE'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Best averages====", strpos($PageText, "\n===Bowling Records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: BOWLING_BEST_AVERAGE', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/bowling/best_career_bowling_average.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_SPAN', 'C_MATCHES', 'C_OVERS', 'C_MAIDENS', 'C_RUNS', 'C_WICKETS', 'C_BEST_BOWLING', 'C_AVERAGE', 'C_ECONOMY_RATE', 'C_STRIKE_RATE', 'C_4_WICKETS', 'C_5_WICKETS' ],
            true,
            $defaultLimit,
            [ 'C_AVERAGE', 'C_WICKETS', 'C_ECONOMY_RATE', 'C_STRIKE_RATE', 'C_BEST_BOWLING', 'C_5_WICKETS', 'C_4_WICKETS', 'C_NAME' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME', 'C_ECONOMY_RATE', 'C_STRIKE_RATE', 'C_AVERAGE' ],
            function($row) {
                return (explode('.', $row['C_OVERS'])[0] * 6) + explode('.', $row['C_OVERS'])[1] >= 250;
            }
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_AVERAGE']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . (@SUF_getPlayerCurrentTeam($row['C_NAME']) ? SUF_generateTeamNameLink(SUF_getPlayerCurrentTeam($row['C_NAME'])) : ''),
                str_replace('-', '&#8211;', $row['C_SPAN']),
                $row['C_MATCHES'],
                $row['C_OVERS'],
                $row['C_MAIDENS'],
                $row['C_RUNS'],
                $row['C_WICKETS'],
                '{{ntsh|{{#expr:' . (explode('/', $row['C_BEST_BOWLING'])[0] + 1) . '+1/' . (explode('/', $row['C_BEST_BOWLING'])[1] + 1) . '}}}}' . $row['C_BEST_BOWLING'],
                $row['C_STRIKE_RATE'],
                $row['C_ECONOMY_RATE']
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'BOWLING_BEST_ECONOMY_RATE'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Best economy rates====", strpos($PageText, "\n===Bowling Records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: BOWLING_BEST_ECONOMY_RATE', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.cricinfo.com/ipl2009/engine/records/bowling/best_career_economy_rate.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_SPAN', 'C_MATCHES', 'C_OVERS', 'C_MAIDENS', 'C_RUNS', 'C_WICKETS', 'C_BEST_BOWLING', 'C_AVERAGE', 'C_ECONOMY_RATE', 'C_STRIKE_RATE', 'C_4_WICKETS', 'C_5_WICKETS' ],
            true,
            $defaultLimit,
            [ 'C_ECONOMY_RATE', 'C_WICKETS', 'C_AVERAGE', 'C_STRIKE_RATE', 'C_BEST_BOWLING', 'C_5_WICKETS', 'C_4_WICKETS', 'C_NAME' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME', 'C_ECONOMY_RATE', 'C_STRIKE_RATE', 'C_AVERAGE' ],
            function($row) {
                return (explode('.', $row['C_OVERS'])[0] * 6) + explode('.', $row['C_OVERS'])[1] >= 250;
            }
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_ECONOMY_RATE']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . (@SUF_getPlayerCurrentTeam($row['C_NAME']) ? SUF_generateTeamNameLink(SUF_getPlayerCurrentTeam($row['C_NAME'])) : ''),
                str_replace('-', '&#8211;', $row['C_SPAN']),
                $row['C_MATCHES'],
                $row['C_OVERS'],
                $row['C_MAIDENS'],
                $row['C_RUNS'],
                $row['C_WICKETS'],
                '{{ntsh|{{#expr:' . (explode('/', $row['C_BEST_BOWLING'])[0] + 1) . '+1/' . (explode('/', $row['C_BEST_BOWLING'])[1] + 1) . '}}}}' . $row['C_BEST_BOWLING'],
                $row['C_STRIKE_RATE'],
                $row['C_AVERAGE']
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'BOWLING_BEST_FIGURES_INNINGS'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Best bowling figures in an innings====", strpos($PageText, "\n===Bowling Records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: BOWLING_BEST_FIGURES_INNINGS', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/bowling/best_figures_innings.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_OVERS', 'C_MAIDENS', 'C_RUNS', 'C_WICKETS', 'C_ECONOMY_RATE', 7 => 'C_TEAM', 'C_OPPOSITION', 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_WICKETS', 'C_RUNS', 'C_ECONOMY_RATE', 'C_MAIDENS', 'C_NAME', 'C_DATE' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME', 'C_RUNS', 'C_ECONOMY_RATE' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                '{{ntsh|{{#expr:' . ($row['C_WICKETS'] + 1) . '+1/' . ($row['C_RUNS'] + 1) . '}}}}' . "'''{$row['C_WICKETS']} for {$row['C_RUNS']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_TEAM']),
                $row['C_OVERS'],
                $row['C_MAIDENS'],
                $row['C_ECONOMY_RATE'],
                'style="text-align:left"|' . SUF_generateTeamNameLink(preg_replace('/^v /i', '', $row['C_OPPOSITION'])),
                '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'BOWLING_MOST_RUNS_INNINGS'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Most runs conceded in an innings====", strpos($PageText, "\n===Bowling Records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: BOWLING_MOST_RUNS_INNINGS', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/bowling/most_runs_conceded_innings.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_OVERS', 'C_MAIDENS', 'C_RUNS', 'C_WICKETS', 'C_ECONOMY_RATE', 7 => 'C_TEAM', 'C_OPPOSITION', 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_RUNS', 'C_WICKETS', 'C_ECONOMY_RATE', 'C_MAIDENS', 'C_NAME', 'C_DATE' ],
            CricinfoDataParser::SORT_ASCENDING,
            [ 'C_NAME', 'C_RUNS', 'C_ECONOMY_RATE', 'C_DATE' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_RUNS']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_TEAM']),
                $row['C_OVERS'],
                $row['C_MAIDENS'],
                $row['C_WICKETS'],
                $row['C_ECONOMY_RATE'],
                'style="text-align:left"|' . SUF_generateTeamNameLink(preg_replace('/^v /i', '', $row['C_OPPOSITION'])),
                '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'BOWLING_MOST_WICKETS_SERIES'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Most wickets in a series====", strpos($PageText, "\n===Bowling Records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: BOWLING_MOST_WICKETS_SERIES', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/bowling/most_wickets_series.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_MATCHES', 'C_OVERS', 'C_MAIDENS', 'C_RUNS', 'C_WICKETS', 'C_BEST_BOWLING', 'C_AVERAGE', 'C_ECONOMY_RATE', 'C_STRIKE_RATE', 'C_4_WICKETS', 'C_5_WICKETS' ],
            true,
            $defaultLimit,
            [ 'C_WICKETS', 'C_ECONOMY_RATE', 'C_AVERAGE', 'C_STRIKE_RATE', 'C_BEST_BOWLING', 'C_5_WICKETS', 'C_4_WICKETS', 'C_NAME' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME', 'C_ECONOMY_RATE', 'C_AVERAGE', 'C_STRIKE_RATE' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {

            preg_match('/^\(([\w\d\s]++)\) - .*, (\d{4}(?:\/\d{2})?)$/u', $row['NOTE'], $noteMatch);
            $row['C_TEAM'] = $noteMatch[1];
            $row['C_YEAR'] = $noteMatch[2];
            if ( $row['C_YEAR'] == '2007/08' ) {
                $row['C_YEAR'] = 2008;
            }
            if ( $row['C_YEAR'] == '2009/10' ) {
                $row['C_YEAR'] = 2010;
            }

            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_WICKETS']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_TEAM']),
                "[[{$row['C_YEAR']} Indian Premier League|{$row['C_YEAR']}]]",
                $row['C_MATCHES'],
                $row['C_OVERS'],
                $row['C_MAIDENS'],
                $row['C_RUNS'],
                $row['C_ECONOMY_RATE'],
                $row['C_AVERAGE'],
                $row['C_STRIKE_RATE'],
                '{{ntsh|{{#expr:' . (explode('/', $row['C_BEST_BOWLING'])[0] + 1) . '+1/' . (explode('/', $row['C_BEST_BOWLING'])[1] + 1) . '}}}}' . $row['C_BEST_BOWLING']
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    # INDIVIDUAL RECORDS (FIELDING AND WICKETKEEPING)

    'FIELDING_MOST_DISMISSALS_KEEPER'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Most dismissals====", strpos($PageText, "\n===Wicketkeeping and fielding records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: FIELDING_MOST_DISMISSALS_KEEPER', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/keeping/most_dismissals_career.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_SPAN', 'C_MATCHES', 'C_INNINGS', 'C_DISMISSALS', 'C_CATCHES', 'C_STUMPINGS', 'C_MAX_DISMISSALS_INNINGS', 'C_AVERAGE_DISMISSALS_INNINGS' ],
            true,
            $defaultLimit,
            [ 'C_DISMISSALS', 'C_AVERAGE_DISMISSALS_INNINGS', 'C_MAX_DISMISSALS_INNINGS', 'C_NAME' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_DISMISSALS']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . (@SUF_getPlayerCurrentTeam($row['C_NAME']) ? SUF_generateTeamNameLink(SUF_getPlayerCurrentTeam($row['C_NAME'])) : ''),
                str_replace('-', '&#8211;', $row['C_SPAN']),
                $row['C_MATCHES'],
                $row['C_INNINGS'],
                $row['C_CATCHES'],
                $row['C_STUMPINGS'],
                (int) $row['C_MAX_DISMISSALS_INNINGS'],
                $row['C_AVERAGE_DISMISSALS_INNINGS']
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'FIELDING_MOST_CATCHES_NON_KEEPER'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Most catches (non-keeper)====", strpos($PageText, "\n===Wicketkeeping and fielding records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: FIELDING_MOST_CATCHES_NON_KEEPER', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/fielding/most_catches_career.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_SPAN', 'C_MATCHES', 'C_INNINGS', 'C_CATCHES', 'C_MAX_CATCHES_INNINGS', 'C_AVERAGE_CATCHES_INNINGS' ],
            true,
            $defaultLimit,
            [ 'C_CATCHES', 'C_AVERAGE_CATCHES_INNINGS', 'C_MAX_CATCHES_INNINGS', 'C_NAME' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_CATCHES']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . (@SUF_getPlayerCurrentTeam($row['C_NAME']) ? SUF_generateTeamNameLink(SUF_getPlayerCurrentTeam($row['C_NAME'])) : ''),
                str_replace('-', '&#8211;', $row['C_SPAN']),
                $row['C_MATCHES'],
                $row['C_INNINGS'],
                $row['C_MAX_CATCHES_INNINGS'],
                $row['C_AVERAGE_CATCHES_INNINGS']
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'FIELDING_MOST_DISMISSALS_INNINGS_KEEPER'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Most dismissals in an innings====", strpos($PageText, "\n===Wicketkeeping and fielding records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: FIELDING_MOST_DISMISSALS_INNINGS_KEEPER', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/keeping/most_dismissals_innings.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_DISMISSALS', 'C_CATCHES', 'C_STUMPINGS', 'C_INNINGS', 6 => 'C_TEAM', 'C_OPPOSITION', 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_DISMISSALS', 'C_NAME', 'C_DATE' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_DISMISSALS']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_TEAM']),
                $row['C_INNINGS'],
                'style="text-align:left"|' . SUF_generateTeamNameLink(preg_replace('/^v /i', '', $row['C_OPPOSITION'])),
                $row['C_CATCHES'],
                $row['C_STUMPINGS'],
                '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'FIELDING_MOST_CATCHES_INNINGS_NON_KEEPER'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Most catches in an innings (non-keeper)====", strpos($PageText, "\n===Wicketkeeping and fielding records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: FIELDING_MOST_CATCHES_INNINGS_NON_KEEPER', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/fielding/most_catches_innings.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_CATCHES', 'C_INNINGS', 4 => 'C_TEAM', 'C_OPPOSITION', 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_CATCHES', 'C_NAME', 'C_DATE' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_CATCHES']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_TEAM']),
                $row['C_INNINGS'],
                'style="text-align:left"|' . SUF_generateTeamNameLink(preg_replace('/^v /i', '', $row['C_OPPOSITION'])),
                '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'FIELDING_MOST_DISMISSALS_SERIES_KEEPER'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Most dismissals in a series====", strpos($PageText, "\n===Wicketkeeping and fielding records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: FIELDING_MOST_DISMISSALS_SERIES_KEEPER', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/keeping/most_dismissals_series.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_MATCHES', 'C_INNINGS', 'C_DISMISSALS', 'C_CATCHES', 'C_STUMPINGS', 'C_MAX_DISMISSALS_INNINGS', 'C_AVERAGE_DISMISSALS_INNINGS' ],
            true,
            $defaultLimit,
            [ 'C_DISMISSALS', 'C_AVERAGE_DISMISSALS_INNINGS', 'C_MAX_DISMISSALS_INNINGS', 'C_NAME' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {

            preg_match('/^\(([\w\d\s]++)\) - .*, (\d{4}(?:\/\d{2})?)$/u', $row['NOTE'], $noteMatch);
            $row['C_TEAM'] = $noteMatch[1];
            $row['C_YEAR'] = $noteMatch[2];
            if ( $row['C_YEAR'] == '2007/08' ) {
                $row['C_YEAR'] = 2008;
            }
            if ( $row['C_YEAR'] == '2009/10' ) {
                $row['C_YEAR'] = 2010;
            }

            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_DISMISSALS']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_TEAM']),
                "[[{$row['C_YEAR']} Indian Premier League|{$row['C_YEAR']}]]",
                $row['C_MATCHES'],
                $row['C_CATCHES'],
                $row['C_STUMPINGS'],
                (int) $row['C_MAX_DISMISSALS_INNINGS'],
                $row['C_AVERAGE_DISMISSALS_INNINGS']
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'FIELDING_MOST_CATCHES_SERIES_NON_KEEPER'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n====Most catches in a series (non-keeper)====", strpos($PageText, "\n===Wicketkeeping and fielding records===", strpos($PageText, "\n==Individual records==")));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: FIELDING_MOST_CATCHES_SERIES_NON_KEEPER', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/indian-premier-league-2011/engine/records/fielding/most_catches_series.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_MATCHES', 'C_INNINGS', 'C_CATCHES', 'C_MAX_CATCHES_INNINGS', 'C_AVERAGE_CATCHES_INNINGS' ],
            true,
            $defaultLimit,
            [ 'C_CATCHES', 'C_AVERAGE_CATCHES_INNINGS', 'C_MAX_CATCHES_INNINGS', 'C_NAME' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {

            preg_match('/^\(([\w\d\s]++)\) - .*, (\d{4}(?:\/\d{2})?)$/u', $row['NOTE'], $noteMatch);
            $row['C_TEAM'] = $noteMatch[1];
            $row['C_YEAR'] = $noteMatch[2];
            if ( $row['C_YEAR'] == '2007/08' ) {
                $row['C_YEAR'] = 2008;
            }
            if ( $row['C_YEAR'] == '2009/10' ) {
                $row['C_YEAR'] = 2010;
            }

            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_CATCHES']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_TEAM']),
                "[[{$row['C_YEAR']} Indian Premier League|{$row['C_YEAR']}]]",
                $row['C_MATCHES'],
                $row['C_MAX_CATCHES_INNINGS'],
                $row['C_AVERAGE_CATCHES_INNINGS']
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    # BATTING PARTNERSHIP RECORDS

    # Due to technical limitations, it is not possible to include the contribution and/or final scores of the batsmen in the result (requires spidering over about 15 scorecards)
    # It is not possible to distinguish conflicting names as they are not linked to their profile pages
    # so if these functions are called the result wikitext must be checked after the edit (even though conflicting names are currently extremely rare)

    'BATTING_HIGHEST_PARTNERSHIP_WICKET'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n===Highest partnerships by wicket===", strpos($PageText, "\n==Partnership records=="));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: BATTING_HIGHEST_PARTNERSHIP_WICKET', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2010/engine/records/fow/highest_partnerships_by_wicket.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_WICKET', 'C_RUNS', 3 => 'C_PARTNERS', 'C_TEAM', 'C_OPPOSITION', 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            null
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{{nts|" . ((int) $row['C_WICKET']) . '}}' . substr($row['C_WICKET'], -2, 2) . "'''",
                "'''{{nts|" . ((int) $row['C_RUNS']) . '}}' . ((strpos($row['C_RUNS'], '*') !== false) ? '*' : '') . "'''",
                'style="text-align:left"|'
                . "\n* " . SUF_generatePlayerSortNameLink(explode(', ', $row['C_PARTNERS'])[0], '', true)
                . "\n* " . SUF_generatePlayerSortNameLink(explode(', ', $row['C_PARTNERS'])[1], '', true) . "\n",
                'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_TEAM']),
                'style="text-align:left"|' . SUF_generateTeamNameLink(preg_replace('/^v /i', '', $row['C_OPPOSITION'])),
                '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
            );
        }

        # Fix a syntax error caused by newlines at the end ot a table cell
        $newTableRows = array_map(  function($row) {
                                        return preg_replace('/^(\|(?:.*?\|\|){2}.*?\n) \|\|/us', '\1|', $row);
                                    }, $newTableRows );

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'BATTING_HIGHEST_PARTNERSHIP_RUNS'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n===Highest partnerships by runs===", strpos($PageText, "\n==Partnership records=="));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: BATTING_HIGHEST_PARTNERSHIP_RUNS', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/fow/highest_partnerships_for_any_wicket.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_PARTNERS', 'C_RUNS', 'C_WICKET', 4 => 'C_TEAM', 'C_OPPOSITION', 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_RUNS', 'C_WICKET', 'C_DATE' ],
            CricinfoDataParser::SORT_DESCENDING
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{{nts|" . ((int) $row['C_RUNS']) . '}}' . ((strpos($row['C_RUNS'], '*') !== false) ? '*' : '') . "'''",
                "'''{{nts|" . ((int) $row['C_WICKET']) . '}}' . substr($row['C_WICKET'], -2, 2) . "'''",
                'style="text-align:left"|'
                . "\n* " . SUF_generatePlayerSortNameLink(explode(', ', $row['C_PARTNERS'])[0], '', true)
                . "\n* " . SUF_generatePlayerSortNameLink(explode(', ', $row['C_PARTNERS'])[1], '', true) . "\n",
                'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_TEAM']),
                'style="text-align:left"|' . SUF_generateTeamNameLink(preg_replace('/^v /i', '', $row['C_OPPOSITION'])),
                '[[' . date('Y', strtotime($row['C_DATE'])) . ' Indian Premier League|' . date('Y', strtotime($row['C_DATE'])) . ']]',
                'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
            );
        }

        $newTableRows = array_map(  function($row) {
                                        return preg_replace('/^(\|(?:.*?\|\|){2}.*?\n) \|\|/us', '\1|', $row);
                                    }, $newTableRows );

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    # MISCELLANEOUS RECORDS

    'MOST_MATCHES'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n===Most matches===", strpos($PageText, "\n==Miscellaneous records=="));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: MOST_MATCHES', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/ipl2009/engine/records/individual/most_matches_career.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_NAME', 'C_SPAN', 'C_MATCHES', 'C_RUNS', 'C_HIGH_SCORE', 'C_BATTING_AVERAGE', 'C_100', 'C_WICKETS', 'C_BEST_BOWLING', 'C_BOWLING_AVERAGE', 'C_5_WICKETS', 'C_CATCHES', 'C_STUMPINGS' ],
            true,
            5,
            [ 'C_MATCHES', 'C_NAME' ],
            CricinfoDataParser::SORT_DESCENDING,
            [ 'C_NAME' ]
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_MATCHES']}'''",
                'style="text-align:left"|' . SUF_generatePlayerSortNameLink($row['C_NAME'], $row['C_NAME:href'], true),
                'style="text-align:left"|' . (@SUF_getPlayerCurrentTeam($row['C_NAME']) ? SUF_generateTeamNameLink(SUF_getPlayerCurrentTeam($row['C_NAME'])) : ''),
                str_replace('-', '&#8211;', $row['C_SPAN']),
                $row['C_RUNS'],
                $row['C_BATTING_AVERAGE'],
                $row['C_WICKETS'],
                $row['C_BOWLING_AVERAGE'],
                $row['C_CATCHES'] + $row['C_STUMPINGS']
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    'MOST_EXTRAS_INNINGS'  =>  function() {

        global $PageText, $wikiTableBodyRegex, $defaultLimit;

        $tablePosition = strpos($PageText, "\n===Most extras conceded in an innings===", strpos($PageText, "\n==Partnership records=="));
        if ( $tablePosition === false ) {
            trigger_error('Cannot find section header for function: MOST_EXTRAS_INNINGS', E_USER_WARNING);
            return false;
        }

        $parser = new CricinfoDataParser();
        $parser->load('http://stats.espncricinfo.com/indian-premier-league-2013/engine/records/team/most_extras_innings.html?id=117;type=trophy');
        if ( $parser->loadFailed ) {
            return false;
        }

        $parseResult = $parser->parse(
            0,
            [ 'C_TEAM', 'C_SCORE', 'C_OVERS', 'C_EXTRAS', 'C_BYES', 'C_LEG_BYES', 'C_WIDES', 'C_NO_BALLS', 9 => 'C_OPPOSITION', 'C_GROUND', 'C_DATE', 'C_SCORECARD' ],
            true,
            $defaultLimit,
            [ 'C_EXTRAS', 'C_SCORE', 'C_DATE' ],
            CricinfoDataParser::SORT_DESCENDING
        );

        $newTableRows = [];

        foreach ( $parseResult as $row ) {
            $newTableRows[] = SUF_generateWikiTableRow(
                "'''{$row['C_EXTRAS']}'''",
                'style="text-align:left"|' . SUF_generateTeamNameLink(preg_replace('/^v /i', '', $row['C_OPPOSITION'])),
                '{{ntsh|{{#expr:' . (explode('/', $row['C_SCORE'])[0] + 1) . '+1/' . (((strpos($row['C_SCORE'], '/') !== false) ? explode('/', $row['C_SCORE'])[1] : 10) + 1) . '}}}}' . "'''{$row['C_SCORE']}'''",
                $row['C_OVERS'],
                $row['C_BYES'],
                $row['C_LEG_BYES'],
                $row['C_WIDES'],
                $row['C_NO_BALLS'],
                'style="text-align:left"|' . SUF_generateTeamNameLink($row['C_TEAM']),
                'style="text-align:left"|' . '<small>' . SUF_generateGroundNameLink($row['C_GROUND:href']) . '</small>',
                "<small>[http://www.espncricinfo.com{$row['C_SCORECARD:href']} " . date('d F Y', strtotime($row['C_DATE'])) . ']</small>'
            );
        }

        preg_match($wikiTableBodyRegex, $PageText, $tableMatch, 0, $tablePosition);

        $PageText = str_replace($tableMatch[1], SUF_encodeWikiTemplates(implode("\n|-\n", $newTableRows)) . "\n", $PageText);
        return true;
    },


    # ---------- END OF STATS UPDATE FUNCTIONS ----------

];

?>