/******************************************************************************
*
* This program prints out the NBA schedule for any day in the 1993-1994
* NBA regular season.  The program has evolved over the years (see the
* acknowledgements section below) to become a (somewhat) flexible program.
*
* By default, the current day's schedule is printed.  One can also
* specify one or more dates on the command line and get the schedule for  
* that/those date(s).  Any national TV coverage (TNT and NBC) along with     
* the game tip-off time is also listed.
*
*
* USAGE
*
*	nba [-s] [-s team] [team] [-m team1 team2] [mm/dd... | all | end]
*
*	Examples:
*	 nba                         <- today's games
*	 nba 12/25 1/1               <- games on Christmas and New Years
*	 nba -s                      <- summary for the next week
*	 nba -s 11/5                 <- summary for the first week of season
*	 nba -s celtics              <- Boston summary for the next week
*	 nba -m chicago lakers end   <- Chicago/LA games for the rest of season
*	 nba Magic all               <- Orlando's full season schedule
*
*	 nba -help (or -h or -?)     <- print help message.
*
*	Team names can be either the team nickname (Knicks) or the city.
*	City names with spaces can either be put in quotes ("New York")
*	or entered as a single word without spaces (NewYork)
*
*
* COMPILING
*
* Compilinge should be easy... "cc -o nba nba.c"                                
*
* Before compiling the program there are a couple things to check...
*
* 1) The tip-off times are normalized in the matrix to the Eastern time zone.
*    To change the time to show either Central, Mountain, or Pacific time zone
*    just change the "TZ_FIX" #define in the code before compiling (other time
*    zones are not supported...sorry).                                           
*
* 2) The team names can be printed out as either a City (Boston) or as the
*    team's nickname (Celtics).  Check the "TEAMNAME" #define in the code.
*
*    (Note: when entering a team name to get specific team schedules you can
*    use either the city name or the nickname regardless of the TEAMNAME
*    #define).
*
* 3) The program is set up to include national TV coverage on NBC and TNT
*    as well as "superstations".  Unfortunately, not everybody gets TNT
*    and/or superstations (and I guess there are some who don't get NBC
*    either).  To take this into account you can disable the display of
*    individual networks.  To do this go down to the "tv_coverage[]"
*    structure and edit the "0" and "1" entries in the first column of
*    each line.  A "0" entry indicates that you wish to have that TV
*    coverage printed, a "1" means don't bother.
*
*    (Note: I sent out a couple requests for "superstation" information
*    but only received (useful) responses about WGN out of Chicago).
*   
*
* Brought to you again this year by:                                      
*
* =============================================================================
*    /     ___/   \   /	|| Len Carr, (908) 615-6072, len@mt747.att.com
*   /     __/        /	|| AT&T CellRelay Systems, Holmdel Corporate Plaza
* ____/ ____/ __/ __/	|| 2137 Highway 35 North, Holmdel, NJ 07733
* =============================================================================
*
* ACKNOWLEDGEMENTS
*	I make no claims that every piece of code include here is my own...
*	unfortunately I did not keep track of exactly what enhancements
*	specific people have added over the four (or five) years that I've
*	been doing this program.  The following people have contributed
*	various enhancements to my original source for the program.  Without
*	their efforts, the program would not be anywhere near as flexable
*	(or popular) as it has turned out to be...
*
*			Toshio Hori (toshi@nml.t.u-tokyo.ac.jp)
*			Dan Kinney (dkinney@bothell.sgi.com)
*			Dennis P. Joyce (dpj4303@ritvax.rit.edu)
*			King-Ip Lin (kilin@wam.umd.edu)
*			Mike Northam (mbn@greyskul.hf.intel.com)
*
******************************************************************************/

#include  <stdio.h>
#include  <string.h>
#include  <ctype.h>
#include  <time.h>

/****************************************************************************
* All times in the schedule matrix are based on the Eastern time zone.
* To change to one of the other three below, comment out the Eastern
* entry and un-comment the desired one.
****************************************************************************/
#define TZ_FIX  0 /* Eastern */
/* #define TZ_FIX 2 /* Central */
/* #define TZ_FIX 4 /* Mountain */
/* #define TZ_FIX 6 /* Pacific */

/****************************************************************************
* Structure to contain information about team names.  The first entry is
* used for "long form" schedules.  The second entry is used for summary
* displays.  The third entry is used for a more "friendly" long form of
* the schedule.  If the "TEAMNAME" define is set to "1" then the team
* names will be used instead of the city.
****************************************************************************/
/* #define TEAMNAME 0	/* Use team city (Boston) instead of name (Celtics) */
#define TEAMNAME 1	/* Use team name (Celtics) instead of city (Boston) */
struct	{
	char	*longname;
	char	*summary;
	char	*teamname;
} teams[] = {
	{"Atlanta",		"Atl",	"Hawks"},
	{"Boston",		"Bos",	"Celtics"},
	{"Charlotte",		"Cha",	"Hornets"},
	{"Chicago",		"Chi",	"Bulls"},
	{"Cleveland",		"Cle",	"Cavaliers"},
	{"Dallas",		"Dal",	"Mavericks"},
	{"Denver",		"Den",	"Nuggets"},
	{"Detroit",		"Det",	"Pistons"},
	{"Golden State",	"GS",	"Warriors"},
	{"Houston",		"Hou",	"Rockets"},
	{"Indiana",		"Ind",	"Pacers"},
	{"LA Clippers",		"LAC",	"Clippers"},
	{"LA Lakers",		"LAL",	"Lakers"},
	{"Miami",		"Mia",	"Heat"},
	{"Milwaukee",		"Mil",	"Bucks"},
	{"Minnesota",		"Min",	"Timberwolves"},
	{"New Jersey",		"NJ",	"Nets"},
	{"New York",		"NY",	"Knicks"},
	{"Orlando",		"Orl",	"Magic"},
	{"Philadelphia",	"Phi",	"76ers"},
	{"Phoenix",		"Pho",	"Suns"},
	{"Portland",		"Por",	"Trailblazers"},
	{"Sacramento",		"Sac",	"Kings"},
	{"San Antonio",		"SA",	"Spurs"},
	{"Seattle",		"Sea",	"Supersonics"},
	{"Utah",		"Uta",	"Jazz"},
	{"Washington",		"Was",	"Bullets"},
	{"All Star Break",	"ASB",	"All Star Break"},
	{"All Star Game",	"ASG",	"All Star Game"},
	{"",			"",	""}
};

/****************************************************************************
* Structure to contain information about "home" games played at an
* alternate game site.  The first entry is used for "long form"
* schedules while the second entry is used for summary displays.
****************************************************************************/
#define NUM_ALT_SITES	2
struct	{
	char	*alt_site;
	char	*summary;
} alternate_site[] = {
	{"(in Baltimore)",	"b = Game played in Baltimore"},
	{"(in Hartford)",	"h = Game played in Hartford"},
	{"",			""}
};

/****************************************************************************
* Fairly static set of game start times...the actual times displayed in
* the "long form" schedules use these entries modulated by "TZ_FIX".
****************************************************************************/
char  *game_time[] = {
	"(9:00 am)",	"(9:30 am)",	"(10:00 am)",	"(10:30 am)",
	"(11:00 am)",	"(11:30 am)",	"(12:00 Noon)",	"(12:30 pm)",
	"(1:00 pm)",	"(1:30 pm)",	"(2:00 pm)",	"(2:30 pm)",
	"(3:00 pm)",	"(3:30 pm)",	"(4:00 pm)",	"(4:30 pm)",
	"(5:00 pm)",	"(5:30 pm)",	"(6:00 pm)",	"(6:30 pm)",
	"(7:00 pm)",	"(7:30 pm)",	"(8:00 pm)",	"(8:30 pm)",
	"(9:00 pm)",	"(9:30 pm)",	"(10:00 pm)",	"(10:30 pm)",	""
};

/****************************************************************************
* TV coverage structure.  This structure is set up to provide information
* about national TV coverage.  The structure can "easily" be expanded to
* contain up to 10 TV stations.
*
* The first entry is a boolean indication of whether or not to print this
* particular station (hey, if I'm a poor schmuck in a whole in the wall town
* like Pittsfield, NH then I may not want to print out stuff off of TNT!  To
* change the value enter a "0" to print TV information for that network and
* enter "1" to ignore that network's TV coverage.
*
* The second entry is used for "long form" schedules while the third
* entry is used for the summary display.
****************************************************************************/
#define	NUM_TV	5
struct	{
	int	printit;
	char	*network;
	char	*summary;
} tv_coverage[] = {
	/* 0 */		{0, "(TNT)",	"T = Game broadcast on TNT"},
	/* 1 */		{0, "(TNT*)",	"t = Game may be broadcast on TNT"},
	/* 2 */		{0, "(NBC)",	"N = Game broadcast on NBC"},
	/* 3 */		{0, "(NBC*)",	"n = Game may be broadcast on NBC"},
	/* 4 */		{1, "(WGN)",	"G = Game broadcast on WGN"},
	/* 5 */		{1, "",		""} /* Always leave this one blank */
};

/****************************************************************************
* Psuedo-static day-of-the-week/day-of-the-year type stuff.  This is mostly
* used to determine where to find dates like 2/17 in the schedule matrix
* described later.
****************************************************************************/
int days[] = {
     31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  /* jan feb mar apr may jun jul aug sep oct nov dec */
};
struct	{
	char	*longform;
	char	*summary;
} weekday[] = {
	"Friday",	"FR",
	"Saturday",	"SA",
	"Sunday",	"SU",
	"Monday",	"MO",
	"Tuesday",	"TU",
	"Wednesday",	"WE",
	"Thursday",	"TH"
};

/******************************************************************************
* Schedule matrix...each character string represents one day in the life of
* the NBA for the 1993-1994 season.  There are 27 different teams in the NBA
* (plus entries for the All Star break) represented by the characters "a-z",
* "{", "|", and "} and correspond to the "nba_teams" array above.
*
* In general the matrix can be viewed as visitor/home/time triplet where the
* first entry is the visiting team, the second is the home team, and the
* third is the tip-off time.  This 3 character set is modified slightly in
* order to store any TV coverage and "alternate home site" information.
*
* If there is a digit between the visitor and the home team then we look in
* the "alternate_site" array for the actual location that the game is being
* played.
*
* If there is a digit after the tip-off time then the "tv_coverage" array is
* checked to see whether NBC, TNT or a superstation are broadcasting the game.
******************************************************************************/
char  *nba_schedule[] = {
	/* 11/5  (001) */	"kaTrbTdcU0oeTphUqjVvlZumZ0snU{tTgwZixVfzW",
	/* 11/6  (002) */	"ndV4ifVhkTcoWzpUtsTmyYb{T",
	/* 11/7  (003) */	"reSlgWwuWjvZqxV",
	/* 11/8  (004) */	"obTadV4yzW",
	/* 11/9  (005) */	"ceTqfV{hTjiZulZvmZtrTksTpxVgyY",
	/* 11/10 (006) */	"doVbtU0xuWmwZazWr{T",
	/* 11/11 (007) */	"scTpjVhlZonTkqTeyY",
	/* 11/12 (008) */	"cbTeiZrkU0gmZfpUnsTavZxwZ0hzWt{T",
	/* 11/13 (009) */	"bdV4zfVigWujVxlZtqTorTayY",
	/* 11/14 (010) */	"emZwqShvU",
	/* 11/15 (011) */	"jtT",
	/* 11/16 (012) */	"waTrfVxgWuiZckTlmZpoVjqTzsTevZdyU0",
	/* 11/17 (013) */	"qbTwcTshTznTatTrxVo{T",
	/* 11/18 (014) */	"egWmiZjkTflZdvZ4",
	/* 11/19 (015) */	"sbT{cU0xhUdmZanTwpUztTvuWfyY",
	/* 11/20 (016) */	"caTyiZljVbkTxoWgpUsqTzrVeuWn0{T",
	/* 11/21 (017) */	"thSmqSfvZdwW",
	/* 11/22 (018) */	"k1bTnrTlxV",
	/* 11/23 (019) */	"maTlfVdjVisU0gvZc{T",
	/* 11/24 (020) */	"mcT{eTbhTtkTinTaoVqpUguWywZdxV4jzW",
	/* 11/25 (021) */	"",
	/* 11/26 (022) */	"{aTnbTocTdfV4vgWmkTypUitTjwZqzW",
	/* 11/27 (023) */	"taTyeTqgWjlZcnTboWmpUhrGzuWfxVs{T",
	/* 11/28 (024) */	"ihSwvZ",
	/* 11/29 (025) */	"qlZkwZoxV",
	/* 11/30 (026) */	"baTudU0heTfiZojVvnTytTgzW",
	/* 12/1  (027) */	"{bTxcTklZfmZeqTvsTpwZ",
	/* 12/2  (028) */	"uhTpiZjrTkzUy{T",
	/* 12/3  (029) */	"jaTvbTofVcgZ0dnTuqTxsU0",
	/* 12/4  (030) */	"seTkiZmlZwrGxtTpyYczWv{T",
	/* 12/5  (031) */	"jeSfgWpmZuoV",
	/* 12/6  (032) */	"{yYrzW",
	/* 12/7  (033) */	"ldVveTnfVgiZcjVwkTrmZbqU0hsT",
	/* 12/8  (034) */	"wbTahTloVvpUdtTyxV{zW",
	/* 12/9  (035) */	"xaTecTyfVriZnjVskT{uW",
	/* 12/10 (036) */	"zgWohU0lpUdqTbsTwtTmvZ",
	/* 12/11 (037) */	"qcTedV4ufVziZyjVbnTtoWhpUkrTgxVa0{T",
	/* 12/12 (038) */	"imLsvUlwZ",
	/* 12/13 (039) */	"tbTnqTouWxzW",
	/* 12/14 (040) */	"pcTaeTvfU0mhT{kTjnTgrTsyY",
	/* 12/15 (041) */	"dbT4slZzpUgtTiuWowZvxV",
	/* 12/16 (042) */	"kaTxfVenTcqTmrTh{T",
	/* 12/17 (043) */	"zbTgcTrdU0plZmtTsuZ0iwZoyY",
	/* 12/18 (044) */	"gaTxdVehTfjVqkTtnTluWpvZiyYz{T",
	/* 12/19 (045) */	"meSovZswW",
	/* 12/20 (046) */	"cdV4olZ{pUfrThtTkuW",
	/* 12/21 (047) */	"zeTugWchTviW0rqTmsTjxVkyY",
	/* 12/22 (048) */	"abTpdV{lZfoVntT",
	/* 12/23 (049) */	"bcToeTdhT4liZgjVmnTfpUarTqsTkvZ{wZzxVuyY",
	/* 12/24 (050) */	"",
	/* 12/25 (051) */	"sdV2juJ2",
	/* 12/26 (052) */	"keGpgWjmZwnTaqQivUbxV",
	/* 12/27 (053) */	"hcTtlZ{oVwsTbuWpzW",
	/* 12/28 (054) */	"haTceTgfVtiZxnTqrTjyY",
	/* 12/29 (055) */	"qdVymZasTlvZbzWw{T",
	/* 12/30 (056) */	"dcT4igWwhTxkTblZsnTeoVjpU{rTtuW",
	/* 12/31 (057) */	"",
	/* 1/1   (058) */	"",
	/* 1/2   (059) */	"qbStgWnhTcrQzvUfwWmxV",
	/* 1/3   (060) */	"fzW",
	/* 1/4   (061) */	"caThdVmgWwiZvjVekTqnTsrTyuW0txV",
	/* 1/5   (062) */	"beTjfVylZgpUoqTdsU0mwZuzWk{T",
	/* 1/6   (063) */	"vcTxiZroV",
	/* 1/7   (064) */	"vaTebTtfVxgWlmZupU0wyYnzWd{T",
	/* 1/8   (065) */	"eaTrcTfdVwgWkhTtjVnlZqoVbpU{sTzyY",
	/* 1/9   (066) */	"xmZvrQiuU0",
	/* 1/10  (067) */	"jsU0btT",
	/* 1/11  (068) */	"ghTimZkoV{qTlrTcuWyvZnwZpxV",
	/* 1/12  (069) */	"daT4jbTpfVniZgkTesTltT",
	/* 1/13  (070) */	"qeTrhTzoVcwZuxVj{T",
	/* 1/14  (071) */	"faTlbU0zdVyiZcmZspUgqTktTnvZ",
	/* 1/15  (072) */	"jdV4teTxfVakTsoWhrGuwZnyYl{T",
	/* 1/16  (073) */	"gbSzqQcvU",
	/* 1/17  (074) */	"oaLtdLseQzhTuiU0wmNprGx{G",
	/* 1/18  (075) */	"vgWbjVlnThoVfuWmyY",
	/* 1/19  (076) */	"iaTtcT{dVbfVnkTpqTxrTlsTywZezW",
	/* 1/20  (077) */	"jgWumZxpU",
	/* 1/21  (078) */	"qaTibTkdVyfVelZhnTcoWrsU0mvZwzW",
	/* 1/22  (079) */	"ocTygWzjVdkTapUiqTstTvuWewZfxVh0{T",
	/* 1/23  (080) */	"{nTtrQ",
	/* 1/24  (081) */	"fbTdhT4okTyzW",
	/* 1/25  (082) */	"ejVcnTaoVurU0{sTqvZwxVlyY",
	/* 1/26  (083) */	"uaTnbTscThiZkmZzpUftT",
	/* 1/27  (084) */	"deT4kgWwjVrlZqyYf{T",
	/* 1/28  (085) */	"acTodVhmZnsTutTpvZizU0",
	/* 1/29  (086) */	"neTwfVhgWqiZkjVplZotTaxVryYs{T",
	/* 1/30  (087) */	"ubF2rvZ",
	/* 1/31  (088) */	"afVehU0ilZ",
	/* 2/1   (089) */	"dgW4{kTnoVyqTbrTluWvwZmxVjzW",
	/* 2/2   (090) */	"saTybTkcTohTgiZfpUetTr{T",
	/* 2/3   (091) */	"xeTmjVuvZdzW",
	/* 2/4   (092) */	"raU0xbTncTmfVyhUdiZpkTosT{tTgwZ",
	/* 2/5   (093) */	"aeTqhTckTwlZtnTyoWvzW",
	/* 2/6   (094) */	"fgWpjQzmZxqQsrG2duL2i{G",
	/* 2/7   (095) */	"haTikTrnU0ctT",
	/* 2/8   (096) */	"qeTpfVzgWdlZumZjoVwvZ{xV",
	/* 2/9   (097) */	"hbTicU0knTeqTasTrtTpuWlwZvyYmzW",
	/* 2/10  (098) */	"naT{fVjhTdoV4irTgxV",
	/* 2/11  (099) */	"|pY0",
	/* 2/12  (100) */	"|pS0",
	/* 2/13  (101) */	"}pR2",
	/* 2/14  (102) */	"",
	/* 2/15  (103) */	"geTvfV{hTwiZajVlmZopUrqTbsTkxVtyY",
	/* 2/16  (104) */	"jcTndV4zlZgoVvuWtwZ",
	/* 2/17  (105) */	"q1bTreTkfVaiZynThxVp{T",
	/* 2/18  (106) */	"ocTgdV4alZepUysU0muWtvZzwZq0{T",
	/* 2/19  (107) */	"hfVbiZujVnxVlzW",
	/* 2/20  (108) */	"ecMagWykLtmZsoL{qTdrG2bvZ",
	/* 2/21  (109) */	"cdLfhT{nTxpKwuWtzW",
	/* 2/22  (110) */	"peTgjVfkTioVnqTyrTlvZbwZ",
	/* 2/23  (111) */	"yaTidV4bgWvlZksTqtTxzWe{T",
	/* 2/24  (112) */	"fcTrjU0upUmwZ",
	/* 2/25  (113) */	"oaTieTrgWhkTwlZxmZqsTntTbyYuzWd{T4",
	/* 2/26  (114) */	"kdV4feTnhTzjV{oWatTxvZ",
	/* 2/27  (115) */	"ylWbmZipKfqQcsF2ruP2gvZ",
	/* 2/28  (116) */	"edU0jzW",
	/* 3/1   (117) */	"paTliZsjVvkTnoVhqT{tTrwZcyY",
	/* 3/2   (118) */	"ebTmdV4vhTclZnpUzxV",
	/* 3/3   (119) */	"teTsfVuiW0qrTa{T",
	/* 3/4   (120) */	"mbU0vdVsgWqkTpuWlxV",
	/* 3/5   (121) */	"kaTzfVciZljVtnThoWwyYm{T",
	/* 3/6   (122) */	"deG2pgWtqQzuWywWsxL2",
	/* 3/7   (123) */	"rhTbnTmoVivZ",
	/* 3/8   (124) */	"ucTadVweTlfVgsTjxViyYpzW",
	/* 3/9   (125) */	"raTqhTgnTkoVwpUstTzvZu{T",
	/* 3/10  (126) */	"viZyjU0fmZ",
	/* 3/11  (127) */	"daT4rbTehUflZunTwoWcpUkqTtsTyxVg{T",
	/* 3/12  (128) */	"wdVahTxjVokTcqTerV",
	/* 3/13  (129) */	"nbSjfUilWmpKusE2vyYt{G",
	/* 3/14  (130) */	"bcTxgWhwZmzW0",
	/* 3/15  (131) */	"sdU0ueT{iZvjVzlZonTtpUkrThyY",
	/* 3/16  (132) */	"dbT4acTukT{mZfsTqwZvxV",
	/* 3/17  (133) */	"ijVglZfnTypUorT",
	/* 3/18  (134) */	"zcTydV4wgWakTqmZesTptThuW{vZ",
	/* 3/19  (135) */	"ifVhjVzkTenTbrGquWwxV",
	/* 3/20  (136) */	"abE3ycE3{gWvlWsmLtoJdpK",
	/* 3/21  (137) */	"zaT{jVnmZ",
	/* 3/22  (138) */	"tcTkeTogWsiZjpUlqTdrU0nuWvwZxyY",
	/* 3/23  (139) */	"caTmfVlhTekTdtTszW",
	/* 3/24  (140) */	"ngWoiZmjVrpUxwZuyYb{T",
	/* 3/25  (141) */	"laTchUrkTdqTetTfuWwvZozW",
	/* 3/26  (142) */	"naTlcTkdV4fgWxiZzjVpyYq{T",
	/* 3/27  (143) */	"t1bTheSomZrsE2juU0xvZ",
	/* 3/28  (144) */	"lkTgyY",
	/* 3/29  (145) */	"qaTtdVleTxfVpmZhnTboVcrU0{sTyvZjwZizW",
	/* 3/30  (146) */	"kbTjiZnqT",
	/* 3/31  (147) */	"ulZvoVawZexU0myY",
	/* 4/1   (148) */	"{bThdU0cfVpiZjmZknTsqTvtTauW",
	/* 4/2   (149) */	"efVskTnrTpwZcxViyYgzWo{T",
	/* 4/3   (150) */	"dhH2jlQamZvqSbtSguW",
	/* 4/4   (151) */	"",
	/* 4/5   (152) */	"{dVceTlgWhkTrnTbqTosTuvZfwZixVzyY",
	/* 4/6   (153) */	"baTkcTwmZlpUotTxuWn{T",
	/* 4/7   (154) */	"ygWijU0aqTerTfzW",
	/* 4/8   (155) */	"pbTqcTdkTgmZhsTrtTuwZfyYe{T",
	/* 4/9   (156) */	"{aTodV4xjL3snTipUctTmvZlzL3",
	/* 4/10  (157) */	"jgWbhG3rqG3uyL2",
	/* 4/11  (158) */	"ncTfiZbkTsrU0lwZpxV",
	/* 4/12  (159) */	"qdVoeTugWthTpjVylZimZfvZwzW",
	/* 4/13  (160) */	"eaThbTdnT4qoVktTmuWgxV",
	/* 4/14  (161) */	"viZwjVcsU0lyYxzWr{T",
	/* 4/15  (162) */	"sbTdcU0neTgfVvmZaoWkpUhqT{rT",
	/* 4/16  (163) */	"taTwfVziZmlZeoWuxL3jyL3",
	/* 4/17  (164) */	"rcK2khFqnMgpKdsP2jvZb{F",
	/* 4/18  (165) */	"adV4ufVilZ",
	/* 4/19  (166) */	"obTmgWshTpnTarTqtTyuWzwZjxU0k{T",
	/* 4/20  (167) */	"{cTekTglZymZhoVpsT",
	/* 4/21  (168) */	"cbTwiZfjVanTtrTvzW",
	/* 4/22  (169) */	"bdV1{eT1jfV1zgW1tkT1roW1vpU1luW1xyY1",
	/* 4/23  (170) */	"saThcL3miL3nkToqTwuW",
	/* 4/24  (171) */	"rdG2beL3pfUgjL3xlL3zmL3qsThtGyvL3iwWc{G"
};

/****************************************************************************
* Some boring globals...it seems to be a pretty convient place to put 'em.
****************************************************************************/
int	TODAYSmonth;
int	TODAYSday;
int playing = -1;
int summary_form = 0;

/****************************************************************************
* MAIN
*
* Main program loop.  All arguements are parsed and appropriate routines
* are called.
****************************************************************************/
main(argc,argv)
int argc;
char  *argv[];
{
	extern	int	is_team();
	extern	int	get_nba_day();
	extern	void	do_long_sched();
	extern	void	do_all();
	extern	void	do_summary_sched();
	extern	void	print_usage();

	struct	tm	*time_tm;
	register int	i,j;
	int		arg_count;
	int		month;
	int		day;
	int		nba_day;
	int		team;
	int		newteam;
	long		current_date;
	char		*ptr;
	int		teamtwo = -1;


	current_date = time((long *)NULL);
	time_tm = localtime(&current_date);
	TODAYSmonth = time_tm->tm_mon+1;
	TODAYSday = time_tm->tm_mday,0;

	arg_count = 1;
	team = -1;

	if (argc > arg_count) {
		/*
		 * Look for the help option...if specified, it must be the
		 * first option.
		 */
		if ((strcmp(argv[arg_count], "-help") == 0) ||
		    (strcmp(argv[arg_count], "-h") == 0) ||
		    (strcmp(argv[arg_count], "-?") == 0))
		{
			print_usage(argv[0]);
			exit(0);
		}

		/*
		 * Check for a request for summary or a specific team.
		 */
		if (strcmp(argv[arg_count], "-s") == 0)
		{
			summary_form = 1;
			if (arg_count+1 != argc)
			{
				arg_count++;
				if (is_team(argv[arg_count], &newteam))
				{
					team = newteam;
					arg_count++;
				}
			}
			else
			{
				arg_count++;
			}
		}

		/*
		 * Look for a specific match up between two teams.
		 */
		else
		if (strcmp(argv[arg_count], "-m") == 0)
		{
			playing=1;
			arg_count++;
			if (is_team(argv[arg_count], &newteam))
			{
				team = newteam;
				arg_count++;
				if (is_team(argv[arg_count], &newteam))
				{
					teamtwo = newteam;
					arg_count++;
				}
				else
				{
					fprintf(stdout,"\n%s: Is not a NBA team\n",argv[arg_count]);
					exit(0);
				}
			}
			else 
			{
				fprintf(stdout,"\n%s: Is not a NBA team\n",argv[arg_count]);
				exit(0);
			}

			do_all(team,teamtwo,"end");
		}

		/*
		 * Check to see if one specific team is requested.
		 */
		else
		if (is_team(argv[arg_count], &newteam))
		{
			team = newteam;
			arg_count++;
		}
	}

	/*
	 * Check for a requested date on the command line.
	 */
	if (argc == arg_count)
	{
		/*
		 * No date/options requested...give today's schedule.
		 */
		nba_day = get_nba_day(TODAYSmonth,TODAYSday,1);
		if (nba_day < 0)
			exit(1);

		if (summary_form == 1)			/* Do SUMMARY format */
			do_summary_sched(TODAYSmonth,TODAYSday,nba_day,team);
		else					/* Do LONG format */
			do_long_sched(TODAYSmonth,TODAYSday,nba_day,team);

		exit(0);
	}

	/*
	 * Loop through all the rest of the options...they should all
	 * be date requests.
	 */
	for (;arg_count<argc;arg_count++)
	{
		/*
		 * Validate the date format.
		 */
		j = strlen(argv[arg_count]);
		ptr = strchr(argv[arg_count],'/');

		/*
		 * See if the user has requested a special date format...
		 * "all" will print the entire schedule..."end" will
		 * print from today to the end of the season.
		 */
		if (strcmp(argv[arg_count], "all") == 0)
		{
			do_all(team,teamtwo,"all");
		}
		else
		if (strcmp(argv[arg_count], "end") == 0)
		{
			do_all(team,teamtwo,"end");
		}

		/*
		 * Check the date format.
		 */
		else
		if ((strspn(argv[arg_count],"0123456789/") != j) ||
		    (j < 3) || (j > 5) ||
		    (argv[arg_count][0] == '/') ||
		    (argv[arg_count][j-1] == '/') ||
		    (ptr == NULL))
		{
			fprintf(stderr,"Invalid date \"%s\"...format is \"mm/dd\"\n",
			argv[arg_count]);
			continue;
		}

		/*
		 * Do some basic date validation...
		 */
		month = atoi(argv[arg_count]);
		day = atoi(++ptr);
	
		if (month > 12)
		{
			fprintf(stderr, "Invalid date \"%d/%d\"...months are from 1 - 12.\n", month,day);
			continue;
		}
	
		if (day == 0)
		{
			fprintf(stderr, "Invalid date \"%d/%d\"...the day can not be \"0\"\n", month,day);
			continue;
		}
		else
		if (day > days[month-1])
		{
			fprintf(stderr,	"Invalid date \"%d/%d\"...there are only %d days in the month.\n", month,day,days[month-1]);
			continue;
		}
	
		/*
		 * Figure out what julian date is being requested and convert
		 * it to the specific day of the NBA season.
		 */
		nba_day = get_nba_day(month,day,1);
		if (nba_day < 0)
			continue;
	
		if (summary_form == 1)			/* Do SUMMARY format */
			do_summary_sched(month,day,nba_day,team);
		else					/* Do LONG format */
			do_long_sched(month,day,nba_day,team,teamtwo);
	}

	exit(0);
}

/****************************************************************************
* DO_ALL
*
* This routine will loop through the entire schedule, either from the
* beginning of the season (with the "all" option) or starting from the
* current date to the end of the season (with the "end" option).  The
* schedule is printed out for each day.
****************************************************************************/
void do_all(team, teamtwo, daterange)
int	team,teamtwo;
char	*daterange;
{
	int month,day,nba_day;

	if (strcmp(daterange,"all") == 0)
	{
		month = 11;
		day = 1;
	}
	else
	{
		month = TODAYSmonth;
		day = TODAYSday;
	}

	for (; month != 5; month++)
	{
		if (month == 13)
		month = 1;

		for (; day <= days[month-1]; day++)
		{
			if ((month == 11) & (day < 5))
				continue;
			if ((month == 4)  && (day > 25))
				break;

			nba_day = get_nba_day(month, day, 0);
			if (nba_day < 0)
				continue;

			do_long_sched(month, day, nba_day, team,teamtwo);
		}

		day = 1;
	}

	exit(0);
}

/****************************************************************************
* IS_TEAM
*
* This routine will validate a team that is input by the user to determine
* if the entry is a valid team.
****************************************************************************/
int
is_team(name, team)
char *name;
int *team;
{
	char	newname[25], checkname[25];
	int	i, j, k;

	/*
	 * Convert the given name to lower case and all others are lower
	 * case...ignore spaces.
	 */
	for (i = k = 0; i < strlen(name); i++)
	{
		if (name[i] == ' ')
			continue;
		newname[k++] = tolower(name[i]);
	}
	newname[k] = '\0';

	/*
	 * Scan the NBA teams for one that matches the given name
	 */
	for (i = 0; teams[i].longname[0] != '\0'; i++)
	{
		/*
		 * Convert the requested name to lower case...ignore spaces.
		 */
		for (j = k = 0; j < strlen(teams[i].longname); j++)
		{
			if (teams[i].longname[j] == ' ')
				continue;
			checkname[k++] = tolower(teams[i].longname[j]);
		}
		checkname[k] = '\0';

		if (strcmp(checkname, newname) == 0)
		{
			*team = i;
			return(1);
		}
	}

	/*
	 * Scan the NBA teams for one that matches the given name
	 */
	for (i = 0; teams[i].teamname[0] != '\0'; i++)
	{
		/*
		 * Convert the name to check to lower case
		 */
		for (j = k = 0; j < strlen(teams[i].teamname); j++)
		{
			if (teams[i].teamname[j] == ' ')
				continue;
			checkname[k++] = tolower(teams[i].teamname[j]);
		}
		checkname[k] = '\0';

		if (strcmp(checkname, newname) == 0)
		{
			*team = i;
			return(1);
		}
	}

	/*
	 * No team found
	 */
	*team = -1;
	return(0);
}

/****************************************************************************
* GET_NBA_DAY
*
* This routine figures out where to point into the NBA schedule matrix
* for a requested day.
****************************************************************************/
get_nba_day(month,day, errmsg)
int month,day,errmsg;
{
	int	nba_day = 0;

	for (month--;month > 0;month--)
		nba_day += days[month-1];
	nba_day += day;

	if (nba_day >= 309)
		nba_day -= 309;
	else
		nba_day += 56;

	if ((nba_day < 0) || (nba_day >= 171))
	{
		if (errmsg == 1)
			fprintf(stderr,"The NBA regular season runs from 11/5 to 4/24.\n");
		return (-1);
	}

	return (nba_day);
}

/****************************************************************************
* DO_LONG_SCHED
*
* This is the "real" smarts of the program...it takes in a request for a
* schedule on a specific day and prints out the "long form" of the NBA
* schedule for that date.
*
* Optionally, if one team is sent in as a paramter then the schedule for
* just that team is printed.  If two teams are sent in, just the head-head
* matchups between those teams are printed.
****************************************************************************/
void
do_long_sched(month,day,nba_day,team,teamtwo)
int		month;
int		day;
register int	nba_day;
int		team;
int		teamtwo;
{
	register int	i;
	register int	j;
	int		home;
	int		visitor;
	int		tip_off;
	int		alt_site;
	int		footer;
	int		tv_game;
	int		day_o_week;
	int		found;
	char		tmpVisitor[25];
	char		tmpHome[25];
	char		HomeTeam[15];
	char		AwayTeam[15];


	day_o_week = nba_day % 7;

	if (team == -1)
	{
		if (nba_day == 9)
			fprintf(stdout,"\nNBA schedule for today...\n");
		else
			fprintf(stdout,"\nNBA schedule for %s, %d/%d...\n",
				weekday[day_o_week].longform,month,day);
	}

	/*
	 * This one's easy...an empty string means nothing is scheduled.
	 */
	if ((team == -1) && (nba_schedule[nba_day][0] == '\0'))
	{
		fprintf(stdout,"          No games scheduled\n");
		return;
	}

	for (i=footer=found=0;nba_schedule[nba_day][i] != '\0';)
	{
		/*
		 * The first character is the visiting team.
		 */
		visitor = nba_schedule[nba_day][i++] - 'a';

		/*
		 * If the next character is a digit...look up the
		 * alternate game site
		 */
		if (isdigit(nba_schedule[nba_day][i]))
			alt_site = nba_schedule[nba_day][i++] - '0';
		else
			alt_site = 2;

		/*
		 * The next charater is the home team.
		 */
		home = nba_schedule[nba_day][i++] - 'a';

		/*
		 * The next character is the tip-off time.
		 */
		tip_off = nba_schedule[nba_day][i++] - '?' - TZ_FIX;

		/*
		 * If the next character is a digit...look up the
		 * TV coverage.
		 */
		if (isdigit(nba_schedule[nba_day][i]))
			tv_game = nba_schedule[nba_day][i++] - '0';
		else
			tv_game = NUM_TV;

		/*
		 * If the user compiled the TV coverage structure to ignore
		 * this particular network don't print it.
		 */
		if (tv_coverage[tv_game].printit != 0)
			tv_game = NUM_TV;

		/*
		 * If the "TV coverage" string has an asterick in it then
		 * we need to print out a footer saying that the network
		 * hasn't made up it's mind to televise the game yet.
		 */
		if (strchr(tv_coverage[tv_game].network, '*') != NULL)
			footer = 1;

		/*
		 * A TEAMNAME of "1" means that we need to print out
		 * the team's nickname.
		 */
		if (TEAMNAME == 1)
		{
			strcpy(HomeTeam, teams[home].teamname);
			strcpy(AwayTeam, teams[visitor].teamname);
		}
		else
		{
			strcpy(HomeTeam, teams[home].longname);
			strcpy(AwayTeam, teams[visitor].longname);
		}

		/*
		 * If a team isn't specified, print out every entry
		 * from the schedule matrix.
		 */
		if (team == -1)
		{
			fprintf(stdout,"%8s  %-12s at %-12s %s %s\n",
				tv_coverage[tv_game].network,
				AwayTeam, HomeTeam,
				game_time[tip_off],
				alternate_site[alt_site].alt_site);
		}

		/*
		 * At least one specified team has been found...
		 *
		 * If two team names were sent in see if this is the
		 * matchup requested.
		 */
		if (teamtwo != -1)
		{
			if (((visitor == team) && (home == teamtwo)) ||
			    ((visitor == teamtwo) && (home == team)))
			{
				strcpy(tmpHome, HomeTeam);
				strcpy(tmpVisitor, AwayTeam);
				fprintf(stdout,"%-6s %10s, %2d/%-2d %-12s at %-12s %s %s\n",
					tv_coverage[tv_game].network,
					weekday[day_o_week].longform,
					month, day,
					tmpVisitor, tmpHome,
					game_time[tip_off],
					alternate_site[alt_site].alt_site);

				found++;
				break;
			}
		}    	

		/*
		 * Only one team was specified...is this the right one?
		 */
		if ((teamtwo == -1) && ((visitor == team) || (home == team)))
		{
			/*
			 * CAPITALIZE the name of the specified team.
			 */
			if (visitor == team)
			{
				strcpy(tmpHome, HomeTeam);
				for (j = 0; j < strlen(AwayTeam); j++)
					tmpVisitor[j] = toupper(AwayTeam[j]);
				tmpVisitor[j] = '\0';
			}

			else
			{
				strcpy(tmpVisitor, AwayTeam);
				for (j = 0; j < strlen(HomeTeam); j++)
					tmpHome[j] = toupper(HomeTeam[j]);
				tmpHome[j] = '\0';
			}
      
			fprintf(stdout,"%-6s %10s, %2d/%-2d %-12s at %-12s %s %s\n",
				tv_coverage[tv_game].network,
				weekday[day_o_week].longform,
				month, day,
				tmpVisitor, tmpHome,
				game_time[tip_off],
				alternate_site[alt_site].alt_site);

			found++;
			break;
		}
	}

	/*
	 * The schedule matrix wasn't empty but we didn't find any games
	 * for the requested team(s).
	 */
	if ((nba_schedule[nba_day][i] != '\0') && (found == 0))
	{
		fprintf(stdout,"          No games scheduled\n");
		return;
	}

	if ((footer == 1) && (team == -1))
		fprintf(stdout,"\n      * Specific TV game not determined yet.\n");

	return;
}

/****************************************************************************
* DO_SUMMARY_SCHED
*
* Another meaty routine similar to "do_long_sched".  This one will print
* out a summary of NBA games for one week from the requested date.
*
* Optionally, if one team is sent in as a paramter then the schedule for
* just that team is printed.
****************************************************************************/
void
do_summary_sched(month,day,nba_day,team)
int		month;
int		day;
register int	nba_day;
int		team;
{
	register int	i,j,k;
	int		home;
	int		visitor;
	char		footer[3];
	int		alt_site;
	char		site_footers[10];
	int		tv_game;
	char		tv_footers[10];
	int		day_o_week;
	int		most_lines = 3;
	char		summary_matrix[7][17][14];

	/*
	 * Initialize the matrix for the summary display.
	 */
	for (j=0;j<7;j++)
	{
		strcpy(summary_matrix[j][0],  "-----------");
		strcpy(summary_matrix[j][2],  "-----------");
		strcpy(summary_matrix[j][16], "-----------");

		day_o_week = (nba_day + j) % 7;
		sprintf(summary_matrix[j][1],"| %s %2d/%-2d ",
		weekday[day_o_week].summary,month,day);
		day++;
		if (day > days[month-1])
		{
			day = 1;
			if (++month == 13)
				month = 1;
		}

		for (k=3;k<=15;k++)
			strcpy(summary_matrix[j][k],"|          ");
	}

	for (k=0;k<=16;k++)
	{
		if ((k == 0) || (k == 2) || (k == 16))
			strcat(summary_matrix[6][k],"-\n");
		else
			strcat(summary_matrix[6][k],"|\n");
	}

	strcpy(site_footers,"000000000");
	strcpy(tv_footers,"000000000");

	for (j=0;j<7;j++)
	{
		if ((nba_day+j) >= 171)
		{
			/* We just went past end of season! */
			strcpy(summary_matrix[j][3],"|  SEASON  ");
			strcpy(summary_matrix[j][4],"|  IS OVER ");

			if (j == 6)
			{
				strcat(summary_matrix[j][3],"|\n");
				strcat(summary_matrix[j][4],"|\n");
			}

			if (most_lines < 4)
				most_lines = 4;

			continue;
		}

		if (nba_schedule[nba_day+j][0] == '\0')
		{
			/* No games scheduled */
			continue;
		}

		for (i=0,k=3; nba_schedule[nba_day+j][i] != '\0';k++)
		{
			footer[0] = footer[1] = footer[2] = '\0';

			/*
			 * The first character is the visiting team.
			 */
			visitor = nba_schedule[nba_day+j][i++] - 'a';

			/*
			 * If the next character is a digit...look up the
			 * alternate game site
			 */
			if (isdigit(nba_schedule[nba_day+j][i]))
			{
				alt_site = nba_schedule[nba_day+j][i++] - '0';
				strncat(footer,alternate_site[alt_site].summary,1);
				site_footers[alt_site] = '1';
			} /* if (isdigit()) */

			/*
			 * The next charater is the home team.
			 */
			home = nba_schedule[nba_day+j][i++] - 'a';

			/*
			 * The next character is the tip-off time....skip it...
			 * there is no room on a summary chart!
			 */
			i++;

			/*
			 * If the next character is a digit...look up the
			 * TV coverage.
			 */
			if (isdigit(nba_schedule[nba_day+j][i]))
			{
				tv_game = nba_schedule[nba_day+j][i++] - '0';
				/*
				 * If the user compiled the TV coverage
				 * structure to ignore this particular
				 * network don't print it.
				 */
				if (tv_coverage[tv_game].printit != 0)
					tv_game = NUM_TV;
				else
				{
					strncat(footer,tv_coverage[tv_game].summary,1);
					if ((team == visitor) || (team == home) || (team == -1))
					tv_footers[tv_game] = '1';
				}
			}

			/*
			 * If we are only looking for a specific team...always
			 * put it in the first data row of the printout.
			 */
			if (team != -1)
				k = 3;

			if ((team == visitor) || (team == home) || (team == -1)){
				sprintf(summary_matrix[j][k],"| %3s-%-3s%2s",
					teams[visitor].summary,
					teams[home].summary,
					footer);

				if (j == 6)
					strcat(summary_matrix[j][k],"|\n");
				if (k > most_lines)
					most_lines = k;
			}
		}
	}

	/*
	 * Now print out the summary matrix...
	 */
	for (k=0;k<=most_lines;k++)
	{
		for (j=0;j<7;j++)
		{
			if (summary_matrix[j][k] != NULL)
				fprintf(stdout,"%s",summary_matrix[j][k]);
		}
	}

	for (j=0;j<7;j++)
	{
		if (summary_matrix[j][k] != NULL)
			fprintf(stdout,"%s",summary_matrix[j][16]);
	}

	/*
	 * Print out any footnotes...first alternate game sites...
	 */
	for (j=0;j < NUM_ALT_SITES;j++)
		if (site_footers[j] == '1')
			fprintf(stdout,"%s\n",alternate_site[j].summary);

	/*
	 * ...then TV coverage
	 */
	for (j=0;j < NUM_TV;j++)
		if (tv_footers[j] == '1')
			fprintf(stdout,"%s\n",tv_coverage[j].summary);

	return;
}

/****************************************************************************
* PRINT_USAGE
*
* Just a dopey little routine to print out the usage message.
****************************************************************************/
void
print_usage(prog_name)
char	*prog_name;
{
	fprintf(stdout, "Usage: %s [-s] [-s team] [team] [-m team1 team2] [mm/dd... | all | end]\n\nExamples:\n", prog_name);
	fprintf(stdout, " %s                         <- today's games\n",prog_name);
	fprintf(stdout, " %s 12/25 1/1               <- games on Christmas and New Years\n",prog_name);
	fprintf(stdout, " %s -s                      <- summary for the next week\n", prog_name);
	fprintf(stdout, " %s -s 11/5                 <- summary for the first week of the season\n", prog_name);
	fprintf(stdout, " %s -s celtics              <- Boston summary for the next week\n", prog_name);
	fprintf(stdout, " %s -m chicago lakers end   <- Chicago/LA games for the rest of the season\n", prog_name);
	fprintf(stdout, " %s Magic all               <- Orlando's full season schedule\n", prog_name);
	fprintf(stdout, "\nTeam names can be either the team nickname (Knicks) or the city.\n");
	fprintf(stdout, "City names with spaces can either be put in quotes (\"New York\")\n");
	fprintf(stdout, "or entered as a single word without spaces (NewYork)\n");
}
