The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Games::Baseball::Scorecard

SYNOPSIS

        my $score = Games::Baseball::Scorecard->new($dir, $name, {
                color  => [ .4, .4, .4 ], # grey
                fonts  => [ # Myriad Condensed regular/bold
                        [ myriadrcrrl =>  9 ],
                        [ myriadrcbrl => 14 ],
                        [ myriadrcrrl => 14 ],
                        [ myriadrcbrl => 22 ],
                ],
        });

        # fill initial scorecard out
        $s->init({
                scorer  => 'Pudge',
                date    => '2004-10-24, 20:05-23:25',
                at      => 'Fenway Park, Boston',
                temp    => '48 clear',
                wind    => '7 to RF',
                att     => '35,001',
                home    => {
                        team    => 'Boston Red Sox',
                        starter => 38, # jersey number
                        lineup  => [
                                # [ num, position ],
                                [ 18, 8 ], # Damon, starting at CF
                                # ...
                        ],
                        roster  => {
                                # num => name
                                18 => 'Damon, Johnny',
                                38 => 'Schilling, Curt',
                                # ...
                        },
                },
                away    => {
                        team    => 'St. Louis Cardinals',
                        # ...
                }
        });

        # draw the game
        $s->inn; # new inning / end of last inning

                $s->ab; # new at-bat
                        # works to full count
                        $s->pitches(qw(s b s b b f));
                        # struck out looking
                        $s->out('!K');

                $s->ab;
                        # home run to left-center
                        $s->hit(4, 'lc');

        # calculate/draw stats
        $self->totals;

        # finish the job
        $s->generate;

        # open final PDF
        $s->pdfopen;

DESCRIPTION

Games::Baseball::Scorecard is a frontend to a PDF scorecard written in Metapost by Christopher Swingley (http://www.frontier.iarc.uaf.edu/~cswingle/baseball/scorecards.php). That scorecard is drawn out, and has a nice API for actually drawing out the elements of the game: all the ball, strikes, outs, etc.

Being Metapost, it is laborious to do all this. So this module provides a nice frontend, that also keeps track of balls and strikes and hits and runs and outs and more, making input of the game quite simple and efficient.

This module does not include the entire API, but most of it. Patches and ideas welcome. Feel free to call output directly if you want to generate Metapost on your own, or to modify the $SCORECARD variable (which contains the base Metapost code), or the $TEX (single page) and $TEXD (duplex) TeX files.

I won't give a tutorial on scoring baseball games, or on Metapost, below. Seek other resources (Swingley's URL above has a nice tutorial on scoring baseball games, using the scorecard he designed, which is what we're using here).

SYSTEM REQUIREMENTS

You will need TeX and Metapost installed. mpost, mptopdf, and pdftex must be in your $ENV{PATH}. For opening the PDF with pdfopen, you will need open (Mac OS X) in your path. The names of these programs can be modified with the variables $MPOST, $MPTOPDF, $PDFTEX, and $OPEN.

Also, the font by default (in the $SCORECARD variable) is Helvetica Narrow. Use whatever fonts you have installed for TeX. The original used Myriad Condensed, which I don't have (getting a decent-looking font and size, and figuring out how to use it, was the hardest part of the project for me -- as I don't know TeX -- so I picked a font everyone else could use, that should be installed by default in most TeX installations).

See the distribution at http://www.frontier.iarc.uaf.edu/~cswingle/baseball/scorecards.php for more information.

METHODS

The main methods are included below. There are some other methods that are used, but you shouldn't need to call them so I won't list them all here.

Basic Methods

new([DIR, BASE, OPTS])

The new method takes three optional arguments: a directory to build in, and a base name for the scorecard file, and an options hashref. Defaults are the current directory, and "scorecard". The base name is used to generate the build files and the resulting PDFs, which will be ${base}_away.pdf, ${base}_home.pdf, and $base.pdf (both away and home together).

Options can be "color", an arrayref of RGB values (0 to 1), and "fonts", an arrayref of four fonts (copyright notice font, basepath play labels, balls/strikes/outs/other labels, and outs and other large label), with the font name and size (see SYNOPSIS).

Defaults are black, and Helvetica Narrow (phvr8rn/phvr8rn).

debug([LEVEL])

Set debug level. 0 is off, 1 shows the commands being executed, 2 shows all output.

init(DATA)

The <init> method accepts a single hashref that has all the data needed to generate the initial scorecard. You can some of the methods directly on your own, but you really don't want to.

The hashref contains various root-level string keys: date, temp, wind, at, att, scorer. Each takes a simple string.

It also takes two hashref keys, away and home. Each works the same way. The team key takes the team name, the starter key takes the jersey number of the starter, the roster key takes a hashref of jersey number/name for the entire active roster.

The lineup key takes an arrayref -- in order -- of each starter, with each element as an arrayref of [ jersey number, position ].

The position is standard baseball position numbering: 1 P, 2 C, 3 1B, 4 2B, 5 3B, 6 SS, 7 LF, 8 CF, 9 RF. I use 0 for DH.

Players are thus referenced by their jersey number, when making them the starter, putting them in the starting lineup, or when adding a new player or pitcher.

The lefties key is optional; if present, it is used to determine which pitchers are lefties. It takes a simple arrayref listing the jersey numbers of the southpaws on the roster.

If not using this module to generate the entire game, but just the initial scorecard, then the roster needs only include the players in the starting lineup.

generate

The generate method takes the Metapost code and generates the PDFs. Call this last, after everything has been done to the scorecard.

Calls close for you.

Returns the path to the PDF file.

close

The close method finishes up the Metapost file, and closes it for you.

Do not call this method if you also call generate, as that method calls this one. Only call this method if you do not wish to generate the PDF files, but only want to write out the Metapost file.

pdfopen([FILE])

Opens the PDF (or filename provided) using the program specified in $OPEN (default 'open', used by Mac OS X to open the document in the default PDF viewer).

home_away([WHICH])

Switch which team is home, and which is away. If WHICH then set specifically.

Scoring Methods

These are the methods for scoring an actual game.

Setup Methods

inn

Call inn to start a new half-inning, and to finish the final inning. It generates the inning stats.

Note: if you go to more than 11 innings, things will break. See LIMITATIONS.

ab

Call ab to start a new at-bat. Note: call add_pitcher and add_player before calling ab.

Note: if you have more than 9 batters in an inning, things will break. See LIMITATIONS.

add_player(ORDER, NUMBER, POS [, INN])

This adds a new player -- with the given jersey number and position -- in the given place in the batting order. If you are scoring an actual game, call this only at the point the player enters the game. The inning will be figured out automatically then.

The player will be added to the lineup list on the left of the card, and stats for that lineup position will be added to that player (instead of the previous one) from that moment on, and a line will be drawn on the sheet for where that player entered.

Call this before you call ab (unless the player enters as a pinch runner).

Note: if you add more than three batters for a given position, the overflow will go to one of the six spots below the nine lineup positions. No stats will be printed for them. More than six of those, and the names will not be printed either.

add_pitcher(NUMBER, [, INN])

This adds a new pitcher -- with the given jersey number -- to the scorecard. If you are scoring an actual game, call this only at the point the pitcher enters the game. The inning will be figured out automatically then.

The pitcher will be added to the lineup list on the left of the card, and stats for pitching will be added to that pitcher (instead of the previous one) from that moment on, and a line will be drawn on the sheet for where that pitcher entered.

Call this before you call ab.

Note: if you add more than six pitchers, the module will die. See LIMITATIONS.

At-Bat Methods

These methods will draw in the at-bat graphic for the current at-bat, and will also keep track of stats for later drawing (per-inning stats, per-batter stats, and game totals).

Note: At-bats do not progress the way they would in a game. You put in all of the information for a given at-bat in that at-bat before moving on to the next. For example, if a runner reaches on a walk, and then is hit home by a home run, you would mark the walk, then that the runner advanced home, before moving on to the next at-bat.

play_ball(TEXT[, TEAMS])

play_ball is a convenience method for handling input as text instead of method calls (internally, it converts the text to method calls).

The first token on each line is the method call, and the rest are arguments to the method call.

Shorthands include 'p' for pitches, 'bb' 'ibb' and 'hp' for reach() by BB/IBB/HBP, and '->' for advance. Any other tokens that are not method names are out('token').

Example:

        $s->inn;
        $s->ab;
                $s->pitches(qw(b s b s b));
                $s->out('!K');
        $s->ab;
                $s->pitches(qw(b b b));
                $s->reach('bb');
                $s->advance(2);
        $s->ab;
                $s->hit(1, 'l');

Is equivalent to:

        $s->play_ball(<<'EOT');
                inn
                ab
                        p b s b s b
                        !K
                ab
                        p b b b
                        bb
                        -> 2
                ab
                        hit 1 l
        
        EOT

Prefixing a method name with 'ha' will call home_away for that method (useful for adding new players, such as 'ha add_player 9 3 8' to add a player #3 to center field in the ninth spot for the fielding team, as doing it without 'ha' would make the change for the team at bat).

You can also put data for init in the text, at the top. Include any of the "root-level" strings, e.g.:

        scorer  Pudge
        date    2004-10-24, 20:05-23:25

After those, add the string 'away' or 'home', with the team name following; then 'starter' with the starer's number; then the string 'lineup' followed by the lineup data:

        away    Boston Red Sox
        starter 32
        lineup
                18 8
                44 6
                24 7

Then put the other string ('home'), followed by the data for that team. To complete the data, pass in a hashref with the team name (exactly the same as included following the string 'home' or 'away') as the key to a hashref, and the 'roster' / 'lefties' keys filled out (just as in init).

See the example3.plx script and example3.txt files for an example.

pitches(PITCHES)

pitches records the individual pitches of the at-bat (except for the one that generates an out or puts the ball in play). It takes a list of strings, each string representing a pitch. Each pitch can be one of s, b, or f.

This puts the pitch markers in the at-bat graphic, and also increments counts for the stat drawing later.

hit(BASES [, WHERE, LABEL])

hit denotes a hit of BASES bases, to WHERE.

WHERE is an optional string, for where the ball left the park or where the fielder recovered it, with these options:

        infield:
                il      left
                ic      center
                ir      right

        outfield:
                l       left
                lc      left center
                cl      center left
                cr      center right
                rc      right center
                r       right

LABEL is an optional label to put on the way to first base.

reach(LABEL [, BASES])

reach denotes reaching base by a method other than a hit. LABEL is the method of reaching, and BASES is optional number of bases reached (default is, of course, 1).

Special LABELs include 'bb', 'ibb', 'hp', 'K', 'SAC', and 'SF'. 'K' is special in that it is added to the stats totals; the others are not included as at-bats; and 'bb', 'ibb', and 'hp' are counted as balls, instead of strikes.

out(LABEL)

out records that the at-bat resulted in an out. LABEL is the way in which the out was recorded, e.g., F8, 4-3, SF7, SAC4-3, DP6-4-3, K, and so on.

SF and SAC outs will not be recorded as official at-bats. The string '!K' is used to denote a strikeout looking.

If you use SF, SAC, DP, K, and !K, then the stats for those can be properly tabulated at the end.

tout(BASE, LABEL [, NUM, PITCHER])

tout records that the runner was thrown out at BASE. LABEL is the way in which the out was recorded, e.g., CS2-6, FC, DP.

PITCHER is the number of the pitcher who gets the out (for IP) if not the one that pitched to that batter.

It is not necessary to include the base the runner is coming from; that is remembered for you.

NUM is used in case the out is not in sequential order: e.g., if a batter walks, then the next batter strikes out, then the first batter is caught stealing, without NUM set to 2, the code would guess that it is the first out, since the at-bat is earlier. By setting NUM to 2 for the throwout, the strikeout will be set to out 1, and the next out after that will be out 3.

If you use CS for LABEL, then the stats for that can be properly tabulated at the end.

advance(BASE [, LABEL])

advance advances a runner to BASE. LABEL is the optional way in which the runner advanced, e.g., SB.

If you advance home (4), a run is recorded for that runner, and is marked as earned for the pitcher. To advance home for an unearned run, use 'U' instead of '4'.

and EARNED is true, the run is earned.

It is not necessary to include the base the runner is coming from; that is remembered for you.

If you use SB, then the stats for that can be properly tabulated at the end.

At-Bat Stat Methods

These methods add additional stats (and in some cases, graphics) that are not easily decipherable from the other at-bat events, so we need them explicitly.

rbi([RBIS])

Add RBI number of RBIs to current batter's totals (default is 1). Don't include RBIs added by a hit(4), as that is added automatically.

error(POSITION)

Notes that an error was committed by the player at POSITION. (Keeping track of error by POSITION not yet implemented, but feel free to include it anyway, for when it is implemented.)

balk

Notes that there was a balk.

wp

Notes that there was a wild pitch.

pb

Notes that there was a passed ball.

dp

Notes that a double play was executed. Do not use if the batter was out by double play, but only if there was a double play in which the batter was safe, as calling out('DP6-4-3') already records the double play for you.

At-Bat Label Methods

These methods are simply for adding additional labels in the at-bat graphic, for whatever you wish.

waybase(LABEL [, BASE, BIG])

Add label LABEL on the way to BASE. If BASE is excluded, notes it on way to the next base after the one the runner is currently at.

atbase(LABEL [, BASE, BIG])

Add label LABEL at BASE. If BASE is excluded, notes it at the base the runner is currently at.

Stat Totals Methods

win(NUMBER)
loss(NUMBER)
save(NUMBER)
blown_save(NUMBER)

NUMBER is the jersey number of the pitcher who got the (win, loss, save, blown save). Call these methods while the pitcher's team is still on the field (while the opposing team is still at bat), any time before the totals are calculated.

totals

This generates the stat totals for the game, batters, and pitchers. Call it after the finall inn method call, if you wish to generate the stat totals.

LIMITATIONS

This module makes no attempt to try to work around the physical limitations of the scorecard. So if there are more than 11 innings, more than nine batters in an inning, more than three players in a lineup position, or more than ten pitchers, it will fail, either by dying, or just screwing up the output.

More than four foul balls will not be recorded for a given at-bat in the graphic (but the pitch counts will still be incremented appropriately).

Also, no attempt is made to make sure you have the right number of outs in an innings, balls/strikes in a walk/strikeout, and so on. We don't even necessarily check to make sure you've called inn() before you call your first ab(), or that you don't use an incorrect base number, and so on. Or that David Ortiz isn't pitching, or playing all positions at once. Just don't record something illegal in a baseball game, and you likely won't run into problems here, either.

There are also likely things that happen in the game that the API here does not well-address.

Patches are welcome for all of this, if you want it.

TODO

Automatically, or otherwise, handle more than 9 batters per inning, or more than 11 innings, perhaps by adding a new scorecard, or by re-using existing innings for overflow.

AUTHOR

Chris Nandor <projects@pudge.net>, http://projects.pudge.net/

Copyright (c) 2005 Chris Nandor. Licensed under the terms of the GNU General Public License, Version 2 available from http://www.gnu.org/copyleft/gpl.html.

Front end to mpost_scorecard by Christopher Swingley, also licensed under the GPL.

SEE ALSO

http://www.frontier.iarc.uaf.edu/~cswingle/baseball/scorecards.php

VERSION

$Id: Scorecard.pm,v 1.5 2005/10/21 04:48:58 pudge Exp $

__END__