-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSTORM.BAS
664 lines (664 loc) · 35.3 KB
/
STORM.BAS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
10 CLEAR
20 REM *** HURRICANE TRACKING PROGRAM FOR KAYPRO WRITTEN IN MBASIC-80 BY CHRISTOPHER D. VAN DER KAAY 2024 ***
25 GOSUB 13000 ' SUBROUTINE TO CREATE OPENING SCREEN OF PROGRAM
30 DIM LAT(20), LON(20), WDSPD(20), DRECT(20), SPEED(20), PRJLT(3), PRJLN(3), DCHANGE(20), PRESSURE(10, 3), CPRESS(20), PRJWND(3)
32 DIM ACTLT(20), ACTLN(20) ' ARRAYS FOR ACTUAL MEASURED POSITIONS
33 DIM WINDR (12,5), WINDRADII(12) 'ARRAYS TO CALCULATE PROJECTED THREE DAY WIND SPEED RADII
35 DIM X(4), P(4,4), Q(4,4), R(4,4), K(4,4), Z(4,1), F(4,4), H(4,4), S(4,4), INVS(2,2)
37 INIT = 0 ' VARIABLE IN THE KALMAN FILTER SUBROUTINE TO CONTROL INITIALIZATION
40 PI = 3.14159265358979
50 R = 6371 ' RADIUS OF EARTH IN KILOMETERS
55 DT = 1 ' TIME DELAY FOR KALMAN FILTER
60 MNLAT = 90: MXLAT = -90: MNLON = 180: MXLON = -180
63 NUMDAYS = 3 ' HURRICANE PROJECTION DURATION
67 LMBDA = 0.7 ' INITIALIZE LAMBDA VALUE
70 PRINT CHR$(12) ' CLEAR SCREEN
75 MENU = (80 - LEN(" HURRICANE TRACKER FOR THE KAYPRO II COMPUTER ")) / 2
80 PRINT STRING$(MENU, "*") " HURRICANE TRACKER FOR THE KAYPRO II COMPUTER " STRING$(MENU, "*")
100 PRINT "THIS PROGRAM CALCULATES A PROJECTED PATH OF HURRICANES & VARIOUS RELATED DATA"
110 PRINT
120 PRINT "ESTIMATION METHOD: LINEAR AND EXPONENTIAL WEIGHTING WITH KALMAN FILTERING"
130 PRINT "PARAMETERS: DIRECTION, SPEED, COORDINATES, DIRECTIONAL CHANGES, CENTRAL PRESSURE"
160 PRINT "- PREDICTIVE MODEL: USES TIME-DECAY WEIGHTING, LINEAR & EXPONENTIAL AVERAGING"
170 PRINT "- VISUAL REPRESENTATION: PROJECTED 3 DAY & HISTORIC PATHS ON ASCII MAP"
180 PRINT "- KALMAN FILTER: IMPROVES ACCURACY OF PROJECTED POSITIONS"
190 PRINT "- WIND SPEED AND RADII PROJECTIONS: ESTIMATES FOR 3 DAYS BASED ON HISTORICAL DATA"
195 PRINT "- CALCULATES DISTANCES: USES HAVERSINE FORMULA FOR DISTANCE CALCULATIONS"
200 PRINT:PRINT "OPTIONS:"
210 PRINT "1. MANUAL ENTRY OF HURRICANE DATA (MAX 20 DAYS); DATA SAVED TO STORM.DAT"
220 PRINT "2. LOAD FROM FILE (E.G., ELENA.DAT); SEE STORM.TXT FOR FILE LAYOUT"
223 PRINT "3. USE PRESET VALUES AND GO TO MAIN MENU"
240 PRINT:PRINT "CHOOSE AN OPTION (1, 2, OR 3): ";: INPUT OPTN$
242 IF OPTN$ < "1" OR OPTN$ > "3" THEN PRINT "INVALID SELECTION! PLEASE ENTER 1, 2, OR 3": GOTO 240
245 IF OPTN$ = "1" THEN GOTO 260
246 IF OPTN$ = "2" THEN GOTO 1300
247 IF OPTN$ = "3" THEN GOSUB 19000 : GOTO 1600 ' INITIALIZE HURRICANE DATA, DEFAULT HOME LOCATION, AND JUMP TO MAIN MENU
249 GOTO 200
260 PRINT "HOW MANY DAYS DO YOU WANT TO ENTER (2-20)";: INPUT NMDAYS
270 IF NMDAYS < 2 OR NMDAYS > 20 THEN PRINT CHR$(7):PRINT "INVALID NUMBER OF POINTS! PLEASE ENTER A VALUE BETWEEN 1 AND 20.": GOTO 260
280 REM INPUT HURRICANE DATA
290 FOR I = 1 TO NMDAYS
300 PRINT "ENTER DATA FOR DAY "; I
310 REM INPUT STORM DIRECTION AND SPEED FOR EACH DAY
312 INPUT "CENTRAL PRESSURE IN MILLIBARS (860-1090): ", CPRESS
314 WHILE CPRESS < 860 OR CPRESS > 1090
316 PRINT CHR$(7):PRINT "INVALID CENTRAL PRESSURE! PLEASE ENTER A VALUE BETWEEN 860-1050."
317 INPUT "CENTRAL PRESSURE IN MILLIBARS (860-1090): ", CPRESS
318 WEND
319 CPRESS(I) = CPRESS
320 INPUT "DIRECTION IN DEGREES (0-360): ", DRECT
330 WHILE DRECT < 0 OR DRECT > 360
340 PRINT CHR$(7):PRINT "INVALID DIRECTION! PLEASE ENTER A VALUE BETWEEN 0 AND 360."
350 INPUT "DIRECTION IN DEGREES (0-360): ", DRECT
360 WEND
370 DRECT(I) = DRECT
380 INPUT "TRANSLATIONAL SPEED (MOVEMENT SPEED) IN KT: ", SPEED
390 WHILE SPEED < 0 OR SPEED > 100
400 PRINT CHR$(7):PRINT "INVALID TRANSLATIONAL SPEED (MOVEMENT SPEED)! PLEASE ENTER A REALISTIC VALUE."
410 INPUT "TRANSLATIONAL SPEED (MOVEMENT SPEED) IN KT: ", SPEED
420 WEND
430 SPEED(I) = SPEED
440 INPUT "LATITUDE (E.G., 19.3N OR 19.3S): ", LATI$
450 WHILE RIGHT$(LATI$, 1) <> "N" AND RIGHT$(LATI$, 1) <> "S"
460 PRINT CHR$(7):PRINT "INVALID LATITUDE! ONLY NORTH (N) AND SOUTH (S) LATITUDES ARE ALLOWED."
470 INPUT "LATITUDE (E.G., 19.3N OR 19.3S): ", LATI$
480 WEND
490 INPUT "LONGITUDE (E.G., 56.5E OR 56.5W): ", LONGI$
500 WHILE RIGHT$(LONGI$, 1) <> "E" AND RIGHT$(LONGI$, 1) <> "W"
510 PRINT CHR$(7):PRINT "INVALID LONGITUDE! ONLY EAST (E) AND WEST (W) LONGITUDES ARE ALLOWED."
520 INPUT "LONGITUDE (E.G., 56.5E OR 56.5W): ", LONGI$
530 WEND
540 INPUT "MAX SUSTAINED WIND SPEED (1-220 KT): ", WDSPD
550 IF WDSPD < 1 OR WDSPD > 220 THEN PRINT CHR$(7): PRINT "INVALID WIND SPEED. PLEASE ENTER A REALISTIC VALUE.": GOTO 540
560 WDSPD(I) = WDSPD
570 IF RIGHT$(LATI$, 1) = "S" THEN LAT(I) = VAL(LEFT$(LATI$, LEN(LATI$) - 1)) * -1: GOTO 590
580 LAT(I) = VAL(LEFT$(LATI$, LEN(LATI$) - 1))
590 IF RIGHT$(LONGI$, 1) = "W" THEN LON(I) = VAL(LEFT$(LONGI$, LEN(LONGI$) - 1)) * -1: GOTO 610
600 LON(I) = VAL(LEFT$(LONGI$, LEN(LONGI$) - 1))
610 PRINT CHR$(7):PRINT "*********************************"
620 PRINT " SUMMARY FOR DAY "; I
630 PRINT "*********************************"
640 PRINT "LATITUDE: "; LAT(I)
650 PRINT "LONGITUDE: "; LON(I)
655 PRINT "CENTRAL PRESSURE: "; CPRESS(I); " MB"
660 PRINT "MAX SUSTAINED WIND SPEED: "; WDSPD(I); " KT"
670 PRINT "STORM DIRECTION: "; DRECT(I); " DEGREES"
680 PRINT "TRANSLATIONAL SPEED: "; SPEED(I); " KT"
690 PRINT "*********************************"
700 NEXT I
710 GOSUB 10000 ' END OF MANUAL ENTRY AND WRITE TO FILE STORM.DAT
720 GOTO 1600 ' JUMP TO MAIN MENU
1300 REM *** USER FILE LOAD MENU ***
1310 PRINT CHR$(12):INPUT "DO YOU WANT TO VIEW YOUR DATA FILES (Y/N)? ", CHOICE$
1320 REM IF CHOICE$ = "Y" THEN FILES ELSE 1310
1330 PRINT:INPUT "SPECIFY THE DATA FILE TO LOAD: ", FILE$
1340 IF FILE$ = "" THEN PRINT CHR$(7):PRINT "YOU MUST SPECIFY A FILE.":GOTO 1310
1350 REM ON ERROR GOTO 30
1360 REM OPEN "I",1,FILE$
1370 PRINT "ATTEMPTING TO OPEN FILE..."
1380 REM INPUT #1, NMDAYS
1390 FOR I = 1 TO NMDAYS
1400 REM IF EOF(1) THEN PRINT:PRINT CHR$(7):"ERROR LOADING FILE! MISSING DATA.":CLOSE 1: GOTO 30
1405 REM INPUT #1, DRECT(I)
1410 REM IF EOF(1) THEN PRINT:PRINT CHR$(7):"ERROR LOADING FILE! MISSING DATA.":CLOSE 1: GOTO 30
1420 REM INPUT #1, SPEED(I)
1430 REM IF EOF(1) THEN PRINT:PRINT CHR$(7):"ERROR LOADING FILE! MISSING DATA.":CLOSE 1: GOTO 30
1440 REM INPUT #1, LAT(I)
1450 REM IF EOF(1) THEN PRINT:PRINT CHR$(7):"ERROR LOADING FILE! MISSING DATA.":CLOSE 1: GOTO 30
1460 REM INPUT #1, LON(I)
1463 REM IF EOF(1) THEN PRINT:PRINT CHR$(7):"ERROR LOADING FILE! MISSING DATA.":CLOSE 1: GOTO 30
1465 REM INPUT #1, CPRESS(I)
1470 REM IF EOF(1) THEN PRINT:PRINT CHR$(7):"ERROR LOADING FILE! MISSING DATA.":CLOSE 1: GOTO 30
1480 REM INPUT #1, WDSPD(I)
1490 REM IF EOF(1) THEN PRINT CHR$(7):PRINT "FILE LOADED. EXITING DATA READ ROUTINE...": CLOSE 1: GOTO 1600
1500 NEXT I
1510 END
1600 REM *** MAIN MENU ***
1601 GOSUB 1800 ' SUBROUTINE FOR MAIN PROGRAM CALCULATIONS
1602 GOSUB 5000
1605 PRINT CHR$(12) 'CLEAR SCREEN
1610 PRINT STRING$(77, "*")
1615 PRINT TAB(25);"HURRICANE TRACKING PROGRAM"
1616 PRINT TAB(29);"MAIN MENU"
1620 PRINT STRING$(77, "*")
1625 PRINT
1630 PRINT TAB(5);"1. UPDATE HOME SELECTION (CURRENT HOME SELECTION IS ";HMCITY$;")"
1635 PRINT TAB(5);"2. GENERATE HURRICANE TRACKING MAP"
1640 PRINT TAB(5);"3. MAP LEGEND"
1645 PRINT TAB(5);"4. STORM PROJECTION DATA"
1650 PRINT TAB(5);"5. WIND SPEED RADII PROJECTIONS"
1660 PRINT TAB(5);"6. GENERATE PRINTED REPORT"
1663 PRINT TAB(5);"7. ADJUST LAMBDA VALUE"
1665 PRINT TAB(5);"8. PROGRAM INFORMATION"
1670 PRINT TAB(5);"9. RESTART PROGRAM (ENTER NEW OR LOAD DATA)"
1675 PRINT TAB(5);"10. END PROGRAM"
1680 PRINT
1685 PRINT STRING$(77, "*")
1690 PRINT "CHOOSE AN OPTION (1-10): ";: INPUT MENU$
1695 IF MENU$ < 1 OR MENU$ > 10 THEN PRINT "INVALID SELECTION! PLEASE ENTER A NUMBER BETWEEN 1 AND 10": GOTO 1690
1700 IF MENU$ = "1" THEN GOTO 12000
1705 IF MENU$ = "2" THEN GOTO 2520
1710 IF MENU$ = "3" THEN GOTO 9000
1715 IF MENU$ = "4" THEN GOTO 9400
1720 IF MENU$ = "5" THEN GOTO 30000
1735 IF MENU$ = "6" THEN GOTO 16000
1737 IF MENU$ = "7" THEN GOTO 4000
1740 IF MENU$ = "8" THEN GOTO 25000
1745 IF MENU$ = "9" THEN GOTO 10
1747 IF MENU$ = "10" THEN PRINT "THANK YOU FOR USING THE HURRICANE TRACKER PROGRAM!"
1750 END
1800 REM *** SUBROUTINE FOR MAIN PROGRAM CALCULATIONS ***
1805 TOTDRECT = 0
1810 TOTSPEED = 0
1815 TOTALWEIGHT = 0
1820 FOR I = 1 TO NMDAYS
1825 TOTDRECT = TOTDRECT + DRECT(I) * I
1830 TOTSPEED = TOTSPEED + SPEED(I) * I
1835 TOTALWEIGHT = TOTALWEIGHT + I
1840 NEXT I
1845 REM CALCULATE DIRECTIONAL CHANGE BETWEEN POINTS
1850 FOR I = 2 TO NMDAYS
1855 DCHANGE(I) = DRECT(I) - DRECT(I-1)
1860 NEXT I
1865 AVGCHANGE = 0
1870 WEIGHTSUM = 0
1875 LMBDA = 0.9
1880 FOR I = 2 TO NMDAYS
1885 WEIGHT = LMBDA ^ (NMDAYS - I)
1890 AVGCHANGE = AVGCHANGE + DCHANGE(I) * WEIGHT
1895 WEIGHTSUM = WEIGHTSUM + WEIGHT
1900 NEXT I
1905 AVGCHANGE = AVGCHANGE / WEIGHTSUM
1910 AVGDRCT = TOTDRECT / TOTALWEIGHT
1915 AVGSPEED = TOTSPEED / TOTALWEIGHT
1930 FOR DAY = 1 TO NUMDAYS
1935 DX = SIN((AVGDRCT + (DAY * AVGCHANGE)) * PI / 180) * AVGSPEED * 24 * 1.852 / 111
1940 DY = COS((AVGDRCT + (DAY * AVGCHANGE)) * PI / 180) * AVGSPEED * 24 * 1.852 / 111
1945 IF DAY <> 1 THEN GOTO 1965
1950 PRJLT(DAY) = LAT(NMDAYS) + DY
1955 PRJLN(DAY) = LON(NMDAYS) + DX
1960 GOTO 1975
1965 PRJLT(DAY) = PRJLT(DAY-1) + DY
1970 PRJLN(DAY) = PRJLN(DAY-1) + DX
1975 REM SIMULATE ACTUAL MEASUREMENT DATA FOR KALMAN FILTER DEMONSTRATION
1980 REM IN REAL-WORLD USE, REPLACE THESE LINES WITH CODE TO INPUT ACTUAL MEASURED POSITIONS
1985 REM CURRENT SIMULATION ADDS SMALL RANDOM DEVIATIONS TO PROJECTED POSITIONS
1990 ACTLT(DAY) = PRJLT(DAY) + (RND - 0.5) * 0.1 ' SIMULATED ACTUAL LATITUDE
1995 ACTLN(DAY) = PRJLN(DAY) + (RND - 0.5) * 0.1 ' SIMULATED ACTUAL LONGITUDE
2000 GOSUB 20000 ' CALL KALMAN FILTER SUBROUTINE
2005 NEXT DAY
2010 REM FIND EXTREMES IN LATITUDE AND LONGITUDE FOR ALL POINTS
2015 FOR I = 1 TO NMDAYS
2020 IF LAT(I) > MXLAT THEN MXLAT = LAT(I)
2025 IF LAT(I) < MNLAT THEN MNLAT = LAT(I)
2030 IF LON(I) > MXLON THEN MXLON = LON(I)
2035 IF LON(I) < MNLON THEN MNLON = LON(I)
2040 NEXT I
2050 REM UPDATE EXTREMES TO INCLUDE HOME AND PROJECTED LOCATIONS
2055 IF HMELT > MXLAT THEN MXLAT = HMELT
2060 IF HMELT < MNLAT THEN MNLAT = HMELT
2065 IF HMELN > MXLON THEN MXLON = HMELN
2070 IF HMELN < MNLON THEN MNLON = HMELN
2075 IF PRJLT(NUMDAYS) > MXLAT THEN MXLAT = PRJLT(NUMDAYS)
2080 IF PRJLT(NUMDAYS) < MNLAT THEN MNLAT = PRJLT(NUMDAYS)
2085 IF PRJLN(NUMDAYS) > MXLON THEN MXLON = PRJLN(NUMDAYS)
2090 IF PRJLN(NUMDAYS) < MNLON THEN MNLON = PRJLN(NUMDAYS)
2095 RETURN
2520 REM ***INITIALIZE ASCII MAP CREATION
2525 PRINT CHR$(12) 'CLEAR SCREEN
2527 GOSUB 3000
2530 GDXHM = 5 + INT((HMELN - MNLON) * 70 / (MXLON - MNLON)) ' CALCULATE HOME X-COORDINATE
2540 GDYHM = 9 - INT((HMELT - MNLAT) * 8 / (MXLAT - MNLAT)) ' CALCULATE HOME Y-COORDINATE
2550 REM Calculate map coordinates for additional reference points
2555 GDX_PR = 5 + INT((PR_LON - MNLON) * 70 / (MXLON - MNLON))
2560 GDY_PR = 9 - INT((PR_LAT - MNLAT) * 8 / (MXLAT - MNLAT))
2565 GDX_CUBA = 5 + INT((CUBA_LON - MNLON) * 70 / (MXLON - MNLON))
2570 GDY_CUBA = 9 - INT((CUBA_LAT - MNLAT) * 8 / (MXLAT - MNLAT))
2575 GDX_BAHAMAS = 5 + INT((BAHAMAS_LON - MNLON) * 70 / (MXLON - MNLON))
2580 GDY_BAHAMAS = 9 - INT((BAHAMAS_LAT - MNLAT) * 8 / (MXLAT - MNLAT))
2595 GDX_MIAMI = 5 + INT((MIAMI_LON - MNLON) * 70 / (MXLON - MNLON))
2600 GDY_MIAMI = 9 - INT((MIAMI_LAT - MNLAT) * 8 / (MXLAT - MNLAT))
2605 GDX_TAMPA = 5 + INT((TAMPA_LON - MNLON) * 70 / (MXLON - MNLON))
2610 GDY_TAMPA = 9 - INT((TAMPA_LAT - MNLAT) * 8 / (MXLAT - MNLAT))
2615 GDX_KW = 5 + INT((KW_LON - MNLON) * 70 / (MXLON - MNLON))
2620 GDY_KW = 9 - INT((KW_LAT - MNLAT) * 8 / (MXLAT - MNLAT))
2625 GDX_JAX = 5 + INT((JAX_LON - MNLON) * 70 / (MXLON - MNLON))
2630 GDY_JAX = 9 - INT((JAX_LAT - MNLAT) * 8 / (MXLAT - MNLAT))
2631 GDX_PEN = 5 + INT((PEN_LON - MNLON) * 70 / (MXLON - MNLON))
2632 GDY_PEN = 9 - INT((PEN_LAT - MNLAT) * 8 / (MXLAT - MNLAT))
2633 GDX_MOB = 5 + INT((MOB_LON - MNLON) * 70 / (MXLON - MNLON))
2634 GDY_MOB = 9 - INT((MOB_LAT - MNLAT) * 8 / (MXLAT - MNLAT))
2640 FOR Y = 1 TO 9 ' START Y-AXIS LOOP FOR ASCII MAP
2650 FOR X = 1 TO 80 ' START X-AXIS LOOP FOR ASCII MAP
2660 P$ = "." ' DEFAULT ASCII CHARACTER FOR MAP
2670 FOR DAY = 1 TO NUMDAYS ' LOOP THROUGH EACH DAY'S DURATION
2680 GDXPJ = 5 + INT((PRJLN(DAY) - MNLON) * 70 / (MXLON - MNLON)) ' CALCULATE PROJECTED X-COORDINATE FOR THE DAY
2690 GDYPJ = 9 - INT((PRJLT(DAY) - MNLAT) * 8 / (MXLAT - MNLAT)) ' CALCULATE PROJECTED Y-COORDINATE FOR THE DAY
2700 IF X = GDXPJ AND Y = GDYPJ THEN P$ = "X" ' CHECK AND SET PROJECTED POSITION CHARACTER
2710 NEXT DAY
2720 IF X = GDXHM AND Y = GDYHM THEN P$ = "H" ' CHECK AND SET HOME POSITION CHARACTER
2725 IF X = GDX_PR AND Y = GDY_PR THEN P$ = "R" ' Puerto Rico
2730 IF X = GDX_CUBA AND Y = GDY_CUBA THEN P$ = "C" ' Cuba
2735 IF X = GDX_BAHAMAS AND Y = GDY_BAHAMAS THEN P$ = "B" ' Bahamas
2745 IF X = GDX_MIAMI AND Y = GDY_MIAMI THEN P$ = "M" ' Miami
2750 IF X = GDX_TAMPA AND Y = GDY_TAMPA THEN P$ = "T" ' Tampa
2755 IF X = GDX_KW AND Y = GDY_KW THEN P$ = "K" ' Key West
2760 IF X = GDX_JAX AND Y = GDY_JAX THEN P$ = "J" ' Jacksonville
2763 IF X = GDX_PEN AND Y = GDY_PEN THEN P$ = "P" ' Pensacola
2764 IF X = GDX_MOB AND Y = GDY_MOB THEN P$ = "A" ' Pensacola
2765 FLAG = 0 ' RESET FLAG FOR STORM DATA OVERLAP CHECK
2770 FOR I = 1 TO NMDAYS ' LOOP THROUGH HISTORICAL DATA POINTS
2780 GRIDX = 5 + INT((LON(I) - MNLON) * 70 / (MXLON - MNLON)) ' CALCULATE X-COORDINATE FOR HISTORICAL DATA
2790 GRIDY = 9 - INT((LAT(I) - MNLAT) * 8 / (MXLAT - MNLAT)) ' CALCULATE Y-COORDINATE FOR HISTORICAL DATA
2800 IF X = GRIDX AND Y = GRIDY AND FLAG = 0 THEN GOSUB 9300 : FLAG = 1 'CHECK AND PROCESS OVERLAP OF STORM DATA WITH PREVIOUS DATA
2810 NEXT I
2820 PRINT P$; ' PRINT CURRENT ASCII CHARACTER FOR THE POSITION
2830 NEXT X ' END OF X-AXIS LOOP
2840 NEXT Y ' END OF Y-AXIS LOOP
2850 PRINT "PRESS ENTER TO RETURN TO MAIN MENU "; : INPUT TEMP$
2860 GOTO 1600
3000 REM *** ASCII MAP REFERENCE POINT COORDINATES SUBROUTINE ***
3003 PR_LAT = 18.2208: PR_LON = -66.5901
3005 CUBA_LAT = 21.5218: CUBA_LON = -77.7812
3010 BAHAMAS_LAT = 25.0343: BAHAMAS_LON = -77.3963
3020 MIAMI_LAT = 25.7617: MIAMI_LON = -80.1918
3025 TAMPA_LAT = 27.9506: TAMPA_LON = -82.4572
3030 KW_LAT = 24.5551: KW_LON = -81.7800
3035 JAX_LAT = 30.3322: JAX_LON = -81.6557
3036 PEN_LAT = 30.4213: PEN_LON = -87.2169
3037 MOB_LAT = 30.6954: MOB_LON = -88.0399
3040 RETURN
4000 REM *** SUBROUTINE TO ADJUST LAMBDA VALUE ***
4005 PRINT CHR$(12) ' CLEAR SCREEN
4010 PRINT STRING$(79, "*")
4015 PRINT "LAMBDA ADJUSTMENT"
4020 PRINT STRING$(79, "*")
4025 PRINT "CURRENT LAMBDA VALUE: "; LMBDA
4030 PRINT
4035 PRINT "LAMBDA CONTROLS THE WEIGHT GIVEN TO RECENT DATA IN FORECASTS."
4040 PRINT "A LOWER VALUE GIVES MORE WEIGHT TO RECENT DATA."
4045 PRINT "RECOMMENDED RANGE: 0.5 TO 0.9"
4050 PRINT
4055 INPUT "ENTER NEW LAMBDA VALUE (OR PRESS ENTER TO KEEP CURRENT VALUE): ", NEW_LMBDA$
4060 IF NEW_LMBDA$ = "" THEN PRINT "NO CHANGE MADE. RETURNING TO MAIN MENU": GOTO 4095
4065 NEW_LMBDA = VAL(NEW_LMBDA$)
4070 IF NEW_LMBDA < 0.1 OR NEW_LMBDA > 0.99 THEN PRINT CHR$(7): PRINT "INVALID VALUE. PLEASE ENTER A NUMBER BETWEEN 0.1 AND 0.99.": GOTO 4055
4075 LMBDA = NEW_LMBDA
4080 PRINT
4085 PRINT "LAMBDA HAS BEEN UPDATED TO: "; LMBDA
4090 PRINT
4093 PRINT "PRESS ENTER TO RETURN TO MAIN MENU";: INPUT TEMP$
4095 GOTO 1600
5000 REM *** PROJECT THREE DAY DAY WINDSPEEDS ***
5010 REM INPUT: CPRESS(20), WDSPD(20), PRJLT(3), SPEED(20)
5040 REM INITIALIZE VARIABLES
5050 SUMCPRESS = 0: SUMWDSPD = 0: SUMSPEED = 0: WEIGHTSUM = 0: TOTAL_VARIANCE = 0
5100 AVGCPRESS = 0: AVGWDSPD = 0: AVGSPEED = 0
5130 REM *** CALCULATE AVERAGE CENTRAL PRESSURE, WIND SPEEDS, AND MOVEMENT SPEED ***
5140 FOR I = 1 TO NMDAYS
5150 SUMCPRESS = SUMCPRESS + CPRESS(I)
5160 SUMWDSPD = SUMWDSPD + WDSPD(I)
5170 SUMSPEED = SUMSPEED + SPEED(I)
5180 NEXT I
5190 AVGCPRESS = SUMCPRESS / NMDAYS
5200 AVGWDSPD = SUMWDSPD / NMDAYS
5210 AVGSPEED = SUMSPEED / NMDAYS
5220 REM CALCULATE STANDARD DEVIATION OF WIND SPEEDS
5230 FOR I = 1 TO NMDAYS
5240 TOTAL_VARIANCE = TOTAL_VARIANCE + (WDSPD(I) - AVGWDSPD) ^ 2
5250 NEXT I
5260 STANDARD_DEVIATION = SQR(TOTAL_VARIANCE / NMDAYS)
5270 REM DETERMINE SMOOTHING FACTOR BASED ON STANDARD DEVIATION
5280 SMOOTHING_FACTOR = 1 / (1 + STANDARD_DEVIATION)
5285 IF SMOOTHING_FACTOR < 0.1 THEN SMOOTHING_FACTOR = 0.1 ' ENSURE IT DOESN'T GET TOO LOW
5290 REM CALCULATE WEIGHTED AVERAGE WIND SPEED USING SMOOTHING FACTOR
5300 SUMWDSPD = 0: WEIGHTSUM = 0
5340 FOR I = 1 TO NMDAYS
5350 WEIGHT = SMOOTHING_FACTOR ^ (NMDAYS - I)
5370 SUMWDSPD = SUMWDSPD + WDSPD(I) * WEIGHT
5390 WEIGHTSUM = WEIGHTSUM + WEIGHT
5400 NEXT I
5420 AVGWDSPD = SUMWDSPD / WEIGHTSUM
5440 REM ADJUST PROJECTION BASED ON CENTRAL PRESSURE, WIND SPEEDS, MOVEMENT SPEED, AND LATITUDE
5450 FOR DAY = 1 TO NUMDAYS
5460 REM ADJUST VALUES FOR EACH DAY
5461 BASE_WDSPD = WDSPD(NMDAYS)
5462 CPRESS_FACTOR = 1 + (AVGCPRESS - CPRESS(NMDAYS)) / AVGCPRESS
5463 SPEED_FACTOR = 1 + (SPEED(NMDAYS) - AVGSPEED) / AVGSPEED
5470 REM CALCULATE LATITUDE WEIGHT
5480 IF PRJLT(DAY) > 0 AND PRJLT(DAY) <= 30 THEN LAT_WEIGHT = 1.1 ' TROPICAL LATITUDES
5490 IF PRJLT(DAY) > 30 AND PRJLT(DAY) <= 60 THEN LAT_WEIGHT = 1.2 ' MID-LATITUDES
5500 IF PRJLT(DAY) > 60 OR PRJLT(DAY) < -60 THEN LAT_WEIGHT = 0.9 ' POLAR REGIONS
5510 IF PRJLT(DAY) <= 0 AND PRJLT(DAY) >= -30 THEN LAT_WEIGHT = 1.1 ' TROPICAL LATITUDES IN THE SOUTHERN HEMISPHERE
5520 REM CALCULATE ADJUSTED WIND SPEED
5530 ADJ_FACTOR = (CPRESS_FACTOR + SPEED_FACTOR) / 2 * LAT_WEIGHT
5540 PRJWND(DAY) = BASE_WDSPD * (1 + (ADJ_FACTOR - 1) * (DAY / 3))
5550 REM ENSURE WIND SPEED IS WITHIN REALISTIC BOUNDS (20 TO 200 KNOTS)
5560 IF PRJWND(DAY) < 20 THEN PRJWND(DAY) = 20
5570 IF PRJWND(DAY) > 200 THEN PRJWND(DAY) = 200
5580 NEXT DAY
5590 RETURN
9000 REM *** MAP LEGEND ***
9005 PRINT CHR$(12)
9010 PRINT STRING$(79, "*")
9020 PRINT "MAP LEGEND"
9030 PRINT STRING$(79, "*")
9040 PRINT "D : < 39 KT : TROPICAL DEPRESSION "; "H : "; HMCITY$; " ("; HMELT; ","; HMELN; ")"
9050 PRINT "S : 39 - 73 KT : TROPICAL STORM "; "R : PUERTO RICO"
9060 PRINT "1 : 74 - 95 KT : CATEGORY 1 HURRICANE "; "C : CUBA"
9070 PRINT "2 : 96 - 110 KT : CATEGORY 2 HURRICANE "; "B : BAHAMAS"
9080 PRINT "3 : 111 - 129 KT : CATEGORY 3 HURRICANE "; "M : MIAMI, FL"
9090 PRINT "4 : 130 - 156 KT : CATEGORY 4 HURRICANE "; "T : TAMPA, FL"
9100 PRINT "5 : > 156 KT : CATEGORY 5 HURRICANE "; "K : KEY WEST, FL"
9110 PRINT "X : : PROJECTED PATH OF STORM "; "J : JACKSONVILLE, FL"
9120 PRINT STRING$(79, "-")
9130 PRINT "P : PENSACOLA, FL "; "A : MOBILE, AL"
9140 PRINT STRING$(79, "*")
9150 PRINT "PRESS ENTER TO RETURN TO MAIN MENU ";: INPUT TEMP$
9230 GOTO 1600
9300 REM *** SUBROUTINE TO DETERMINE STORM SYMBOL BASED ON WIND SPEED ***
9310 IF WDSPD(I) < 39 THEN P$ = "D" : RETURN
9320 IF WDSPD(I) >= 39 AND WDSPD(I) <= 73 THEN P$ = "S" : RETURN
9330 IF WDSPD(I) >= 74 AND WDSPD(I) <= 95 THEN P$ = "1" : RETURN
9340 IF WDSPD(I) >= 96 AND WDSPD(I) <= 110 THEN P$ = "2" : RETURN
9350 IF WDSPD(I) >= 111 AND WDSPD(I) <= 129 THEN P$ = "3" : RETURN
9360 IF WDSPD(I) >= 130 AND WDSPD(I) <= 156 THEN P$ = "4" : RETURN
9370 P$ = "5"
9375 RETURN
9400 REM *** CALCULATE AND DISPLAY DISTANCES FROM HOME USING HAVERSINE FORMULA ***
9403 PRINT CHR$(12)
9404 PRINT STRING$(79, "*")
9410 PRINT " DISTANCE CALCULATION REPORT"
9411 PRINT STRING$(79, "*")
9412 PRINT " HOME LOCATION: "; HMCITY$; " ("; HMELT; ", "; HMELN; ")"
9413 PRINT " CURRENT STORM LOCATION: "; LAT(NMDAYS); ", "; LON(NMDAYS)
9414 LAT1 = HMELT: LON1 = HMELN
9417 LAT2 = LAT(NMDAYS): LON2 = LON(NMDAYS): GOSUB 31000
9418 PRINT " DISTANCE FROM "; HMCITY$; " TO CURRENT STORM LOCATION: "; INT(DISTNM * 100) / 100; " NM, "; INT(DISTKM * 100) / 100; " KM"
9419 PRINT STRING$(79, "-")
9420 FOR PROJDAY = 1 TO NUMDAYS
9421 PRINT " PROJECTION DAY "; PROJDAY; ": POSITION: "; PRJLT(PROJDAY); ", "; PRJLN(PROJDAY)
9422 NEXT PROJDAY
9426 PRINT STRING$(79, "-")
9427 FOR DAY = 1 TO NUMDAYS
9428 PRINT " PROJECTED WIND SPEED FOR DAY "; DAY; ": "; PRJWND(DAY); " KT"
9429 NEXT DAY
9430 PRINT STRING$(79, "-")
9434 LAT2 = PRJLT(1): LON2 = PRJLN(1)
9436 GOSUB 31000
9438 PRINT " DISTANCE FROM "; HMCITY$; " TO DAY 1 PROJECTION: "; INT(DISTNM * 100) / 100; " NM, "; INT(DISTKM * 100) / 100; " KM"
9442 LAT2 = PRJLT(2): LON2 = PRJLN(2)
9444 GOSUB 31000
9446 PRINT " DISTANCE FROM "; HMCITY$; " TO DAY 2 PROJECTION: "; INT(DISTNM * 100) / 100; " NM, "; INT(DISTKM * 100) / 100; " KM"
9450 LAT2 = PRJLT(3): LON2 = PRJLN(3)
9452 GOSUB 31000
9454 PRINT " DISTANCE FROM "; HMCITY$; " TO DAY 3 PROJECTION: "; INT(DISTNM * 100) / 100; " NM, "; INT(DISTKM * 100) / 100; " KM"
9456 PRINT STRING$(79, "*") '
9458 PRINT " PRESS ENTER TO RETURN TO MENU ";
9460 INPUT TEMP$
9462 GOTO 1600 ' RETURN TO MENU
10000 REM *** SUBROUTINE TO WRITE USER-INPUT DATA TO STORM.DAT ***
10003 PRINT:PRINT "DO YOU WANT YOU SAVE YOUR DATA (Y/N)";:INPUT SAVE$
10005 IF SAVE$ = "Y" THEN GOTO 10010 ELSE GOTO 10120 ' BYPASS DATA SAVE AND SEND USER TO CALCULATIONS
10010 REM OPEN "O",#1,"STORM.DAT"
10020 PRINT:PRINT "WRITING TO STORM.DAT"
10030 REM PRINT#1, NMDAYS
10040 FOR I = 1 TO NMDAYS
10050 REM PRINT#1, DRECT(I)
10060 REM PRINT#1, SPEED(I)
10070 REM PRINT#1, LAT(I)
10080 REM PRINT#1, LON(I)
10085 REM PRINT#1, CPRESS(I)
10090 REM PRINT#1, WDSPD(I)
10100 NEXT I
10110 REM PRINT CHR$(7):PRINT "WRITING TO FILE COMPLETE. EXITING DATA WRITE ROUTINE...":CLOSE 1: GOTO 1600 ' JUMP TO MAIN MENU
10120 RETURN
12000 REM *** HOME SELECTION MENU ***
12010 PRINT CHR$(12) ' CLEAR SCREEN
12020 PRINT STRING$(75,"*")
12030 PADDING = (75 - LEN("HOME SELECTION MENU")) / 2
12040 PRINT STRING$(PADDING, " ") "HOME SELECTION MENU" STRING$(PADDING, " ")
12050 PRINT STRING$(75,"*")
12070 PRINT " 1. ATLANTA, GA 15. MIAMI, FL 29. PANAMA CITY, FL"
12080 PRINT " 2. CHARLESTON, SC 16. MOBILE, AL 30. PENSACOLA, FL"
12090 PRINT " 3. JACKSONVILLE, FL 17. NEW ORLEANS, LA 31. PORT ST. LUCIE, FL"
12100 PRINT " 4. SAVANNAH, GA 18. ORLANDO, FL 32. SARASOTA, FL"
12110 PRINT " 5. TAMPA, FL 19. PALM BEACH, FL 33. ST. PETERSBURG, FL"
12120 PRINT " 6. FORT LAUDERDALE, FL 20. PONCE, PR 34. TALLAHASSEE, FL"
12130 PRINT " 7. CAPE HATTERAS, NC 21. PUNTA GORDA, FL 35. TARPON SPRINGS, FL"
12140 PRINT " 8. CHARLOTTE, NC 22. SAN JUAN, PR 36. WILMINGTON, NC"
12150 PRINT " 9. GALVESTON, TX 23. SEBRING, FL 37. WEST PALM BEACH, FL"
12151 PRINT "10. HOUSTON, TX 24. FORT MYERS, FL 38. COZUMEL, MX"
12152 PRINT "11. KEY WEST, FL 25. PUNTA CANA, DR 39. NASSAU, BAHAMAS"
12153 PRINT "12. LAKE CHARLES, LA 26. GULFPORT, MS 40. NAPLES, FL"
12154 PRINT "13. LAREDO, TX 27. BILOXI, MS 41. KINGSVILLE, TX"
12155 PRINT "14. LUBBOCK, TX 28. BROWNSVILLE, TX 42. CORPUS CHRISTI, TX"
12156 PRINT STRING$(75,"*")
12170 INPUT "ENTER YOUR CHOICE (1-42): ", CHOICE
12180 WHILE CHOICE < 1 OR CHOICE > 42
12190 PRINT CHR$(7): INPUT "INVALID SELECTION! ENTER YOUR CHOICE (1-42): ", CHOICE
12199 WEND
12200 IF CHOICE = 1 THEN HMELT = 33.75: HMELN = -84.39: HMCITY$="ATLANTA, GA"
12210 IF CHOICE = 2 THEN HMELT = 32.78: HMELN = -79.93: HMCITY$="CHARLESTON, SC"
12220 IF CHOICE = 3 THEN HMELT = 30.33: HMELN = -81.65: HMCITY$="JACKSONVILLE, FL"
12230 IF CHOICE = 4 THEN HMELT = 32.08: HMELN = -81.09: HMCITY$="SAVANNAH, GA"
12240 IF CHOICE = 5 THEN HMELT = 27.95: HMELN = -82.46: HMCITY$="TAMPA, FL"
12250 IF CHOICE = 6 THEN HMELT = 26.12: HMELN = -80.14: HMCITY$="FORT LAUDERDALE, FL"
12260 IF CHOICE = 7 THEN HMELT = 35.25: HMELN = -75.53: HMCITY$="CAPE HATTERAS, NC"
12270 IF CHOICE = 8 THEN HMELT = 35.23: HMELN = -80.84: HMCITY$="CHARLOTTE, NC"
12280 IF CHOICE = 9 THEN HMELT = 29.29: HMELN = -94.79: HMCITY$="GALVESTON, TX"
12290 IF CHOICE = 10 THEN HMELT = 29.76: HMELN = -95.37: HMCITY$="HOUSTON, TX"
12300 IF CHOICE = 11 THEN HMELT = 24.55: HMELN = -81.78: HMCITY$="KEY WEST, FL"
12310 IF CHOICE = 12 THEN HMELT = 30.22: HMELN = -93.22: HMCITY$="LAKE CHARLES, LA"
12320 IF CHOICE = 13 THEN HMELT = 27.53: HMELN = -99.49: HMCITY$="LAREDO, TX"
12330 IF CHOICE = 14 THEN HMELT = 33.58: HMELN = -101.86: HMCITY$="LUBBOCK, TX"
12340 IF CHOICE = 15 THEN HMELT = 25.76: HMELN = -80.19: HMCITY$="MIAMI, FL"
12350 IF CHOICE = 16 THEN HMELT = 30.69: HMELN = -88.04: HMCITY$="MOBILE, AL"
12360 IF CHOICE = 17 THEN HMELT = 29.95: HMELN = -90.07: HMCITY$="NEW ORLEANS, LA"
12370 IF CHOICE = 18 THEN HMELT = 28.54: HMELN = -81.38: HMCITY$="ORLANDO, FL"
12380 IF CHOICE = 19 THEN HMELT = 26.71: HMELN = -80.05: HMCITY$="PALM BEACH, FL"
12390 IF CHOICE = 20 THEN HMELT = 18.01: HMELN = -66.61: HMCITY$="PONCE, PR"
12400 IF CHOICE = 21 THEN HMELT = 26.93: HMELN = -82.05: HMCITY$="PUNTA GORDA, FL"
12410 IF CHOICE = 22 THEN HMELT = 18.47: HMELN = -66.11: HMCITY$="SAN JUAN, PR"
12420 IF CHOICE = 23 THEN HMELT = 27.50: HMELN = -81.44: HMCITY$="SEBRING, FL"
12430 IF CHOICE = 24 THEN HMELT = 26.63: HMELN = -81.87: HMCITY$="FORT MYERS, FL"
12440 IF CHOICE = 25 THEN HMELT = 18.58: HMELN = -68.40: HMCITY$="PUNTA CANA, DR"
12450 IF CHOICE = 26 THEN HMELT = 30.37: HMELN = -89.09: HMCITY$="GULFPORT, MS"
12460 IF CHOICE = 27 THEN HMELT = 30.39: HMELN = -88.89: HMCITY$="BILOXI, MS"
12470 IF CHOICE = 28 THEN HMELT = 25.90: HMELN = -97.49: HMCITY$="BROWNSVILLE, TX"
12480 IF CHOICE = 29 THEN HMELT = 30.16: HMELN = -85.66: HMCITY$="PANAMA CITY, FL"
12490 IF CHOICE = 30 THEN HMELT = 30.42: HMELN = -87.22: HMCITY$="PENSACOLA, FL"
12500 IF CHOICE = 31 THEN HMELT = 27.27: HMELN = -80.30: HMCITY$="PORT ST. LUCIE, FL"
12510 IF CHOICE = 32 THEN HMELT = 27.34: HMELN = -82.53: HMCITY$="SARASOTA, FL"
12520 IF CHOICE = 33 THEN HMELT = 27.77: HMELN = -82.64: HMCITY$="ST. PETERSBURG, FL"
12530 IF CHOICE = 34 THEN HMELT = 30.45: HMELN = -84.28: HMCITY$="TALLAHASSEE, FL"
12540 IF CHOICE = 35 THEN HMELT = 28.15: HMELN = -82.76: HMCITY$="TARPON SPRINGS, FL"
12550 IF CHOICE = 36 THEN HMELT = 27.64: HMELN = -80.38: HMCITY$="VERO BEACH, FL"
12560 IF CHOICE = 37 THEN HMELT = 26.71: HMELN = -80.05: HMCITY$="WEST PALM BEACH, FL"
12570 IF CHOICE = 38 THEN HMELT = 34.23: HMELN = -77.94: HMCITY$="WILMINGTON, NC"
12580 IF CHOICE = 39 THEN HMELT = 20.51: HMELN = -86.95: HMCITY$="COZUMEL, MX"
12590 IF CHOICE = 40 THEN HMELT = 25.05: HMELN = -77.35: HMCITY$="NASSAU, BAHAMAS"
12600 IF CHOICE = 41 THEN HMELT = 26.14: HMELN = -81.79: HMCITY$="NAPLES, FL"
12610 IF CHOICE = 42 THEN HMELT = 27.80: HMELN = -97.39: HMCITY$="CORPUS CHRISTI, TX"
12620 GOTO 1600
13000 PRINT CHR$(12) ' CLEAR SCREEN AND HOME CURSOR
13010 PRINT "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
13020 PRINT "+ +"
13030 PRINT "+ HURRICANE TRACKER +"
13040 PRINT "+ FOR THE +"
13050 PRINT "+ KAYPRO COMPUTER +"
13060 PRINT "+ +"
13070 PRINT "+ WRITTEN BY: CHRISTOPHER D. VAN DER KAAY +"
13080 PRINT "+ 2024 +"
13090 PRINT "+ +"
13100 PRINT "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
13110 FOR PAUSE = 1 TO 3000 ' ADJUST 5000 TO THE REQUIRED DELAY; THE LARGER THE NUMBER, THE LONGER THE DELAY.
13120 NEXT PAUSE
13130 RETURN
16000 REM *** SUBROUTINE TO PRINT REPORT USING LPRINT ***
16010 PRINT "NOTHING HERE YET!"
16750 GOTO 1600
19000 REM *** SUBROUTINE TO INITIALIZE HURRICANE DATA AND DEFAULT HOME LOCATION ***
19003 HMELT = 27.50: HMELN = -81.44: HMCITY$="SEBRING, FL"
19005 NMDAYS = 11
19010 LAT(1) = 24.1 : LAT(2) = 20.9 : LAT(3) = 21.4 : LAT(4) = 21.4 : LAT(5) = 22.0 : LAT(6) = 22.8 : LAT(7) = 23.9 : LAT(8) = 24.4 : LAT(9) = 25.5 : LAT(10) = 26.3: LAT(11) = 27.3
19020 LON(1) = -83.3 : LON(2) = -76.6 : LON(3) = -78.3 : LON(4) = -79.7 : LON(5) = -80.7 : LON(6) = -82.0 : LON(7) = -83.2 : LON(8) = -83.6 : LON(9) = -84.0 : LON(10) = -84.2: LON(11) = -84.4
19030 CPRESS(1) = 1005 : CPRESS(2) = 1012 : CPRESS(3) = 1012 : CPRESS(4) = 1010 : CPRESS(5) = 1009 : CPRESS(6) = 1009 : CPRESS(7) = 1007 : CPRESS(8) = 1003 : CPRESS(9) = 1001 : CPRESS(10) = 1001: CPRESS(11) = 992
19040 WDSPD(1) = 40 : WDSPD(2) = 25 : WDSPD(3) = 25 : WDSPD(4) = 25 : WDSPD(5) = 25 : WDSPD(6) = 30 : WDSPD(7) = 35 : WDSPD(8) = 40 : WDSPD(9) = 50 : WDSPD(10) = 60 : WDSPD(11) = 65
19050 DRECT(1) = 315 : DRECT(2) = 290 : DRECT(3) = 290 : DRECT(4) = 285 : DRECT(5) = 285 : DRECT(6) = 300 : DRECT(7) = 310 : DRECT(8) = 320 : DRECT(9) = 330 : DRECT(10) = 330 : DRECT(11) = 330
19060 SPEED(1) = 14 : SPEED(2) = 14 : SPEED(3) = 14 : SPEED(4) = 12 : SPEED(5) = 14 : SPEED(6) = 13 : SPEED(7) = 13 : SPEED(8) = 12 : SPEED(9) = 13 : SPEED(10) = 13 : SPEED(11) = 13
19070 RETURN
20000 REM *** KALMAN FILTER SUBROUTINE ***
20010 REM INITIALIZE KALMAN FILTER VARIABLES IF NOT DONE ALREADY
20020 IF INIT = 0 THEN GOTO 20030 ELSE GOTO 20160
20030 X(1) = ATN(TAN(PRJLT(DAY) * PI / 180)) ' CONVERT TO RADIANS
20040 X(2) = PRJLN(DAY) * PI / 180 ' CONVERT TO RADIANS
20050 X(3) = 0.0001: X(4) = 0.0001 ' SMALL NON-ZERO INITIAL VELOCITIES
20060 P(1,1) = 1: P(1,2) = 0: P(1,3) = 0: P(1,4) = 0
20070 P(2,1) = 0: P(2,2) = 1: P(2,3) = 0: P(2,4) = 0
20080 P(3,1) = 0: P(3,2) = 0: P(3,3) = 0.1: P(3,4) = 0
20090 P(4,1) = 0: P(4,2) = 0: P(4,3) = 0: P(4,4) = 0.1
20100 Q(1,1) = 0.5: Q(1,2) = 0: Q(1,3) = 0: Q(1,4) = 0
20110 Q(2,1) = 0: Q(2,2) = 0.5: Q(2,3) = 0: Q(2,4) = 0
20120 Q(3,1) = 0: Q(3,2) = 0: Q(3,3) = 0.05: Q(3,4) = 0
20130 Q(4,1) = 0: Q(4,2) = 0: Q(4,3) = 0: Q(4,4) = 0.05
20140 R(1,1) = 0.05: R(1,2) = 0: R(2,1) = 0: R(2,2) = 0.05
20150 INIT = 1
20160 REM PREDICTION STEP
20170 F(1,1) = 1: F(1,2) = 0: F(1,3) = DT: F(1,4) = 0
20180 F(2,1) = 0: F(2,2) = 1: F(2,3) = 0: F(2,4) = DT / COS(X(1))
20190 F(3,1) = 0: F(3,2) = 0: F(3,3) = 1: F(3,4) = 0
20200 F(4,1) = 0: F(4,2) = 0: F(4,3) = 0: F(4,4) = 1
20210 X(1) = X(1) + X(3) * DT
20220 X(2) = X(2) + X(4) * DT / COS(X(1))
20230 X(3) = X(3) + RND(1) * 0.0001 - 0.00005 ' ADD SMALL RANDOM NOISE TO VELOCITY
20240 X(4) = X(4) + RND(1) * 0.0001 - 0.00005 ' ADD SMALL RANDOM NOISE TO VELOCITY
20250 FOR I = 1 TO 4
20260 FOR J = 1 TO 4
20270 P(I,J) = 0
20280 FOR K = 1 TO 4
20290 P(I,J) = P(I,J) + F(I,K) * P(K,J) * F(J,K)
20300 NEXT K
20310 P(I,J) = P(I,J) + Q(I,J)
20320 NEXT J
20330 NEXT I
20335 REM UPDATE Q MATRIX BASED ON CURRENT STATE
20340 FOR I = 1 TO 4
20350 Q(I,I) = Q(I,I) * (1 + 20 * (ABS(X(3)) + ABS(X(4)))) ' MORE AGGRESSIVE ADAPTATION
20360 NEXT I
20370 REM MEASUREMENT UPDATE STEP
20380 Z(1,1) = ATN(TAN(ACTLT(DAY) * PI / 180)) ' CONVERT TO RADIANS
20390 Z(2,1) = ACTLN(DAY) * PI / 180 ' CONVERT TO RADIANS
20400 Y1 = Z(1,1) - X(1)
20410 Y2 = Z(2,1) - X(2)
20420 S(1,1) = P(1,1) + R(1,1): S(1,2) = P(1,2)
20430 S(2,1) = P(2,1): S(2,2) = P(2,2) + R(2,2)
20440 DET = S(1,1) * S(2,2) - S(1,2) * S(2,1)
20450 IF ABS(DET) < 1E-10 THEN DET = 1E-10 ' AVOID DIVISION BY ZERO
20460 INVS(1,1) = S(2,2) / DET: INVS(1,2) = -S(1,2) / DET
20470 INVS(2,1) = -S(2,1) / DET: INVS(2,2) = S(1,1) / DET
20480 FOR I = 1 TO 4
20490 K(I,1) = P(I,1) * INVS(1,1) + P(I,2) * INVS(2,1)
20500 K(I,2) = P(I,1) * INVS(1,2) + P(I,2) * INVS(2,2)
20510 NEXT I
20520 FOR I = 1 TO 4
20530 X(I) = X(I) + K(I,1) * Y1 + K(I,2) * Y2
20540 NEXT I
20550 FOR I = 1 TO 4
20560 FOR J = 1 TO 4
20570 P(I,J) = P(I,J) - (K(I,1) * P(1,J) + K(I,2) * P(2,J))
20580 NEXT J
20590 NEXT I
20600 REM ENSURE LATITUDE STAYS WITHIN -90 TO 90 DEGREES
20610 IF X(1) > PI/2 THEN X(1) = PI/2
20620 IF X(1) < -PI/2 THEN X(1) = -PI/2
20630 REM ENSURE LONGITUDE STAYS WITHIN -180 TO 180 DEGREES
20640 WHILE X(2) > PI: X(2) = X(2) - 2*PI: WEND
20650 WHILE X(2) < -PI: X(2) = X(2) + 2*PI: WEND
20660 REM UPDATE THE PROJECTED POSITIONS WITH KALMAN FILTER ESTIMATES
20670 PRJLT(DAY) = X(1) * 180 / PI ' CONVERT BACK TO DEGREES
20680 PRJLN(DAY) = X(2) * 180 / PI ' CONVERT BACK TO DEGREES
20685 REM DYNAMIC ADAPTATION OF R MATRIX
20690 INNOVATION_THRESHOLD = 0.1 ' ADJUST AS NEEDED
20695 IF ABS(Y1) > INNOVATION_THRESHOLD THEN GOTO 20710
20700 IF ABS(Y2) > INNOVATION_THRESHOLD THEN GOTO 20710
20705 GOTO 20720
20710 R(1,1) = R(1,1) * 0.9 ' DECREASE R IF INNOVATION IS LARGE
20715 R(2,2) = R(2,2) * 0.9
20718 GOTO 20730
20720 R(1,1) = R(1,1) * 1.1 ' INCREASE R IF INNOVATION IS SMALL
20725 R(2,2) = R(2,2) * 1.1
20730 IF R(1,1) < 0.01 THEN R(1,1) = 0.01 ' SET A LOWER BOUND FOR R
20735 IF R(2,2) < 0.01 THEN R(2,2) = 0.01
20780 RETURN
25000 REM *** PROGRAM DETAILS ***
25010 PRINT CHR$(12) ' CLEAR SCREEN
25020 PRINT STRING$(77, "*")
25060 PRINT "THIS PROGRAM ALLOWS USERS TO TRACK AND PREDICT THE PATH OF HURRICANES"
25070 PRINT "BASED ON MANUAL ENTRY OR LOADED DATA FILES. IT USES A KALMAN FILTER"
25080 PRINT "AND WEIGHTED AVERAGING TECHNIQUES TO PROVIDE ACCURATE PREDICTIONS."
25100 PRINT "FEATURES:"
25110 PRINT " - PREDICTIVE MODEL: COMBINES LINEAR AND EXPONENTIAL WEIGHTING."
25120 PRINT " - VISUAL REPRESENTATION: ASCII MAP SHOWING PROJECTED AND HISTORIC PATHS."
25130 PRINT " - KALMAN FILTER: ENHANCES ACCURACY OF PROJECTED POSITIONS."
25150 PRINT " - WIND SPEED PROJECTIONS: ESTIMATES WIND SPEEDS FOR UP TO 3 DAYS USING"
25160 PRINT " SMOOTHED WEIGHTED AVERAGES AND ADJUSTMENTS FOR CENTRAL PRESSURE."
25170 PRINT " THE SMOOTHING FACTOR IS DERIVED FROM THE STANDARD DEVIATION OF"
25180 PRINT " HISTORICAL WIND SPEED DATA TO MINIMIZE ERRORS."
25190 PRINT " - WIND RADII CALCULATIONS: PROJECTS 34, 50, AND 64 KT WIND RADII FOR"
25200 PRINT " 3 DAYS BASED ON PROJECTED WIND SPEEDS AND HISTORICAL DATA."
25210 PRINT " - DISTANCE CALCULATIONS: UTILIZES THE HAVERSINE FORMULA FOR ACCURATE"
25220 PRINT " DISTANCE MEASUREMENTS BETWEEN COORDINATES."
25230 PRINT STRING$(77, "*")
25240 PRINT:PRINT "PRESS ENTER TO RETURN TO THE MAIN MENU ";:INPUT TEMP$
25260 GOTO 1600
30000 REM *** CALCULATE PROJECTED THREE DAY WIND SPEED RADII ***
30040 FOR DAY = 1 TO NUMDAYS
30050 REM BASE WIND RADII FOR DAY 1, 2, AND 3
30060 WINDR(1, DAY) = 0
30070 WINDR(2, DAY) = 0
30080 WINDR(3, DAY) = 0
30100 NEXT DAY
30110 REM BASE WIND RADII
30120 WINDRADII(1) = 105: WINDRADII(2) = 90: WINDRADII(3) = 40: WINDRADII(4) = 70
30130 WINDRADII(5) = 140: WINDRADII(6) = 140: WINDRADII(7) = 60: WINDRADII(8) = 90
30140 WINDRADII(9) = 200: WINDRADII(10) = 200: WINDRADII(11) = 100: WINDRADII(12) = 150
30150 REM CALCULATE PROJECTED WIND RADII BASED ON WIND SPEED ADJUSTMENTS
30160 FOR DAY = 1 TO NUMDAYS
30170 WDSPD_ADJ = PRJWND(DAY) / WDSPD(NMDAYS)
30180 FOR Q = 1 TO 12
30190 WINDR(Q, DAY) = INT(WINDRADII(Q) * WDSPD_ADJ)
30200 NEXT Q
30210 NEXT DAY
30280 REM PRINT WIND RADII FOR THREE DAYS
30290 FOR DAY = 1 TO NUMDAYS
30305 LAT1 = HMELT: LON1 = HMELN
30307 LAT2 = PRJLT(DAY): LON2 = PRJLN(DAY)
30308 GOSUB 31000
30310 PRINT STRING$(79, "*")
30315 PRINT "DAY "; DAY
30320 PRINT "PROJ MAX WIND: "; PRJWND(DAY); " KT | PROJ DIST TO "; HMCITY$; ": "; INT(DISTNM * 100) / 100; " NM, "; INT(DISTKM * 100) / 100; " KM"
30330 PRINT " 64 KT WIND RADII:"
30340 PRINT " NE: "; WINDR(1, DAY); " NM SE: "; WINDR(2, DAY); " NM SW: "; WINDR(3, DAY); " NM NW: "; WINDR(4, DAY); " NM"
30350 PRINT " 50 KT WIND RADII:"
30360 PRINT " NE: "; WINDR(5, DAY); " NM SE: "; WINDR(6, DAY); " NM SW: "; WINDR(7, DAY); " NM NW: "; WINDR(8, DAY); " NM"
30370 PRINT " 34 KT WIND RADII:"
30380 PRINT " NE: "; WINDR(9, DAY); " NM SE: "; WINDR(10, DAY); " NM SW: "; WINDR(11, DAY); " NM NW: "; WINDR(12, DAY); " NM"
30390 PRINT STRING$(79, "*")
30392 PRINT "PRESS ENTER TO VIEW NEXT DAY WIND RADII ";:INPUT TEMP$
30400 NEXT DAY
30410 PRINT "PRESS ENTER TO RETURN TO MAIN MENU ";:INPUT TEMP$
30430 GOTO 1600
31000 REM *** SUBROUTINE TO CALCULATE DISTANCE USING HAVERSINE FORMULA ***
31030 RDLT1 = LAT1 * PI / 180
31040 RDLN1 = LON1 * PI / 180
31050 RDLT2 = LAT2 * PI / 180
31060 RDLN2 = LON2 * PI / 180
31090 DLAT = RDLT2 - RDLT1
31100 DLON = RDLN2 - RDLN1
31120 A = SIN(DLAT / 2) ^ 2 + COS(RDLT1) * COS(RDLT2) * SIN(DLON / 2) ^ 2
31140 C = 2 * ATN(SQR(A) / (SQR(1 - A) + 0.0000001))
31160 DISTKM = R * C
31170 IF DISTKM < 0 THEN DISTKM = -DISTKM
31180 DISTNM = DISTKM * 0.539957 ' CONVERT KILOMETERS TO NAUTICAL MILES
31200 RETURN