Projekt

Obecné

Profil

Stáhnout (14.8 KB) Statistiky
| Větev: | Tag: | Revize:
1
//
2
// Author: A. Konig
3
//
4

    
5
using ServerApp.DataDownload;
6
using ServerApp.Parser.OutputInfo;
7
using System;
8
using System.Collections.Generic;
9
using System.Globalization;
10
using System.IO;
11
using System.Net;
12
using System.Text.Json;
13
using static System.Text.Json.JsonElement;
14

    
15
namespace ServerApp.WeatherPredictionParser
16
{
17
    /// <summary>
18
    /// Class representing a parser for json prediction data
19
    /// </summary>
20
    /// <author>A. Konig</author>
21
    public class JsonParser : IJsonParser
22
    {
23
        /// <summary> Data loader </summary>
24
        DataDownloader loader;
25
        /// <summary> Currently parsed day </summary>
26
        DateTime currParsedDay;
27
        /// <summary> Sunrise time of currently parsed day </summary>
28
        DateTime sunriseTime;
29
        /// <summary> Sunset time of currently parsed day </summary>
30
        DateTime sunsetTime;
31

    
32

    
33
        /// <summary>
34
        /// Constructor
35
        /// </summary>
36
        /// <param name="loader"></param>
37
        public JsonParser(DataDownloader loader)
38
        {
39
            this.loader = loader;
40
        }
41

    
42
        /// <summary>
43
        /// Parse weather prediction
44
        /// Results is in attributes current for current weather and pred for weather prediction for today, tommorrow and day after tommorrow
45
        /// </summary>
46
        override public void ParsePrediction()
47
        {
48
            // TODO ask DataDownloader for download said file and return path to it
49
            
50
            // get file
51
            string file = loader.DownloadWeatherPrediction();
52
            DateTime now = DateTime.Now;
53
            Console.WriteLine(File.Exists(file));
54

    
55
            Current = new WeatherInfo();
56
            Predictions = new List<WeatherInfo>();
57

    
58
            if (!File.Exists(file))
59
                return;
60

    
61
            // read file
62
            string data = File.ReadAllText(file);
63

    
64
            // parse
65
            JsonDocument doc = JsonDocument.Parse(data);
66
            JsonElement root = doc.RootElement;
67
            var weatherP = root.EnumerateObject();
68

    
69
            while (weatherP.MoveNext())
70
            {
71
                string name = weatherP.Current.Name;
72
                Console.WriteLine(name);
73

    
74
                switch (name)
75
                {
76
                    // current weather
77
                    case "current_condition":
78
                        {
79
                            ArrayEnumerator currentWeather = weatherP.Current.Value.EnumerateArray();
80
                            Current = ParseCurrentWeather(currentWeather);
81

    
82
                            break;
83
                        }
84
                    // weather prediction
85
                    case "weather":
86
                        {
87
                            ArrayEnumerator weather = weatherP.Current.Value.EnumerateArray();
88
                            ParseWeatherPredict(weather);
89

    
90
                            break;
91
                        }
92
                }
93
            }
94

    
95
            // sunrise + sunset into data
96
            EncompassSunRiseSetTimes();
97

    
98
            //TestConsoleOutput();
99
        }
100

    
101
        /// <summary>
102
        /// Test console output
103
        /// </summary>
104
        private void TestConsoleOutput()
105
        {
106
            Console.WriteLine(Current);
107
            foreach (WeatherInfo w in Predictions)
108
                Console.WriteLine(w);
109
        }
110

    
111
        /// <summary>
112
        /// Change data in a way that they now reflect sunrise and sunset times
113
        /// If current time under sunrise or over sunset -> WeatherConditions is Dark
114
        /// If prediction time is under sunrise or over sunset and more than half of the interval is under/over said time -> WeatherCondition is Dark
115
        /// </summary>
116
        private void EncompassSunRiseSetTimes()
117
        {
118
            // change current weather
119
            if ((Current.startTime.TimeOfDay > sunsetTime.TimeOfDay) || (Current.startTime.TimeOfDay < sunriseTime.TimeOfDay))
120
                Current.condition = WeatherConditions.Dark;
121

    
122
            // change prediction
123
            for (int i = 0; i < Predictions.Count - 1; i++)
124
            {
125
                WeatherInfo w = Predictions[i];
126
                WeatherInfo wNext = Predictions[i + 1];
127

    
128
                // if wNext time < than w time then it is prediction from the next day -> add 24 to correctly calculate timespan
129
                int timespan = wNext.startTime.Hour - w.startTime.Hour;
130
                if (wNext.startTime.Hour < w.startTime.Hour)
131
                    timespan = (wNext.startTime.Hour+24) - w.startTime.Hour;
132
                
133
                w.intervalLength = timespan;
134

    
135
                // if start under sunset
136
                if (w.startTime.TimeOfDay > sunsetTime.TimeOfDay)
137
                    w.condition = WeatherConditions.Dark;
138

    
139
                // if start under sunrise
140
                if (w.startTime.TimeOfDay < sunriseTime.TimeOfDay)
141
                {
142
                    double howMuch = ((sunriseTime.Hour * 60 + sunriseTime.Minute) - (w.startTime.Hour * 60 + w.startTime.Minute)) / 60.0;
143

    
144
                    if (howMuch >= timespan / 2.0)
145
                        w.condition = WeatherConditions.Dark;
146
                }
147

    
148
                // if start under sunrise
149
                TimeSpan endTime = new TimeSpan(w.startTime.TimeOfDay.Hours + timespan, w.startTime.TimeOfDay.Minutes, 0);
150
                if (endTime > sunsetTime.TimeOfDay)
151
                {
152
                    double howMuch = ((endTime.Hours * 60 + endTime.Minutes) - (sunsetTime.Hour * 60 + sunsetTime.Minute)) / 60.0;
153

    
154
                    if (howMuch >= timespan / 2.0)
155
                        w.condition = WeatherConditions.Dark;
156
                }
157
            }
158

    
159
            // last prediction
160
            WeatherInfo wLast = Predictions[Predictions.Count - 1];
161
            TimeSpan endTimeW = new TimeSpan(24, 0, 0);
162
            int timespanLast = endTimeW.Hours - wLast.startTime.Hour;
163
            wLast.intervalLength = timespanLast;
164

    
165
            // if start under sunset
166
            if (wLast.startTime.TimeOfDay > sunsetTime.TimeOfDay)
167
                wLast.condition = WeatherConditions.Dark;
168

    
169
            // if start under sunrise
170
            if (wLast.startTime.TimeOfDay < sunriseTime.TimeOfDay)
171
            {
172
                double howMuch = ((sunriseTime.Hour * 60 + sunriseTime.Minute) - (wLast.startTime.Hour * 60 + wLast.startTime.Minute)) / 60.0;
173

    
174
                if (howMuch >= timespanLast / 2.0)
175
                    wLast.condition = WeatherConditions.Dark;
176
            }
177

    
178
            // if start under sunrise
179
            if (endTimeW > sunsetTime.TimeOfDay)
180
            {
181
                double howMuch = ((endTimeW.Hours * 60 + endTimeW.Minutes) - (sunsetTime.Hour * 60 + sunsetTime.Minute)) / 60.0;
182

    
183
                if (howMuch >= timespanLast / 2.0)
184
                    wLast.condition = WeatherConditions.Dark;
185
            }
186
        }
187

    
188
        /// <summary>
189
        /// Parse weather prediction
190
        /// </summary>
191
        /// <param name="weather"> ArrayEnumerator of weather predictions </param>
192
        private void ParseWeatherPredict(ArrayEnumerator weather)
193
        {
194
            while (weather.MoveNext())
195
            {
196
                // prediction for one day
197
                var obj = weather.Current.EnumerateObject();
198

    
199
                while (obj.MoveNext())
200
                {
201
                    switch (obj.Current.Name)
202
                    {
203
                        case "date":
204
                            {
205
                                DateTime.TryParseExact(obj.Current.Value.GetString(), "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out currParsedDay);
206
                                break;
207
                            }
208
                        // hourly predictions
209
                        case "hourly":
210
                            {
211
                                ParseHourly(obj.Current.Value.EnumerateArray());
212
                                break;
213
                            }
214
                        // sunset / sunrise hours
215
                        case "astronomy":
216
                            {
217
                                ParseAstronomy(obj.Current.Value.EnumerateArray());
218
                                break;
219
                            }
220
                    }
221
                }
222
            }
223
        }
224

    
225
        /// <summary>
226
        /// Parse sunrise and sunset times
227
        /// </summary>
228
        /// <param name="astronomy"> Astronomy array enumerator </param>
229
        private void ParseAstronomy(ArrayEnumerator astronomy)
230
        {
231
            while (astronomy.MoveNext())
232
            {
233
                var astrInfo = astronomy.Current.EnumerateObject();
234
                
235
                while (astrInfo.MoveNext())
236
                {
237
                    switch (astrInfo.Current.Name)
238
                    {
239
                        case "sunrise":
240
                            {
241
                                DateTime.TryParseExact(astrInfo.Current.Value.GetString(), "hh:mm tt", CultureInfo.InvariantCulture, DateTimeStyles.None, out sunriseTime);
242
                                Console.WriteLine("\t sunrise time : " + sunriseTime + " " + astrInfo.Current.Value.GetString());
243
                                break;
244
                            }
245
                        case "sunset":
246
                            {
247
                                DateTime.TryParseExact(astrInfo.Current.Value.GetString(), "hh:mm tt", CultureInfo.InvariantCulture, DateTimeStyles.None, out sunsetTime);
248
                                Console.WriteLine("\t sunset time : " + sunsetTime + " " + astrInfo.Current.Value.GetString());
249
                                break;
250
                            }
251
                    }
252
                }
253
            }
254
        }
255

    
256
        /// <summary>
257
        /// Parse hourly predictions
258
        /// </summary>
259
        /// <param name="hourly">Enumerated array of hourly predictions</param>
260
        private void ParseHourly(ArrayEnumerator hourly)
261
        {
262
            while (hourly.MoveNext())
263
            {
264
                // one hourly prediction
265
                var oneH = hourly.Current.EnumerateObject();
266
                WeatherInfo weather = new WeatherInfo();
267

    
268
                while (oneH.MoveNext())
269
                {
270
                    switch (oneH.Current.Name)
271
                    {
272
                        case "FeelsLikeC":
273
                            {
274
                                Double.TryParse(oneH.Current.Value.GetString(), out weather.temp);
275
                                break;
276
                            }
277
                        case "cloudcover":
278
                            {
279
                                int cloudCover;
280
                                Int32.TryParse(oneH.Current.Value.GetString(), out cloudCover);
281
                                weather.condition = ValueToConditions.CloudCoverToConditions(cloudCover);
282
                                break;
283
                            }
284
                        // take into account highest value from "chanceofrain" and "chaceofsnow"
285
                        case "chanceofrain":
286
                            {
287
                                int rain;
288
                                Int32.TryParse(oneH.Current.Value.GetString(), out rain);
289
                                weather.rain = rain > weather.rain ? rain : weather.rain;
290
                                break;
291
                            }
292
                        case "chanceofsnow":
293
                            {
294
                                int snow;
295
                                Int32.TryParse(oneH.Current.Value.GetString(), out snow);
296
                                weather.rain = snow > weather.rain ? snow : weather.rain;
297
                                break;
298
                            }
299
                        // wind kmph has to be translated to mps
300
                        case "WindGustKmph":
301
                            {
302
                                double windkmh;
303
                                Double.TryParse(oneH.Current.Value.GetString(), out windkmh);
304
                                weather.wind= windkmh * 1000 / (60.0*60.0);
305
                                break;
306
                            }
307
                        case "time":
308
                            {
309
                                int h;
310
                                Int32.TryParse(oneH.Current.Value.GetString(), out h);
311
                                h /= 100;
312
                                DateTime time = new DateTime(currParsedDay.Year, currParsedDay.Month, currParsedDay.Day, h, 0, 0);
313
                                weather.startTime = time;
314
                                break;
315
                            }
316
                    }
317
                }
318

    
319
                // Console.WriteLine(weather.ToString());
320
                Predictions.Add(weather);
321
            }
322

    
323
        }
324

    
325
        /// <summary>
326
        /// Parse current weather
327
        /// </summary>
328
        /// <param name="currentWeather">Enumerated hour of weather data</param>
329
        /// <returns>WeatherInfo with current weather</returns>
330
        private WeatherInfo ParseCurrentWeather(ArrayEnumerator currentWeather)
331
        {
332
            WeatherInfo res = new WeatherInfo();
333
            //res.current = true;
334

    
335
            while (currentWeather.MoveNext())
336
            {
337
                var obj = currentWeather.Current.EnumerateObject();
338

    
339
                while (obj.MoveNext())
340
                {
341
                    switch (obj.Current.Name)
342
                    {
343
                        case "localObsDateTime":
344
                            {
345
                                DateTime.TryParse(obj.Current.Value.GetString(), out res.startTime);
346
                                break;
347
                            }
348
                        case "FeelsLikeC":
349
                            {
350
                                Double.TryParse(obj.Current.Value.GetString(), out res.temp);
351
                                break;
352
                            }
353
                        case "cloudcover":
354
                            {
355
                                int cloudCover;
356
                                Int32.TryParse(obj.Current.Value.GetString(), out cloudCover);
357
                                res.condition = ValueToConditions.CloudCoverToConditions(cloudCover);
358
                                break;
359
                            }
360
                        case "precipMM":
361
                            {
362
                                double rainMM;
363
                                Double.TryParse(obj.Current.Value.GetString(), out rainMM);
364
                                res.rain = rainMM > 0 ? 100 : 0;
365
                                break;
366
                            }
367
                        case "windspeedKmph":
368
                            {
369
                                double wind;
370
                                Double.TryParse(obj.Current.Value.GetString(), out wind);
371
                                res.wind = wind * 1000 / (60.0 * 60.0);
372
                                break;
373
                            }
374
                    }
375
                }
376

    
377
            }
378

    
379
            return res;
380
        }
381

    
382
    }
383
}
(2-2/2)