1 /*****************************************************************************
2  * weather.c
3  *
4  * DESCRIPTION
5  *    This file contains all the utility functions needed to handle weather
6  * "ugly" strings.  Originally I didn't need to parse them, but for people
7  * to use them in ArcView, I had to.
8  *
9  * HISTORY
10  *   5/2003 Arthur Taylor (MDL / RSIS): Created.
11  *
12  * NOTES
13  *****************************************************************************
14  */
15 /*
16  * Uncomment the following to have error messages stored in the UglyStringType
17  * This uses myerror.*
18  */
19 #define STORE_ERRORS
20 
21 /*
22  * Uncomment the following to have error messages sent to stdout.
23  */
24 /* #define VERBOSE */
25 #undef VERBOSE
26 
27 /*
28  * Uncomment the following to test Weather names.
29  */
30 /* #define DEBUG_WEATHER */
31 
32 
33 #include <stdio.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include "weather.h"
37 
38 #ifdef STORE_ERRORS
39 #include "myerror.h"
40 #endif
41 
42 typedef struct {
43    const char *abrev, *name;
44    uChar number;
45 } WxTable;
46 
47 /* Unknown <NoCov>:EW:<NoInten>:<NoVis>:10to20g30 */
48 /* Original enumeration.
49 enum {
50    WX_NOWX, WX_K, WX_BD, WX_BS, WX_H, WX_F, WX_L, WX_R, WX_RW,
51    WX_A, WX_FR, WX_ZL, WX_ZR, WX_IP, WX_S, WX_SW, WX_T
52 };
53 */
54 enum {
55    WX_NOWX, WX_K, WX_BD, WX_BS, WX_H, WX_F, WX_L, WX_R, WX_RW,
56    WX_A, WX_FR, WX_ZL, WX_ZR, WX_IP, WX_S, WX_SW, WX_T, WX_BN,
57    WX_ZF, WX_IC, WX_IF, WX_VA, WX_ZY, WX_WP, WX_UNKNOWN
58 };
59 
60 /* SA -> Snowfall aob freezing */
61 /* LC -> Caution Advised on area Lakes */
62 /*   {"WG", "Frequent Gusts", WX_WG},*/
63 static const WxTable WxCode[] = {
64    /* 0 */ {"<NoWx>", "No Weather", WX_NOWX},
65    /* Dry Obstruction to visibility. */
66    /* 14 */ {"K", "Smoke", WX_K},
67    /* 15 */ {"BD", "Blowing Dust", WX_BD},
68    /* 13 */ {"BS", "Blowing Snow", WX_BS},
69    /* Moist Obstruction to visibility. */
70    /* 12 */ {"H", "Haze", WX_H},
71    /* 11 */ {"F", "Fog", WX_F},
72    /* 5 */ {"L", "Drizzle", WX_L},
73    /* Warm moisture. */
74    /* 3 */ {"R", "Rain", WX_R},
75    /* 4 */ {"RW", "Rain Showers", WX_RW},
76 /* 'A' has have been dropped as of 8/12/2004 */
77    /* 2 */ {"A", "Hail", WX_A},
78 /* 'A' has have been dropped as of 8/12/2004 */
79    /* Freezing / Mix moisture. */
80    /* 16 */ {"FR", "Frost", WX_FR},
81    /* 7 */ {"ZL", "Freezing Drizzle", WX_ZL},
82    /* 6 */ {"ZR", "Freezing Rain", WX_ZR},
83    /* Frozen moisture. */
84    /* 10 */ {"IP", "Ice Pellets (sleet)", WX_IP},
85    /* 8 */ {"S", "Snow", WX_S},
86    /* 9 */ {"SW", "Snow Showers", WX_SW},
87    /* Extra. */
88    /* 1 */ {"T", "Thunderstorms", WX_T},
89    {"BN", "Blowing Sand", WX_BN},
90    {"ZF", "Freezing Fog", WX_ZF},
91    {"IC", "Ice Crystals", WX_IC},
92    {"IF", "Ice Fog", WX_IF},
93    {"VA", "Volcanic Ash", WX_VA},
94    {"ZY", "Freezing Spray", WX_ZY},
95    {"WP", "Water Spouts", WX_WP},
96    {"<unknown>", "Unknown Weather", WX_UNKNOWN}
97 };
98 
99 /* GChc found in output streams... not allowed to add yet. */
100 /* Original enumeration.
101 enum {
102    COV_NOCOV, COV_ISO, COV_SCT, COV_NUM, COV_WIDE, COV_OCNL, COV_SCHC,
103    COV_CHC, COV_LKLY, COV_DEF, COV_PATCHY, COV_AREAS
104 };
105 */
106 enum {
107    COV_NOCOV, COV_ISO, COV_SCT, COV_NUM, COV_WIDE, COV_OCNL, COV_SCHC,
108    COV_CHC, COV_LKLY, COV_DEF, COV_PATCHY, COV_AREAS, COV_PDS, COV_FRQ,
109    COV_INTER, COV_BRIEF, COV_UNKNOWN
110 };
111 
112 static const WxTable WxCover[] = {
113    /* 0 */ {"<NoCov>", "No Coverage/Probability", COV_NOCOV},
114    /* 1 */ {"Iso", "Isolated", COV_ISO},
115    /* 2 */ {"Sct", "Scattered", COV_SCT},
116    /* 3 */ {"Num", "Numerous", COV_NUM},
117    /* 4 */ {"Wide", "Widespread", COV_WIDE},
118    /* 5 */ {"Ocnl", "Occasional", COV_OCNL},
119    /* 6 */ {"SChc", "Slight Chance of", COV_SCHC},
120    /* 7 */ {"Chc", "Chance of", COV_CHC},
121    /* 8 */ {"Lkly", "Likely", COV_LKLY},
122    /* 9 */ {"Def", "Definite", COV_DEF},
123    /* 10 */ {"Patchy", "Patchy", COV_PATCHY},
124    /* 11 */ {"Areas", "Areas of", COV_AREAS},
125 /* Added 8/13/2004 */
126    /* 12 */ {"Pds", "Periods of", COV_PDS},
127    /* 13 */ {"Frq", "Frequent", COV_FRQ},
128    /* 14 */ {"Inter", "Intermittent", COV_INTER},
129    /* 15 */ {"Brf", "Brief", COV_BRIEF},
130 /* Finished Added 8/13/2004 */
131    {"<unknown>", "Unknown Coverage", COV_UNKNOWN}
132 };
133 
134 enum { INT_NOINT, INT_DD, INT_D, INT_M, INT_P, INT_UNKNOWN };
135 
136 static const WxTable WxIntens[] = {
137    /* 0 */ {"<NoInten>", "No Intensity", INT_NOINT},
138    /* 1 */ {"--", "Very Light", INT_DD},
139    /* 2 */ {"-", "Light", INT_D},
140    /* 3 */ {"m", "Moderate", INT_M},
141    /* 4 */ {"+", "Heavy", INT_P},
142    {"<unknown>", "Unknown Intensity", INT_UNKNOWN}
143 };
144 
145 enum {
146    VIS_NOVIS, VIS_0, VIS_8, VIS_16, VIS_24, VIS_32, VIS_48, VIS_64, VIS_80,
147    VIS_96, VIS_128, VIS_160, VIS_192, VIS_224, VIS_UNKNOWN = 255
148 };
149 
150 static const WxTable WxVisib[] = {
151    /* 0 */ {"<NoVis>", "255", VIS_NOVIS},
152    /* 1 */ {"0SM", "0", VIS_0},
153    /* 2 */ {"1/4SM", "8", VIS_8},
154    /* 3 */ {"1/2SM", "16", VIS_16},
155    /* 4 */ {"3/4SM", "24", VIS_24},
156    /* 5 */ {"1SM", "32", VIS_32},
157    /* 6 */ {"11/2SM", "48", VIS_48},
158    /* 7 */ {"2SM", "64", VIS_64},
159    /* 8 */ {"21/2SM", "80", VIS_80},
160    /* 9 */ {"3SM", "96", VIS_96},
161    /* 10 */ {"4SM", "128", VIS_128},
162    /* 11 */ {"5SM", "160", VIS_160},
163    /* 12 */ {"6SM", "192", VIS_192},
164    /* Past 6 SM (encode as 7 SM). */
165    /* 13 */ {"P6SM", "224", VIS_224},
166    {"<unknown>", "Unknown Visibility", VIS_UNKNOWN}
167 };
168 
169 enum {
170    HAZ_NOHAZ, HAZ_FL, HAZ_GW, HAZ_HVYRN, HAZ_DMGW, HAZ_A, HAZ_LGA, HAZ_OLA,
171    HAZ_OBO, HAZ_OGA, HAZ_DRY, HAZ_TOR, HAZ_UNKNOWN, HAZ_PRI1 = 253,
172    HAZ_PRI2 = 254, HAZ_OR = 255
173 };
174 
175 /* Note: HazCode currently can handle up to (21 + 4) different WxAttrib
176  * numbers because it is stored in a "sInt4" (2^31 = 21,47,48,36,48) */
177 static const WxTable WxAttrib[] = {
178    /* 0 */ {"", "None", HAZ_NOHAZ},
179    /* 1 */ {"FL", "Frequent Lightning", HAZ_FL},
180    /* 2 */ {"GW", "Gusty Winds", HAZ_GW},
181    /* 3 */ {"HvyRn", "Heavy Rain", HAZ_HVYRN},
182    /* 4 */ {"DmgW", "Damaging Wind", HAZ_DMGW},
183    /* 5 */ {"SmA", "Small Hail", HAZ_A},
184    /* 6 */ {"LgA", "Large Hail", HAZ_LGA},
185    /* 7 */ {"OLA", "Outlying Areas", HAZ_OLA},
186    /* 8 */ {"OBO", "on Bridges and Overpasses", HAZ_OBO},
187 /* Added 8/13/2004 */
188    /* 9 */ {"OGA", "On Grassy Areas", HAZ_OGA},
189    /* 10 */ {"Dry", "dry", HAZ_DRY},
190    /* 11 */ {"TOR", "Tornado", HAZ_TOR},
191    /* 12 */ {"Primary", "Highest Ranking", HAZ_PRI2},
192    /* 13 */ {"Mention", "Include Unconditionally", HAZ_PRI1},
193 /* Finished Added 8/13/2004 */
194    /* 14 */ {"OR", "or", HAZ_OR},
195    /* 15 */ {"MX", "mixture", HAZ_OR},
196    {"<unknown>", "Unknown Hazard", HAZ_UNKNOWN}
197 };
198 
199 /*****************************************************************************
200  * NDFD_WxTable1() --
201  *
202  * Original: makeWxImageCodes() Marc Saccucci (MDL)
203  * Adapted to NDFD_WxTable() Arthur Taylor / MDL
204  *
205  * PURPOSE
206  *   To use the same weather table scheme used by Marc Saccucci in
207  * makeWxImageCodes() in the NDFD source tree.  The purpose of both
208  * procedures is to simplify the weather string (aka ugly string) to a single
209  * integral code number, which contains the most relevant weather.  The
210  * intent is to create a simpler field which can more readily be viewed as
211  * an image.
212  *
213  * ARGUMENTS
214  * ugly = The ugly weather string to encode. (Input)
215  *
216  * FILES/DATABASES: None
217  *
218  * RETURNS: int (the encoded number.)
219  *
220  * HISTORY
221  *  11/2002 Marc Saccucci (MDL): Created matching algorithm in
222  *              makeWxImageCodes().
223  *   6/2003 MS: Altered matching combinations in makeWxImageCodes().
224  *   7/2003 Arthur Taylor (MDL/RSIS): Created NDFD_WxTable()
225  *
226  * NOTES
227  *  1) The table used:
228  * new_code  primary weather/probability       Description (sample value)
229  * ========  ===========================       ==========================
230  * 0         <NoWx>                            No weather
231  * 1         L/Sct,SChc,Patchy,Iso,Chc         Rain (LoProb L)
232  * 2         R-/Sct,SChc,Patchy,Iso,Chc        Rain (LoProb R-)
233  * 3         R/Sct,SChc,Patchy,Iso,Chc         Rain (LoProb R)
234  * 4         R+/Sct,SChc,Patchy,Iso,Chc        Rain (LoProb R+)
235  * 5         R/T;Sct,SChc,Patchy,Iso,Chc       Rain (LoProb R/T)
236  * 6         RW/Sct,SChc,Patchy,Iso,Chc        Rain (LoProb Rw)
237  * 7         RW/T;Sct,SChc,Patchy,Iso,Chc      Rain (LoProb RW/T)
238  * 8         T/Sct,SChc,Patchy,Iso,Chc         Rain (LoProb T)
239  * 9         L/Wide,Lkly,Num,Ocnl,Def,Areas    Rain (HiProb L)
240  * 10        R-/Wide,Lkly,Num,Ocnl,Def,Areas   Rain (HiProb R-)
241  * 11        R/Wide,Lkly,Num,Ocnl,Def,Areas    Rain (HiProb R)
242  * 12        R+/Wide,Lkly,Num,Ocnl,Def,Areas   Rain (HiProb R+)
243  * 13        R/T;Wide,Lkly,Num,Ocnl,Def,Areas  Rain (HiProb R/T)
244  * 14        RW/Wide,Lkly,Num,Ocnl,Def,Areas   Rain (HiProb RW)
245  * 15        RW/T;Wide,Lkly,Num,Ocnl,Def,Areas Rain (HiProb RW/T)
246  * 16        T/Wide,Lkly,Num,Ocnl,Def,Areas    Rain (HiProb T)
247  * 17        T+                                Severe Tstorms
248  * 18        R/S;Sct,SChc,Patchy,Iso,Chc       Wintry Mix (LoProb R/S)
249  * 19        RW/SW;Sct,SChc,Patchy,Iso,Chc     Wintry Mix (LoProb RW/SW)
250  * 20        R/IP;Sct,SChc,Patchy,Iso,Chc      Wintry Mix (LoProb R/IP)
251  * 21        S/IP;Sct,SChc,Patchy,Iso,Chc      Wintry Mix (LoProb S/IP)
252  * 22        R/S;Wide,Lkly,Num,Ocnl,Def,Areas  Wintry Mix (HiProb R/S)
253  * 23        RW/SW;Wide,Lkly,Num,Ocnl,Def,AreasWintry Mix (HiProb RW/SW)
254  * 24        R/IP;Wide,Lkly,Num,Ocnl,Def,Areas Wintry Mix (HiProb R/IP)
255  * 25        S/IP;Wide,Lkly,Num,Ocnl,Def,Areas Wintry Mix (HiProb S/IP)
256  * 26        IP-/Sct,SChc,Patchy,Iso,Chc       Ice (LoProb IP-)
257  * 27        IP/Sct,SChc,Patchy,Iso,Chc        Ice (LoProb IP)
258  * 28        IP+/Sct,SChc,Patchy,Iso,Chc       Ice (LoProb IP+)
259  * 29        ZL/Sct,SChc,Patchy,Iso,Chc        Ice (LoProb ZL)
260  * 30        ZL/R;Sct,SChc,Patchy,Iso,Chc      Ice (LoProb R/ZL)
261  * 31        ZR-/Sct,SChc,Patchy,Iso,Chc       Ice (LoProb ZR-)
262  * 32        ZR/Sct,SChc,Patchy,Iso,Chc        Ice (LoProb ZR)
263  * 33        ZR+/Sct,SChc,Patchy,Iso,Chc       Ice (LoProb ZR+)
264  * 34        ZR/R;Sct,SChc,Patchy,Iso,Chc      Ice (LoProb R/ZR)
265  * 35        ZR/IP;Sct,SChc,Patchy,Iso,Chc     Ice (LoProb ZR/IP)
266  * 36        IP-/Wide,Lkly,Num,Ocnl,Def,Areas  Ice (HiProb IP-)
267  * 37        IP/Wide,Lkly,Num,Ocnl,Def,Areas   Ice (HiProb IP)
268  * 38        IP+/Wide,Lkly,Num,Ocnl,Def,Areas  Ice (HiProb IP+)
269  * 39        ZL/Wide,Lkly,Num,Ocnl,Def,Areas   Ice (HiProb ZL)
270  * 40        ZL/R;Wide,Lkly,Num,Ocnl,Def,Areas Ice (HiProb R/ZL)
271  * 41        ZR-/Wide,Lkly,Num,Ocnl,Def,Areas  Ice (HiProb ZR-)
272  * 42        ZR/Wide,Lkly,Num,Ocnl,Def,Areas   Ice (HiProb ZR)
273  * 43        ZR+/Wide,Lkly,Num,Ocnl,Def,Areas  Ice (HiProb ZR+)
274  * 44        ZR/R;Wide,Lkly,Num,Ocnl,Def,Areas Ice (HiProb R/ZR)
275  * 45        ZR/IP;Wide,Lkly,Num,Ocnl,Def,AreasIce (HiProb ZR/IP)
276  * 46        SW/Sct,SChc,Patchy,Iso,Chc        Snow (LoProb SW)
277  * 47        S-/Sct,SChc,Patchy,Iso,Chc        Snow (LoProb S-)
278  * 48        S/Sct,SChc,Patchy,Iso,Chc         Snow (LoProb S)
279  * 49        S+/Sct,SChc,Patchy,Iso,Chc        Snow (LoProb S+)
280  * 50        SW/Wide,Lkly,Num,Ocnl,Def,Areas   Snow (HiProb SW)
281  * 51        S-/Wide,Lkly,Num,Ocnl,Def,Areas   Snow (HiProb S-)
282  * 52        S/Wide,Lkly,Num,Ocnl,Def,Areas    Snow (HiProb S)
283  * 53        S+/Wide,Lkly,Num,Ocnl,Def,Areas   Snow (HiProb S+)
284  * 54        F                                 Fog
285  * 55        H                                 Haze
286  * 56        K                                 Smoke
287  * 57        BS                                Blowing Snow
288  * 58        BD                                Blowing Dust
289  *****************************************************************************
290  */
NDFD_WxTable1(UglyStringType * ugly)291 static int NDFD_WxTable1 (UglyStringType * ugly)
292 {
293    switch (ugly->wx[0]) {
294       case WX_NOWX:
295          return 0;
296       case WX_R:
297          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
298              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
299              (ugly->cover[0] == COV_CHC)) {
300             switch (ugly->wx[1]) {
301                case WX_S:
302                case WX_SW:
303                   return 18; /* Rain/Snow Showers */
304                case WX_ZR:
305                   return 34; /* Rain/Freezing Rain */
306                case WX_IP:
307                   return 20; /* Rain/Sleet */
308                case WX_ZL:
309                   return 30; /* Rain/Freezing Drizzle */
310                case WX_T:
311                   return 5; /* Rain/Thunderstorms */
312                default:
313                   switch (ugly->intens[0]) {
314                      case INT_D:
315                      case INT_DD:
316                         return 2; /* Light Rain */
317                      case INT_P:
318                         return 4; /* Heavy Rain */
319                      default:
320                         return 3; /* Normal Rain */
321                   }
322             }
323          } else {
324             switch (ugly->wx[1]) {
325                case WX_S:
326                case WX_SW:
327                   return 22; /* Rain/Snow Showers */
328                case WX_ZR:
329                   return 44; /* Rain/Freezing Rain */
330                case WX_IP:
331                   return 24; /* Rain/Sleet */
332                case WX_ZL:
333                   return 40; /* Rain/Freezing Drizzle */
334                case WX_T:
335                   return 13; /* Rain/Thunderstorms */
336                default:
337                   switch (ugly->intens[0]) {
338                      case INT_D:
339                      case INT_DD:
340                         return 10; /* Light Rain */
341                      case INT_P:
342                         return 12; /* Heavy Rain */
343                      default:
344                         return 11; /* Normal Rain */
345                   }
346             }
347          }
348       case WX_RW:
349          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
350              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
351              (ugly->cover[0] == COV_CHC)) {
352             switch (ugly->wx[1]) {
353                case WX_T:
354                   return 7; /* Rain Showers/Thunderstorms */
355                case WX_SW:
356                   return 19; /* Rain Showers/Snow Showers */
357                default:
358                   return 6; /* Rain Showers */
359             }
360          } else {
361             switch (ugly->wx[1]) {
362                case WX_T:
363                   return 15; /* Rain Showers/Thunderstorms */
364                case WX_SW:
365                   return 23; /* Rain Showers/Snow Showers */
366                default:
367                   return 14; /* Rain Showers */
368             }
369          }
370       case WX_L:
371          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
372              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
373              (ugly->cover[0] == COV_CHC)) {
374             switch (ugly->wx[1]) {
375                case WX_ZL:
376                   return 29; /* Drizzle/Freezing Drizzle */
377                case WX_F:
378                default:
379                   return 1; /* Drizzle */
380             }
381          } else {
382             switch (ugly->wx[1]) {
383                case WX_ZL:
384                   return 40; /* Drizzle/Freezing Drizzle */
385                case WX_F:
386                default:
387                   return 9; /* Drizzle */
388             }
389          }
390       case WX_ZL:
391          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
392              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
393              (ugly->cover[0] == COV_CHC)) {
394             switch (ugly->wx[1]) {
395                case WX_R:
396                   return 30; /* Freezing Drizzle/Rain */
397                case WX_L:
398                default:
399                   return 29; /* Freezing Drizzle */
400             }
401          } else {
402             switch (ugly->wx[1]) {
403                case WX_R:
404                   return 40; /* Freezing Drizzle/Rain */
405                case WX_L:
406                default:
407                   return 39; /* Freezing Drizzle */
408             }
409          }
410       case WX_ZR:
411          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
412              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
413              (ugly->cover[0] == COV_CHC)) {
414             switch (ugly->wx[1]) {
415                case WX_R:
416                   return 34; /* Freezing Rain/Rain */
417                case WX_IP:
418                   return 35; /* Freezing Rain/Sleet */
419                default:
420                   switch (ugly->intens[0]) {
421                      case INT_D:
422                      case INT_DD:
423                         return 31; /* Light Freezing Rain */
424                      case INT_P:
425                         return 33; /* Heavy Freezing Rain */
426                      default:
427                         return 32; /* Normal Freezing Rain */
428                   }
429             }
430          } else {
431             switch (ugly->wx[1]) {
432                case WX_R:
433                   return 44; /* Freezing Rain/Rain */
434                case WX_IP:
435                   return 45; /* Freezing Rain/Sleet */
436                default:
437                   switch (ugly->intens[0]) {
438                      case INT_D:
439                      case INT_DD:
440                         return 41; /* Light Freezing Rain */
441                      case INT_P:
442                         return 43; /* Heavy Freezing Rain */
443                      default:
444                         return 42; /* Normal Freezing Rain */
445                   }
446             }
447          }
448       case WX_IP:
449          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
450              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
451              (ugly->cover[0] == COV_CHC)) {
452             switch (ugly->wx[1]) {
453                case WX_R:
454                   return 20; /* Sleet/Rain */
455                case WX_S:
456                   return 21; /* Sleet/Snow */
457                case WX_ZR:
458                   return 35; /* Sleet/Freezing Rain */
459                default:
460                   switch (ugly->intens[0]) {
461                      case INT_D:
462                      case INT_DD:
463                         return 26; /* Light Sleet */
464                      case INT_P:
465                         return 28; /* Heavy Sleet */
466                      default:
467                         return 27; /* Normal Sleet */
468                   }
469             }
470          } else {
471             switch (ugly->wx[1]) {
472                case WX_R:
473                   return 24; /* Sleet/Rain */
474                case WX_S:
475                   return 25; /* Sleet/Snow */
476                case WX_ZR:
477                   return 45; /* Sleet/Freezing Rain */
478                default:
479                   switch (ugly->intens[0]) {
480                      case INT_D:
481                      case INT_DD:
482                         return 36; /* Light Sleet */
483                      case INT_P:
484                         return 38; /* Heavy Sleet */
485                      default:
486                         return 37; /* Normal Sleet */
487                   }
488             }
489          }
490       case WX_SW:
491          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
492              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
493              (ugly->cover[0] == COV_CHC)) {
494             switch (ugly->wx[1]) {
495                case WX_R:
496                   return 18; /* Snow Showers/Rain */
497                case WX_RW:
498                   return 19; /* Snow Showers/Rain Showers */
499                default:
500                   return 46; /* Snow Showers */
501             }
502          } else {
503             switch (ugly->wx[1]) {
504                case WX_R:
505                   return 22; /* Snow Showers/Rain */
506                case WX_RW:
507                   return 23; /* Snow Showers/Rain Showers */
508                default:
509                   return 50; /* Snow Showers */
510             }
511          }
512       case WX_S:
513          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
514              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
515              (ugly->cover[0] == COV_CHC)) {
516             switch (ugly->wx[1]) {
517                case WX_R:
518                case WX_RW:
519                   return 18; /* Snow/Rain */
520                case WX_IP:
521                   return 21; /* Snow/Sleet */
522                default:
523                   switch (ugly->intens[0]) {
524                      case INT_D:
525                      case INT_DD:
526                         return 47; /* Light Snow */
527                      case INT_P:
528                         return 49; /* Heavy Snow */
529                      default:
530                         return 48; /* Normal Snow */
531                   }
532             }
533          } else {
534             switch (ugly->wx[1]) {
535                case WX_R:
536                case WX_RW:
537                   return 22; /* Snow/Rain */
538                case WX_IP:
539                   return 25; /* Snow/Sleet */
540                default:
541                   switch (ugly->intens[0]) {
542                      case INT_D:
543                      case INT_DD:
544                         return 51; /* Light Snow */
545                      case INT_P:
546                         return 53; /* Heavy Snow */
547                      default:
548                         return 52; /* Normal Snow */
549                   }
550             }
551          }
552       case WX_T:
553          /*
554           * Check Severe storms.  If so, this is most important weather
555           * type.
556           */
557          if (ugly->intens[0] == INT_P) {
558             return 17;  /* Severe Thunderstorms */
559          }
560          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
561              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
562              (ugly->cover[0] == COV_CHC)) {
563             switch (ugly->wx[1]) {
564                case WX_R:
565                   return 5; /* Thunderstorms/Rain */
566                case WX_RW:
567                   return 7; /* Thunderstorms/Rain Showers */
568                default:
569                   return 8; /* Thunderstorms. */
570             }
571          } else {
572             switch (ugly->wx[1]) {
573                case WX_R:
574                   return 13; /* Thunderstorms/Rain */
575                case WX_RW:
576                   return 15; /* Thunderstorms/Rain Showers */
577                default:
578                   return 16; /* Thunderstorms. */
579             }
580          }
581       case WX_F:
582          return 54;     /* Fog */
583       case WX_H:
584          return 55;     /* Haze */
585       case WX_K:
586          return 56;     /* Smoke */
587       case WX_BS:
588          return 57;     /* Blowing Snow */
589       case WX_BD:
590          return 58;     /* Blowing Dust */
591       case WX_FR:      /* Ignore Frost */
592       case WX_A:       /* Ignore Hail */
593       default:
594          return 0;
595    }
596 }
597 
598 /*****************************************************************************
599  * NDFD_WxTable2_StdInten() --
600  *
601  * Arthur Taylor / MDL
602  *
603  * PURPOSE
604  *   A helper routine to NDFD_WxTable2() to assist with adjusting the
605  * intensity.  For the most part if intens is INT_D or INT_DD, we want to
606  * subtract 1 from the base value.  If it is INT_P, we want to add 1,
607  * otherwise just return base.
608  *
609  * ARGUMENTS
610  *   base = The base encoded number to adjust. (Input)
611  * intens = The intensity of the first weather key. (Input)
612  *
613  * FILES/DATABASES: None
614  *
615  * RETURNS: int (the resulting encoded number.)
616  *
617  * HISTORY
618  *   1/2004 Arthur Taylor (MDL/RSIS): Created.
619  *
620  * NOTES
621  *****************************************************************************
622  */
NDFD_WxTable2_StdInten(int base,int intens)623 static int NDFD_WxTable2_StdInten (int base, int intens)
624 {
625    switch (intens) {
626       case INT_D:
627       case INT_DD:
628          return base - 1;
629       case INT_P:
630          return base + 1;
631       default:
632          return base;
633    }
634 }
635 
636 /*****************************************************************************
637  * NDFD_WxTable2() --
638  *
639  * Original: makeWxImageCodes() Marc Saccucci Jan 2004 (MDL)
640  * Adapted to NDFD_WxTable() Arthur Taylor / MDL
641  *
642  * PURPOSE
643  *   To use the same weather table scheme used by Marc Saccucci in
644  * makeWxImageCodes() in the NDFD source tree.  The purpose of both
645  * procedures is to simplify the weather string (aka ugly string) to a single
646  * integral code number, which contains the most relevant weather.  The
647  * intent is to create a simpler field which can more readily be viewed as
648  * an image.
649  *
650  * ARGUMENTS
651  * ugly = The ugly weather string to encode. (Input)
652  *
653  * FILES/DATABASES: None
654  *
655  * RETURNS: int (the encoded number.)
656  *
657  * HISTORY
658  *  11/2002 Marc Saccucci (MDL): Created matching algorithm in
659  *              makeWxImageCodes().
660  *   6/2003 MS: Altered matching combinations in makeWxImageCodes().
661  *   1/2004 MS: Updated to include intensity considerations for all Precip
662                 types.
663  *   1/2004 Arthur Taylor (MDL/RSIS): Created NDFD_WxTable2()
664  *
665  * NOTES
666  *  1) The table used:
667  *  new_code  Sample Value  Legend Value    Description
668  *  --------  ------------ --------------   ------------
669  *  0            -        -      No Predominant Weather
670  *  1            L-      Rain    (LoProb L-)
671  *  2            L       Rain    (LoProb L)
672  *  3            L+      Rain    (LoProb L+)
673  *  4            R-      Rain    (LoProb R-)
674  *  5            R       Rain    (LoProb R)
675  *  6            R+      Rain    (LoProb R+)
676  *  7            R/T+    Severe  (LoProb R/T+)
677  *  8            T/R+    Rain    (LoProb T/R+)
678  *  9            T/R-    Rain    (LoProb T/R-)
679  *  10           R/T     Rain    (LoProb R/T)
680  *  11           RW-     Rain    (LoProb RW-)
681  *  12           RW      Rain    (LoProb RW)
682  *  13           RW+     Rain    (LoProb RW+)
683  *  14           RW/T+   Severe  (LoProb RW/T+)
684  *  15           RW/T    Rain    (LoProb RW/T)
685  *  16           T/RW+   Rain    (LoProb T/RW+)
686  *  17           T/RW-   Rain    (LoProb T/RW-)
687  *  18           T       Rain    (LoProb T)
688  *  19           T+      Severe  (LoProb T+)
689  *  20           L-      Rain    (HiProb L-)
690  *  21           L       Rain    (HiProb L)
691  *  22           L+      Rain    (HiProb L+)
692  *  23           R-      Rain    (HiProb R-)
693  *  24           R       Rain    (HiProb R)
694  *  25           R+      Rain    (HiProb R+)
695  *  26           R/T+    Severe  (HiProb R/T+)
696  *  27           R/T     Rain    (HiProb R/T)
697  *  28           T/R+    Rain    (HiProb T/R+)
698  *  29           T/R-    Rain    (HiProb T/R-)
699  *  30           RW-     Rain    (HiProb RW-)
700  *  31           RW      Rain    (HiProb RW)
701  *  32           RW+     Rain    (HiProb RW+)
702  *  33           RW/T    Rain    (HiProb RW/T)
703  *  34           RW/T+   Severe  (HiProb RW/T+)
704  *  35           T/RW+   Rain    (HiProb T/RW+)
705  *  36           T/RW-   Rain    (HiProb T/RW-)
706  *  37           T       Rain    (HiProb T)
707  *  38           T+      Severe  (HiProb T+)
708  *  39           R/S-    Mix     (LoProb R/S-)
709  *  40           R/S     Mix     (LoProb R/S)
710  *  41           R/S+    Mix     (LoProb R/S+)
711  *  42           RW/SW-  Mix     (LoProb RW/SW-)
712  *  43           RW/SW   Mix     (LoProb RW/SW)
713  *  44           RW/SW+  Mix     (LoProb RW/SW+)
714  *  45           R/IP-   Mix     (LoProb R/IP-)
715  *  46           R/IP    Mix     (LoProb R/IP)
716  *  47           R/IP+   Mix     (LoProb R/IP+)
717  *  48           S/IP-   Mix     (LoProb S/IP-)
718  *  49           S/IP    Mix     (LoProb S/IP)
719  *  50           S/IP+   Mix     (LoProb S/IP+)
720  *  51           R/S-    Mix     (HiProb R/S-)
721  *  52           R/S     Mix     (HiProb R/S)
722  *  53           R/S+    Mix     (HiProb R/S+)
723  *  54           RW/SW-  Mix     (HiProb RW/SW-)
724  *  55           RW/SW   Mix     (HiProb RW/SW)
725  *  56           RW/SW+  Mix     (HiProb RW/SW+)
726  *  57           R/IP-   Mix     (HiProb R/IP-)
727  *  58           R/IP    Mix     (HiProb R/IP)
728  *  59           R/IP+   Mix     (HiProb R/IP+)
729  *  60           S/IP-   Mix     (HiProb S/IP-)
730  *  61           S/IP    Mix     (HiProb S/IP)
731  *  62           S/IP+   Mix     (HiProb S/IP+)
732  *  63           IP-     Ice     (LoProb IP-)
733  *  64           IP      Ice     (LoProb IP)
734  *  65           IP+     Ice     (LoProb IP+)
735  *  66           ZL-     Ice     (LoProb ZL-)
736  *  67           ZL      Ice     (LoProb ZL)
737  *  68           ZL+     Ice     (LoProb ZL+)
738  *  69           R/ZL-   Ice     (LoProb R/ZL-)
739  *  70           R/ZL    Ice     (LoProb R/ZL)
740  *  71           R/ZL+   Ice     (LoProb R/ZL+)
741  *  72           ZR-     Ice     (LoProb ZR-)
742  *  73           ZR      Ice     (LoProb ZR)
743  *  74           ZR+     Ice     (LoProb ZR+)
744  *  75           R/ZR-   Ice     (LoProb R/ZR-)
745  *  76           R/ZR    Ice     (LoProb R/ZR)
746  *  77           R/ZR+   Ice     (LoProb R/ZR+)
747  *  78           IP/ZR-  Ice     (LoProb IP/ZR-)
748  *  79           IP/ZR   Ice     (LoProb IP/ZR)
749  *  80           IP/ZR+  Ice     (LoProb IP/ZR+)
750  *  81           IP-     Ice     (HiProb IP-)
751  *  82           IP      Ice     (HiProb IP)
752  *  83           IP+     Ice     (HiProb IP+)
753  *  84           ZL-     Ice     (HiProb ZL-)
754  *  85           ZL      Ice     (HiProb ZL)
755  *  86           ZL+     Ice     (HiProb ZL+)
756  *  87           R/ZL-   Ice     (HiProb R/ZL-)
757  *  88           R/ZL    Ice     (HiProb R/ZL)
758  *  89           R/ZL+   Ice     (HiProb R/ZL+)
759  *  90           ZR-     Ice     (HiProb ZR-)
760  *  91           ZR      Ice     (HiProb ZR)
761  *  92           ZR+     Ice     (HiProb ZR+)
762  *  93           R/ZR-   Ice     (HiProb R/ZR-)
763  *  94           R/ZR    Ice     (HiProb R/ZR)
764  *  95           R/ZR+   Ice     (HiProb R/ZR+)
765  *  96           IP/ZR-  Ice     (HiProb IP/ZR-)
766  *  97           IP/ZR   Ice     (HiProb IP/ZR)
767  *  98           IP/ZR+  Ice     (HiProb IP/ZR+)
768  *  99           L/ZL-   Ice     (LoProb L/ZL-)
769  *  100          L/ZL    Ice     (LoProb L/ZL)
770  *  101          L/ZL+   Ice     (LoProb L/ZL+)
771  *  102          L/ZL-   Ice     (HiProb L/ZL-)
772  *  103          L/ZL    Ice     (HiProb L/ZL)
773  *  104          L/ZL+   Ice     (HiProb L/ZL+)
774  *  105          SW-     Snow    (LoProb SW-)
775  *  106          SW      Snow    (LoProb SW)
776  *  107          SW+     Snow    (LoProb SW+)
777  *  108          S-      Snow    (LoProb S-)
778  *  109          S       Snow    (LoProb S)
779  *  110          S+      Snow    (LoProb S+)
780  *  111          SW-     Snow    (HiProb SW-)
781  *  112          SW      Snow    (HiProb SW)
782  *  113          SW+     Snow    (HiProb SW+)
783  *  114          S-      Snow    (HiProb S-)
784  *  115          S       Snow    (HiProb S)
785  *  116          S+      Snow    (HiProb S+)
786  *  117          F       Fog     (Fog)
787  *  118          F+      Fog     (Dense Fog)
788  *  119          H       Haze
789  *  120          K       Smoke
790  *  121          BS      Blowing (Blowing Snow)
791  *  122          BD      Blowing (Blowing Dust)
792  *****************************************************************************
793  */
NDFD_WxTable2(UglyStringType * ugly)794 static int NDFD_WxTable2 (UglyStringType * ugly)
795 {
796    switch (ugly->wx[0]) {
797       case WX_NOWX:
798          return 0;
799       case WX_R:
800          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
801              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
802              (ugly->cover[0] == COV_CHC)) {
803             switch (ugly->wx[1]) {
804                case WX_S:
805                   return (NDFD_WxTable2_StdInten (40, ugly->intens[0]));
806                case WX_ZR: /* Rain/Freezing Rain */
807                   return (NDFD_WxTable2_StdInten (76, ugly->intens[0]));
808                case WX_IP: /* Rain/Sleet */
809                   return (NDFD_WxTable2_StdInten (46, ugly->intens[0]));
810                case WX_ZL: /* Rain/Freezing Drizzle */
811                   return (NDFD_WxTable2_StdInten (70, ugly->intens[0]));
812                case WX_SW: /* Rain/Snow Showers */
813                   return (NDFD_WxTable2_StdInten (40, ugly->intens[0]));
814                case WX_T: /* Rain/Thunderstorms */
815                   switch (ugly->intens[0]) {
816                      case INT_D:
817                      case INT_DD:
818                         return 9;
819                      case INT_P:
820                         return 8;
821                      default:
822                         return 27;
823                   }
824                default:
825                   return (NDFD_WxTable2_StdInten (5, ugly->intens[0]));
826             }
827          } else {
828             switch (ugly->wx[1]) {
829                case WX_S: /* Rain/Snow */
830                   return (NDFD_WxTable2_StdInten (52, ugly->intens[0]));
831                case WX_ZR: /* Rain/Freezing Rain */
832                   return (NDFD_WxTable2_StdInten (94, ugly->intens[0]));
833                case WX_IP: /* Rain/Sleet */
834                   return (NDFD_WxTable2_StdInten (58, ugly->intens[0]));
835                case WX_ZL: /* Rain/Freezing Drizzle */
836                   return (NDFD_WxTable2_StdInten (88, ugly->intens[0]));
837                case WX_SW: /* Rain/Snow Showers */
838                   return (NDFD_WxTable2_StdInten (52, ugly->intens[0]));
839                case WX_T: /* Rain/Thunderstorms */
840                   switch (ugly->intens[0]) {
841                      case INT_D:
842                      case INT_DD:
843                         return 29;
844                      case INT_P:
845                         return 28;
846                      default:
847                         return 27;
848                   }
849                default:
850                   return (NDFD_WxTable2_StdInten (24, ugly->intens[0]));
851             }
852          }
853       case WX_RW:
854          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
855              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
856              (ugly->cover[0] == COV_CHC)) {
857             switch (ugly->wx[1]) {
858                case WX_T: /* Rain Showers/Thunderstorms */
859                   switch (ugly->intens[0]) {
860                      case INT_D:
861                      case INT_DD:
862                         return 17;
863                      case INT_P:
864                         return 16;
865                      default:
866                         return 15;
867                   }
868                case WX_SW: /* Rain Showers/Snow Showers */
869                case WX_S: /* Rain Showers/Snow */
870                   return (NDFD_WxTable2_StdInten (43, ugly->intens[0]));
871                default:
872                   return (NDFD_WxTable2_StdInten (12, ugly->intens[0]));
873             }
874          } else {
875             switch (ugly->wx[1]) {
876                case WX_T: /* Rain Showers/Thunderstorms */
877                   switch (ugly->intens[0]) {
878                      case INT_D:
879                      case INT_DD:
880                         return 36;
881                      case INT_P:
882                         return 35;
883                      default:
884                         return 33;
885                   }
886                case WX_SW: /* Rain Showers/Snow Showers */
887                case WX_S: /* Rain Showers/Snow */
888                   return (NDFD_WxTable2_StdInten (55, ugly->intens[0]));
889                default:
890                   return (NDFD_WxTable2_StdInten (31, ugly->intens[0]));
891             }
892          }
893       case WX_L:
894          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
895              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
896              (ugly->cover[0] == COV_CHC)) {
897             switch (ugly->wx[1]) {
898                case WX_ZL: /* Drizzle/Freezing Drizzle */
899                   return (NDFD_WxTable2_StdInten (100, ugly->intens[0]));
900                case WX_F:
901                default: /* Drizzle */
902                   return (NDFD_WxTable2_StdInten (2, ugly->intens[0]));
903             }
904          } else {
905             switch (ugly->wx[1]) {
906                case WX_ZL: /* Drizzle/Freezing Drizzle */
907                   return (NDFD_WxTable2_StdInten (103, ugly->intens[0]));
908                case WX_F:
909                default: /* Drizzle */
910                   return (NDFD_WxTable2_StdInten (21, ugly->intens[0]));
911             }
912          }
913       case WX_ZL:
914          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
915              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
916              (ugly->cover[0] == COV_CHC)) {
917             switch (ugly->wx[1]) {
918                case WX_R: /* Freezing Drizzle/Rain */
919                   return (NDFD_WxTable2_StdInten (70, ugly->intens[0]));
920                case WX_L: /* Freezing Drizzle/Drizzle */
921                   return (NDFD_WxTable2_StdInten (100, ugly->intens[0]));
922                default:
923                   return (NDFD_WxTable2_StdInten (67, ugly->intens[0]));
924             }
925          } else {
926             switch (ugly->wx[1]) {
927                case WX_R: /* Freezing Drizzle/Rain */
928                   return (NDFD_WxTable2_StdInten (88, ugly->intens[0]));
929                case WX_L: /* Freezing Drizzle/Drizzle */
930                   return (NDFD_WxTable2_StdInten (103, ugly->intens[0]));
931                default: /* Freezing Drizzle */
932                   return (NDFD_WxTable2_StdInten (85, ugly->intens[0]));
933             }
934          }
935       case WX_ZR:
936          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
937              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
938              (ugly->cover[0] == COV_CHC)) {
939             switch (ugly->wx[1]) {
940                case WX_R: /* Freezing Rain/Rain */
941                   return (NDFD_WxTable2_StdInten (76, ugly->intens[0]));
942                case WX_IP: /* Freezing Rain/Sleet */
943                   return (NDFD_WxTable2_StdInten (79, ugly->intens[0]));
944                default:
945                   return (NDFD_WxTable2_StdInten (73, ugly->intens[0]));
946             }
947          } else {
948             switch (ugly->wx[1]) {
949                case WX_R: /* Freezing Rain/Rain */
950                   return (NDFD_WxTable2_StdInten (94, ugly->intens[0]));
951                case WX_IP: /* Freezing Rain/Sleet */
952                   return (NDFD_WxTable2_StdInten (97, ugly->intens[0]));
953                default:
954                   return (NDFD_WxTable2_StdInten (91, ugly->intens[0]));
955             }
956          }
957       case WX_IP:
958          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
959              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
960              (ugly->cover[0] == COV_CHC)) {
961             switch (ugly->wx[1]) {
962                case WX_R: /* Sleet/Rain */
963                   return (NDFD_WxTable2_StdInten (46, ugly->intens[0]));
964                case WX_S: /* Sleet/Snow */
965                   return (NDFD_WxTable2_StdInten (49, ugly->intens[0]));
966                case WX_ZR: /* Sleet/Freezing Rain */
967                   return (NDFD_WxTable2_StdInten (79, ugly->intens[0]));
968                default:
969                   return (NDFD_WxTable2_StdInten (64, ugly->intens[0]));
970             }
971          } else {
972             switch (ugly->wx[1]) {
973                case WX_R: /* Sleet/Rain */
974                   return (NDFD_WxTable2_StdInten (58, ugly->intens[0]));
975                case WX_S: /* Sleet/Snow */
976                   return (NDFD_WxTable2_StdInten (61, ugly->intens[0]));
977                case WX_ZR: /* Sleet/Freezing Rain */
978                   return (NDFD_WxTable2_StdInten (97, ugly->intens[0]));
979                default:
980                   return (NDFD_WxTable2_StdInten (82, ugly->intens[0]));
981             }
982          }
983       case WX_SW:
984          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
985              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
986              (ugly->cover[0] == COV_CHC)) {
987             switch (ugly->wx[1]) {
988                case WX_R: /* Snow Showers/Rain */
989                case WX_RW: /* Snow Showers/Rain Showers */
990                   return (NDFD_WxTable2_StdInten (43, ugly->intens[0]));
991                default: /* Snow Showers */
992                   return (NDFD_WxTable2_StdInten (106, ugly->intens[0]));
993             }
994          } else {
995             switch (ugly->wx[1]) {
996                case WX_R: /* Snow Showers/Rain */
997                case WX_RW: /* Snow Showers/Rain Showers */
998                   return (NDFD_WxTable2_StdInten (55, ugly->intens[0]));
999                default: /* Snow Showers */
1000                   return (NDFD_WxTable2_StdInten (112, ugly->intens[0]));
1001             }
1002          }
1003       case WX_S:
1004          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
1005              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
1006              (ugly->cover[0] == COV_CHC)) {
1007             switch (ugly->wx[1]) {
1008                case WX_R: /* Snow/Rain */
1009                case WX_RW: /* Snow/Rain Showers */
1010                   return (NDFD_WxTable2_StdInten (40, ugly->intens[0]));
1011                case WX_IP: /* Snow/Sleet */
1012                   return (NDFD_WxTable2_StdInten (49, ugly->intens[0]));
1013                default:
1014                   return (NDFD_WxTable2_StdInten (109, ugly->intens[0]));
1015             }
1016          } else {
1017             switch (ugly->wx[1]) {
1018                case WX_R: /* Snow/Rain */
1019                case WX_RW:
1020                   return (NDFD_WxTable2_StdInten (52, ugly->intens[0]));
1021                case WX_IP: /* Snow/Sleet */
1022                   return (NDFD_WxTable2_StdInten (61, ugly->intens[0]));
1023                default:
1024                   return (NDFD_WxTable2_StdInten (115, ugly->intens[0]));
1025             }
1026          }
1027       case WX_T:
1028          /*
1029           * Check Severe storms.  If so, this is most important weather
1030           * type.
1031           */
1032 /*
1033          if (ugly->intens[0] == INT_P) {
1034             return 17;  * Severe Thunderstorms *
1035          }
1036 */
1037          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
1038              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
1039              (ugly->cover[0] == COV_CHC)) {
1040             switch (ugly->wx[1]) {
1041                case WX_RW: /* Thunderstorms/Rain Showers */
1042                   switch (ugly->intens[0]) {
1043                      case INT_D:
1044                      case INT_DD:
1045                         return 17;
1046                      case INT_P:
1047                         return 14;
1048                      default:
1049                         return 15;
1050                   }
1051                case WX_R: /* Thunderstorms/Rain */
1052                   switch (ugly->intens[0]) {
1053                      case INT_D:
1054                      case INT_DD:
1055                         return 9;
1056                      case INT_P:
1057                         return 7;
1058                      default:
1059                         return 10;
1060                   }
1061                default: /* Thunderstorms. */
1062                   switch (ugly->intens[0]) {
1063                      case INT_D:
1064                      case INT_DD:
1065                         return 18;
1066                      case INT_P:
1067                         return 19;
1068                      default:
1069                         return 18;
1070                   }
1071             }
1072          } else {
1073             switch (ugly->wx[1]) {
1074                case WX_RW: /* Thunderstorms/Rain Showers */
1075                   switch (ugly->intens[0]) {
1076                      case INT_D:
1077                      case INT_DD:
1078                         return 36;
1079                      case INT_P:
1080                         return 34;
1081                      default:
1082                         return 33; /* corrected from 37 */
1083                   }
1084                case WX_R: /* Thunderstorms/Rain */
1085                   switch (ugly->intens[0]) {
1086                      case INT_D:
1087                      case INT_DD:
1088                         return 29;
1089                      case INT_P:
1090                         return 26;
1091                      default:
1092                         return 27;
1093                   }
1094                default: /* Thunderstorms. */
1095                   switch (ugly->intens[0]) {
1096                      case INT_D:
1097                      case INT_DD:
1098                         return 37;
1099                      case INT_P:
1100                         return 38;
1101                      default:
1102                         return 37;
1103                   }
1104             }
1105          }
1106       case WX_A:       /* Ignore Hail */
1107          return 0;
1108       case WX_F:       /* Fog */
1109          switch (ugly->intens[0]) {
1110             case INT_P:
1111                return 118;
1112             default:
1113                return 117;
1114          }
1115       case WX_H:       /* Haze */
1116          return 119;
1117       case WX_K:       /* Smoke */
1118          return 120;
1119       case WX_FR:      /* Ignore Frost */
1120          return 0;
1121       case WX_BS:      /* Blowing Snow */
1122          return 121;
1123       case WX_BD:      /* Blowing Dust */
1124          return 122;
1125       default:
1126          return 0;
1127    }
1128 }
1129 
1130 /*****************************************************************************
1131  * NDFD_WxTable3() --
1132  *
1133  * Original: makeWxImageCodes() Marc Saccucci Feb 2004 (MDL)
1134  * Adapted to NDFD_WxTable3() Arthur Taylor / MDL
1135  *
1136  * PURPOSE
1137  *   To use the same weather table scheme used by Marc Saccucci in
1138  * makeWxImageCodes() in the NDFD source tree.  The purpose of both
1139  * procedures is to simplify the weather string (aka ugly string) to a single
1140  * integral code number, which contains the most relevant weather.  The
1141  * intent is to create a simpler field which can more readily be viewed as
1142  * an image.
1143  *
1144  * ARGUMENTS
1145  * ugly = The ugly weather string to encode. (Input)
1146  *
1147  * FILES/DATABASES: None
1148  *
1149  * RETURNS: int (the encoded number.)
1150  *
1151  * HISTORY
1152  *  11/2002 Marc Saccucci (MDL): Created matching algorithm in
1153  *              makeWxImageCodes().
1154  *   6/2003 MS: Altered matching combinations in makeWxImageCodes().
1155  *   1/2004 MS: Updated to include intensity considerations for all Precip
1156  *              types.
1157  *   2/2004 MS: Updated to include: 123..129 ZF, IF, IC, BN, ZY, VA, WP
1158  *   2/2004 Arthur Taylor (MDL/RSIS): Created NDFD_WxTable3()
1159  *
1160  * NOTES
1161  *  1) The table used:
1162  *  new_code  Sample Value  Legend Value    Description
1163  *  --------  ------------ --------------   ------------
1164  *  0            -        -      No Predominant Weather
1165  *  1            L-      Rain    (LoProb L-)
1166  *  2            L       Rain    (LoProb L)
1167  *  3            L+      Rain    (LoProb L+)
1168  *  4            R-      Rain    (LoProb R-)
1169  *  5            R       Rain    (LoProb R)
1170  *  6            R+      Rain    (LoProb R+)
1171  *  7            R/T+    Severe  (LoProb R/T+)
1172  *  8            T/R+    Rain    (LoProb T/R+)
1173  *  9            T/R-    Rain    (LoProb T/R-)
1174  *  10           R/T     Rain    (LoProb R/T)
1175  *  11           RW-     Rain    (LoProb RW-)
1176  *  12           RW      Rain    (LoProb RW)
1177  *  13           RW+     Rain    (LoProb RW+)
1178  *  14           RW/T+   Severe  (LoProb RW/T+)
1179  *  15           RW/T    Rain    (LoProb RW/T)
1180  *  16           T/RW+   Rain    (LoProb T/RW+)
1181  *  17           T/RW-   Rain    (LoProb T/RW-)
1182  *  18           T       Rain    (LoProb T)
1183  *  19           T+      Severe  (LoProb T+)
1184  *  20           L-      Rain    (HiProb L-)
1185  *  21           L       Rain    (HiProb L)
1186  *  22           L+      Rain    (HiProb L+)
1187  *  23           R-      Rain    (HiProb R-)
1188  *  24           R       Rain    (HiProb R)
1189  *  25           R+      Rain    (HiProb R+)
1190  *  26           R/T+    Severe  (HiProb R/T+)
1191  *  27           R/T     Rain    (HiProb R/T)
1192  *  28           T/R+    Rain    (HiProb T/R+)
1193  *  29           T/R-    Rain    (HiProb T/R-)
1194  *  30           RW-     Rain    (HiProb RW-)
1195  *  31           RW      Rain    (HiProb RW)
1196  *  32           RW+     Rain    (HiProb RW+)
1197  *  33           RW/T    Rain    (HiProb RW/T)
1198  *  34           RW/T+   Severe  (HiProb RW/T+)
1199  *  35           T/RW+   Rain    (HiProb T/RW+)
1200  *  36           T/RW-   Rain    (HiProb T/RW-)
1201  *  37           T       Rain    (HiProb T)
1202  *  38           T+      Severe  (HiProb T+)
1203  *  39           R/S-    Mix     (LoProb R/S-)
1204  *  40           R/S     Mix     (LoProb R/S)
1205  *  41           R/S+    Mix     (LoProb R/S+)
1206  *  42           RW/SW-  Mix     (LoProb RW/SW-)
1207  *  43           RW/SW   Mix     (LoProb RW/SW)
1208  *  44           RW/SW+  Mix     (LoProb RW/SW+)
1209  *  45           R/IP-   Mix     (LoProb R/IP-)
1210  *  46           R/IP    Mix     (LoProb R/IP)
1211  *  47           R/IP+   Mix     (LoProb R/IP+)
1212  *  48           S/IP-   Mix     (LoProb S/IP-)
1213  *  49           S/IP    Mix     (LoProb S/IP)
1214  *  50           S/IP+   Mix     (LoProb S/IP+)
1215  *  51           R/S-    Mix     (HiProb R/S-)
1216  *  52           R/S     Mix     (HiProb R/S)
1217  *  53           R/S+    Mix     (HiProb R/S+)
1218  *  54           RW/SW-  Mix     (HiProb RW/SW-)
1219  *  55           RW/SW   Mix     (HiProb RW/SW)
1220  *  56           RW/SW+  Mix     (HiProb RW/SW+)
1221  *  57           R/IP-   Mix     (HiProb R/IP-)
1222  *  58           R/IP    Mix     (HiProb R/IP)
1223  *  59           R/IP+   Mix     (HiProb R/IP+)
1224  *  60           S/IP-   Mix     (HiProb S/IP-)
1225  *  61           S/IP    Mix     (HiProb S/IP)
1226  *  62           S/IP+   Mix     (HiProb S/IP+)
1227  *  63           IP-     Ice     (LoProb IP-)
1228  *  64           IP      Ice     (LoProb IP)
1229  *  65           IP+     Ice     (LoProb IP+)
1230  *  66           ZL-     Ice     (LoProb ZL-)
1231  *  67           ZL      Ice     (LoProb ZL)
1232  *  68           ZL+     Ice     (LoProb ZL+)
1233  *  69           R/ZL-   Ice     (LoProb R/ZL-)
1234  *  70           R/ZL    Ice     (LoProb R/ZL)
1235  *  71           R/ZL+   Ice     (LoProb R/ZL+)
1236  *  72           ZR-     Ice     (LoProb ZR-)
1237  *  73           ZR      Ice     (LoProb ZR)
1238  *  74           ZR+     Ice     (LoProb ZR+)
1239  *  75           R/ZR-   Ice     (LoProb R/ZR-)
1240  *  76           R/ZR    Ice     (LoProb R/ZR)
1241  *  77           R/ZR+   Ice     (LoProb R/ZR+)
1242  *  78           IP/ZR-  Ice     (LoProb IP/ZR-)
1243  *  79           IP/ZR   Ice     (LoProb IP/ZR)
1244  *  80           IP/ZR+  Ice     (LoProb IP/ZR+)
1245  *  81           IP-     Ice     (HiProb IP-)
1246  *  82           IP      Ice     (HiProb IP)
1247  *  83           IP+     Ice     (HiProb IP+)
1248  *  84           ZL-     Ice     (HiProb ZL-)
1249  *  85           ZL      Ice     (HiProb ZL)
1250  *  86           ZL+     Ice     (HiProb ZL+)
1251  *  87           R/ZL-   Ice     (HiProb R/ZL-)
1252  *  88           R/ZL    Ice     (HiProb R/ZL)
1253  *  89           R/ZL+   Ice     (HiProb R/ZL+)
1254  *  90           ZR-     Ice     (HiProb ZR-)
1255  *  91           ZR      Ice     (HiProb ZR)
1256  *  92           ZR+     Ice     (HiProb ZR+)
1257  *  93           R/ZR-   Ice     (HiProb R/ZR-)
1258  *  94           R/ZR    Ice     (HiProb R/ZR)
1259  *  95           R/ZR+   Ice     (HiProb R/ZR+)
1260  *  96           IP/ZR-  Ice     (HiProb IP/ZR-)
1261  *  97           IP/ZR   Ice     (HiProb IP/ZR)
1262  *  98           IP/ZR+  Ice     (HiProb IP/ZR+)
1263  *  99           L/ZL-   Ice     (LoProb L/ZL-)
1264  *  100          L/ZL    Ice     (LoProb L/ZL)
1265  *  101          L/ZL+   Ice     (LoProb L/ZL+)
1266  *  102          L/ZL-   Ice     (HiProb L/ZL-)
1267  *  103          L/ZL    Ice     (HiProb L/ZL)
1268  *  104          L/ZL+   Ice     (HiProb L/ZL+)
1269  *  105          SW-     Snow    (LoProb SW-)
1270  *  106          SW      Snow    (LoProb SW)
1271  *  107          SW+     Snow    (LoProb SW+)
1272  *  108          S-      Snow    (LoProb S-)
1273  *  109          S       Snow    (LoProb S)
1274  *  110          S+      Snow    (LoProb S+)
1275  *  111          SW-     Snow    (HiProb SW-)
1276  *  112          SW      Snow    (HiProb SW)
1277  *  113          SW+     Snow    (HiProb SW+)
1278  *  114          S-      Snow    (HiProb S-)
1279  *  115          S       Snow    (HiProb S)
1280  *  116          S+      Snow    (HiProb S+)
1281  *  117          F       Fog     (Fog)
1282  *  118          F+      Fog     (Dense Fog)
1283  *  119          H       Haze
1284  *  120          K       Smoke
1285  *  121          BS      Blowing (Blowing Snow)
1286  *  122          BD      Blowing (Blowing Dust)
1287  *  123          ZF      Fog     (Freezing Fog)
1288  *  124          IF      Fog     (Ice Fog)
1289  *  125          IC      Ice     (Ice Crystals)
1290  *  126          BN      Blowing (Blowing Sand)
1291  *  127          ZY      Blowing (Freezing Spray)
1292  *  128          VA      Smoke   (Volcanic Ash)
1293  *  129          WP      Severe  (Water Spouts)
1294  *****************************************************************************
1295  */
NDFD_WxTable3(UglyStringType * ugly)1296 static int NDFD_WxTable3 (UglyStringType * ugly)
1297 {
1298    switch (ugly->wx[0]) {
1299       case WX_NOWX:
1300          return 0;
1301       case WX_R:
1302          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
1303              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
1304              (ugly->cover[0] == COV_CHC)) {
1305             switch (ugly->wx[1]) {
1306                case WX_S:
1307                   return (NDFD_WxTable2_StdInten (40, ugly->intens[0]));
1308                case WX_ZR: /* Rain/Freezing Rain */
1309                   return (NDFD_WxTable2_StdInten (76, ugly->intens[0]));
1310                case WX_IP: /* Rain/Sleet */
1311                   return (NDFD_WxTable2_StdInten (46, ugly->intens[0]));
1312                case WX_ZL: /* Rain/Freezing Drizzle */
1313                   return (NDFD_WxTable2_StdInten (70, ugly->intens[0]));
1314                case WX_SW: /* Rain/Snow Showers */
1315                   return (NDFD_WxTable2_StdInten (40, ugly->intens[0]));
1316                case WX_T: /* Rain/Thunderstorms */
1317                   switch (ugly->intens[0]) {
1318                      case INT_D:
1319                      case INT_DD:
1320                         return 9;
1321                      case INT_P:
1322                         return 8;
1323                      default:
1324                         return 27;
1325                   }
1326                default:
1327                   return (NDFD_WxTable2_StdInten (5, ugly->intens[0]));
1328             }
1329          } else {
1330             switch (ugly->wx[1]) {
1331                case WX_S: /* Rain/Snow */
1332                   return (NDFD_WxTable2_StdInten (52, ugly->intens[0]));
1333                case WX_ZR: /* Rain/Freezing Rain */
1334                   return (NDFD_WxTable2_StdInten (94, ugly->intens[0]));
1335                case WX_IP: /* Rain/Sleet */
1336                   return (NDFD_WxTable2_StdInten (58, ugly->intens[0]));
1337                case WX_ZL: /* Rain/Freezing Drizzle */
1338                   return (NDFD_WxTable2_StdInten (88, ugly->intens[0]));
1339                case WX_SW: /* Rain/Snow Showers */
1340                   return (NDFD_WxTable2_StdInten (52, ugly->intens[0]));
1341                case WX_T: /* Rain/Thunderstorms */
1342                   switch (ugly->intens[0]) {
1343                      case INT_D:
1344                      case INT_DD:
1345                         return 29;
1346                      case INT_P:
1347                         return 28;
1348                      default:
1349                         return 27;
1350                   }
1351                default:
1352                   return (NDFD_WxTable2_StdInten (24, ugly->intens[0]));
1353             }
1354          }
1355       case WX_RW:
1356          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
1357              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
1358              (ugly->cover[0] == COV_CHC)) {
1359             switch (ugly->wx[1]) {
1360                case WX_T: /* Rain Showers/Thunderstorms */
1361                   switch (ugly->intens[0]) {
1362                      case INT_D:
1363                      case INT_DD:
1364                         return 17;
1365                      case INT_P:
1366                         return 16;
1367                      default:
1368                         return 15;
1369                   }
1370                case WX_SW: /* Rain Showers/Snow Showers */
1371                case WX_S: /* Rain Showers/Snow */
1372                   return (NDFD_WxTable2_StdInten (43, ugly->intens[0]));
1373                default:
1374                   return (NDFD_WxTable2_StdInten (12, ugly->intens[0]));
1375             }
1376          } else {
1377             switch (ugly->wx[1]) {
1378                case WX_T: /* Rain Showers/Thunderstorms */
1379                   switch (ugly->intens[0]) {
1380                      case INT_D:
1381                      case INT_DD:
1382                         return 36;
1383                      case INT_P:
1384                         return 35;
1385                      default:
1386                         return 33;
1387                   }
1388                case WX_SW: /* Rain Showers/Snow Showers */
1389                case WX_S: /* Rain Showers/Snow */
1390                   return (NDFD_WxTable2_StdInten (55, ugly->intens[0]));
1391                default:
1392                   return (NDFD_WxTable2_StdInten (31, ugly->intens[0]));
1393             }
1394          }
1395       case WX_L:
1396          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
1397              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
1398              (ugly->cover[0] == COV_CHC)) {
1399             switch (ugly->wx[1]) {
1400                case WX_ZL: /* Drizzle/Freezing Drizzle */
1401                   return (NDFD_WxTable2_StdInten (100, ugly->intens[0]));
1402                case WX_F:
1403                default: /* Drizzle */
1404                   return (NDFD_WxTable2_StdInten (2, ugly->intens[0]));
1405             }
1406          } else {
1407             switch (ugly->wx[1]) {
1408                case WX_ZL: /* Drizzle/Freezing Drizzle */
1409                   return (NDFD_WxTable2_StdInten (103, ugly->intens[0]));
1410                case WX_F:
1411                default: /* Drizzle */
1412                   return (NDFD_WxTable2_StdInten (21, ugly->intens[0]));
1413             }
1414          }
1415       case WX_ZL:
1416          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
1417              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
1418              (ugly->cover[0] == COV_CHC)) {
1419             switch (ugly->wx[1]) {
1420                case WX_R: /* Freezing Drizzle/Rain */
1421                   return (NDFD_WxTable2_StdInten (70, ugly->intens[0]));
1422                case WX_L: /* Freezing Drizzle/Drizzle */
1423                   return (NDFD_WxTable2_StdInten (100, ugly->intens[0]));
1424                default:
1425                   return (NDFD_WxTable2_StdInten (67, ugly->intens[0]));
1426             }
1427          } else {
1428             switch (ugly->wx[1]) {
1429                case WX_R: /* Freezing Drizzle/Rain */
1430                   return (NDFD_WxTable2_StdInten (88, ugly->intens[0]));
1431                case WX_L: /* Freezing Drizzle/Drizzle */
1432                   return (NDFD_WxTable2_StdInten (103, ugly->intens[0]));
1433                default: /* Freezing Drizzle */
1434                   return (NDFD_WxTable2_StdInten (85, ugly->intens[0]));
1435             }
1436          }
1437       case WX_ZR:
1438          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
1439              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
1440              (ugly->cover[0] == COV_CHC)) {
1441             switch (ugly->wx[1]) {
1442                case WX_R: /* Freezing Rain/Rain */
1443                   return (NDFD_WxTable2_StdInten (76, ugly->intens[0]));
1444                case WX_IP: /* Freezing Rain/Sleet */
1445                   return (NDFD_WxTable2_StdInten (79, ugly->intens[0]));
1446                default:
1447                   return (NDFD_WxTable2_StdInten (73, ugly->intens[0]));
1448             }
1449          } else {
1450             switch (ugly->wx[1]) {
1451                case WX_R: /* Freezing Rain/Rain */
1452                   return (NDFD_WxTable2_StdInten (94, ugly->intens[0]));
1453                case WX_IP: /* Freezing Rain/Sleet */
1454                   return (NDFD_WxTable2_StdInten (97, ugly->intens[0]));
1455                default:
1456                   return (NDFD_WxTable2_StdInten (91, ugly->intens[0]));
1457             }
1458          }
1459       case WX_IP:
1460          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
1461              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
1462              (ugly->cover[0] == COV_CHC)) {
1463             switch (ugly->wx[1]) {
1464                case WX_R: /* Sleet/Rain */
1465                   return (NDFD_WxTable2_StdInten (46, ugly->intens[0]));
1466                case WX_S: /* Sleet/Snow */
1467                   return (NDFD_WxTable2_StdInten (49, ugly->intens[0]));
1468                case WX_ZR: /* Sleet/Freezing Rain */
1469                   return (NDFD_WxTable2_StdInten (79, ugly->intens[0]));
1470                default:
1471                   return (NDFD_WxTable2_StdInten (64, ugly->intens[0]));
1472             }
1473          } else {
1474             switch (ugly->wx[1]) {
1475                case WX_R: /* Sleet/Rain */
1476                   return (NDFD_WxTable2_StdInten (58, ugly->intens[0]));
1477                case WX_S: /* Sleet/Snow */
1478                   return (NDFD_WxTable2_StdInten (61, ugly->intens[0]));
1479                case WX_ZR: /* Sleet/Freezing Rain */
1480                   return (NDFD_WxTable2_StdInten (97, ugly->intens[0]));
1481                default:
1482                   return (NDFD_WxTable2_StdInten (82, ugly->intens[0]));
1483             }
1484          }
1485       case WX_SW:
1486          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
1487              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
1488              (ugly->cover[0] == COV_CHC)) {
1489             switch (ugly->wx[1]) {
1490                case WX_R: /* Snow Showers/Rain */
1491                case WX_RW: /* Snow Showers/Rain Showers */
1492                   return (NDFD_WxTable2_StdInten (43, ugly->intens[0]));
1493                default: /* Snow Showers */
1494                   return (NDFD_WxTable2_StdInten (106, ugly->intens[0]));
1495             }
1496          } else {
1497             switch (ugly->wx[1]) {
1498                case WX_R: /* Snow Showers/Rain */
1499                case WX_RW: /* Snow Showers/Rain Showers */
1500                   return (NDFD_WxTable2_StdInten (55, ugly->intens[0]));
1501                default: /* Snow Showers */
1502                   return (NDFD_WxTable2_StdInten (112, ugly->intens[0]));
1503             }
1504          }
1505       case WX_S:
1506          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
1507              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
1508              (ugly->cover[0] == COV_CHC)) {
1509             switch (ugly->wx[1]) {
1510                case WX_R: /* Snow/Rain */
1511                case WX_RW: /* Snow/Rain Showers */
1512                   return (NDFD_WxTable2_StdInten (40, ugly->intens[0]));
1513                case WX_IP: /* Snow/Sleet */
1514                   return (NDFD_WxTable2_StdInten (49, ugly->intens[0]));
1515                default:
1516                   return (NDFD_WxTable2_StdInten (109, ugly->intens[0]));
1517             }
1518          } else {
1519             switch (ugly->wx[1]) {
1520                case WX_R: /* Snow/Rain */
1521                case WX_RW:
1522                   return (NDFD_WxTable2_StdInten (52, ugly->intens[0]));
1523                case WX_IP: /* Snow/Sleet */
1524                   return (NDFD_WxTable2_StdInten (61, ugly->intens[0]));
1525                default:
1526                   return (NDFD_WxTable2_StdInten (115, ugly->intens[0]));
1527             }
1528          }
1529       case WX_T:
1530          if ((ugly->cover[0] == COV_SCT) || (ugly->cover[0] == COV_SCHC) ||
1531              (ugly->cover[0] == COV_PATCHY) || (ugly->cover[0] == COV_ISO) ||
1532              (ugly->cover[0] == COV_CHC)) {
1533             switch (ugly->wx[1]) {
1534                case WX_RW: /* Thunderstorms/Rain Showers */
1535                   switch (ugly->intens[0]) {
1536                      case INT_D:
1537                      case INT_DD:
1538                         return 17;
1539                      case INT_P:
1540                         return 14;
1541                      default:
1542                         return 15;
1543                   }
1544                case WX_R: /* Thunderstorms/Rain */
1545                   switch (ugly->intens[0]) {
1546                      case INT_D:
1547                      case INT_DD:
1548                         return 9;
1549                      case INT_P:
1550                         return 7;
1551                      default:
1552                         return 10;
1553                   }
1554                default: /* Thunderstorms. */
1555                   switch (ugly->intens[0]) {
1556                      case INT_D:
1557                      case INT_DD:
1558                         return 18;
1559                      case INT_P:
1560                         return 19;
1561                      default:
1562                         return 18;
1563                   }
1564             }
1565          } else {
1566             switch (ugly->wx[1]) {
1567                case WX_RW: /* Thunderstorms/Rain Showers */
1568                   switch (ugly->intens[0]) {
1569                      case INT_D:
1570                      case INT_DD:
1571                         return 36;
1572                      case INT_P:
1573                         return 34;
1574                      default:
1575                         return 33;
1576                   }
1577                case WX_R: /* Thunderstorms/Rain */
1578                   switch (ugly->intens[0]) {
1579                      case INT_D:
1580                      case INT_DD:
1581                         return 29;
1582                      case INT_P:
1583                         return 26;
1584                      default:
1585                         return 27;
1586                   }
1587                default: /* Thunderstorms. */
1588                   switch (ugly->intens[0]) {
1589                      case INT_D:
1590                      case INT_DD:
1591                         return 37;
1592                      case INT_P:
1593                         return 38;
1594                      default:
1595                         return 37;
1596                   }
1597             }
1598          }
1599       case WX_A:       /* Ignore Hail */
1600          return 0;
1601       case WX_F:       /* Fog */
1602          switch (ugly->intens[0]) {
1603             case INT_P:
1604                return 118;
1605             default:
1606                return 117;
1607          }
1608       case WX_H:       /* Haze */
1609          return 119;
1610       case WX_K:       /* Smoke */
1611          return 120;
1612       case WX_FR:      /* Ignore Frost */
1613          return 0;
1614       case WX_BS:      /* Blowing Snow */
1615          return 121;
1616       case WX_BD:      /* Blowing Dust */
1617          return 122;
1618       case WX_ZF:      /* Freezing Fog */
1619          return 123;
1620       case WX_IF:      /* Ice Fog */
1621          return 124;
1622       case WX_IC:      /* Ice Crystals */
1623          return 125;
1624       case WX_BN:      /* Blowing Sand */
1625          return 126;
1626       case WX_ZY:      /* Freezing Spray */
1627          return 127;
1628       case WX_VA:      /* Volcanic Ash */
1629          return 128;
1630       case WX_WP:      /* Water Spouts */
1631          return 129;
1632       default:
1633          return 0;
1634    }
1635 }
1636 
1637 /*****************************************************************************
1638  * NDFD_Wx2Code4() --
1639  *
1640  * Original: wx2code() Mark Armstrong Nov 2004 (MDL)
1641  * Adapted to NDFD_Wx2Code() Arthur Taylor (MDL)
1642  *
1643  * PURPOSE
1644  *   Converts from a Weather Type to the code value used in makeWxImageCodes.
1645  *
1646  * ARGUMENTS
1647  * wxtype = The weather type to encode. (Input)
1648  *
1649  * FILES/DATABASES: None
1650  *
1651  * RETURNS: int (the encoded number.)
1652  *
1653  * HISTORY
1654  *  11/2004 Mark Armstrong (MDL): Created matching algorithm "wx2code"
1655  *  11/2004 Arthur Taylor (MDL): Modified to assist with NDFD_WxTable4()
1656  *
1657  * NOTES
1658  *****************************************************************************
1659  */
NDFD_Wx2Code4(int wxtype)1660 static int NDFD_Wx2Code4 (int wxtype)
1661 {
1662    switch (wxtype) {
1663       case WX_R:
1664          return 0;
1665       case WX_RW:
1666          return 10;
1667       case WX_L:
1668          return 20;
1669       case WX_ZL:
1670          return 30;
1671       case WX_ZR:
1672          return 40;
1673       case WX_IP:
1674          return 50;
1675       case WX_SW:
1676          return 60;
1677       case WX_S:
1678          return 70;
1679       case WX_T:
1680          return 80;
1681       case WX_F:
1682          return 90;
1683       default:
1684          return 0;
1685    }
1686 }
1687 
1688 /*****************************************************************************
1689  * NDFD_CodeIntens4() --
1690  *
1691  * Original: code_intensity() Mark Armstrong Nov 2004 (MDL)
1692  * Adapted to NDFD_CodeIntens4() Arthur Taylor (MDL)
1693  *
1694  * PURPOSE
1695  *   Converts from two types of weather intensities to the code value used in
1696  * makeWxImageCodes when dealing with intensities.
1697  *
1698  * ARGUMENTS
1699  * inten1 = The first intensity to encode. (Input)
1700  * inten2 = The second intensity to encode. (Input)
1701  *
1702  * FILES/DATABASES: None
1703  *
1704  * RETURNS: int (the encoded number.)
1705  *
1706  * HISTORY
1707  *  11/2004 Mark Armstrong (MDL): Created matching algorithm "code_intensity"
1708  *  11/2004 Arthur Taylor (MDL): Modified to assist with NDFD_WxTable4()
1709  *
1710  * NOTES
1711  *****************************************************************************
1712  */
NDFD_CodeIntens4(int inten1,int inten2)1713 static int NDFD_CodeIntens4 (int inten1, int inten2)
1714 {
1715    switch (inten2) {
1716       case INT_NOINT:
1717       case INT_UNKNOWN:
1718       case INT_M:
1719          if ((inten1 == INT_NOINT) || (inten1 == INT_UNKNOWN) ||
1720              (inten1 == INT_M)) {
1721             return 0;
1722          } else if ((inten1 == INT_D) || (inten1 == INT_DD)) {
1723             return 1;
1724          }
1725          /* Default case */
1726          /* else if (inten1 == INT_P) */
1727          return 2;
1728       case INT_D:
1729       case INT_DD:
1730          if ((inten1 == INT_NOINT) || (inten1 == INT_UNKNOWN) ||
1731              (inten1 == INT_M)) {
1732             return 3;
1733          } else if ((inten1 == INT_D) || (inten1 == INT_DD)) {
1734             return 4;
1735          }
1736          /* Default case */
1737          /* else if (inten1 == INT_P) */
1738          return 5;
1739       case INT_P:
1740       default:
1741          if ((inten1 == INT_NOINT) || (inten1 == INT_UNKNOWN) ||
1742              (inten1 == INT_M)) {
1743             return 6;
1744          } else if ((inten1 == INT_D) || (inten1 == INT_DD)) {
1745             return 7;
1746          }
1747          /* Default case */
1748          /* else if (inten1 == INT_P) */
1749          return 8;
1750    }
1751 }
1752 
1753 /*****************************************************************************
1754  * NDFD_WxTable4() --
1755  *
1756  * Original: makeWxImageCodes() Mark Armstrong Nov 2004 (MDL)
1757  * Adapted to NDFD_WxTable4() Arthur Taylor (MDL)
1758  *
1759  * PURPOSE
1760  *   To use the same weather table scheme used by Mark Armstrong in
1761  * makeWxImageCodes().  The purpose of both procedures is to simplify the
1762  * weather string (aka ugly string) to a single integral code number, which
1763  * contains the most relevant weather.  The intent is to create a simpler
1764  * field which can more readily be viewed as an image.
1765  *
1766  * ARGUMENTS
1767  * ugly = The ugly weather string to encode. (Input)
1768  *
1769  * FILES/DATABASES: None
1770  *
1771  * RETURNS: int (the encoded number.)
1772  *
1773  * HISTORY
1774  *  11/2004 Mark Armstrong (MDL): Created "makeWxImageCodes"
1775  *  11/2004 Arthur Taylor (MDL): Created NDFD_WxTable4
1776  *
1777  * NOTES
1778  *  1) The table used... In the past I have included the table as part of the
1779  * documentation here, but since the table is now > 1000 lines long, I think
1780  * it best to look in "/degrib/data/imageGen/colortable/Wx_200411.colortable"
1781  *****************************************************************************
1782  */
NDFD_WxTable4(UglyStringType * ugly)1783 static int NDFD_WxTable4 (UglyStringType * ugly)
1784 {
1785    int code = 0;
1786    int numValid = ugly->numValid;
1787    int cover1 = ugly->cover[1];
1788    int intens1 = ugly->intens[1];
1789 
1790    if (numValid > 1) {
1791       if ((ugly->wx[1] != WX_R) && (ugly->wx[1] != WX_S) &&
1792           (ugly->wx[1] != WX_RW) && (ugly->wx[1] != WX_SW) &&
1793           (ugly->wx[1] != WX_T) && (ugly->wx[1] != WX_ZR) &&
1794           (ugly->wx[1] != WX_IP) && (ugly->wx[1] != WX_ZL) &&
1795           (ugly->wx[1] != WX_L) && (ugly->wx[1] != WX_F)) {
1796          numValid = 1;
1797          cover1 = COV_UNKNOWN;
1798          intens1 = INT_UNKNOWN;
1799       }
1800    }
1801 
1802    switch (ugly->wx[0]) {
1803       case WX_NOWX:    /* NoWx */
1804       case WX_A:       /* Hail */
1805       case WX_FR:      /* Frost */
1806          code = 0;
1807          break;
1808       case WX_R:       /* Rain */
1809          code = 1;
1810          if (numValid > 1) {
1811             code = 100 + NDFD_Wx2Code4 (ugly->wx[1]);
1812          }
1813          break;
1814       case WX_RW:      /* Rain Showers */
1815          code = 4;
1816          if (numValid > 1) {
1817             code = 200 + NDFD_Wx2Code4 (ugly->wx[1]);
1818          }
1819          break;
1820       case WX_L:       /* Drizzle */
1821          code = 7;
1822          if (numValid > 1) {
1823             code = 300 + NDFD_Wx2Code4 (ugly->wx[1]);
1824          }
1825          break;
1826       case WX_ZL:      /* Freezing Drizzle */
1827          code = 10;
1828          if (numValid > 1) {
1829             code = 400 + NDFD_Wx2Code4 (ugly->wx[1]);
1830          }
1831          break;
1832       case WX_ZR:      /* Freezing Rain */
1833          code = 13;
1834          if (numValid > 1) {
1835             code = 500 + NDFD_Wx2Code4 (ugly->wx[1]);
1836          }
1837          break;
1838       case WX_IP:      /* Sleet */
1839          code = 16;
1840          if (numValid > 1) {
1841             code = 600 + NDFD_Wx2Code4 (ugly->wx[1]);
1842          }
1843          break;
1844       case WX_SW:      /* Snow Showers */
1845          code = 19;
1846          if (numValid > 1) {
1847             code = 700 + NDFD_Wx2Code4 (ugly->wx[1]);
1848          }
1849          break;
1850       case WX_S:       /* Snow */
1851          code = 22;
1852          if (numValid > 1) {
1853             code = 800 + NDFD_Wx2Code4 (ugly->wx[1]);
1854          }
1855          break;
1856       case WX_T:       /* Thunderstorms */
1857          code = 25;
1858          if (numValid > 1) {
1859             code = 900 + NDFD_Wx2Code4 (ugly->wx[1]);
1860          }
1861          break;
1862       case WX_F:       /* Fog */
1863          code = 28;
1864          if (numValid > 1) {
1865             code = 1000 + NDFD_Wx2Code4 (ugly->wx[1]);
1866          }
1867          break;
1868       case WX_K:       /* Smoke */
1869          code = 31;
1870          break;
1871       case WX_BS:      /* Blowing Snow */
1872          code = 32;
1873          break;
1874       case WX_BD:      /* Blowing Dust */
1875          code = 33;
1876          break;
1877       case WX_ZF:      /* Freezing Fog */
1878          code = 34;
1879          break;
1880       case WX_IF:      /* Ice Fog */
1881          code = 35;
1882          break;
1883       case WX_IC:      /* Ice Crystals */
1884          code = 36;
1885          break;
1886       case WX_BN:      /* Blowing Sand */
1887          code = 37;
1888          break;
1889       case WX_ZY:      /* Freezing Spray */
1890          code = 38;
1891          break;
1892       case WX_VA:      /* Volcanic Ash */
1893          code = 39;
1894          break;
1895       case WX_WP:      /* Water Spouts */
1896          code = 40;
1897          break;
1898       case WX_H:       /* Haze */
1899          code = 41;
1900          break;
1901       default:
1902          code = 0;
1903    }                    /* End of Switch statement. */
1904 
1905    if ((ugly->wx[0] == WX_R) || (ugly->wx[0] == WX_S) ||
1906        (ugly->wx[0] == WX_RW) || (ugly->wx[0] == WX_SW) ||
1907        (ugly->wx[0] == WX_T) || (ugly->wx[0] == WX_ZR) ||
1908        (ugly->wx[0] == WX_IP) || (ugly->wx[0] == WX_ZL) ||
1909        (ugly->wx[0] == WX_L) || (ugly->wx[0] == WX_F)) {
1910       code += NDFD_CodeIntens4 (ugly->intens[0], intens1);
1911    }
1912 
1913    if ((ugly->cover[0] == COV_WIDE) || (ugly->cover[0] == COV_LKLY) ||
1914        (ugly->cover[0] == COV_NUM) || (ugly->cover[0] == COV_OCNL) ||
1915        (ugly->cover[0] == COV_DEF) || (ugly->cover[0] == COV_AREAS) ||
1916        (ugly->cover[0] == COV_PDS) || (ugly->cover[0] == COV_FRQ) ||
1917        (ugly->cover[0] == COV_INTER) || (ugly->cover[0] == COV_BRIEF) ||
1918        (cover1 == COV_WIDE) || (cover1 == COV_LKLY) || (cover1 == COV_NUM) ||
1919        (cover1 == COV_OCNL) || (cover1 == COV_DEF) ||
1920        (cover1 == COV_AREAS) || (cover1 == COV_PDS) || (cover1 == COV_FRQ) ||
1921        (cover1 == COV_INTER) || (cover1 == COV_BRIEF)) {
1922       code += 1100;
1923    }
1924 
1925    return code;
1926 }
1927 
1928 /*****************************************************************************
1929  * FreeUglyString() --
1930  *
1931  * Arthur Taylor / MDL
1932  *
1933  * PURPOSE
1934  *   To free the data structure used to hold the parsed ugly string.
1935  *
1936  * ARGUMENTS
1937  * ugly = The ugly string structure to free. (Output)
1938  *
1939  * FILES/DATABASES: None
1940  *
1941  * RETURNS: void
1942  *
1943  * HISTORY
1944  *   9/2003 Arthur Taylor (MDL/RSIS): Created.
1945  *
1946  * NOTES
1947  *****************************************************************************
1948  */
FreeUglyString(UglyStringType * ugly)1949 void FreeUglyString (UglyStringType * ugly)
1950 {
1951    int j;               /* Used to free all the English words. */
1952 
1953    for (j = 0; j < NUM_UGLY_WORD; j++) {
1954       free (ugly->english[j]);
1955    }
1956    free (ugly->errors);
1957 }
1958 
1959 /*****************************************************************************
1960  * InitUglyString() --
1961  *
1962  * Arthur Taylor / MDL
1963  *
1964  * PURPOSE
1965  *   To initialize the structure used to hold the parsed ugly string.
1966  *
1967  * ARGUMENTS
1968  * ugly = The ugly string structure to modify. (Output)
1969  *
1970  * FILES/DATABASES: None
1971  *
1972  * RETURNS: void
1973  *
1974  * HISTORY
1975  *   5/2003 Arthur Taylor (MDL/RSIS): Created.
1976  *   7/2003 AAT: Made it initialize whole UglyString structure instead of
1977  *          just some of the word in the structure.
1978  *
1979  * NOTES
1980  *****************************************************************************
1981  */
InitUglyString(UglyStringType * ugly)1982 static void InitUglyString (UglyStringType * ugly)
1983 {
1984    int i;               /* Used to traverse all the words. */
1985    int j;               /* Used to traverse all the attributes. */
1986 
1987    ugly->numValid = 0;
1988    ugly->minVis = 0;
1989    ugly->validIndex = 0;
1990    ugly->SimpleCode = 0;
1991    ugly->errors = NULL;
1992    for (i = 0; i < NUM_UGLY_WORD; i++) {
1993       ugly->wx[i] = 0;
1994       ugly->cover[i] = 0;
1995       ugly->intens[i] = 0;
1996       ugly->vis[i] = VIS_UNKNOWN;
1997       for (j = 0; j < NUM_UGLY_ATTRIB; j++) {
1998          ugly->attrib[i][j] = 0;
1999       }
2000       ugly->f_or[i] = 0;
2001       ugly->f_priority[i] = 0;
2002       ugly->english[i] = NULL;
2003       ugly->wx_inten[i] = 0;
2004       ugly->HazCode[i] = 0;
2005    }
2006 }
2007 
2008 /*****************************************************************************
2009  * FindInTable() --
2010  *
2011  * Arthur Taylor / MDL
2012  *
2013  * PURPOSE
2014  *   Look through a given table for a particular "phrase".
2015  *
2016  * ARGUMENTS
2017  *    table = The table to look in. (Input)
2018  * tableLen = The length of the table (Input)
2019  *     data = The string (or phrase) to look for. (Input)
2020  *      ans = The index where the string was found. (Output)
2021  *
2022  * FILES/DATABASES: None
2023  *
2024  * RETURNS: int
2025  *  1 = Found it but string is "invalid" or "missing".
2026  *  0 = Found it.
2027  * -1 = Did not find it.
2028  *
2029  * HISTORY
2030  *   5/2003 Arthur Taylor (MDL/RSIS): Created.
2031  *
2032  * NOTES
2033  *****************************************************************************
2034  */
FindInTable(const WxTable * table,int tableLen,char * data,uChar * ans)2035 static int FindInTable (const WxTable * table, int tableLen, char *data, uChar *ans)
2036 {
2037    int i;               /* Index used to walk through the table. */
2038 
2039    for (i = 0; i < tableLen; i++) {
2040       if (strcmp (data, table[i].abrev) == 0) {
2041          *ans = i;
2042          return 0;
2043       }
2044    }
2045    if (strcmp (data, "<Invalid>") == 0) {
2046       return 1;
2047    } else {
2048       return -1;
2049    }
2050 }
2051 
2052 /*****************************************************************************
2053  * UglyLookUp() --
2054  *
2055  * Arthur Taylor / MDL
2056  *
2057  * PURPOSE
2058  *   Determine which table to look in based on how many ':' we have seen in
2059  * the current word.  After looking up the data in the appropriate table,
2060  * Places the result in the appropriate places in the UglyStringType data
2061  * structure.
2062  *
2063  * ARGUMENTS
2064  *   ugly = The ugly string structure to modify. (Output)
2065  *   data = The string (or phrase) to look for. (Input)
2066  *   word = Which word we are currently working on. (Input)
2067  *  place = What part of the word (i.e. # of :'s) (Input)
2068  * attNum = What part of attribute piece (i.e. # of ,'s) (Input)
2069  *
2070  * FILES/DATABASES: None
2071  *
2072  * RETURNS: int
2073  *  0 = No problems
2074  * -1 = 'place' was invalid (larger than 4)
2075  * -2 = Couldn't find the phrase 'data' in the look-up tables.
2076  *
2077  * HISTORY
2078  *   5/2003 Arthur Taylor (MDL/RSIS): Created.
2079  *
2080  * NOTES
2081  *****************************************************************************
2082  */
UglyLookUp(UglyStringType * ugly,char * data,uChar word,uChar place,uChar attNum)2083 static int UglyLookUp (UglyStringType * ugly, char *data, uChar word,
2084                        uChar place, uChar attNum)
2085 {
2086    int ans;
2087 
2088    switch (place) {
2089       case 0:          /* Cover */
2090          ans = FindInTable (WxCover, (sizeof (WxCover) / sizeof (WxTable)),
2091                             data, &(ugly->cover[word]));
2092 /* Don't see why <Invalid> should be treated specially. */
2093 /*
2094          if (ans == 1) {
2095             ugly->f_valid = 0;
2096             return 0;
2097          } else
2098 */
2099          if (ans != 0) {
2100             if (strlen (data) == 0) {
2101                ugly->cover[word] = COV_NOCOV;
2102             } else {
2103                ugly->cover[word] = COV_UNKNOWN;
2104 #ifdef VERBOSE
2105                printf ("No '%s' in WxCover\n", data);
2106 #endif
2107 #ifdef STORE_ERRORS
2108                reallocSprintf (&(ugly->errors), "No '%s' in WxCover ", data);
2109 #endif
2110 /*
2111                return -2;
2112 */
2113             }
2114          }
2115          break;
2116       case 1:          /* Weather */
2117          ans = FindInTable (WxCode, (sizeof (WxCode) / sizeof (WxTable)),
2118                             data, &(ugly->wx[word]));
2119 /* Don't see why <Invalid> should be treated specially. */
2120 /*
2121          if (ans == 1) {
2122             ugly->f_valid = 0;
2123             return 0;
2124          } else
2125 */
2126          if (ans != 0) {
2127             if (strlen (data) == 0) {
2128                ugly->wx[word] = WX_NOWX;
2129             } else {
2130 #ifdef VERBOSE
2131                printf ("No '%s' in WxCode\n", data);
2132 #endif
2133 #ifdef STORE_ERRORS
2134                reallocSprintf (&(ugly->errors), "No '%s' in WxCode ", data);
2135 #endif
2136                return -2;
2137             }
2138          }
2139          break;
2140       case 2:          /* Intensity */
2141          ans = FindInTable (WxIntens, (sizeof (WxIntens) / sizeof (WxTable)),
2142                             data, &(ugly->intens[word]));
2143 /* Don't see why <Invalid> should be treated specially. */
2144 /*
2145          if (ans == 1) {
2146             ugly->f_valid = 0;
2147             return 0;
2148          } else
2149 */
2150          if (ans != 0) {
2151             if (strlen (data) == 0) {
2152                ugly->intens[word] = INT_NOINT;
2153             } else {
2154 #ifdef VERBOSE
2155                printf ("No '%s' in WxIntens\n", data);
2156 #endif
2157 #ifdef STORE_ERRORS
2158                reallocSprintf (&(ugly->errors), "No '%s' in WxIntens ", data);
2159 #endif
2160                return -2;
2161             }
2162          }
2163          break;
2164       case 3:          /* Vis */
2165          ans = FindInTable (WxVisib, (sizeof (WxVisib) / sizeof (WxTable)),
2166                             data, &(ugly->vis[word]));
2167 /* Don't see why <Invalid> should be treated specially. */
2168 /*
2169          if (ans == 1) {
2170             ugly->f_valid = 0;
2171             return 0;
2172          } else
2173 */
2174          if (ans != 0) {
2175             if (strlen (data) == 0) {
2176                ugly->vis[word] = 0;
2177             } else {
2178 #ifdef VERBOSE
2179                printf ("No '%s' in WxVisib\n", data);
2180 #endif
2181 #ifdef STORE_ERRORS
2182                reallocSprintf (&(ugly->errors), "No '%s' in WxVisib ", data);
2183 #endif
2184                return -2;
2185             }
2186          }
2187          ugly->vis[word] = atoi (WxVisib[ugly->vis[word]].name);
2188          if (word == 0) {
2189             ugly->minVis = ugly->vis[word];
2190          } else if (ugly->minVis > ugly->vis[word]) {
2191             ugly->minVis = ugly->vis[word];
2192          }
2193          break;
2194       case 4:          /* Attrib */
2195          ans = FindInTable (WxAttrib, (sizeof (WxAttrib) / sizeof (WxTable)),
2196                             data, &(ugly->attrib[word][attNum]));
2197 /* Don't see why <Invalid> should be treated specially. */
2198 /*
2199          if (ans == 1) {
2200             ugly->f_valid = 0;
2201             return 0;
2202          } else
2203 */
2204          if (ans != 0) {
2205 #ifdef VERBOSE
2206             printf ("No '%s' in WxAttrib\n", data);
2207 #endif
2208 #ifdef STORE_ERRORS
2209             reallocSprintf (&(ugly->errors), "No '%s' in WxAttrib ", data);
2210 #endif
2211             return -2;
2212          } else {
2213             /* Check if it is the "OR" or "MX" case. */
2214             if (ugly->attrib[word][attNum] == HAZ_OR) {
2215                ugly->attrib[word][attNum] = 0;
2216                ugly->f_or[word] = 1;
2217             } else if (ugly->attrib[word][attNum] == HAZ_PRI2) {
2218                ugly->attrib[word][attNum] = 0;
2219                ugly->f_priority[word] = 2;
2220             } else if (ugly->attrib[word][attNum] == HAZ_PRI1) {
2221                ugly->attrib[word][attNum] = 0;
2222                ugly->f_priority[word] = 1;
2223             }
2224          }
2225          break;
2226       default:
2227          return -1;
2228    }
2229    return 0;
2230 }
2231 
2232 /*****************************************************************************
2233  * Ugly2English() --
2234  *
2235  * Arthur Taylor / MDL
2236  *
2237  * PURPOSE
2238  *   Converts an Ugly string to an English Phrase.
2239  * Example: "Iso:T:<NoInten>:<NoVis>:" -> "Isolated Thunderstorms"
2240  *   English phrase does not include visibility.
2241  *
2242  * ARGUMENTS
2243  *   ugly = The ugly string structure to modify. (Input/Output)
2244  *
2245  * FILES/DATABASES: None
2246  *
2247  * RETURNS: void
2248  *
2249  * HISTORY
2250  *   5/2003 Arthur Taylor (MDL/RSIS): Created.
2251  *
2252  * NOTES
2253  * 1) buffer size is chosen so each of the 8 parts has 50 bytes for the
2254  *    table entry and the ' ' and ', ' and ' with '.  If NUM_UGLY_ATTRIB
2255  *    increases (from 5), we may need more.
2256  * 2) Instead of static buffer, we could use myerror.c :: AllocSprintf.
2257  *****************************************************************************
2258  */
2259 
safe_strcat(char * target,size_t target_size,const char * string_to_append)2260 static void safe_strcat(char* target, size_t target_size,
2261                         const char* string_to_append)
2262 {
2263     size_t target_length = strlen(target);
2264     if( target_length + strlen(string_to_append) < target_size )
2265         strcat(target + target_length, string_to_append);
2266 }
2267 
Ugly2English(UglyStringType * ugly)2268 static void Ugly2English (UglyStringType * ugly)
2269 {
2270    int i;               /* Loop counter over number of words. */
2271    int j;               /* Loop counter over number of attributes. */
2272    char buffer[400];    /* Temporary storage as we build up the phrase. */
2273    uChar f_first;       /* Flag for first attribute. */
2274    int HazCode[NUM_UGLY_ATTRIB]; /* Sorted list of hazard numbers used to *
2275                                   * create hazard code. */
2276    int k;               /* A counter used to help sort hazard. */
2277    int temp;            /* A temp variable used to help sort hazard. */
2278 
2279    for (i = 0; i < ugly->numValid; i++) {
2280       buffer[0] = '\0';
2281       /* Handle Coverage. */
2282       if (ugly->cover[i] != 0) {
2283          safe_strcat (buffer, sizeof(buffer), WxCover[ugly->cover[i]].name);
2284          safe_strcat (buffer, sizeof(buffer), " ");
2285       }
2286       /* Handle Intensity. */
2287       if (ugly->intens[i] != 0) {
2288          safe_strcat (buffer, sizeof(buffer), WxIntens[ugly->intens[i]].name);
2289          safe_strcat (buffer, sizeof(buffer), " ");
2290       }
2291       safe_strcat (buffer, sizeof(buffer), WxCode[ugly->wx[i]].name);
2292       /* Handle Attributes. */
2293       f_first = 1;
2294       for (j = 0; j < NUM_UGLY_ATTRIB; j++) {
2295          if (ugly->attrib[i][j] != 0) {
2296             /* Fixed by GDAL */
2297             if (ugly->f_priority[i] == 0) {
2298                if (f_first) {
2299                   safe_strcat (buffer, sizeof(buffer), " with ");
2300                   f_first = 0;
2301                } else {
2302                   safe_strcat (buffer, sizeof(buffer), ", ");
2303                }
2304                safe_strcat (buffer, sizeof(buffer), WxAttrib[ugly->attrib[i][j]].name);
2305             }
2306          }
2307       }
2308       ugly->english[i] = (char *) malloc ((strlen (buffer) + 1) *
2309                                           sizeof (char));
2310       strcpy (ugly->english[i], buffer);
2311       /* Compute a code number for wx&inten, as well as attrib. */
2312       if (WxCode[ugly->wx[i]].number != 0) {
2313          ugly->wx_inten[i] = 1 + (WxCode[ugly->wx[i]].number - 1) *
2314                (sizeof (WxIntens) / sizeof (WxTable)) +
2315                WxIntens[ugly->intens[i]].number;
2316       } else {
2317          ugly->wx_inten[i] = 0;
2318       }
2319       /* Compute a code number for hazards. */
2320       for (j = 0; j < NUM_UGLY_ATTRIB; j++) {
2321          HazCode[j] = WxAttrib[ugly->attrib[i][j]].number;
2322          if (HazCode[j] > 250) {
2323             HazCode[j] = 0;
2324          }
2325       }
2326       for (j = 0; j < NUM_UGLY_ATTRIB - 1; j++) {
2327          for (k = j + 1; k < NUM_UGLY_ATTRIB; k++) {
2328             if (HazCode[j] > HazCode[k]) {
2329                temp = HazCode[j];
2330                HazCode[j] = HazCode[k];
2331                HazCode[k] = temp;
2332             }
2333          }
2334       }
2335       /* Hazard is now smallest number first... we now convert from "00 00 00
2336        * 04 05" to 405 */
2337       ugly->HazCode[i] = 0;
2338       for (j = 0; j < NUM_UGLY_ATTRIB; j++) {
2339          ugly->HazCode[i] = (ugly->HazCode[i] * 100) + HazCode[j];
2340       }
2341    }
2342 }
2343 
2344 /*****************************************************************************
2345  * ParseUglyString() --
2346  *
2347  * Arthur Taylor / MDL
2348  *
2349  * PURPOSE
2350  *   Parse an ASCII ugly string describing weather into a data structure
2351  * which is more easily manipulated.
2352  *
2353  * ARGUMENTS
2354  *      ugly = The ugly string structure to modify. (Output)
2355  *    wxData = The ugly string to parse. (Input)
2356  * simpleVer = The version of the simple Wx table to use.
2357  *             (1 is 6/2003 version), (2 is 1/2004 version). (Input)
2358  *
2359  * FILES/DATABASES: None
2360  *
2361  * RETURNS: int
2362  *  0 = No problems
2363  * -1 = Had difficulties parsing the ugly string.
2364  *
2365  * HISTORY
2366  *   5/2003 Arthur Taylor (MDL/RSIS): Created.
2367  *
2368  * NOTES
2369  * 1) Assumes it is ok to modify the wxData ascii string.  This means that
2370  *    You can NOT pass in constant strings.
2371  *****************************************************************************
2372  */
ParseUglyString(UglyStringType * ugly,char * wxData,int simpleVer)2373 int ParseUglyString (UglyStringType * ugly, char *wxData, int simpleVer)
2374 {
2375    char *cur;           /* Used to help walk though the ascii string. */
2376    char *start;         /* Where current phrase starts. */
2377    uChar attNum = 0;    /* piece of attribute phrase (# of , seen) */
2378    uChar place = 0;     /* location in a word (# of : seen) */
2379    uChar word = 0;      /* Which word in sentence (# of ^ seen) */
2380 
2381    /* Init first message */
2382    ugly->SimpleCode = 0;
2383    InitUglyString (ugly);
2384    start = wxData;
2385    for (cur = wxData; *cur != '\0'; cur++) {
2386       switch (*cur) {
2387          case '^':
2388             *cur = '\0';
2389             if (UglyLookUp (ugly, start, word, place, attNum) != 0) {
2390                *cur = '^';
2391 #ifdef VERBOSE
2392                printf ("(A) %s\n", wxData);
2393 #endif
2394 #ifdef STORE_ERRORS
2395                reallocSprintf (&(ugly->errors), "(A) '%s'\n", wxData);
2396 #endif
2397                /* Convert what we have to "English phrase" */
2398                ugly->numValid = word + 1;
2399                Ugly2English (ugly);
2400                if (simpleVer == 1) {
2401                   ugly->SimpleCode = NDFD_WxTable1 (ugly);
2402                } else if (simpleVer == 2) {
2403                   ugly->SimpleCode = NDFD_WxTable2 (ugly);
2404                } else if (simpleVer == 3) {
2405                   ugly->SimpleCode = NDFD_WxTable3 (ugly);
2406                } else {
2407                   ugly->SimpleCode = NDFD_WxTable4 (ugly);
2408                }
2409                return -1;
2410             }
2411             *cur = '^';
2412             word++;
2413             /* Make sure we don't start writing out of bounds. */
2414             if (word >= NUM_UGLY_WORD) {
2415 #ifdef VERBOSE
2416                printf ("(B) %s\n", wxData);
2417 #endif
2418 #ifdef STORE_ERRORS
2419                reallocSprintf (&(ugly->errors), "(B) '%s'\n", wxData);
2420 #endif
2421                /* Convert what we have to "English phrase" */
2422 /*
2423                ugly->numValid = word + 1;
2424 */
2425                Ugly2English (ugly);
2426                if (simpleVer == 1) {
2427                   ugly->SimpleCode = NDFD_WxTable1 (ugly);
2428                } else if (simpleVer == 2) {
2429                   ugly->SimpleCode = NDFD_WxTable2 (ugly);
2430                } else if (simpleVer == 3) {
2431                   ugly->SimpleCode = NDFD_WxTable3 (ugly);
2432                } else {
2433                   ugly->SimpleCode = NDFD_WxTable4 (ugly);
2434                }
2435                return -1;
2436             }
2437             place = 0;
2438             attNum = 0;
2439             start = cur + 1;
2440             break;
2441          case ':':
2442             *cur = '\0';
2443             if (UglyLookUp (ugly, start, word, place, attNum) != 0) {
2444                *cur = ':';
2445 #ifdef VERBOSE
2446                printf ("(C) %s\n", wxData);
2447 #endif
2448 #ifdef STORE_ERRORS
2449                reallocSprintf (&(ugly->errors), "(C) '%s'\n", wxData);
2450 #endif
2451                /* Convert what we have to "English phrase" */
2452                ugly->numValid = word + 1;
2453                Ugly2English (ugly);
2454                if (simpleVer == 1) {
2455                   ugly->SimpleCode = NDFD_WxTable1 (ugly);
2456                } else if (simpleVer == 2) {
2457                   ugly->SimpleCode = NDFD_WxTable2 (ugly);
2458                } else if (simpleVer == 3) {
2459                   ugly->SimpleCode = NDFD_WxTable3 (ugly);
2460                } else {
2461                   ugly->SimpleCode = NDFD_WxTable4 (ugly);
2462                }
2463                return -1;
2464             }
2465             *cur = ':';
2466             place++;
2467             attNum = 0;
2468             start = cur + 1;
2469             break;
2470          case ',':
2471             if (place == 4) {
2472                *cur = '\0';
2473                if (UglyLookUp (ugly, start, word, place, attNum) != 0) {
2474                   *cur = ',';
2475 #ifdef VERBOSE
2476                   printf ("(D) %s\n", wxData);
2477 #endif
2478 #ifdef STORE_ERRORS
2479                   reallocSprintf (&(ugly->errors), "(D) '%s'\n", wxData);
2480 #endif
2481                   /* Convert what we have to "English phrase" */
2482                   ugly->numValid = word + 1;
2483                   Ugly2English (ugly);
2484                   if (simpleVer == 1) {
2485                      ugly->SimpleCode = NDFD_WxTable1 (ugly);
2486                   } else if (simpleVer == 2) {
2487                      ugly->SimpleCode = NDFD_WxTable2 (ugly);
2488                   } else if (simpleVer == 3) {
2489                      ugly->SimpleCode = NDFD_WxTable3 (ugly);
2490                   } else {
2491                      ugly->SimpleCode = NDFD_WxTable4 (ugly);
2492                   }
2493                   return -1;
2494                }
2495                *cur = ',';
2496                attNum++;
2497                start = cur + 1;
2498             }
2499             break;
2500          default:
2501             break;
2502       }
2503 /*
2504       if (word == 2) {
2505          return;
2506       }
2507 */
2508    }
2509    if (start != NULL) {
2510       if (UglyLookUp (ugly, start, word, place, attNum) != 0) {
2511 #ifdef VERBOSE
2512          printf ("(E) '%s'\n", wxData);
2513 #endif
2514 #ifdef STORE_ERRORS
2515          reallocSprintf (&(ugly->errors), "(E) '%s'\n", wxData);
2516 #endif
2517          /* Convert what we have to "English phrase" */
2518          ugly->numValid = word + 1;
2519          Ugly2English (ugly);
2520          if (simpleVer == 1) {
2521             ugly->SimpleCode = NDFD_WxTable1 (ugly);
2522          } else if (simpleVer == 2) {
2523             ugly->SimpleCode = NDFD_WxTable2 (ugly);
2524          } else if (simpleVer == 3) {
2525             ugly->SimpleCode = NDFD_WxTable3 (ugly);
2526          } else {
2527             ugly->SimpleCode = NDFD_WxTable4 (ugly);
2528          }
2529          return -1;
2530       }
2531    }
2532 
2533    ugly->numValid = word + 1;
2534    /* Convert what we have to "English phrase" */
2535    Ugly2English (ugly);
2536    if (simpleVer == 1) {
2537       ugly->SimpleCode = NDFD_WxTable1 (ugly);
2538    } else if (simpleVer == 2) {
2539       ugly->SimpleCode = NDFD_WxTable2 (ugly);
2540    } else if (simpleVer == 3) {
2541       ugly->SimpleCode = NDFD_WxTable3 (ugly);
2542    } else {
2543       ugly->SimpleCode = NDFD_WxTable4 (ugly);
2544    }
2545 #ifdef VERBOSE
2546    if (place != 4) {
2547       printf ("Too few ugly words? '%s'\n", wxData);
2548    }
2549 #endif
2550 #ifdef STORE_ERRORS
2551 /*
2552    if (place != 4) {
2553       reallocSprintf (&(ugly->errors), "Too few ugly words? '%s'\n", wxData);
2554    }
2555 */
2556 #endif
2557    return 0;
2558 }
2559 
2560 /*****************************************************************************
2561  * PrintUglyString() --
2562  *
2563  * Arthur Taylor / MDL
2564  *
2565  * PURPOSE
2566  *   Prints all the relevant data in an ugly string.  Mainly for debugging
2567  * purposes.
2568  *
2569  * ARGUMENTS
2570  *   ugly = The ugly string structure to print. (Input)
2571  *
2572  * FILES/DATABASES: None
2573  *
2574  * RETURNS: void
2575  *
2576  * HISTORY
2577  *   5/2003 Arthur Taylor (MDL/RSIS): Created.
2578  *
2579  * NOTES
2580  *****************************************************************************
2581  */
PrintUglyString(UglyStringType * ugly)2582 void PrintUglyString (UglyStringType * ugly)
2583 {
2584    int i;               /* Used to traverse the ugly string structure. */
2585    double vis;          /* Used to determine if we have "missing" vis. */
2586 
2587    printf ("numValid %d\n", ugly->numValid);
2588    for (i = 0; i < ugly->numValid; i++) {
2589       if (ugly->vis[i] == VIS_UNKNOWN) {
2590          vis = 9999;
2591       } else {
2592          vis = ugly->vis[i] / 32.;
2593       }
2594       printf ("Wx=%d, Cov=%d, inten=%d, vis=%d, attrib=%d,%d,%d,%d,%d\n",
2595               ugly->wx[i], ugly->cover[i], ugly->intens[i],
2596               ugly->vis[i], ugly->attrib[i][0], ugly->attrib[i][1],
2597               ugly->attrib[i][2], ugly->attrib[i][3], ugly->attrib[i][4]);
2598       printf ("Wx=%s, Cov=%s, intens=%s, vis=%f, attrib=%s,%s,%s,%s,%s\n",
2599               WxCode[ugly->wx[i]].name, WxCover[ugly->cover[i]].name,
2600               WxIntens[ugly->intens[i]].name, vis,
2601               WxAttrib[ugly->attrib[i][0]].name,
2602               WxAttrib[ugly->attrib[i][1]].name,
2603               WxAttrib[ugly->attrib[i][2]].name,
2604               WxAttrib[ugly->attrib[i][3]].name,
2605               WxAttrib[ugly->attrib[i][4]].name);
2606    }
2607    printf ("\n");
2608 }
2609 
2610 #ifdef DEBUG_WEATHER
2611 /*****************************************************************************
2612  * main() --
2613  *
2614  * Arthur Taylor / MDL
2615  *
2616  * PURPOSE
2617  *   To test the ParseUglyString() procedure.
2618  *
2619  * ARGUMENTS
2620  * argc = The number of arguments on the command line. (Input)
2621  * argv = The arguments on the command line. (Input)
2622  *
2623  * FILES/DATABASES: None
2624  *
2625  * RETURNS: int
2626  *
2627  * HISTORY
2628  *   5/2003 Arthur Taylor (MDL/RSIS): Created.
2629  *
2630  * NOTES
2631  *****************************************************************************
2632  */
main(int argc,char ** argv)2633 int main (int argc, char **argv)
2634 {
2635    UglyStringType ugly;
2636    char buffer[100];
2637 
2638    strcpy (buffer, "Pds:R:+:<NoVis>:Mention^Ocnl:R:m:<NoVis>:^Sct:"
2639            "T:<NoInten>:<NoVis>:");
2640    ParseUglyString (&ugly, buffer, 3);
2641    PrintUglyString (&ugly);
2642    if (ugly.errors != NULL) {
2643       printf ("Errors: %s\n", ugly.errors);
2644    }
2645    FreeUglyString (&ugly);
2646    return 0;
2647 
2648    strcpy (buffer, "Sct:SW:-:<NoVis>:");
2649    ParseUglyString (&ugly, buffer, 3);
2650    PrintUglyString (&ugly);
2651    strcpy (buffer, "Ocnl:R:-:<NoVis>:^Ocnl:S:-:<NoVis>:^SChc:ZR:-:<NoVis>:");
2652    ParseUglyString (&ugly, buffer, 3);
2653    PrintUglyString (&ugly);
2654    strcpy (buffer, "Wide:FR:-:<NoVis>:OLA");
2655    ParseUglyString (&ugly, buffer, 3);
2656    PrintUglyString (&ugly);
2657    strcpy (buffer, "<NoCov>:<NoWx>:<NoInten>:<NoVis>:");
2658    ParseUglyString (&ugly, buffer, 3);
2659    PrintUglyString (&ugly);
2660    strcpy (buffer, "Sct:RW:-:<NoVis>:^Iso:T:m:<NoVis>:");
2661    ParseUglyString (&ugly, buffer, 3);
2662    PrintUglyString (&ugly);
2663    strcpy (buffer, "Sct:T:+:<NoVis>:DmgW,LgA");
2664    ParseUglyString (&ugly, buffer, 3);
2665    PrintUglyString (&ugly);
2666    return 0;
2667 }
2668 #endif
2669