% swimgraf.sty
% To produce graphs of swim times using PSTricks tools
% Martin J. Osborne 2002/5 Version 1.0
% http://www.economics.utoronto.ca/osborne
% For documentation and files of records, see
% http://www.economics.utoronto.ca/osborne/latex
% This material is subject to the LaTeX Project Public License.  See
%   http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html
% for details.

\RequirePackage{mathpazo}
\RequirePackage{pstricks}
\RequirePackage{pstcol,pst-plot}
\RequirePackage{keyval}

\newif\ifswg@eventmismatch
\newif\ifswg@continue
\newif\ifswg@plotlabel\swg@plotlabeltrue
\newif\ifswg@a\swg@afalse
\newif\ifswg@b\swg@bfalse
\newif\ifswg@c\swg@cfalse
\newif\ifswg@d\swg@dfalse
\newif\ifswg@e\swg@efalse
\newif\ifswg@f\swg@ffalse
\newif\ifswg@j\swg@jfalse
\newif\ifswg@n\swg@nfalse
\newif\ifswg@w\swg@wfalse
\newif\ifswg@x\swg@xfalse
\newif\ifswg@y\swg@yfalse
\newif\ifswg@z\swg@zfalse
\newif\ifswg@agerec\swg@agerecfalse
\newif\ifswg@screcinrange\swg@screcinrangefalse
\newif\ifswg@lcrecinrange\swg@lcrecinrangefalse
\newif\ifswg@continue\swg@continuetrue
\newif\ifswg@star
\newif\ifswg@hyphen
\newif\ifswg@qm
\newif\ifswg@colon
\newif\ifswg@period
\newif\ifswg@plus
\newif\ifswg@matchfound
\newif\ifswg@nmn
\newif\ifswg@nmd
\newif\ifswg@eventfound
\newif\ifswg@inrange
\newif\ifswg@indescription\swg@indescriptionfalse
\newif\ifswg@putyr\swg@putyrfalse

\newdimen\swg@monthbaseh
\newdimen\swg@titlebaseh
\newdimen\swg@tempdima
\newdimen\swg@tempdimb
\newdimen\swg@tempdimh
\newdimen\swg@tempdiml
\newdimen\swg@avgw
\newdimen\swg@avgh
\newdimen\swg@top
\newdimen\swg@bottom
\newdimen\swg@labelh
\newdimen\swg@lpos
\newdimen\swg@keyh

\newcount\swg@htime
\newcount\swg@ltime
\newcount\swg@lhvytime
\newcount\swg@age
\newcount\swg@endage
\newcount\swg@hvylines
\newcount\swg@lghlines
\newcount\swg@midy
\newcount\swg@day
\newcount\swg@month
\newcount\swg@year
\newcount\swg@daycount
\newcount\swg@diycount
\newcount\swg@startday
\newcount\swg@startyear
\newcount\swg@startdiy
\newcount\swg@endday
\newcount\swg@enddaycount
\newcount\swg@enddiy
\newcount\swg@bdaydiy
\newcount\swg@mid
\newcount\swg@i
\newcount\swg@recsday
\newcount\swg@receday
\newcount\swg@agecount
\newcount\swg@vlabelsecs
\newcount\swg@vlabelmins
\newcount\@tempcntc
\newcount\@tempcntd
\newcount\@tempcntx
\newcount\@tempcnty
\newcount\@tempcntz
\newcount\@tempcntyr

% If you use the landscape option of the article style and 
% 'lettersize' paper, the landgraph option for swimgraf defines
% margins etc. that seem to allow you to use the whole page
% (I don't understand the logic of the topmargin)

\DeclareOption{landgraph}{\textwidth 11in\textheight 8.5in
\oddsidemargin -1in\evensidemargin -1in\topmargin -1.5in}

% Age-specific standards/records
\DeclareOption{a}{\swg@atrue}
\DeclareOption{b}{\swg@btrue}
\DeclareOption{c}{\swg@ctrue}
\DeclareOption{d}{\swg@dtrue}
\DeclareOption{e}{\swg@etrue}
\DeclareOption{f}{\swg@ftrue}
% Age-open standards/records
\DeclareOption{j}{\swg@jtrue}
\DeclareOption{n}{\swg@ntrue}
\DeclareOption{w}{\swg@wtrue}
\DeclareOption{x}{\swg@xtrue}
\DeclareOption{y}{\swg@ytrue}
\DeclareOption{z}{\swg@ztrue}

\input swimgraf.cfg

\ProcessOptions

%---------------------------------------%
% LABELS ON VERTICAL AXIS               %
%---------------------------------------%
% Modify PSTricks labels on vertical axis 
% to convert seconds into minutes and seconds

\def\psvlabel#1{%
  \swg@tominssecso#1\relax
  \swg@timeresult}

%-------------------------------------%
% ERRORS                              %
%-------------------------------------%

% Following modeled on PSTricks error messages
\def\swg@err#1#2{%
\begingroup
\newlinechar`\^^J
\edef\swg@tempc{#2}%
\expandafter\errhelp\expandafter{\swg@tempc}%
\typeout{^^JSwimgraph error: type \space H <return> \space for immediate help.}%
\errmessage{#1}%
\endgroup}

\def\swg@ehpa{%
This result will be ignored.^^J
Type \space <return> \space to proceed or \space X <return> \space to quit.}
\def\swg@ehpb{%
Your command was ignored. Will recover best I can.^^J
Type \space <return> \space to proceed or \space X <return> \space to quit.}
\def\swg@ehpc{%
You need to fix this error before proceding.^^J
Type \space X <return> \space to quit.}

%-------------------------------------%
% DATE UTILITY                        %
%-------------------------------------%
% \swg@date year-month-day defines \swg@year, \swg@month, \swg@day,
% \swg@diycount (day in year), and \swg@daycount (index of day since 2000/1/1)
% Doesn't account for leap years

\def\swg@date#1-#2-#3 {%
  \swg@year=#1
  \swg@month=#2
  \swg@day=#3
  \ifnum\swg@month=1
  \else\ifnum\swg@month=2
    \advance\swg@day by31
  \else\ifnum\swg@month=3
    \advance\swg@day by59
  \else\ifnum\swg@month=4
    \advance\swg@day by90
  \else\ifnum\swg@month=5
    \advance\swg@day by120
  \else\ifnum\swg@month=6
    \advance\swg@day by151
  \else\ifnum\swg@month=7
    \advance\swg@day by181
  \else\ifnum\swg@month=8
    \advance\swg@day by212
  \else\ifnum\swg@month=9
    \advance\swg@day by243
  \else\ifnum\swg@month=10
    \advance\swg@day by273
  \else\ifnum\swg@month=11
    \advance\swg@day by304
  \else\ifnum\swg@month=12
    \advance\swg@day by334
  \else
    \swg@err{The month \the\swg@month\space (in the date #1-#2-#3) does not exist}\swg@ehpc
  \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
  \swg@diycount=\swg@day
% \swg@daycount is index of day since 2000/1/1
  \swg@daycount=\swg@year
  \advance\swg@daycount by-2000
% doesn't account for leap years
  \multiply\swg@daycount by365
  \advance\swg@daycount by\swg@diycount
}

%-------------------------------------%
% TIME UTILITIES                      %
%-------------------------------------%
% Test time format

% The function \in@ is in LaTeX
% \in@{x}{y} sets \ifin@ true if the string y contains the string x
% and false otherwise
% Here it is in case it disappears:
%\def\in@#1#2{%
% \def\in@@##1#1##2##3\in@@{%
%  \ifx\in@##2\in@false\else\in@true\fi}%
% \in@@#2#1\in@\in@@}
%\newif\ifin@

% Given time in various formats, define \swg@mins, \swg@secs, and \swg@msecs.
% Formats accepted: m:s.x (put m in \swg@mins, s in \swg@secs, x in \swg@msecs)
%   m:s (put m in \swg@mins, s in \swg@secs, and 0 in \swg@msecs)
%   s.x (put s in \swg@secs and x in \swg@msecs)
%   s (put s in \swg@secs and 0 in \swg@msecs)
\def\swg@parsetime#1{%
  \in@{:}{#1}%
  \ifin@%
    \in@{.}{#1}%
    \ifin@%
      \swg@t@msm#1\relax%
    \else%
      \swg@t@ms#1\relax%
    \fi%
  \else%
    \in@{.}{#1}%
    \ifin@%
      \swg@t@sm#1\relax%
    \else%
      \swg@t@s#1\relax%
    \fi%
  \fi%
}

\def\swg@t@msm#1:#2.#3\relax{%
  \def\swg@mins{#1}\def\swg@secs{#2}\def\swg@msecs{#3}}
\def\swg@t@ms#1:#2\relax{%
  \def\swg@mins{#1}\def\swg@secs{#2}\def\swg@msecs{0}}
\def\swg@t@sm#1.#2\relax{%
  \def\swg@mins{0}\def\swg@secs{#1}\def\swg@msecs{#2}}
\def\swg@t@s#1\relax{%
  \def\swg@mins{0}\def\swg@secs{#1}\def\swg@msecs{0}}

% Convert time to seconds.milliseconds (OK for argument to be in this format)
% Puts result in \swg@timeresult
% Use syntax \expandafter\swg@tosecs\yourtime\relax
% Result is in \swg@timeresult
\def\swg@tosecs#1\relax{%
  \swg@parsetime{#1}%
  \@tempcnta=\swg@mins%
  \multiply\@tempcnta by60%
  \advance\@tempcnta by\swg@secs\relax%
  \edef\swg@timeresult{\the\@tempcnta.\swg@msecs}%
}

% Same, but ignore any milliseconds
\def\swg@tosecso#1\relax{%
  \swg@parsetime{#1}%
  \@tempcnta=\swg@mins%
  \multiply\@tempcnta by60%
  \advance\@tempcnta by\swg@secs\relax%
  \edef\swg@timeresult{\the\@tempcnta}%
}

% Convert time to minutes:seconds.msecs if minutes > 0, else seconds.msecs
% (OK for argument to already be in this format)
% Puts result in \swg@timeresult
% Use syntax \expandafter\swg@tominssecs\yourtime\relax
\def\swg@tominssecs#1\relax{%
  \swg@parsetime{#1}%
  \@tempcnta=\swg@secs%
  \divide\@tempcnta by60%
  \@tempcntc=\@tempcnta%
  \advance\@tempcntc by\swg@mins%
  \multiply\@tempcnta by60%
  \@tempcntb=\swg@secs%
  \advance\@tempcntb by-\@tempcnta%
  \ifnum\@tempcntc=0%
    \edef\swg@timeresult{\the\@tempcntb.\swg@msecs}%
  \else\ifnum\@tempcntb<10%
    \edef\swg@timeresult{\the\@tempcntc:0\the\@tempcntb.\swg@msecs}%
  \else%
    \edef\swg@timeresult{\the\@tempcntc:\the\@tempcntb.\swg@msecs}%
  \fi\fi%
}

% Convert time to minutes:seconds (with minutes = 0 for times less than
% a minute)
% (OK for argument to already be in this format)
% Puts result in \swg@timeresult
% Use syntax \expandafter\swg@tominssecso\yourtime\relax
\def\swg@tominssecso#1\relax{%
  \swg@parsetime{#1}%
  \@tempcnta=\swg@secs%
  \divide\@tempcnta by60%
  \@tempcntc=\@tempcnta%
  \advance\@tempcntc by\swg@mins%
  \multiply\@tempcnta by60%
  \@tempcntb=\swg@secs%
  \advance\@tempcntb by-\@tempcnta%
  \ifnum\@tempcntb<10%
    \edef\swg@timeresult{\the\@tempcntc:0\the\@tempcntb}%
  \else%
    \edef\swg@timeresult{\the\@tempcntc:\the\@tempcntb}%
  \fi%
}

%-------------------------------------%
% RECORDS                             %
%-------------------------------------%
%
% \swg@readrec#1#2: read records from file
% #1: record type (w, n, ...)
% #2: event name [e.g. "50 free"]
% Defines
% \swg@reclabel (label for record as it appears on graph)
% \swg@screc (short course record)
% \swg@lcrec (long course record)
\def\swg@readrec#1#2
  {
% need \edef here: if #2 is a macro, which it is in this application, it
% needs to be expanded when \swg@event is defined
  \edef\swg@event{#2}
% to get rid of CR, which is converted to space, at end of line that is read
  \endlinechar=-1
  \openin1=\swg@recfile
% first line of file is comment
% second line is label (as it appears on graph)
  \read1 to\@templine
  \read1 to\swg@reclabel
  \loop
    \read1 to\@templine
      \ifx\@templine\swg@event\swg@eventmismatchfalse
      \else\swg@eventmismatchtrue\fi
      \ifeof1\relax\swg@eventmismatchfalse\else\fi
    \ifswg@eventmismatch
  \repeat
  \ifeof1
    \def\swg@screc{0}
    \def\swg@lcrec{0}
  \else
    \read1 to \swg@sc
    \read1 to \swg@lc
    \typeout{\swg@reclabel: \swg@sc\space(SC), \swg@lc\space(LC)}
    \expandafter\swg@tosecs\swg@sc\relax
    \edef\swg@screc{\swg@timeresult}
    \expandafter\swg@tosecs\swg@lc\relax
    \edef\swg@lcrec{\swg@timeresult}
  \fi
  \endlinechar=13
  \closein1
  }

% Draw line, given record type and times, and start and end days.
% #1: type of record: w, n, ... (needed to determine color)
% #2: SC record time
% #3: LC record time
% #4: start day
% #5: end day
\def\swg@xrecline#1#2#3#4#5{%
  \def\swg@recsccolor{\csname swg@#1sccolor\endcsname}
  \def\swg@reclccolor{\csname swg@#1lccolor\endcsname}
% if no record on file, or if above htime, don't draw any line
  \edef\@argii{#2}\edef\@argiii{#3}\def\@zero{0}
  \swg@screcinrangefalse
  \swg@lcrecinrangefalse
  \swg@tempdima=\@argii mm
  \swg@tempdimb=\@argiii mm
  \swg@tempdimh=\the\swg@htime mm
  \swg@tempdiml=\the\swg@ltime mm
  \ifx\@argii\@zero
  \else
    \ifdim\swg@tempdima<\swg@tempdimh
      \ifdim\swg@tempdima>\swg@tempdiml
        \swg@screcinrangetrue
        \psline[linecolor=\swg@recsccolor,linewidth=\swg@reclinewidth]%
(#4,#2)(#5,#2)
      \fi
      \else
        \ifswg@screcinrange\else\typeout{Note: SC record is out of range.}
        \fi
    \fi
  \ifswg@screcinrange\else\typeout{Note: SC record is out of range.}\fi
  \fi
  \ifx\@argiii\@zero
    \else
    \ifdim\swg@tempdimb<\swg@tempdimh
      \ifdim\swg@tempdimb>\swg@tempdiml
        \swg@lcrecinrangetrue
        \psline[linecolor=\swg@reclccolor,linewidth=\swg@reclinewidth]%
(#4,#3)(#5,#3)
      \fi
      \else
        \ifswg@lcrecinrange\else\typeout{Note: LC record is out of range.}
        \fi
    \fi
    \ifswg@lcrecinrange\else\typeout{Note: LC record is out of range.}
    \fi
  \fi
  \let\psunit=\psxunit
  \pssetlength{\swg@avgw}{#4}
  \psaddtolength{\swg@avgw}{#5}
  \divide\swg@avgw by2
  \let\psunit=\psyunit
% If there is no short course record
  \ifx\@argii\@zero
% then if there is no long course record, do nothing
    \ifx\@argiii\@zero
% and if there is a long course record and it is in the range, label it
    \else
      \ifswg@lcrecinrange
        \def\swg@avghh{#3}
        \rput*[framesep=0pt](\swg@avgw,\swg@avghh)%
{\color{\swg@recsccolor}\swg@reclabel}
      \fi
    \fi
% If there is a short course record
  \else
% but no long course record, just label the short course record
    \ifx\@argiii\@zero
      \ifswg@screcinrange
        \def\swg@avghh{#2}
        \rput*(\swg@avgw,\swg@avghh){\color{\swg@recsccolor}\swg@reclabel}
      \fi
% and if there are both long course and short course records, label them
    \else
      \ifswg@lcrecinrange
        \ifswg@screcinrange
          \pssetlength{\swg@avgh}{#2}
          \psaddtolength{\swg@avgh}{#3}
          \divide\swg@avgh by2
          \rput*(\swg@avgw,\swg@avgh){\color{\swg@recsccolor}\swg@reclabel}
        \else
          \def\swg@avghh{#3}
          \rput*(\swg@avgw,\swg@avghh){\color{\swg@recsccolor}\swg@reclabel}
        \fi
      \else
        \ifswg@screcinrange
          \def\swg@avghh{#2}
          \rput*(\swg@avgw,\swg@avghh){\color{\swg@recsccolor}\swg@reclabel}
        \fi
      \fi
    \fi
  \fi
  }

% Read record from file and pass appropriate parameters to \swg@xrecline
% #1: record type (w, n, ...)
% #2: event name (e.g. "50 free")
% #3: start day
% #4: end day
\def\swg@recline#1#2#3#4{
% name of record file: like fw.dat (female), mw.dat (male) for age-open
% and fw11.dat (female), mw11.dat (male) for age-specific (age 11)
  \def\swg@recfile{%
    \swg@filepath\swg@sex #1\ifswg@agerec\the\swg@agecount\fi.dat}
  \IfFileExists{\swg@recfile}{
    \swg@readrec{#1}{#2}
    \swg@xrecline{#1}{\swg@screc}{\swg@lcrec}{#3}{#4}
    }{\typeout{FYI: file \swg@recfile\space does not exist.}}
  }
%
% Line for age-specific record, series #1 (a, b, ...)
% Calls \swg@recline
\def\swg@agerecline#1{%
  \swg@recsday=0
  \swg@receday=\swg@bdaydiy
  \advance\swg@receday by-\swg@startdiy
  \ifnum\swg@startdiy>\swg@bdaydiy\advance\swg@receday by365\fi
  \swg@agecount=\swg@age
  \loop
    \ifnum\swg@agecount=\swg@endage\swg@receday=\swg@endday\fi
%    \typeout{Swimmer's age: \the\swg@agecount}
%    \typeout{sday: \the\swg@recsday.  eday: \the\swg@receday}
% braces enclosing next two lines are essential, because \swg@recline 
% includes a \loop
    {\swg@recline{#1}{\swg@dist\swg@strokex}%
       {\the\swg@recsday}{\the\swg@receday}}
    \ifnum\swg@agecount<\swg@endage\advance\swg@agecount by1
       \swg@recsday=\swg@receday
       \advance\swg@receday by365
  \repeat
  }

%-------------------------------------%
% PUTMONTH                            %
%-------------------------------------%
% Put month labels on graph
% Draws a vertical line at the beginning of the month 
% and puts the month name.
% \@tempcntb counts day in year.  Is set to #3 by \swg@putmonth.
% \@tempcntd counts day since base date.
% \@tempcntc is x-coordinate of vertical line for month
%    It is initialized at 0; upon entering the macro, its value is the
%    x-coordinate for the line for the (start of the) previous month.  The
%    macro increases its value to the x-coordinate for the start of the
%    current month, by
%    increasing it by #3 - \@tempcntb to a maximum of \swg@endday
% #1: month name
% #2: # of days in month
% #3: # of days in year till 1st of month

\def\swg@putmonth#1#2#3{
  \@tempcnta=#3%
  \advance\@tempcntd by-\@tempcntc
  \advance\@tempcntc by#3\advance\@tempcntc by-\@tempcntb
  \advance\@tempcntd by\@tempcntc
  \ifnum\@tempcntd<\swg@enddaycount
% don't put vertical line if first day is first of month
    \ifnum\@tempcntc>0
      \ifnum\@tempcnta=0% at start of new year
        \def\swg@linecolor{\swg@yearlinecolor}%
      \else
        \def\swg@linecolor{\swg@monthlinecolor}%
      \fi
    \psline[linecolor=\swg@linecolor]%
(\the\@tempcntc.5,\swg@ltime)(\the\@tempcntc.5,\swg@htime)%
    \fi
  \else\@tempcntc=\swg@endday % \@tempcntc gets stuck at \swg@endday
  \fi
  \advance\@tempcntc by#2
  \ifnum\@tempcntc<\swg@endday
    \@tempcnta=#2\divide\@tempcnta by2
    \advance\@tempcntc by-\@tempcnta
    \rput[B](\@tempcntc,\swg@monthbaseh){#1}
    \advance\@tempcntc by\@tempcnta
  \fi
  \advance\@tempcntc by-#2
  \@tempcntb=#3}

%-------------------------------------%
% UTILITIES                           %
%-------------------------------------%
%
% \end is a terminator
% Macro checks if second character of line is =.  Line must contain at least
% 3 characters, else macro will bomb
\def\swg@parsedataline#1#2#3\end{
  \ifx#2=
    \def\swg@switch{#1}
    \def\swg@content{#3}
  \else\swg@err{Bad syntax in file '\swg@datafile' on line '\swg@fileline':^^J\space\space second character is not '='}\swg@ehpc
  \fi
}

% Parser for line of swimmer's data file giving times
\def\swg@parseresultline#1 #2 #3\end{
  \def\swg@fdist{#1}
  \def\swg@fstroke{#2}
  \def\swg@ftime{#3}}

\def\swg@parsedatline#1 #2\end{
  \def\swg@datargi{#1}
  \def\swg@datargii{#2}}

% Read data from \swg@datafile and transfer appropriate parts of it to
% swgs1.tmp (short course times), swgs1d.tmp (corresponding meet names),
% swgl1.tmp (long course times), swgl1d.tmp (corresponding meet names),
% and also similar files with 2 suffixes [for second series; not yet
% implemented].  The time files are in the format to be read by PSTricks'
% \readdata, and the meet name files are used by \swg@plotlabel.
% #1: event distance.  #2: stroke.
\def\swg@readdata#1#2
  {
  \swg@matchfoundfalse
  \edef\swg@argi{#1}
  \edef\swg@argii{#2}
% to get rid of CR, which is converted to space, at end of line that is read
  \endlinechar=-1
  \openin0=\swg@datafile
  \immediate\openout1=swgs1.tmp  % short course times, series 1
  \immediate\openout2=swgs1d.tmp % short course descriptions, series 1
  \immediate\openout3=swgl1.tmp  % long course times, series 1
  \immediate\openout4=swgl1d.tmp % short course descriptions, series 1
% first three lines are ignored (name and birthdate have already been read)
  \read0 to\swg@fileline
  \read0 to\swg@fileline
  \read0 to\swg@fileline
  \read0 to\swg@fileline
  \loop
    \read0 to\swg@fileline
% Next line necessary because blank line is read at end of file, before
% \ifeof0 is true.  It also allows all lines starting % to be ignored.
    \ifx\swg@fileline\@empty
    \else
      \expandafter\swg@parsedataline\swg@fileline\end
      \if\swg@switch m
        \ifswg@eventfound\swg@txdata\fi
        \let\swg@meetname=\swg@content
%\typeout{Meet: \swg@meetname}
      \else\if\swg@switch d
        \ifswg@eventfound\swg@txdata\fi
        \let\swg@meetdate=\swg@content
%\typeout{Date: \swg@meetdate}
      \else\if\swg@switch c
        \global\let\swg@fcourse=\swg@content
      \else\if\swg@switch n
        \global\let\swg@s@graphnote=\swg@content
      \else\if\swg@switch r
        \ifswg@eventfound\swg@txdata\fi
        \global\let\swg@descmod=\swg@switch
        \swg@checkdata
      \else\if\swg@switch u
        \ifswg@eventfound\swg@txdata\fi
        \global\let\swg@descmod=\swg@switch
        \swg@checkdata
      \else\if\swg@switch R
        \ifswg@eventfound\swg@txdata\fi
        \global\let\swg@descmod=\swg@switch
        \swg@checkdata
      \fi\fi\fi\fi\fi\fi\fi
    \fi
    \ifeof0\relax\swg@continuefalse\else\swg@continuetrue\fi
    \ifswg@continue
  \repeat
  \endlinechar=13
  \ifswg@eventfound\swg@txdata\fi
  \closein0
  \immediate\closeout1
  \immediate\closeout2
  \immediate\closeout3
  \immediate\closeout4
  \ifswg@matchfound\else
    \swg@err{No data for event '#1 #2' in date range requested}\swg@ehpc
  \fi
  }

% Check if result is for right event and within date range, in which case
% extract variables and set \swg@eventfound true.
% Called by \swg@readdata, which defines relevant variables.
\def\swg@checkdata{%
  \expandafter\swg@parseresultline\swg@content\end
%\typeout{Event \swg@fdist\space\swg@fstroke\space\swg@fcourse\space\swg@ftime}
  \ifx\swg@argi\swg@fdist
    \ifx\swg@argii\swg@fstroke
% Check if date is in right range, and if so create right variables
% to write to swgsi.tmp or swgli.tmp (using \swg@txdata)
      \expandafter\swg@date \swg@meetdate {}
      \ifnum\swg@daycount>\swg@startday
        \ifnum\swg@daycount<\swg@enddaycount
          \swg@matchfoundtrue
          \advance\swg@daycount by-\swg@startday
          \advance\swg@daycount by1%
          \expandafter\swg@tosecs\swg@ftime\relax%
% CANNOT write \let\swg@ftime=\swg@timeresult on next line (why not??)
          \global\let\swg@xtime=\swg@timeresult
          \global\swg@eventfoundtrue
% Reset switches that do not persist between events
          \gdef\swg@s@graphnote{}
        \fi
      \fi
    \fi
  \fi
}

% Transfer data to files to be read by PSTricks macro.
% Called by \swg@readdata, which defines relevant variables
\def\swg@txdata{%
  \if\swg@fcourse s
    \immediate\write1{\the\swg@daycount\space\swg@xtime}
    \ifx\swg@s@graphnote\@empty
      \immediate\write2{\swg@descmod\space\swg@meetname}
    \else
      \immediate\write2{%
        \swg@descmod\space\swg@meetname\space(\swg@s@graphnote)}
    \fi
  \else\if\swg@fcourse l
    \immediate\write3{\the\swg@daycount\space\swg@xtime}
    \ifx\swg@s@graphnote\@empty
      \immediate\write4{\swg@descmod\space\swg@meetname}
    \else
      \immediate\write4{%
        \swg@descmod\space\swg@meetname\space(\swg@s@graphnote)}
    \fi
  \else
    \swg@err{'\swg@fcourse' is not a legal course length for the event '\swg@fdist\space\swg@fstroke'^^J
\space at the meet '\swg@meetname' (must be 's' or 'l')}\swg@ehpa
  \fi\fi
  \global\swg@eventfoundfalse
}

% If file #1.tmp exists, transfer appropriate data from it to swgtime.tmp,
% read it into \swg@times, and plot it and label points if requested
  \def\swg@readplot#1#2{
    \IfFileExists{#1.tmp}{
      \readdata{\swg@times}{#1.tmp}
      \dataplot[plotstyle=line,linecolor=#2,linewidth=\swg@linewidth]%
        {\swg@times}
      \dataplot[plotstyle=dots,dotstyle=square*,linecolor=#2,%
         linewidth=\swg@linewidth]{\swg@times}
      \ifswg@plotlabel\swg@plotlabel{#1}\fi
      }{}
    }

% Puts labels (vertically) on swimmer's graph, getting them from file
% created by \swg@readdata
\def\swg@plotlabel#1{
  \endlinechar=-1
  \openin1=#1.tmp
  \openin2=#1d.tmp
  \loop
    \read1 to\@templine
    \read2 to\swg@desc
    \ifx\@templine\@empty
    \else
      \expandafter\swg@parsedatline\swg@desc\end
      \edef\swg@desc{\swg@datargii}
      \if\swg@datargi u
        \gdef\swg@labelpos{r}
        \gdef\swg@sign{-}
      \else\if\swg@datargi R
        \gdef\swg@labelpos{0}
        \gdef\swg@sign{}
      \else\if\swg@datargi r
        \gdef\swg@labelpos{l}
        \gdef\swg@sign{}
      \fi\fi\fi
% labelpos 0 means no label
      \if\swg@labelpos 0
      \else
        \expandafter\swg@parsedatline\@templine\end
        \pssetlength{\swg@lpos}{\swg@datargii}
        \psaddtolength{\swg@lpos}{\swg@sign\swg@labelvsep}
        \rput[\swg@labelpos]{90}(\swg@datargi,\swg@lpos)%
          {\color{\swg@labelcolor}\swg@labelfontsize\swg@desc}
      \fi
    \fi
    \ifeof1\relax\swg@continuefalse\else\swg@continuetrue\fi
    \ifswg@continue
  \repeat
  \closein1
  \closein2
  \endlinechar=13
  }

\def\swg@back{back}
\def\swg@breast{breast}
\def\swg@fly{fly}
\def\swg@free{free}
\def\swg@IM{IM}
\def\swg@FR{FR} % free relay
\def\swg@MR{MR} % medley relay

%-------------------------------------%
% SWIMGRAPH                           %
%-------------------------------------%
%
% \swimgraph[options]{distance stroke}{startdate}{enddate}{lowtime}{hightime}%
%                            #1           #2        #3       #4        #5
% options: any legal arguments for \psset
% distance: 50, 100, 200, 400, 800, 1500, 4x50, 4x100
% stroke: breast, fly, free, back, IM, FR, MR
% startdate: year-month-day
% enddate: year-month-day
% lowtime: lowest time for y axis, in seconds or minutes:seconds
% hightime: highest time for y axis, in seconds or minutes:seconds

\define@key{swimgraph}{xunit}{\psset{xunit=#1}}
\define@key{swimgraph}{yunit}{\psset{yunit=#1}}
\define@key{swimgraph}{framesep}{\psset{framesep=#1}}
\define@key{swimgraph}{nolabels}[true]{\swg@plotlabelfalse}
\define@key{swimgraph}{datafile}{\def\swg@datafile{#1}}
\define@key{swimgraph}{recordpath}{\def\swg@filepath{#1}}
\define@key{swimgraph}{wsccolor}{\def\swg@wsccolor{#1}}
\define@key{swimgraph}{wlccolor}{\def\swg@wlccolor{#1}}
\define@key{swimgraph}{xsccolor}{\def\swg@xsccolor{#1}}
\define@key{swimgraph}{xlccolor}{\def\swg@xlccolor{#1}}
\define@key{swimgraph}{ysccolor}{\def\swg@ysccolor{#1}}
\define@key{swimgraph}{ylccolor}{\def\swg@ylccolor{#1}}
\define@key{swimgraph}{zsccolor}{\def\swg@zsccolor{#1}}
\define@key{swimgraph}{zlccolor}{\def\swg@zlccolor{#1}}
\define@key{swimgraph}{jsccolor}{\def\swg@jsccolor{#1}}
\define@key{swimgraph}{jlccolor}{\def\swg@jlccolor{#1}}
\define@key{swimgraph}{nsccolor}{\def\swg@nsccolor{#1}}
\define@key{swimgraph}{nlccolor}{\def\swg@nlccolor{#1}}
\define@key{swimgraph}{asccolor}{\def\swg@asccolor{#1}}
\define@key{swimgraph}{alccolor}{\def\swg@alccolor{#1}}
\define@key{swimgraph}{bsccolor}{\def\swg@bsccolor{#1}}
\define@key{swimgraph}{blccolor}{\def\swg@blccolor{#1}}
\define@key{swimgraph}{csccolor}{\def\swg@csccolor{#1}}
\define@key{swimgraph}{clccolor}{\def\swg@clccolor{#1}}
\define@key{swimgraph}{dsccolor}{\def\swg@dsccolor{#1}}
\define@key{swimgraph}{dlccolor}{\def\swg@dlccolor{#1}}
\define@key{swimgraph}{esccolor}{\def\swg@esccolor{#1}}
\define@key{swimgraph}{elccolor}{\def\swg@elccolor{#1}}
\define@key{swimgraph}{fsccolor}{\def\swg@rsccolor{#1}}
\define@key{swimgraph}{flccolor}{\def\swg@flccolor{#1}}
\define@key{swimgraph}{sccolor}{\def\swg@sccolor{#1}}
\define@key{swimgraph}{lccolor}{\def\swg@lccolor{#1}}
\define@key{swimgraph}{labelcolor}{\def\swg@labelcolor{#1}}
\define@key{swimgraph}{monthlinecolor}{\def\swg@monthlinecolor{#1}}
\define@key{swimgraph}{yearlinecolor}{\def\swg@yearlinecolor{#1}}
\define@key{swimgraph}{oneseclinecolor}{\def\swg@oneseclinecolor{#1}}
\define@key{swimgraph}{fiveseclinecolor}{\def\swg@fiveseclinecolor{#1}}
\define@key{swimgraph}{labelfontsize}{\def\swg@labelfontsize{#1}}
\define@key{swimgraph}{keyvsep}{\def\swg@keyvsep{#1}}
\define@key{swimgraph}{monthvsep}{\def\swg@monthvsep{#1}}
\define@key{swimgraph}{yearvsep}{\def\swg@yearvsep{#1}}
\define@key{swimgraph}{titlevsep}{\def\swg@titlevsep{#1}}
\define@key{swimgraph}{labelvsep}{\def\swg@labelvsep{#1}}
\define@key{swimgraph}{tlabelpos}{\def\swg@tlabelpos{#1}}
\define@key{swimgraph}{linewidth}{\def\swg@linewidth{#1}}
\define@key{swimgraph}{reclinewidth}{\def\swg@reclinewidth{#1}}

\pagestyle{empty}

\def\swimgraph{%
   \@ifnextchar[{\swg@opt}{\swg@noopt}}

\def\swg@opt[#1]#2#3#4#5#6{%
%   \psset{#1}
  \setkeys{swimgraph}{#1}
% set unit equal to yunit (so that \pssetlength uses psyunit---used to
% position labels and titles).
   \let\psunit=\psyunit
   \swg@main{#2}{#3}{#4}{#5}{#6}}

\def\swg@noopt#1#2#3#4#5{\swg@main{#1}{#2}{#3}{#4}{#5}}

\def\swg@main#1#2#3#4#5{%
% default: short course
  \def\swg@fcourse{s}
  \def\swg@s@graphnote{}
%
%.....................................%
% Basic set up                        %
%.....................................%
%
% start date
  \swg@date #2 
  \swg@age=\swg@year
  \swg@startday=\swg@daycount
  \swg@startdiy=\swg@diycount
  \swg@startyear=\swg@year
%
% end date
  \swg@date #3 
  \swg@endage=\swg@year
  \swg@endday=\swg@daycount
  \swg@enddaycount=\swg@daycount
  \swg@enddiy=\swg@diycount
  \advance\swg@endday by-\swg@startday

%\typeout{Endday: \the\swg@endday}
%
  \ifnum\swg@startday>\swg@enddaycount
    \swg@err{Starting date is after ending date}\swg@ehpc
  \fi

% open data file and get swimmer's name and date of birth 
% (for use with records)
  \openin1=\swg@datafile
  \endlinechar=-1
% first line is comment---ignored
  \read1 to\swg@fileline
% second line is swimmer's name
  \read1 to\swg@name
% third line is swimmer's name
  \read1 to\swg@sex
% fourth line is swimmer's date of birth
  \read1 to\swg@dob
  \endlinechar=13
  \closein1

  \typeout{Swimmer's name: \swg@name.  Date of birth: \swg@dob.}

% swimmer's birthdate
  \expandafter\swg@date \swg@dob {}
  \swg@bdaydiy=\swg@diycount
  \def\swg@bday{\the\swg@diycount}
  \advance\swg@age by-\swg@year
  \ifnum\swg@startdiy<\swg@diycount\advance\swg@age by-1\fi
  \advance\swg@endage by-\swg@year
  \ifnum\swg@enddiy<\swg@diycount\advance\swg@endage by-1\fi

  \swg@parsedatline#1\end
  \let\swg@dist=\swg@datargi
  \let\@@swimstroke=\swg@datargii

  \ifx\@@swimstroke\swg@breast\def\swg@stroke{breast stroke}%
    \def\swg@strokex{ breast}
  \else\ifx\@@swimstroke\swg@fly\def\swg@stroke{butterfly}%
    \def\swg@strokex{ fly}
  \else\ifx\@@swimstroke\swg@free\def\swg@stroke{freestyle}%
    \def\swg@strokex{ free}
  \else\ifx\@@swimstroke\swg@back\def\swg@stroke{backstroke}%
    \def\swg@strokex{ back}
  \else\ifx\@@swimstroke\swg@IM\def\swg@stroke{IM}%
    \def\swg@strokex{ IM}
  \else\ifx\@@swimstroke\swg@FR\def\swg@stroke{Free Relay}%
    \def\swg@strokex{ FR}
  \else\ifx\@@swimstroke\swg@MR\def\swg@stroke{Medley Relay}%
    \def\swg@strokex{ MR}
  \else
    \swg@err{What stroke is '\@@swimstroke'?\space\space  I don't know it}\swg@ehpc
  \fi\fi\fi\fi\fi\fi\fi

  \def\swg@t{#4}
  \expandafter\swg@tosecso\swg@t\relax
  \swg@ltime=\swg@timeresult

  \def\swg@t{#5}
  \expandafter\swg@tosecso\swg@t\relax
  \swg@htime=\swg@timeresult

  \pssetlength{\swg@monthbaseh}{\the\swg@ltime\psyunit}
  \psaddtolength{\swg@monthbaseh}{-\swg@monthvsep}

% number of light lines
  \swg@lghlines=\swg@htime
  \advance\swg@lghlines by-\swg@ltime

% number of heavy lines (5 second intervals)
  \swg@hvylines=\swg@lghlines
  \divide\swg@hvylines by5

  \swg@midy=\swg@htime
  \advance\swg@midy by\swg@ltime
  \divide\swg@midy by2

%.....................................%
% Beginning of \pspicture             %
%.....................................%
  \pssetlength{\swg@top}{\swg@htime}
  \psaddtolength{\swg@top}{\swg@keyvsep}
% \swg@top isn't quite right---equal to middle height of key, so add a bit
  \psaddtolength{\swg@top}{1.6mm}
  \pssetlength{\swg@bottom}{\swg@ltime}
  \psaddtolength{\swg@bottom}{-\swg@monthvsep}
  \psaddtolength{\swg@bottom}{-\swg@yearvsep}
  \psaddtolength{\swg@bottom}{-\swg@titlevsep}

  \vspace*{\fill}

  \begin{center}
% \fbox for debugging size of picture
% \fboxsep 0pt
% \fbox{
  \begin{pspicture}(-\swg@tlabelpos,\swg@bottom)(\swg@endday,\swg@top)
%.....................................%
% Horizontal lines on graph and axes  %
%.....................................%
% Lines every second
  \multido{\i=\swg@ltime+1}{\swg@lghlines}%
    {\psline[linecolor=\swg@oneseclinecolor,linewidth=0.4pt]%
      (0,\i)(\swg@endday,\i)}
% Lines at multiples of 5 second
  \swg@lhvytime=\swg@ltime
  \divide\swg@lhvytime by 5
  \multiply\swg@lhvytime by 5
  \advance\swg@lhvytime by 5
  \multido{\i=\swg@lhvytime+5}{\swg@hvylines}%
    {\psline[linecolor=\swg@fiveseclinecolor]%
      (0,\i)(\swg@endday,\i)}
% Axes
  \psaxes[axesstyle=frame,Dx=50,Oy=\the\swg@lhvytime,Dy=5,%
    tickstyle=bottom,labels=y,ticks=y]%
    (0.5,\swg@lhvytime)(0.5,\swg@ltime)(\swg@endday,\swg@htime)
% Because of the offset in \psaxes, so that it starts numbering at the
% right point, we won't get a line at the lowest time, so put one
  \psline(\swg@endday,\swg@htime)(\swg@endday,\swg@ltime)%
(0.5,\swg@ltime)(0.5,\swg@htime)

%...................................................................%
% Vertical lines indicating month divisions; month and year labels  %
%...................................................................%
% Arguments of \swg@putmonth: month name, # of days in month,
% # of days in year to 1st day of month.
% Goes through loop till December, but \swg@putmonth does something only
% if endday hasn't been reached.
  \@tempcntb=\swg@startdiy
  \@tempcntc=0   % x-coordinate
  \@tempcntx=0   % x-coordinate of beginning of year
  \@tempcntd=\swg@startday
  \@tempcntyr=\swg@startyear
% If startdiy > 335, no month label (not even Dec) will be printed, so first
% year printed will be next year
  \ifnum\@tempcntb>335\advance\@tempcntyr by1\fi
  \loop
    \ifnum\@tempcntb<2\swg@putmonth{Jan}{31}{0}\fi
    \ifnum\@tempcntb<33\swg@putmonth{Feb}{28}{31}\fi
    \ifnum\@tempcntb<61\swg@putmonth{Mar}{31}{59}\fi
    \ifnum\@tempcntb<92\swg@putmonth{Apr}{30}{90}\fi
    \ifnum\@tempcntb<122\swg@putmonth{May}{31}{120}\fi
    \ifnum\@tempcntb<153\swg@putmonth{Jun}{30}{151}\fi
    \ifnum\@tempcntb<183\swg@putmonth{Jul}{31}{181}\fi
    \ifnum\@tempcntb<214\swg@putmonth{Aug}{31}{212}\fi
    \ifnum\@tempcntb<245\swg@putmonth{Sep}{30}{243}\fi
    \ifnum\@tempcntb<275\swg@putmonth{Oct}{31}{273}\fi
    \ifnum\@tempcntb<306\swg@putmonth{Nov}{30}{304}\fi
    \ifnum\@tempcntb<336\swg@putmonth{Dec}{31}{334}\fi
    \ifnum\@tempcntb<367\swg@putmonth{}{31}{365}
% Year label
      \@tempcnty=\@tempcntc
      \swg@mid=\@tempcnty\advance\swg@mid by\@tempcntx
      \divide\swg@mid by2
      \@tempcntz=\@tempcnty\advance\@tempcntz by-\@tempcntx
% put yr label only if at least 30 days of yr present and x=0 or at least
% 32 days of year present (case of Jan at end of plot)
      \ifnum\@tempcntz>29\ifnum\@tempcntx=0\relax\swg@putyrtrue\fi\fi
      \ifnum\@tempcntz>31\relax\swg@putyrtrue\fi
      \ifswg@putyr
        \pssetlength{\swg@labelh}{\swg@monthbaseh}
        \psaddtolength{\swg@labelh}{-\swg@yearvsep}
        \rput[B](\swg@mid,\swg@labelh){\textbf{\the\@tempcntyr}}
      \fi
      \swg@putyrfalse
      \advance\@tempcntyr by 1\fi
    \ifnum\@tempcntd<\swg@enddaycount
       \@tempcntx=\@tempcnty
       \advance\@tempcntb by-365
  \repeat

%..........%
% Records  %
%..........%
  \typeout{Event: \swg@dist\swg@strokex}
% Age-independent standards/records
% National record
  \ifswg@n\swg@recline{n}{\swg@dist\swg@strokex}{0}{\the\swg@endday}\fi
% World record
  \ifswg@w\swg@recline{w}{\swg@dist\swg@strokex}{0}{\the\swg@endday}\fi
% Other records
  \ifswg@j\swg@recline{j}{\swg@dist\swg@strokex}{0}{\the\swg@endday}\fi
  \ifswg@x\swg@recline{x}{\swg@dist\swg@strokex}{0}{\the\swg@endday}\fi
  \ifswg@y\swg@recline{y}{\swg@dist\swg@strokex}{0}{\the\swg@endday}\fi
  \ifswg@z\swg@recline{z}{\swg@dist\swg@strokex}{0}{\the\swg@endday}\fi

% Age-dependent standards/records
  \ifswg@a\swg@agerectrue\swg@agerecline{a}\fi
  \ifswg@b\swg@agerectrue\swg@agerecline{b}\fi
  \ifswg@c\swg@agerectrue\swg@agerecline{c}\fi
  \ifswg@d\swg@agerectrue\swg@agerecline{d}\fi
  \ifswg@e\swg@agerectrue\swg@agerecline{e}\fi
  \ifswg@f\swg@agerectrue\swg@agerecline{f}\fi

  \swg@agerecfalse

%...........................%
% Graph of swimmer's times  %
%...........................%
% Read swimmer's times from file
  \swg@readdata{\swg@dist}{\@@swimstroke}

% Plot times
  \swg@i=1
  \loop
    \swg@readplot{swgs\the\swg@i}{\swg@sccolor}
    \swg@readplot{swgl\the\swg@i}{\swg@lccolor}
    \ifnum\swg@i<4\advance\swg@i by1
  \repeat

%..........................................%
% Key at top and labels at side and bottom %
%..........................................%
  \divide\swg@endday by2
  \pssetlength{\swg@keyh}{\the\swg@htime\psyunit}
  \addtolength{\swg@keyh}{\swg@keyvsep}

% key giving SC and LC colors---on top of graph
  \def\swg@key{
    \psline[linecolor=\swg@sccolor,linewidth=\swg@linewidth](-45,0)(-25,0)
    \rput*[l](-23,0){SC}
    \psline[linecolor=\swg@lccolor,linewidth=\swg@linewidth](7,0)(27,0)
    \rput*[l](29,0){LC}
    }

  \rput(\swg@endday,\swg@keyh){\swg@key}

% label at side
  \rput{90}(-\swg@tlabelpos,\swg@midy){time}

% label at bottom
  \psaddtolength{\swg@labelh}{-\swg@titlevsep}
  \rput[B](\the\swg@endday,\swg@labelh)%
    {\large\textbf{\swg@name's times for {\swg@dist}m \swg@stroke}}

  \end{pspicture}
% } % end of \fbox
  \end{center}

  \vspace*{\fill}

}

%-------------------------------------%
% SWIMTEXT                            %
%-------------------------------------%

% Formats details of result (giving winning time, winner, etc. as specified
% in data file
\def\swg@makeresult{
% convert times to mins:secs.msecs.
  \expandafter\swg@tominssecs\swg@ftime\relax
% CANNOT write \let\swg@ftime=\swg@timeresult on next line (why not??)
  \let\swg@xtime=\swg@timeresult
% start of item
  \item[\swg@fdist m \swg@fstroke
  \ifx\swg@s@age\@empty\else\ (\swg@s@age)\fi
  \if\swg@fcourse s
   (S):
  \else\if\swg@fcourse l
   (L):
  \else
  \typeout{Note: '\swg@fcourse' is unknown course length (must be 's' or 'l'}
  \fi\fi
  ] \swg@xtime
  \ifx\swg@s@place\@empty
  \else
    \ \ -\ \ \swg@s@place
  \fi
  \ifx\swg@s@ageplace\@empty
  \else
    \ (\swg@s@ageplace)
  \fi
  \ifx\swg@s@type\@empty
  \else
    \par \swg@s@type
  \fi
  \ifx\swg@s@wintime\@empty
  \else
    \par Winning time: \swg@s@wintime.
  \fi
  \ifx\swg@s@first\@empty
  \else
    \par First: \swg@s@first.
  \fi
  \ifx\swg@s@second\@empty
  \else
    \ifx\swg@s@first\@empty
      \par
    \fi
    Second: \swg@s@second.
  \fi
  \ifx\swg@s@third\@empty
  \else
    \ifx\swg@s@first\@empty
      \ifx\swg@s@second\@empty
        \par
    \fi\fi
    Third: \swg@s@third.
  \fi
  \ifx\swg@s@fourth\@empty
  \else
    \ifx\swg@s@first\@empty
      \ifx\swg@s@second\@empty
        \ifx\swg@s@third\@empty
        \par
    \fi\fi\fi
    Fourth: \swg@s@fourth.
  \fi
  \ifx\swg@s@other\@empty
  \else
    \par \swg@s@other
  \fi%
  \global\swg@eventfoundfalse
}

% Output any pending result and get new result details.
% Called by \swimtext.
\def\swg@eventx{%
% Output any accumulated result
  \ifswg@eventfound\swg@makeresult\fi
  \expandafter\swg@parseresultline\swg@content\end
  \global\swg@eventfoundtrue
  \gdef\swg@s@place{}
  \gdef\swg@s@ageplace{}
  \gdef\swg@s@wintime{}
  \gdef\swg@s@first{}
  \gdef\swg@s@second{}
  \gdef\swg@s@third{}
  \gdef\swg@s@fourth{}
  \gdef\swg@s@type{}
  \gdef\swg@s@other{}
}

\define@key{swimtext}{datafile}{\def\swg@datafile{#1}}

% Main text macro, which produces a document using the information in the
% data file.

\def\swimtext{%
   \@ifnextchar[{\swg@textopt}{\swg@textnoopt}}

\def\swg@textopt[#1]#2#3{%
  \setkeys{swimtext}{#1}
  \swg@textmain{#2}{#3}}

\def\swg@textnoopt#1#2{\swg@textmain{#1}{#2}}

\def\swg@textmain#1#2{%
% default: short course
  \def\swg@fcourse{s}
  \def\swg@s@age{}

% start date
  \swg@date #1 
  \swg@age=\swg@year
  \swg@startday=\swg@daycount
  \swg@startdiy=\swg@diycount
  \swg@startyear=\swg@year

% end date
  \swg@date #2 
  \swg@endage=\swg@year
  \swg@endday=\swg@daycount
  \swg@enddaycount=\swg@daycount
  \swg@enddiy=\swg@diycount
  \advance\swg@endday by-\swg@startday

  \ifnum\swg@startday>\swg@enddaycount
    \swg@err{Starting date is after ending date}\swg@ehpc
  \fi

  \endlinechar=-1
  \openin0=\swg@datafile
% first line is comment
  \read0 to\swg@fileline
  \read0 to\swg@name
  \read0 to\swg@sex
  \read0 to\swg@dob

  \begin{center}\large\textbf{\swg@name's times at meets between\\#1 and #2}\end{center}

  \global\swg@eventfoundfalse
  \loop
    \read0 to\swg@fileline
% Next line necessary because blank line is read at end of file, before
% \ifeof0 is true.  It also allows all lines starting % to be ignored.
    \ifx\swg@fileline\@empty
    \else
      \expandafter\swg@parsedataline\swg@fileline\end
      \if\swg@switch m
% Get meet name and store it.  Don't output anything yet, because don't
% know if date is in range---output occurs after date is read.
        \global\let\swg@meetname=\swg@content
        \global\swg@nmntrue
      \else\if\swg@switch M
        \global\let\swg@meetname=\swg@content
      \else\if\swg@switch d
        \global\let\swg@meetdate=\swg@content
%\typeout{Date: \swg@meetdate}
        \expandafter\swg@date \swg@meetdate {}
        \swg@inrangefalse % till proved otherwise
        \global\swg@nmdtrue
% If date is in right range, continue
        \ifnum\swg@daycount>\swg@startday
          \ifnum\swg@daycount<\swg@enddaycount
            \global\swg@inrangetrue
            \ifswg@nmn
% Output any accumulated result
              \ifswg@eventfound\swg@makeresult\fi
              \ifswg@indescription
                \end{swgdescription}
                \global\swg@indescriptionfalse
              \fi
              \section*{\swg@meetname}\swg@nmnfalse
            \fi
            \ifswg@nmd
              \ifswg@eventfound\swg@makeresult\fi
              \ifswg@indescription
                \end{swgdescription}
                \global\swg@indescriptionfalse
              \fi
              \subsection*{\swg@meetdate}\swg@nmdfalse
            \fi
            \begin{swgdescription}
            \global\swg@indescriptiontrue
          \fi
        \else\typeout{Date \swg@meetdate\space ignored because out of requested range}
        \fi
      \else\if\swg@switch r
        \ifswg@inrange\swg@eventx\fi
      \else\if\swg@switch u
        \ifswg@inrange\swg@eventx\fi
      \else\if\swg@switch R
        \ifswg@inrange\swg@eventx\fi
      \else\if\swg@switch x
        \ifswg@inrange\swg@eventx\fi
      \else\if\swg@switch a
        \global\let\swg@s@age=\swg@content
      \else\if\swg@switch c
        \global\let\swg@fcourse=\swg@content
      \else\if\swg@switch o
        \let\swg@s@other=\swg@content
      \else\if\swg@switch t
        \let\swg@s@type=\swg@content
      \else\if\swg@switch p
        \let\swg@s@place=\swg@content
      \else\if\swg@switch P
        \let\swg@s@ageplace=\swg@content
      \else\if\swg@switch w
        \let\swg@s@wintime=\swg@content
      \else\if\swg@switch 1
        \let\swg@s@first=\swg@content
      \else\if\swg@switch 2
        \let\swg@s@second=\swg@content
      \else\if\swg@switch 3
        \let\swg@s@third=\swg@content
      \else\if\swg@switch 4
        \let\swg@s@fourth=\swg@content
      \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
    \fi
    \ifeof0\relax\swg@continuefalse\else\swg@continuetrue\fi
    \ifswg@continue%
  \repeat%
% Output any accumulated result
  \ifswg@eventfound\swg@makeresult\fi
  \ifswg@indescription
    \end{swgdescription}
  \fi
  \endlinechar=13
  \closein0

}