# include "stdio.h" # include "cbt.h" # include "ctype.h" # include "assert.h" # include "math.h" # include "/usr/weather/progs/weath.h" # define SAME 0 char gdport[200], gdhap[200]; char *strchr(); double md=1000., dist(), xabs(); int abear; bfile *bf; bfile *happenfile; char *direct[] = {"N", "NE", "E", "SE", "S", "SW", "W", "NW", "N", "xx", "yy"}; main(argc,argv) char *argv[]; { char line[100], request[100], rka[100], rra[300], from[100], fromloc[100]; char sna[100], *s, *excite(); mbuf key, rkey, rrec; bfile *townfile; FILE *fpat, *fair, *hpat, *hap; double lat, lng, fromlat, fromlng; int a1, a2, b1, b2, x, y, townfind, nf, j; townfile = bopen("//usr/spool/town/ustowns", 0); if (townfile==NULL) { fprintf(stderr, "No town list - is /crp mounted?\n"); exit(1); } happenfile = bopen("//usr/spool/town/happen", 0); assert(happenfile!=NULL); bf = bopen("/usr/spool/weather/air", 0); assert(bf!=NULL); fpat = fopen("/usr/spool/town/cityindex", "r"); assert(fpat!=NULL); fair = fopen("/usr/spool/town/citypatch", "r"); assert(fair!=NULL); hpat = fopen("/usr/spool/town/hapindex", "r"); hap = fopen("/usr/spool/town/haplist", "r"); rkey.mdata = rka; rrec.mdata = rra; nf=0; if (argc>1) concat (from, argc, argv); else strcpy(from, "murray hill, nj"); lcase(from); key.mdata = from; key.mlen = strlen(from); bseek(townfile, key); while (bread(townfile, &rkey, &rrec)==NULL) { if (strncmp(from, rkey.mdata, key.mlen)==SAME) { rrec.mdata[rrec.mlen]=0; rkey.mdata[rkey.mlen]=0; strcpy(fromloc, rrec.mdata); strcpy(request, rkey.mdata); nf++; } else break; } if (nf<1) printf("No such place: %s\n", from); else if (nf>1) printf("More than one such place: %s\n", from); else { sscanf(fromloc, "%lf%lf", &fromlat, &fromlng); caps(request); printf(" [Reference point: %s (%.3f N, %.3f W)]\n", request, fromlat, fromlng); } while (gets(request)) { if (strlen(request)==0) continue; if (strcmp(request, "q")==SAME) break; lcase(request); townfind=0; key.mdata = request; key.mlen = strlen(request); bseek(townfile, key); while (bread(townfile, &rkey, &rrec)==NULL) { rkey.mdata[rkey.mlen]=0; rrec.mdata[rrec.mlen]=0; if (strncmp(rkey.mdata, request, key.mlen)!=SAME) break; townfind++; md=1000; sscanf(rra, "%lf%lf", &lat, &lng); caps(rka); printf("%s: (%.3f N, %.3f W)", rka, lat, lng); strcpy(sna, rka); if (nf==1) printf(" %.1f miles %s", dist(fromlat, fromlng, lat, lng), direct[bearing(fromlat, fromlng, lat, lng)]); printf("\n"); printf("Zip code %5.5s. ", rra+15); for(s=rra; *s; s++) ; s-=3; switch(*s) { case '0': puts("Less than 2500 people."); break; case '2': puts("2,500 to 5,000 people."); break; case '3': puts("Between 5,000 and 10,000 people."); break; case '4': puts("10,000 to 25,000 people."); break; case '5': puts("25,000 to 50,000 people."); break; case '6': puts("50,000 to 100,000 people."); break; case '7': puts("Between 100,000 and 250,000 people."); break; case '8': puts("Population over 250,000 but below 500,000."); break; case '9': puts("Population exceeds 500,000."); break; default: puts(""); break; } a1 = lat/4; /* floating remainder not defined, so... */ if ( lat - 4.0*a1 >2.0) a2 = a1+1; else a2 = a1-1; b1 = lng/4; if (lng - 4.0*b1 > 2.0) b2 = b1+1; else b2 = b1-1; if (*s!= '8' && *s!='9') { rewind(fpat); while (fgets(line, 100, fpat)) { x = atoi(line); y = atoi(line+3); if ((x==a1 || x==a2) && (y==b1 || y==b2)) ckair(line+6, lat, lng, fair); } if (md<1000.) { caps(gdport+6); if (strncmp(rka, gdport+6, strlen(rka))) printf(" Nearest city: %s, %5.1f miles %s\n", gdport+6, md, direct[abear]); } } weather(lat, lng); lcase(rka); j = bseek(happenfile, rkey); if (j==1) { bread(happenfile, NULL, &rrec); rrec.mdata[rrec.mlen]=0; bput(rrec.mdata); } else { printf("Nothing much has happened lately in %s.\n", sna); rewind (hpat); md=1000.; if (xabs(lat-(4.0*a1+2.0)) <= 1.80) a2=a1; if (xabs(lng-(4.0*b1+2.0)) <= 1.80) b2=b1; while (fgets(line, 100, hpat)) { x = atoi(line); y = atoi(line+3); if ( (x==a1 || x==a2) && (y==b1 || y==b2)) ckcit (line+6, lat, lng, hap); } if (md<1000.) { strcpy(rka, gdhap+6); caps(gdhap+6); rkey.mlen = strlen(rka); j = bseek (happenfile, rkey); if (j==1) { bread(happenfile, NULL, &rrec); if (md>0) printf("But, %.1f miles away in %s %s, \n", md, excite(md), gdhap+6); else printf("But, nearby in %s %s, \n", excite(md+1.5), gdhap+6); rrec.mdata[rrec.mlen]=0; bput(rrec.mdata); } } } printf("\n"); } if (townfind==0) fprintf(stderr, "Town name not in our file\n"); } exit(0); } bput(s) char *s; { int col=0; char buff[2048], *p; p=buff; while (*s) { if (col==0) { while (col++ < 5) *p++ = ' '; } if (*s==' ' && col>60) { *p++ = '\n'; col=0; } else { *p++ = *s; col++; } s++; } *p=0; printf("%s", buff); } concat (out, ac, av) char *out, *av[]; { int i; out[0]=0; for(i=1; i<ac; i++) { strcat(out, av[i]); if (i+1<ac) strcat(out, " "); } return; } ckair(pos, lat, lng, fair) FILE *fair; char *pos; double lat, lng; { char airport[200], opat[5], *s; long fpt, atol(); double alat, alng, atof(), d; fpt = atol(pos); fseek (fair, fpt, 0); opat[0]=0; while (fgets(airport, 200, fair)) { if (opat[0] && strncmp(opat, airport, 5)!=SAME) break; strncpy(opat, airport, 5); for(s=airport; *s!='\t'; s++) ; *s++ = 0; alat= atof(s); while (*s!=' ')s++; alng = atof(++s); while (*s++ != ' '); d = dist(lat, lng, alat, alng); if (md>d) { md=d; strcpy(gdport, airport); abear = bearing (lat, lng, alat, alng); } } } double dist (aplat, aplon, bplat, bplon) double aplon, aplat, bplon, bplat; { /* this code is from the picadad manual. I don't pretend to understand it. */ double as, bs, ac, bc, p, cd, d, er; double rad=0.0174532925; er = aplon-bplon; if (er<0) er= -er; if (er<0.001) { d = aplat-bplat; if (d<0) d= -d; return(d*69.055); } as = sin(rad*aplat); bs = sin(rad*bplat); ac = cos(rad*aplat); bc = cos(rad*bplat); p = cos(er*rad); cd = (as*bs+ac*bc*p); return( acos(cd)*3956.56); } bearing (lat, lng, alat, alng) double lat, lng, alat, alng; { /* gives bearing of alat, alng from lat, lng as 0-7 */ # define PI 3.1415926 double dlat, dlng, b; dlat = alat-lat; dlng = (alng-lng)*cos(PI*(lat+alat)/360.); b = atan2(-dlng, dlat); /* range -pi to +pi */ b = b*(180./PI); if (b<0) b=360+b; return( (int) (b+22.5)/45.0); } lcase (s) char *s; { int c; for( ; c= *s; s++) if (isupper(c)) *s = tolower(c); } caps(s) char *s; { int c; if (islower(*s)) *s = toupper(*s); for( s++; c= *s; s++) { if (islower(c) && (s[-1]==' ' || s[-1]=='-')) if (strncmp(s, "of ", 3)!=SAME) *s = toupper(c); if (*s==',') break; } for(s++; c= *s; s++) if (islower(c)) *s=toupper(c); } ckcit(pos, lat, lng, fair) FILE *fair; char *pos; double lat, lng; { char citline[200], opat[5], *s; long fpt, atol(); double alat, alng, atof(), d; fpt = atol(pos); fseek (fair, fpt, 0); opat[0]=0; while (fgets(citline, 200, fair)) { if (opat[0] && strncmp(opat, citline, 5)!=SAME) break; strncpy(opat, citline, 5); for(s=citline; *s!='\t'; s++) ; *s++ = 0; if (!ishap(s))continue; alat= atof(s); while (*s!=' ')s++; alng = atof(++s); while (*s++ != ' '); d = dist(lat, lng, alat, alng); if (md>d) { md=d; strcpy(gdhap, citline); } } } ishap(s) char *s; { while (*s)s++; if (s[-3]=='x') return(1); else return(0); } double xabs(x) double x; { return (x>= 0. ? x : -x); } char * excite(x) double x; { /* choose at random from a list of words */ switch(( (int)x)%5) { case 0: return("exciting"); case 1: return("swinging"); case 2: return("nearby"); case 3: return("the bright lights of"); case 4: return("booming"); } return("exciting"); } weather(north, west) double north, west; { double d, dist(), md=5000., tnf, twf; char tn[10], tw[10], *x, *y, fname[100], *vis(), odata[2000], *airname(); struct wline *wp, *bwp; int n, w, f, kbear, isair; n = north; n = n-n%4; w = west; w = w-w%4; bwp=NULL; sprintf(fname, "/usr/spool/weather/obs/%.2d.%.2d", n, w); f = open(fname, 0); if (f<0) return; n=read(f, odata, 2000); assert(n<2000); for(wp=(struct wline *)odata; (char *)wp <odata+n; wp++) { if (wp->anam[0]== '-') continue; strncpy(tn, wp->nlat, 5); tn[5]=0; strncpy(tw, wp->nlng, 6); tw[6]=0; d = dist(tnf=atof(tn), twf=atof(tw), north, west); if (d<md) { md=d; kbear = bearing(north, west, tnf, twf); bwp=wp; } } close(f); if (bwp==NULL) return; strncpy(tn, bwp->anam, 3); tn[3]=0; x = airname(tn); x = strchr(x, ' '); while (isspace(*x))x++; for(y=x+1; *y != ','; y++) if (isupper(*y) && y[-1]!=' ') *y = tolower(*y); y = strchr(x, '*'); if (y==NULL) isair=1; else { *y=0; isair=0; } strncpy(tw, bwp->wweath, 6); tw[6]=0; y = vis(tw, bwp->wcloud[0]); if (y==NULL) return; printf("%.1f miles %s at%s %s,\n", md, direct[kbear], isair ? " the airport in" : "", x); printf(" temperature %.3s, weather%s\n", bwp->wtemp, y); } char * vis(s, cloud) char *s; { int d; static char temp[50]; while (isspace(*s)) s++; d= atoi(s); while (isdigit(*s)) s++; if (!isalpha(*s)) { switch(cloud) { case 'C': s= "clear"; break; case 'P': s= "partly cloudy"; break; case 'O': s= "overcast"; break; default: s= "ordinary"; break; } sprintf(temp, " %s, visibility %d miles", s, d); return(temp); } temp[0]=0; for( ; *s; s++) switch(*s) { case 'A': strcat(temp, " hail"); break; case 'D': strcat(temp, " dust"); break; case 'F': strcat(temp, " fog"); break; case 'H': strcat(temp, " haze"); break; case 'I': if (s[1]=='P') strcat(temp, " sleet"); break; case 'K': strcat(temp, " smoke"); break; case 'L': strcat(temp, " drizzle"); break; case 'R': strcat(temp, " rain"); break; case 'W': strcat(temp, " showers"); break; case 'S': strcat(temp, " snow"); break; case 'T': strcat(temp, " thunderstorms"); break; case 'Z': strcat(temp, " freezing"); break; case ' ': case '-': break; default: return(NULL); } return(temp); } char * airname(s) char *s; { int i; mbuf key, rkey, rec; static char rb[100], rkb[100]; key.mdata = s; key.mlen = strlen(s); i=bseek(bf, key); if (i!=1) return(NULL); rkey.mdata =rkb; rec.mdata = rb; bread(bf, &rkey, &rec); rkey.mdata[rkey.mlen]=0; assert(strcmp(rkey.mdata, key.mdata)==0); rkey.mdata[rkey.mlen]=0; rec.mdata[rec.mlen]=0; return(rec.mdata); }