\def\musecs{$\mu$secs} \itemwidth=.25in @ \section{Archery Database: {\tt AddScore}} This perl script adds a score (or scores) to the archery database. It provides only a basic user interface. <>= <> <
> <> @ \section{Setting up the database and script} Because much of the code is shared between this family of scripts, some of the code is in subroutine files. We [[require]] these. <>= require "custom" || die "can't open custom routines library"; require "archsubs" || die "can't open subroutines library"; @ %def &readrounds &init Early versions of this script allowed you to abort an entry by not typing anything at a prompt. However this became cumbersome when only the third prompt would let you do this. So we now trap [[SIGINT]] and point it to the same abort routine. <>= $SIG{'INT'}='abort'; @ %def $SIG We need know what date it is today (for the default database and date) so we get this from the operating system via the [[gmtime()]] call. <>= $start=time; ($ts,$tmi,$th,$tmd,$tmo,$ty,@junk)=gmtime($start); @ %def $start $ts $tmi $th $tmd $tmo $ty @junk | $start gmtime() Now we read in the rounds database, and open the relevant dbm file for the archery database. [[&init]] handles the command line options that relate to the person and year that are asked for. <>= &readrounds; do &init; @ %def | &readrounds &init \section{The main body of the program} The main part of the program justs loops asking the user for a score to be entered and then prompting for another loop. Unfortunately, we still treat dates as strings (due to problems in the conversion of dates to \musecs\ and back) so all this data cannot be accessed by date order. \subsection{Outline of main loop} <>= while(1) { <> <> <> <> <> } @ We close the dbm database explicitly here, just to be on the safe side. <>= dbmclose(scores); @ \subsection{Entering the date} <>= dateloop: while(1) { print "Enter date ($tmd-$tmo-$year) - "; $date=scalar(); chop $date; $date=join('-',$tmd,$tmo) unless $date; if($date=~/(\d{1,2})-(\d{1,2})/) { $dt_ntrd=1; $dindex=sprintf("%02d:%02d:%04d",$1,$2,$year); $usecs=&retime($1,$2,$year); ($xts,$xtmi,$xth,$xtmd,$xtmo,$xty,@junk)=gmtime($usecs); printf "%02d-%02d-%04d\n",$xtmd,$xtmo,$xty; last dateloop; } else { print "invalid date\n"; } } @ %def dateloop: $date $dt_ntrd $dindex $usecs $xts $xtmi $xth $xtmd $xtmo $xty @junk | STDIN &retime() gmtime() \subsection{Entering the round} <>= $round=&getround; ($rtype,@rdists)=split(/,/,@rounds{$round}); $mult=($rtype='y'?9:10); @ %def $round @rdists $mult | $rtype @rounds{} &getround \subsection{Entering the score} <>= until(defined($sc_ntrd)) { print 'Enter scores (100,100,100) - '; $sclist=scalar(); chop $sclist; &abort unless $sclist; @rscores=split(/,/,$sclist); if(2*$#rscores==$#rdists-1) {$sc_ntrd=1;} else { print "wrong number of scores\n"; } for($i=0;$i<=$#rscores;$i++) { $ms=@rdists[2*$i]*$mult; if(@rscores[$i]>$ms) { printf "invalid: %d>possible ($ms)\n",@rscores[$i]; $sc_ntrd=$undefined; } } } @ %def $sclist @rscores $ms $sc_ntrd | STDIN $mult @rdists $undefined \subsection{Storing the data} The dbm entries are created in a fairly naive fashion at the moment. The round name and scores are turned into a CSV string. Future versions will almost certainly use templates and packing to reduce the amount of information that is stored. <>= $entry=join(',',$round,@rscores); @scores{$dindex}=$entry; @ %def $entry @scores | $round @rscores $dindex \subsection{Prompt the user} Now we prompt the user to see if they want to enter another score. The default answer (ie just pressing [[RETURN]]) is yes on the assumption that more than one score will be entered at a time. It will be changed so that a score entered with today's date will change the default to no on the assumption that the rest of the database is up to date. <>= $loopagain=&yesno("Another score",'y'); last unless $loopagain; undef $sc_ntrd; @ %def $loopagain | &yesno() $sc_ntrd \section{Subroutines} \subsection{[[retime]]} This subroutine is supposed to convert a date in dd-mm-yyyy form into the number of \musecs\ since 1-1-1970, but it sometimes gets it mysteriously wrong, so we don't use it for indexing yet. <>= sub retime { local($d,$m,$y)=@_; local($wm,$md,$yd); $wm=$m-3; if($wm<0) { $wm+=12; $y--; } # modified month number $md=int(30.6*$wm+.5); # month day $yd=int(365.25*($y-1970)+$md+$d)+60; # actual day number 86400*$yd; } @ %def $d $m $y $wm $md $yd \section{Things to do} \itemize \item The way the rounds are stored and accessed needs to be changed. `Compiling' the rounds into a more compact form would save space, and possibly make things a little faster. \item A better user interface would also be a good idea. Possibly making the program run under a different screen mode for larger text. \item Adding a confirm just before the data is inserted into the dbm database. \enditemize \chapter{Variables} \printindex{ids} \chapter{Modules} \printindex{mods}