Skip to main content

API to programatically generate baseball scorecards as PDFs.

Project description

Baseball Scorecard Generator

Baseball Scorecard Generator offers a Python API to generate a series of Metapost files that can be compiled into a scorecard PDF.

How to score a game

Note: Example games and how to score certain plays are provided in the examples folder.

In order to start scoring a game, import the scorecard module on your Python script, and create a Scorecard object:

from scorecard import Scorecard

score = Scorecard(...)

The Scorecard class expects two parameters:

  • output_dir: The location where the Metapost files will be deposited.
  • data: The data for the game to be scored.

Setting up the game data

The game data expects the following information:

  • extended_roster (optional): If set to True, a different format for the roster is expected for each team. Check the roster section of this document for more information.
  • scorer: Name of the scorer.
  • date: Date of the game.
  • at: Baseball stadium where the game took place.
  • att: Official attendance.
  • temp: Temperature and weather at first pitch.
  • wind: Wind at first pitch.
  • away: Information about the away team.
  • home: Information about the home team.
  • umpires: Information about the umpires.

For each team, the following information is expected:

  • team: Name of the team.
  • starter: Player ID for the starting pitcher.
  • roster: Dictionary of the players in the team.
  • lefties: List of player IDs for all left-handed pitchers.
  • lineup: List representing the lineup, each item is a list containing the player ID and their fielding position.
  • bench: List of player IDs that start the game in the bench.
  • bullpen: List of player IDs that start the game in the bullpen.

For the umpire information, a dictionary is expected, where the keys are the position, and the value is the name of the umpire. Valid keys are HP, 1B, 2B, 3B, LF and RF.

Roster

The roster for a team is expected to be a key-value pair, where the key represents the Player ID, and the value is the player information.

The format for the player information varies whether the extended_roster key on the data dictionary was set or not:

  • If the key is not set, the Player ID can be their jersey number, and the player data can be their name.
  • If the key is set, the format becomes the following: 1000: {"jersey": 1, "name": "John Doe"}. 1000 becomes the Player ID, and the jersey number and name of the player can be specified in the inner dictionary.

Play ball!

Once the Scorecard object is created, the game can be recorded.

Start each frame by calling the Scorecard.new_inning method.

inn = score.new_inning()

From here, you can call the following functions:

Pitching substitution

To register a pitching substitution, call the pitching_substitution method.

inn.pitching_substitution(PITCHER_ID)

Arguments:

  • PITCHER_ID (int): Player ID for the entering pitcher.

Defensive substitution

To register a defensive substitution, call the defensive_substitution method.

inn.defensive_substitution(ORDER, PLAYER_ID, POSITION)

Arguments:

  • ORDER (int): Order in the lineup where the fielder will bat (1-9).
  • PLAYER_ID (int): Player ID for the entering fielder.
  • POSITION (str): Position in the field for the new player.

Defensive switch

To register a defensive switch, call the defensive_switch method.

inn.defensive_switch(PLAYER_ID, POSITION)

Arguments:

  • PLAYER_ID (int): Player ID for the fielder.
  • POSITION (str): New defensive position for the fielder.

Offensive substitution

To register a offensive substitution, call the offensive_substitution method.

inn.offensive_substitution(ORDER, PLAYER_ID, POSITION)

Arguments:

  • ORDER (int): Order in the lineup where the batter will bat (1-9).
  • PLAYER_ID (int): Player ID for the entering batter.
  • POSITION (str): Position for the new player, can be either PH for a pinch-hitter, or PR for a pinch-runner.

At-bat

To start a new at-bat, call the new_ab method. This will automatically start an at-bat for the next batter on the batting team.

inn.new_ab()

Once an at-bat is started, the following methods can be called:

Batter methods
Pitches

To register the pitches a batter received, use the pitch_list method.

inn.pitch_list(PITCHES)

Arguments:

  • PITCHES (str): List of pitches, each pitch separated by a space. The following codes are recognized:
    • pso: Pitcher step-off.
    • 1, 2 or 3: Pickoff attempts at 1B, 2B or 3B.
    • vp: Pitch clock violation on the pitcher, counts as a ball.
    • ab: Pitch clock violation on the batter, counts as a strike.
    • s: Swinging strike.
    • c: Called strike.
    • f: Foul.
    • b: Ball.
    • d: Ball in dirt.
    • p: Pitchout, counts as a ball.
    • m: Missed bunt attempt.
    • t: Foul tip.
    • l: Foul bunt. NOTE: For balls put in play, it is not necessary to add a pitch, the batter functions will handle the pitch count automatically.
Hit

To register a hit on the at-bat, use the hit method.

inn.hit(BASES, [RBIS])

Arguments:

  • BASES (int/str): The amount of bases the hit allowed, from 1-4. In case the hit is classified as an unearned home run, use "U".
  • RBIS (int, optional): If the play resulted in runs batted in, set the number of RBIs. Default is 0.
Out

To register an out on the batter, use the out method.

inn.out(PLAY, [RBIS])

Arguments:

  • PLAY (str): The play on which the out was made. Starting the play with the following codes will automatically tally certain statistics:
    • K: Swinging strikeout.
    • !K: Called strikeout.
    • SAC: Sacrifice bunt.
    • SF: Sacrifice fly.
    • DP: Double play.
    • TP: Triple play.
  • RBIS (int, optional): If the play resulted in runs batted in, set the number of RBIs. Default is 0.
Reach base

To register the batter reaching base in a non-hit play, use the reach method.

inn.reach(PLAY, [END_BASE], [RBIS])

Arguments:

  • PLAY (str): The play on which the batter reached base. Starting the play with the following codes will automatically tally certain statistics:
    • E: Fielding error.
    • BB: Base on Balls.
    • IBB: Intent walk.
    • HBP: Hit by pitch.
    • CI: Catcher's interference.
    • K: Strikeout.
  • END_BASE (int, optional): If the batter-runner reached past 1B, use this argument. Default is 1 for 1B.
  • RBIS (int, optional): If the play resulted in runs batted in, set the number of RBIs. Default is 0.
Runner methods
Advance bases

To register a runner advancing bases, use the advance method.

inn.advance(END_BASE, PLAY)

Arguments:

  • END_BASE (int/str): The final base reached by the batter on a play.
    • 2: Second base.
    • 3: Third base.
    • 4: Home, for an earned run.
    • U: Home, for an unearned run.
  • PLAY (str): The play on which the runner advanced. If SB is used in the play, a stolen base is credited to the runner.
Thrown out

To register a runner getting thrown out in the basepaths, use the thrown_out method.

inn.thrown_out(OUT_BASE, PLAY, [OUT_NUMBER], [PITCHER_ID])

Arguments:

  • OUT_BASE (int): The final base reached by the batter on a play.
    • 2: Second base.
    • 3: Third base.
    • 4: Home, for an earned run.
    • U: Home, for an unearned run.
  • PLAY (str): The play on which the runner advanced. If CS is used in the play, a caught stealing is credited to the runner. IF PO is used in the play, a pickoff is credited to the runner.
  • OUT_NUMBER (int, optional): Specific out number to use, otherwise the scorecard will assign the next available out.
  • PITCHER_ID (int, optional): Player ID of the pitcher that made the out. Useful for when pitching changes occur mid-inning and the new pitcher makes an out on an inherited runner.
Other at-bat methods
Error

To register a fielding error, use the error method.

inn.error(POSITION)

Arguments:

  • POSITION: Position of the fielder who made the error (1-9).
Balk

To register a balk, use the balk method.

inn.balk()
Wild pitch

To register a wild pitch, use the wp method.

inn.wp([QUANTITY])

Arguments:

  • QUANTITY (int, optional): The number of wild pitches in the at-bat. Defaults to 1.
Passed ball

To register a passed ball, use the pb method.

inn.pb([QUANTITY])

Arguments:

  • QUANTITY (int, optional): The number of passed balls in the at-bat. Defaults to 1.
At base

To make a comment at any given base, use the atbase method. Useful for noting down pinch-runners.

inn.atbase(LABEL, [BASE])

Arguments:

  • LABEL (str): The label to put at a given base.
  • BASE (int, optional): The base to put the label at. By default, it will be placed at 1B.
No at-bat

To register that the batter was unable to complete their at-bat, likely due to the third out made on one of the runners in the middle of an at-bat, call the no_ab method.

inn.no_ab(LABEL)

Arguments:

  • LABEL (str): Label to put in the center of the diamond.

Noting win/loss/save pitchers

Once the game has been recorded, note down the winning pitcher, losing pitcher and save pitcher with the following methods:

score.winning_pitcher(PITCHER_ID, [IS_AWAY_TEAM])
score.losing_pitcher(PITCHER_ID, [IS_AWAY_TEAM])
score.save_pitcher(PITCHER_ID, [IS_AWAY_TEAM])

Arguments:

  • PITCHER_ID (int): The player ID for the pitcher.
  • IS_AWAY_TEAM (bool): If the pitcher is from the away team, set this to True. Defaults to False, which credits a pitcher from the home team.

Generating the Metapost files

Once all the plays have been registered, and the winning/losing/save pitchers have been registered, run the generate_scorecard method to generate the Metapost scorecards.

score.generate_scorecard()

Generating the PDF

Currently, integration with the Metapost compiler is not available. A compilation script is provided in the examples folder.

Appendix

Normal game data example

Below is an example of a complete game data dictionary, taken from the New York Yankees @ Boston Red Sox 2018-08-03 game.

{
    "scorer": "Vicyorus",
    "date":   "2018-08-03 19:10-21:25",
    "at":     "Fenway Park, Boston, MA",
    "att":    "37,231",
    "temp":   "87F, Partly Cloudy",
    "wind":   "21mph, Out To CF",
    "away"   : {
        "team":    "New York Yankees",
        "starter": 40,
        "roster":  {
            # Lineup
            11 : "Brett Gardner",
            27 : "Giancarlo Stanton",
            18 : "Didi Gregorius",
            31 : "Aaron Hicks",
            25 : "Gleyber Torres",
            33 : "Greg Bird",
            41 : "Miguel Andujar",
            28 : "Austin Romine",
            14 : "Neil Walker",

            # Starting pitcher
            40 : "Luis Severino",

            # Bench
            66 : "Kyle Higashioka",
            38 : "Shane Robinson",
            45 : "Luke Voit",

            # Bullpen
            67 : "A.J. Cole",
            68 : "Dellin Betances",
            36 : "Lance Lynn",
            55 : "Sonny Gray",
            56 : "Jonathan Holder",
            52 : "CC Sabathia",
            53 : "Zack Britton",
            19 : "Masahiro Tanaka",
            57 : "Chad Green",
            48 : "Tommy Kahnle",
            30 : "David Robertson",
            54 : "Aroldis Chapman",
        },
        "lefties" : [
            52, 53, 54
        ],
        "lineup" : [
            [11, "7"],
            [27, "9"],
            [18, "6"],
            [31, "8"],
            [25, "4"],
            [33, "3"],
            [41, "0"],
            [28, "2"],
            [14, "5"],
        ],
        "bench" : [
            [66, "C" ],
            [38, "CF"],
            [45, "1B"],
        ],
        "bullpen" : [
            67, 68, 36, 55, 56, 52, 53, 19, 57, 48, 30, 54
        ],
    },
    "home"   : {
        "team":    "Boston Red Sox",
        "starter": 22,
        "roster":  {
            # Lineup
            50 : "Mookie Betts",
            16 : "Andrew Benintendi",
            25 : "Steve Pearce",
            28 : "J.D. Martinez",
            5  : "Ian Kinsler",
            36 : "Eduardo Núñez",
            12 : "Brock Holt",
            3  : "Sandy León",
            19 : "Jackie Bradley Jr.",

            # Starting pitcher
            22 : "Rick Porcello",

            # Bench
            18 : "Mitch Moreland",
            68 : "Dan Butler",
            2  : "Xander Bogaerts",

            # Bullpen
            47 : "Tyler Thornburg",
            44 : "Brandon Workman",
            31 : "Drew Pomeranz",
            61 : "Brian Johnson",
            37 : "Heath Hembree",
            24 : "David Price",
            46 : "Craig Kimbrel",
            76 : "Hector Velázquez",
            70 : "Ryan Brasier",
            56 : "Joe Kelly",
            17 : "Nathan Eovaldi",
            32 : "Matt Barnes",
        },
        "lefties" : [
            31, 61, 24
        ],
        "lineup" : [
            [50, "9"],
            [16, "7"],
            [25, "3"],
            [28, "0"],
            [5,  "4"],
            [36, "5"],
            [12, "6"],
            [3,  "2"],
            [19, "8"],
        ],
        "bench" : [
            [18, "1B"],
            [68, "C" ],
            [2,  "2B"],
        ],
        "bullpen" : [
            47, 44, 31, 61, 37, 24, 46, 76, 70, 56, 17, 32
        ],
    },
    "umpires" : {
        "HP" : "Adam Hamari",
        "1B" : "Phil Cuzzi",
        "2B" : "Chris Conroy",
        "3B" : "Dan Bellino",
    },
}

Extended roster game data example

The following is an example of the game data if the extended_roster key is set to True, taken from the Seattle Mariners @ Boston Red Sox 2024-07-29 game.

The player IDs in this example correspond to the MLB.com IDs for each player.

{
    "extended_roster": True,
    "scorer": "Vicyorus",
    "date":   "2024-07-29 19:11-21:58",
    "at":     "Fenway Park, Boston, MA",
    "att":    "35,007",
    "temp":   "72F, Partly Cloudy",
    "wind":   "4mph, Out To RF",
    "away"   : {
        "team":    "Seattle Mariners",
        "starter": 669302,
        "roster":  {
            # Lineup
            645302 : { "jersey" : 10, "name" : "Victor Robles" },
            668227 : { "jersey" : 56, "name" : "Randy Arozarena" },
            663728 : { "jersey" : 29, "name" : "Cal Raleigh" },
            593871 : { "jersey" : 7,  "name" : "Jorge Polanco" },
            670042 : { "jersey" : 20, "name" : "Luke Raley" },
            664238 : { "jersey" : 25, "name" : "Dylan Moore" },
            613564 : { "jersey" : 35, "name" : "Jason Vosler" },
            571745 : { "jersey" : 17, "name" : "Mitch Haniger" },
            668942 : { "jersey" : 4,  "name" : "Josh Rojas" },

            # Starting pitcher
            669302 : { "jersey" : 36, "name" : "Logan Gilbert" },

            # Bench
            682988 : { "jersey" : 27, "name" : "Tyler Locklear" },
            641598 : { "jersey" : 18, "name" : "Mitch Garver" },
            687799 : { "jersey" : 2,  "name" : "Cade Marlowe" },
            660844 : { "jersey" : 76, "name" : "Leo Rivas" },

            # Bullpen
            676092 : { "jersey" : 52, "name" : "Collin Snider" },
            608723 : { "jersey" : 30, "name" : "Austin Voth" },
            666619 : { "jersey" : 48, "name" : "Gregory Santos" },
            693433 : { "jersey" : 22, "name" : "Bryan Woo" },
            554340 : { "jersey" : 93, "name" : "Yimi García" },
            663423 : { "jersey" : 46, "name" : "Trent Thornton" },
            622491 : { "jersey" : 58, "name" : "Luis Castillo" },
            669923 : { "jersey" : 68, "name" : "George Kirby" },
            662253 : { "jersey" : 75, "name" : "Andrés Muñoz" },
            642048 : { "jersey" : 60, "name" : "Tayler Saucedo" },
            642100 : { "jersey" : 55, "name" : "Gabe Speier" },
            682243 : { "jersey" : 50, "name" : "Bryce Miller" },
        },
        "lefties" : [
            642048, 642100
        ],
        "lineup" : [
            [645302, "8"],
            [668227, "7"],
            [663728, "2"],
            [593871, "4"],
            [670042, "9"],
            [664238, "6"],
            [613564, "3"],
            [571745, "0"],
            [668942, "5"],
        ],
        "bench" : [
            [682988, "1B"],
            [641598, "DH"],
            [687799, "LF"],
            [660844, "SS"],
        ],
        "bullpen" : [
            676092, 608723, 666619, 693433, 554340, 663423, 622491, 669923, 662253, 642048, 642100, 682243
        ],
    },
    "home"   : {
        "team":    "Boston Red Sox",
        "starter": 601713,
        "roster":  {
            # Lineup
            680776 : { "jersey" : 16, "name" : "Jarren Duran" },
            677800 : { "jersey" : 52, "name" : "Wilyer Abreu" },
            807799 : { "jersey" : 7,  "name" : "Masataka Yoshida" },
            646240 : { "jersey" : 11, "name" : "Rafael Devers" },
            641933 : { "jersey" : 17, "name" : "Tyler O'Neill" },
            642086 : { "jersey" : 2,  "name" : "Dominic Smith" },
            657136 : { "jersey" : 12, "name" : "Connor Wong" },
            666152 : { "jersey" : 70, "name" : "David Hamilton" },
            678882 : { "jersey" : 43, "name" : "Ceddanne Rafaela" },

            # Starting pitcher
            601713 : { "jersey" : 37, "name" : "Nick Pivetta" },

            # Bench
            642197 : { "jersey" : 73, "name" : "Jamie Westbrook" },
            663853 : { "jersey" : 23, "name" : "Romy Gonzalez" },
            608701 : { "jersey" : 30, "name" : "Rob Refsnyder" },
            643376 : { "jersey" : 28, "name" : "Danny Jansen" },

            # Bullpen
            677161 : { "jersey" : 76, "name" : "Zack Kelly" },
            572020 : { "jersey" : 65, "name" : "James Paxton" },
            678394 : { "jersey" : 66, "name" : "Brayan Bello" },
            592155 : { "jersey" : 71, "name" : "Cam Booser" },
            445276 : { "jersey" : 74, "name" : "Kenley Jansen" },
            670174 : { "jersey" : 25, "name" : "Josh Winckowski" },
            657514 : { "jersey" : 83, "name" : "Brennan Bernardino" },
            690544 : { "jersey" : 78, "name" : "Bailey Horn" },
            676710 : { "jersey" : 50, "name" : "Kutter Crawford" },
            622259 : { "jersey" : 61, "name" : "Trey Wingenter" },
            681867 : { "jersey" : 64, "name" : "Cooper Criswell" },
            656557 : { "jersey" : 89, "name" : "Tanner Houck" },
        },
        "lefties" : [
            572020, 592155, 657514, 690544
        ],
        "lineup" : [
            [680776, "8"],
            [677800, "9"],
            [807799, "0"],
            [646240, "5"],
            [641933, "7"],
            [642086, "3"],
            [657136, "2"],
            [666152, "4"],
            [678882, "6"],
        ],
        "bench" : [
            [642197, "2B"],
            [663853, "SS"],
            [608701, "RF"],
            [643376, "C" ],
        ],
        "bullpen" : [
            677161, 572020, 678394, 592155, 445276, 670174, 657514, 690544, 676710, 622259, 681867, 656557
        ],
    },
    "umpires" : {
        "HP" : "Andy Fletcher",
        "1B" : "Jansen Visconti",
        "2B" : "Cory Blaser",
        "3B" : "John Bacon",
    },
}

Credits

This project is heavily based on the work by Chris Nandor (https://sourceforge.net/projects/pudge/files/Games_Baseball_Scorecard/), and uses a modified version of the Metapost scorecard template created by Christopher Swingley (https://swingleydev.com/baseball/scorecards.php).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

baseball_scorecard-0.1.0.tar.gz (53.6 kB view details)

Uploaded Source

Built Distribution

baseball_scorecard-0.1.0-py3-none-any.whl (57.7 kB view details)

Uploaded Python 3

File details

Details for the file baseball_scorecard-0.1.0.tar.gz.

File metadata

  • Download URL: baseball_scorecard-0.1.0.tar.gz
  • Upload date:
  • Size: 53.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.10.12 Linux/5.15.153.1-microsoft-standard-WSL2

File hashes

Hashes for baseball_scorecard-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3555f73010f5cb88ba835c78dd5a5f51f417e2847cef45f6917c04d89bff1b6e
MD5 5fd03e562e1c17b17f0cca97c2e1abcf
BLAKE2b-256 6416ac400fbb0b0e3a3cf4586ea4593bf981b82e0a508551193e8ea45db50296

See more details on using hashes here.

File details

Details for the file baseball_scorecard-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: baseball_scorecard-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 57.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.10.12 Linux/5.15.153.1-microsoft-standard-WSL2

File hashes

Hashes for baseball_scorecard-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c6dbfbcac0b10218a60d248050c080bf468ef48b74e545ee51dea019315d0d2a
MD5 73cad4f81bc5754015712aed6da02717
BLAKE2b-256 dbfc27d0d3a98480c48fa243b2c40ce83d2cf396ad8b0ce2bcd0e8690715c8a0

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page