|
|
1.1 root 1: # include "stdio.h"
2: # include "cbt.h"
3: # include "ctype.h"
4: # include "assert.h"
5: # include "weath.h"
6: # include "signal.h"
7: # include "setjmp.h"
8: # include "math.h"
9: # include "sys/types.h"
10: # include "time.h"
11: # include "sys/timeb.h"
12: # define SAME 0
13:
14: double md=1000., dist();
15: struct timeb ftb;
16: bfile *bf;
17: char *index(), *timezone(), *relhum();
18: struct tm *localtime();
19: bfile *townfile;
20: int marine=0, intr();
21: jmp_buf env;
22: char *direct[] =
23: {"N", "NE", "E", "SE", "S", "SW", "W", "NW", "N", "xx", "yy"};
24:
25: main(argc,argv)
26: char *argv[];
27: {
28: char request[100];
29: townfile = bopen("/usr/mel/ustowns/ustownsn", 0);
30: if (townfile==NULL)
31: {
32: fprintf(stderr, "No town list - is /crp mounted?\n");
33: exit(1);
34: }
35: bf = bopen("/data/weather/airn", 0);
36: assert(bf!=NULL);
37: ftime(&ftb);
38: argc--; argv++;
39: while (argc>0 && argv[0][0]=='-')
40: {
41: switch(argv[0][1])
42: {
43: case 'm': marine=1; break;
44: case 'h': strcpy(request, "murray hill, nj"); break;
45: default:
46: fprintf(stderr, "Unknown arg: %s\n", argv[0]);
47: break;
48: }
49: argc--; argv++;
50: }
51: if (argc>1)
52: {
53: fprintf(stderr, "Sorry: weather changed to expect town on standard input.\n");
54: fprintf(stderr, "Default MH is now 'weather -h'\n");
55: return(0);
56: }
57: if (request[0])
58: wprint(request);
59: else
60: while (1) /* this loop is basically while (gets(request)) with interrupt */
61: {
62: setjmp(env);
63: signal(SIGINT, SIG_DFL);
64: if (gets(request)==NULL)
65: break;
66: signal(SIGINT, intr);
67: wprint(request);
68: }
69: return(0);
70: }
71: wprint(request)
72: char *request;
73: {
74: char sna[100], rka[100], rra[300];
75: double lat, lng;
76: mbuf key, rkey, rrec;
77: int townfind;
78: rkey.mdata = rka; rrec.mdata = rra;
79: lcase(request);
80: while (isspace(*request)) request++;
81: if (*request==0) return;
82: townfind=0;
83: key.mdata = request; key.mlen = strlen(request);
84: bseek(townfile, key);
85: while (bread(townfile, &rkey, &rrec)==NULL)
86: {
87: rkey.mdata[rkey.mlen]=0;
88: rrec.mdata[rrec.mlen]=0;
89: if (strncmp(rkey.mdata, request, key.mlen)!=SAME)
90: break;
91: townfind++;
92: md=1000;
93: sscanf(rra, "%lf%lf", &lat, &lng);
94: caps(rka);
95: printf("%s: (%.3f N, %.3f W)\n", rka, lat, lng);
96: strcpy(sna, rka);
97: /* floating remainder not defined, so... */
98: weather(lat, lng);
99: lfmfore(lat, lng);
100: forecast(lat, lng);
101: }
102: if (townfind==0)
103: fprintf(stderr, "No such town\n");
104: return;
105: }
106: concat (out, ac, av)
107: char *out, *av[];
108: {
109: int i;
110: out[0]=0;
111: for(i=1; i<ac; i++)
112: {
113: strcat(out, av[i]);
114: if (i+1<ac)
115: strcat(out, " ");
116: }
117: return;
118: }
119: double
120: dist (aplat, aplon, bplat, bplon)
121: double aplon, aplat, bplon, bplat;
122: {
123: /* this code is from the picadad manual. I don't pretend
124: to understand it. */
125: double as, bs, ac, bc, p, cd, d, er;
126: double rad=0.0174532925;
127: er = aplon-bplon;
128: if (er<0) er= -er;
129: if (er<0.001)
130: {
131: d = aplat-bplat;
132: if (d<0) d= -d;
133: return(d*69.055);
134: }
135: as = sin(rad*aplat);
136: bs = sin(rad*bplat);
137: ac = cos(rad*aplat);
138: bc = cos(rad*bplat);
139: p = cos(er*rad);
140: cd = (as*bs+ac*bc*p);
141: return( acos(cd)*3956.56);
142: }
143: bearing (lat, lng, alat, alng)
144: double lat, lng, alat, alng;
145: { /* gives bearing of alat, alng from lat, lng as 0-7 */
146: # define PI 3.1415926
147: double dlat, dlng, b;
148: dlat = alat-lat;
149: dlng = (alng-lng)*cos(PI*(lat+alat)/360.);
150: b = atan2(-dlng, dlat); /* range -pi to +pi */
151: b = b*(180./PI);
152: if (b<0) b=360+b;
153: return( (int) (b+22.5)/45.0);
154: }
155: lcase (s)
156: char *s;
157: {
158: int c;
159: for( ; c= *s; s++)
160: if (isupper(c))
161: *s = tolower(c);
162: }
163: caps(s)
164: char *s;
165: {
166: int c;
167: if (islower(*s)) *s = toupper(*s);
168: for( s++; c= *s; s++)
169: {
170: if (islower(c) && (s[-1]==' ' || s[-1]=='-'))
171: if (strncmp(s, "of ", 3)!=SAME)
172: *s = toupper(c);
173: if (*s==',') break;
174: }
175: for(s++; c= *s; s++)
176: if (islower(c)) *s=toupper(c);
177: }
178: weather(north, west)
179: double north, west;
180: {
181: double d, dist(), md=5000., tnf, twf;
182: char tn[10], tw[10], *x, *y, fname[100], *vis(), odata[2000], *airname();
183: char *ampm, *tz, tb[10];
184: int hr, min;
185: struct wline *wp, *bwp;
186: int n, w, f, kbear, isair, windsp, wdir, gust;
187: n = north;
188: n = n-n%4;
189: w = west;
190: w = w-w%4;
191: bwp=NULL;
192: sprintf(fname, "/data/weather/obs/%.2d.%.2d", n, w);
193: f = open(fname, 0);
194: if (f<0) return;
195: printf("fname %s\n", fname);
196: n=read(f, odata, 2000);
197: assert(n<2000);
198: /* next line is for(wp=odata; wp<odata+n; wp++) after delinting */
199: for(wp=(struct wline *) odata; wp< (struct wline *)(odata+n); wp++)
200: {
201: strncpy(tn, wp->nlat, 5); tn[5]=0;
202: strncpy(tw, wp->nlng, 6); tw[6]=0;
203: d = dist(tnf=atof(tn), twf=atof(tw), north, west);
204: printf("airport %.3s dist %f\n", wp, d);
205: if (d<md)
206: {
207: md=d;
208: kbear = bearing(north, west, tnf, twf);
209: bwp=wp;
210: }
211: }
212: close(f);
213: if (bwp==NULL) return;
214: strncpy(tn, bwp->anam, 3); tn[3]=0;
215: x = airname(tn);
216: x = index(x, ' ');
217: while (isspace(*x))x++;
218: for(y=x+1; *y != ','; y++)
219: if (isupper(*y) && isalpha(y[-1]))
220: *y = tolower(*y);
221: y = index(x, '*');
222: if (y==NULL)
223: isair=1;
224: else
225: {
226: *y=0;
227: isair=0;
228: }
229: strncpy(tw, bwp->wweath, 6); tw[6]=0;
230: y = vis(tw, bwp->wcloud[0]);
231: if (y==NULL) return;
232: printf("%.1f miles %s at%s %s", md, direct[kbear],
233: isair ? " the airport in" : "", x);
234: strncpy(tb, bwp->wtime, 4); tb[4]=0;
235: hr = atoi(tb);
236: min = hr%100;
237: hr = hr/100;
238: hr = hr - ftb.timezone/60;
239: if (ftb.dstflag) hr++;
240: if (hr < 0) hr+=24;
241: ampm = (hr>11) ? "PM" : "AM";
242: if (hr>12) hr -= 12;
243: tz = timezone(ftb.timezone, ftb.dstflag);
244: printf(" (%d:%.2d %s %s):\n", hr, min, ampm, tz);
245: strncpy(tb, bwp->wtemp, 3); tb[3]=0;
246: strncpy(tn, bwp->wdewpt, 3); tn[3]=0;
247: printf(" temperature %.3s, humidity %s, weather%s",
248: bwp->wtemp, relhum(atoi(tb), atoi(tn)), y);
249: windsp = atoi(bwp->wwind+2);
250: if (windsp >10)
251: {
252: bwp->wwind[2]=0;
253: wdir = atoi(bwp->wwind);
254: if (bwp->wwind[4]=='G')
255: gust = atoi(bwp->wwind+5);
256: else
257: gust=0;
258: wdir = (wdir*10+22.5)/45.0;
259: printf(",\n winds at %d knots", windsp);
260: printf(" from the %s", direct[wdir]);
261: if (gust) printf(" gusting to %d", gust);
262: }
263: printf("\n");
264: }
265: char *
266: vis(s, cloud)
267: char *s;
268: {
269: int d;
270: static char temp[80];
271: char tb[30];
272: while (isspace(*s)) s++;
273: d= atoi(s);
274: while (isdigit(*s)) s++;
275: if (!isalpha(*s))
276: {
277: switch(cloud)
278: {
279: case 'C': s= "clear"; break;
280: case 'P': s= "partly cloudy"; break;
281: case 'O': s= "overcast"; break;
282: default: s= "ordinary"; break;
283: }
284: sprintf(temp, " %s, visibility %d miles", s, d);
285: return(temp);
286: }
287: temp[0]=0;
288: for( ; *s; s++)
289: switch(*s)
290: {
291: case 'A': strcat(temp, " hail"); break;
292: case 'D': strcat(temp, " dust"); break;
293: case 'F': strcat(temp, " fog"); break;
294: case 'H': strcat(temp, " haze"); break;
295: case 'I': if (s[1]=='P') strcat(temp, " sleet"); break;
296: case 'K': strcat(temp, " smoke"); break;
297: case 'L': strcat(temp, " drizzle"); break;
298: case 'R': strcat(temp, " rain"); break;
299: case 'W': strcat(temp, " showers"); break;
300: case 'S': strcat(temp, " snow"); break;
301: case 'T': strcat(temp, " thunderstorms"); break;
302: case 'Z': strcat(temp, " freezing"); break;
303: case ' ':
304: case '-': break;
305: default: return(NULL);
306: }
307: sprintf(tb, ", visibility %d miles", d);
308: strcat(temp, tb);
309: return(temp);
310: }
311: char *
312: airname(s)
313: char *s;
314: {
315: int i;
316: mbuf key, rkey, rec;
317: static char rb[100], rkb[100];
318: key.mdata = s;
319: key.mlen = strlen(s);
320: i=bseek(bf, key);
321: if (i!=1) return(NULL);
322: rkey.mdata =rkb; rec.mdata = rb;
323: bread(bf, &rkey, &rec);
324: rkey.mdata[rkey.mlen]=0;
325: assert(strcmp(rkey.mdata, key.mdata)==0);
326: rkey.mdata[rkey.mlen]=0;
327: rec.mdata[rec.mlen]=0;
328: return(rec.mdata);
329: }
330: lfmfore(north, west)
331: double north, west;
332: {
333: double d, dist(), md=5000., tnf, twf;
334: char aname[10], *x, *y, fname[60], xl[30], ln[60], lf1[60], ltime[20];
335: int n, w, in, jw, iw, jn;
336: int p1, p2, max, min, hr, dy; char *ampm, *revampm, *tz;
337: FILE *f;
338: n = north;
339: n = n-n%4;
340: w = west;
341: w = w-w%4;
342: in = jn = n;
343: if ( (int) north %4 >=2) jn+=4; else in-=4;
344: iw = jw = w;
345: if ( (int) west %4 >=2 ) jw+=4; else iw-=4;
346: aname[0]=0;
347: for(n=in; n<=jn; n+=4)
348: for(w=iw; w<=jw; w+=4)
349: {
350: sprintf(fname, "/data/weather/lfm/%.2d.%.2d", n, w);
351: f = fopen(fname, "r");
352: if (f==NULL) continue;
353: while (fgets(xl, 20, f))
354: {
355: tnf = atof(xl+4);
356: twf = atof(xl+9);
357: d = dist(tnf, twf, north, west);
358: if (d<md)
359: {
360: md=d;
361: strncpy(aname, xl, 3);
362: aname[3]=0;
363: }
364: }
365: fclose(f);
366: }
367: if (aname[0]==0) return;
368: sprintf(fname, "/data/weather/lfm/%s", aname);
369: f = fopen(fname, "r");
370: if (f==NULL) return;
371: puts("");
372: fgets(ln, 60, f);
373: trimnl(ln);
374: for(x=ln+1; *x!= ','; x++)
375: if (isupper(*x) && isalpha(x[-1]))
376: *x = tolower(*x);
377: y = index(ln, '*');
378: if (y!=NULL) *y=0;
379: printf("Next 48 hours at %s\n", ln);
380: while (fgets(lf1, 60, f))
381: {
382: sscanf(lf1, "%s %d %d %d %d", ltime, &max, &min, &p1, &p2);
383: hr = atoi(ltime+3);
384: dy = atoi(ltime);
385: hr = hr - ftb.timezone/60;
386: hr += 12; /* question is whether the periods end or start as shown
387: in forecast ; this converts to ending */
388: if (hr>=24)
389: {
390: /* this should not be executed ever,since orign hr is 0 or 12 and
391: then we subract 4; */
392: hr-=24; dy++;
393: }
394: if (ftb.dstflag) hr++;
395: if (hr<0) {
396: hr += 24;
397: dy = down(dy);
398: }
399: ampm = (hr>11) ? "PM" : "AM";
400: revampm = (hr>11) ? "AM" : "PM";
401: if (hr>12) hr -= 12;
402: tz = timezone(ftb.timezone, ftb.dstflag);
403: printf("To %d %s %s /%d: high %d low %d, prob. precip. to %d %s %d%% to %d %s %d%%\n",
404: hr, ampm, tz, dy, max, min, hr, revampm, p1, hr, ampm, p2);
405: }
406: fclose(f);
407: }
408: int monlen[12] =
409: /*Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
410: { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
411: down(dy)
412: { /* subtracts one from the day */
413: struct tm *tp;
414: int mn;
415: if (--dy>0) return(dy);
416: tp = localtime(&ftb.time);
417: mn = tp->tm_mon;
418: if (tp->tm_mday<10) mn--;
419: dy = monlen[mn];
420: if (dy==28 && tp->tm_year%4==0)
421: dy++;
422: return(dy);
423: }
424: forecast(north, west)
425: double north, west;
426: {
427: double d, dist(), md=5000., tnf, twf;
428: char aname[10], fname[100], xl[30];
429: int n, w, in, jw, iw, jn;
430: FILE *f;
431: n = north;
432: n = n-n%4;
433: w = west;
434: w = w-w%4;
435: in = jn = n;
436: if ( (int) north %4 >=2) jn+=4; else in-=4;
437: iw = jw = w;
438: if ( (int) west %4 >=2 ) jw+=4; else iw-=4;
439: aname[0]=0;
440: for(n=in; n<=jn; n+=4)
441: for(w=iw; w<=jw; w+=4)
442: {
443: sprintf(fname, "/data/weather/fore/f_%.2d.%.2d", n, w);
444: f = fopen(fname, "r");
445: if (f==NULL) continue;
446: while (fgets(xl, 20, f))
447: {
448: tnf = atof(xl+4);
449: twf = atof(xl+9);
450: d = dist(tnf, twf, north, west);
451: if (d<md)
452: {
453: md=d;
454: strncpy(aname, xl, 3);
455: aname[3]=0;
456: }
457: }
458: fclose(f);
459: }
460: if (aname[0]==0) return;
461: sprintf(fname, "/data/weather/fore/f_%s", aname);
462: f = fopen(fname, "r");
463: if (f!=NULL)
464: {
465: puts("");
466: while (fgets(fname, 100, f))
467: fputs(fname, stdout);
468: fclose(f);
469: }
470: if (marine)
471: {
472: sprintf(fname, "/data/weather/fore/m_%s", aname);
473: f = fopen(fname, "r");
474: if (f!=NULL)
475: {
476: if (f==NULL) return;
477: puts("");
478: while (fgets(fname, 100, f))
479: fputs(fname, stdout);
480: fclose(f);
481: }
482: }
483: puts("");
484: }
485: trimnl(s)
486: char *s;
487: {
488: while (*s)s++;
489: if (*--s=='\n')*s=0;
490: }
491: intr()
492: {
493: longjmp(env, 0);
494: }
495: struct table {
496: int temp;
497: int rh[15];
498: }tab[21] = {
499: {100,100,94,88,83,78,73,69,65,61,57,53,45,38,32,27},
500: {95,100,94,88,83,78,73,68,64,60,56,53,44,37,31,26},
501: {90,100,94,88,83,77,73,68,64,59,56,52,44,37,31,25},
502: {85,100,94,88,82,77,72,67,63,58,55,51,43,36,30,25},
503: {80,100,94,88,82,77,72,67,62,58,54,51,42,35,29,24},
504: {75,100,94,87,82,76,71,66,62,58,54,50,42,34,28,23},
505: {70,100,93,87,81,76,71,66,61,57,53,49,41,34,28,23},
506: {65,100,93,87,81,75,70,65,61,57,52,49,40,33,27,22},
507: {60,100,93,87,81,75,70,65,60,56,52,48,39,32,26,21},
508: {55,100,93,86,80,75,69,64,59,55,51,47,39,31,25,20},
509: {50,100,93,86,80,74,69,64,59,54,50,46,38,31,25,20},
510: {45,100,93,86,80,74,68,63,58,54,49,46,37,30,24,19},
511: {40,100,93,86,79,73,68,62,57,53,49,45,36,29,23,18},
512: {35,100,92,85,79,73,67,61,57,52,48,44,35,28,22,18},
513: {30,100,92,85,78,72,66,61,56,51,47,43,34,27,21,17},
514: {25,100,92,85,78,72,66,60,55,51,46,42,33,26,21,16},
515: {20,100,92,84,77,71,65,60,54,50,45,41,33,25,20,15},
516: {15,100,92,84,77,70,64,59,54,49,44,40,32,25,19,14},
517: {10,100,92,84,76,70,64,58,53,48,43,39,31,24,18,14},
518: {5,100,92,83,76,69,63,57,52,47,42,38,30,23,17,13},
519: {0,100,91,83,75,68,63,56,51,46,41,37,29,22,16,12}
520: };
521: int ddline[15] = {0,2,4,6,8,10,12,14,16,18,20,25,30,35,40};
522: char *
523: relhum(temp, dewpt)
524: {
525: int del1,del2,dd, i, j;
526: static char val[20];
527: dd = temp - dewpt;
528: if (dd < 0)
529: return("??");
530: if (dd > 40)
531: return("dry");
532: temp = ((temp+2)/5)*5;
533: for (i=0;i<15;i++) {
534: if (dd <= ddline[i]) {
535: del1 = ddline[i]-dd;
536: del2 = ddline[i]-ddline[i-1];
537: break;
538: }
539: }
540: for(j=0;j<22;j++) {
541: if (j==21)
542: return("??");
543: else if (tab[j].temp == temp) {
544: sprintf(val, "%d",
545: tab[j].rh[i]+((del1*(tab[j].rh[i-1]-tab[j].rh[i]))/del2));
546: return(val);
547: }
548: }
549: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.