Projekt

Obecné

Profil

Stáhnout (10.9 KB) Statistiky
| Větev: | Tag: | Revize:
1 cdf3c217 A-Konig
//
2
// Author: A. Konig
3
//
4
5 f9dd116f A-Konig
using log4net;
6 cdf3c217 A-Konig
using ServerApp.Parser.InputData;
7 734533a8 A-Konig
using ServerApp.Parser.OutputInfo;
8 0da0ac88 A-Konig
using System;
9 5d9a5bd9 A-Konig
using System.Collections.Generic;
10 0da0ac88 A-Konig
using System.IO;
11 5d9a5bd9 A-Konig
12 734533a8 A-Konig
namespace ServerApp.Parser.Parsers
13 5d9a5bd9 A-Konig
{
14 734533a8 A-Konig
    /// <summary>
15
    /// Class parsing weather files into instances of WeatherInfo divided by given time interval
16
    /// Data parsed from 7am (included) to 18pm (included)
17
    /// </summary>
18 cdf3c217 A-Konig
    /// <author>A. Konig</author>
19 a53b1de8 A-Konig
    public class WeatherParser
20 5d9a5bd9 A-Konig
    {
21 f9dd116f A-Konig
        /// <summary> Logger </summary>
22
        private static readonly ILog _log = LogManager.GetLogger(typeof(WeatherParser));
23 98b568bc A-Konig
24
        /// <summary> Datafile loader  </summary>
25 cdf3c217 A-Konig
        IDataLoader loader;
26 98b568bc A-Konig
27
        /// <summary>
28
        /// Constructor
29
        /// </summary>
30
        /// <param name="loader">Datafile loader</param>
31 cdf3c217 A-Konig
        public WeatherParser(IDataLoader loader)
32 98b568bc A-Konig
        {
33
            this.loader = loader;
34
        }
35
36 734533a8 A-Konig
        /// <summary>
37
        /// Parses weather data to WeatherInfo instances
38
        /// Data parsed from 7am (included) to 18pm (included)
39
        /// </summary>
40 cdf3c217 A-Konig
        /// <param name="weatherFiles">Paths to files with weather data files</param>
41
        /// <param name="endTime">End time of related data</param>
42
        /// <param name="startTime">Start time of related data</param>
43 734533a8 A-Konig
        /// <param name="wholeDay">Should data be parsed as one instance per day (if true parameter interval will be ignored)</param>
44
        /// <param name="interval">Time interval to divide days by, minimum is 1h</param>
45
        /// <returns></returns>
46 cdf3c217 A-Konig
        public List<WeatherInfo> ParseWeatherData(List<string> weatherFiles, DateTime startTime, DateTime endTime, bool wholeDay = true, int interval = 1)
47 0da0ac88 A-Konig
        {
48 734533a8 A-Konig
            List<WeatherInfo> list = new List<WeatherInfo>();
49
50 a53b1de8 A-Konig
            if (weatherFiles == null || interval <= 0)
51 cdf3c217 A-Konig
                return list;
52
53 23e8ae04 A-Konig
            string current = "";
54
            try
55 0da0ac88 A-Konig
            {
56 23e8ae04 A-Konig
                // get all files in folder
57
                foreach (string fileName in weatherFiles)
58 0da0ac88 A-Konig
                {
59 23e8ae04 A-Konig
                    current = fileName;
60
61
                    if (!File.Exists(fileName))
62
                        continue;
63 0da0ac88 A-Konig
64 23e8ae04 A-Konig
                    // parse as one instance per day
65
                    List<WeatherInfo> loadedData = null;
66
                    if (wholeDay)
67
                        loadedData = ProcessOneWeatherFileAsDays(fileName, startTime, endTime);
68
                    // parse according to interval
69
                    else
70
                    {
71
                        loadedData = ProcessOneWeatherFileAsIntervals(fileName, interval, startTime, endTime);
72
                    }
73
74
                    list.AddRange(loadedData);
75
                }
76
            } catch
77
            {
78 f9dd116f A-Konig
                _log.Error("Incorrect Weather input file " + current);
79 0da0ac88 A-Konig
            }
80
81
            return list;
82
        }
83
84 734533a8 A-Konig
        /// <summary>
85
        /// Parses data from one data file as one instance per day
86
        /// </summary>
87
        /// <param name="path">Path ti file</param>
88 cdf3c217 A-Konig
        /// <param name="endTime">End time of related data</param>
89
        /// <param name="startTime">Start time of related data</param>
90 734533a8 A-Konig
        /// <returns>List with WeatherInfo instances</returns>
91 cdf3c217 A-Konig
        private List<WeatherInfo> ProcessOneWeatherFileAsDays(string path, DateTime startTime, DateTime endTime)
92 0da0ac88 A-Konig
        {
93 cdf3c217 A-Konig
            List<WeatherInfo> weatherInfo = new List<WeatherInfo>();
94
95 98b568bc A-Konig
            List<WeatherInstance> list = loader.LoadWeatherFile(path);
96 3729dcae A-Konig
            if (list == null || list.Count == 0)
97 a53b1de8 A-Konig
                return weatherInfo;
98 0da0ac88 A-Konig
99 734533a8 A-Konig
            // array with data [temp, rain, wind, lum]
100 0da0ac88 A-Konig
            double[] recordedAmount = new double[4];
101 734533a8 A-Konig
            // min/max hour taken into account
102 0da0ac88 A-Konig
            int[] minmaxHour = new int[] { 7, 18 };
103 734533a8 A-Konig
            // interval length
104 0da0ac88 A-Konig
            int range = minmaxHour[1] - minmaxHour[0];
105
106 734533a8 A-Konig
            // first day
107
            DateTime lastStartDay = new DateTime(list[0].dateTime.Year, list[0].dateTime.Month, list[0].dateTime.Day, minmaxHour[0], 0, 0);
108
            // number of values in day
109 98b568bc A-Konig
            int values = 0, weatherValues = 0;
110 0da0ac88 A-Konig
            for (int i = 0; i < list.Count; i++)
111
            {
112
                int currHour = list[i].dateTime.Hour;
113
                if (currHour < minmaxHour[0] || currHour > minmaxHour[1])
114
                    continue;
115
116 734533a8 A-Konig
                // start of new day -> make a new instance
117
                DateTime date = new DateTime(list[i].dateTime.Year, list[i].dateTime.Month, list[i].dateTime.Day, minmaxHour[0], 0, 0);
118 0da0ac88 A-Konig
                if (!date.Equals(lastStartDay))
119
                {
120 98b568bc A-Konig
                    WeatherInfo dayInfo = new WeatherInfo(lastStartDay, recordedAmount[0] / values, (int)(recordedAmount[1] / values * 100), recordedAmount[2] / values, recordedAmount[3] / weatherValues, range); 
121 0da0ac88 A-Konig
                    weatherInfo.Add(dayInfo);
122
123
                    recordedAmount = new double[4];
124
                    lastStartDay = date;
125
                    values = 0;
126 98b568bc A-Konig
                    weatherValues = 0;
127 0da0ac88 A-Konig
                }
128
129 cdf3c217 A-Konig
                // if not in allowed time window -> discard
130 a53b1de8 A-Konig
                if (list[i].dateTime < startTime || list[i].dateTime > endTime)
131
                {
132 cdf3c217 A-Konig
                    continue;
133 a53b1de8 A-Konig
                }
134 cdf3c217 A-Konig
135 734533a8 A-Konig
                // aggregate data
136 0da0ac88 A-Konig
                recordedAmount[0] += list[i].temp;
137
                recordedAmount[1] += list[i].rain;
138
                recordedAmount[2] += list[i].wind;
139 98b568bc A-Konig
140 1407c8ba A-Konig
                if (ValueToConditions.TransferLuxToConditions(list[i].lum * 1000) != WeatherConditions.Dark)
141 a53b1de8 A-Konig
                {
142 98b568bc A-Konig
                    recordedAmount[3] += list[i].lum * 1000; weatherValues++;
143 a53b1de8 A-Konig
                }
144 734533a8 A-Konig
145 0da0ac88 A-Konig
                values++;
146
            }
147
148 734533a8 A-Konig
            // data from last day
149 a53b1de8 A-Konig
            if (values != 0)
150
            {
151
                WeatherInfo dayInfo2 = new WeatherInfo(lastStartDay, recordedAmount[0] / values, (int)(recordedAmount[1] / values * 100), recordedAmount[2] / values, recordedAmount[3] / weatherValues, range);
152
                weatherInfo.Add(dayInfo2);
153
            }
154 0da0ac88 A-Konig
155
            return weatherInfo;
156
        }
157
158 98b568bc A-Konig
        /// <summary>
159
        /// Parses data from one data file as one instance per interval length
160
        /// </summary>
161
        /// <param name="path">Path to file</param>
162
        /// <param name="interval">Interval length</param>
163 cdf3c217 A-Konig
        /// <param name="endTime">End time of related data</param>
164
        /// <param name="startTime">Start time of related data</param>
165 98b568bc A-Konig
        /// <returns>List with ActivityInfo instances</returns>
166 cdf3c217 A-Konig
        private List<WeatherInfo> ProcessOneWeatherFileAsIntervals(string path, int interval, DateTime startTime, DateTime endTime)
167 0da0ac88 A-Konig
        {
168 cdf3c217 A-Konig
            List<WeatherInfo> weatherInfo = new List<WeatherInfo>();
169
170 98b568bc A-Konig
            List<WeatherInstance> list = loader.LoadWeatherFile(path);
171 3729dcae A-Konig
            if (list == null || list.Count == 0)
172
                    return weatherInfo;
173 98b568bc A-Konig
174
            // min/max hour taken into account
175
            int[] minmaxHour = new int[] { 7, 18 };
176
            int range = minmaxHour[1] - minmaxHour[0];
177
178
            if (interval > range)
179
                return null;
180
181
            int indices = (int)Math.Ceiling(range / (double)interval);
182
            int[] to = new int[indices];
183
            double[][] data = new double[indices][];
184
            int[] count = new int[indices];
185
            for (int i = 0; i < to.Length; i++)
186
            {
187
                to[i] = minmaxHour[0] + interval * (i + 1);
188
                data[i] = new double[4];
189 a53b1de8 A-Konig
                count[i] = 0;
190 98b568bc A-Konig
            }
191
192
            // first day
193
            DateTime lastStartTime = new DateTime(list[0].dateTime.Year, list[0].dateTime.Month, list[0].dateTime.Day, minmaxHour[0], 0, 0);
194
            int index;
195
            for (int i = 0; i < list.Count; i++)
196
            {
197
                int currHour = list[i].dateTime.Hour;
198
                if (currHour < minmaxHour[0] || currHour > minmaxHour[1])
199
                    continue;
200
201
                // start of the day -> make an instance
202
                DateTime date = new DateTime(list[i].dateTime.Year, list[i].dateTime.Month, list[i].dateTime.Day, list[i].dateTime.Hour, 0, 0);
203
204
                // end of the day
205
                if (!(date.Year == lastStartTime.Year && date.Month == lastStartTime.Month && date.Day == lastStartTime.Day))
206
                {
207
                    // note down all aggregated data
208
                    for (int k = 0; k < to.Length; k++)
209
                    {
210
                        int raincount = 0;
211
                        double rainval = 0;;
212
                        for (int l = 0; l <= k; l++)
213
                        {
214
                            raincount += count[l];
215
                            rainval += data[l][1];
216
                        }
217
218
                        DateTime stTime = new DateTime(lastStartTime.Year, lastStartTime.Month, lastStartTime.Day, to[k] - interval, 0, 0);
219
220
                        WeatherInfo intervalInfo = new WeatherInfo(stTime, data[k][0] / count[k], (int)((rainval / raincount) * 100), data[k][2] / count[k], data[k][3] / count[k], interval);
221
                        if (count[k] != 0)
222 cdf3c217 A-Konig
                            weatherInfo.Add(intervalInfo);
223 98b568bc A-Konig
224
                    }
225
226
                    lastStartTime = date;
227
                    count = new int[indices];
228
                    for (int l = 0; l < data.Length; l++)
229 a53b1de8 A-Konig
                    {
230 98b568bc A-Konig
                        data[l] = new double[4];
231 a53b1de8 A-Konig
                        count[l] = 0;
232
                    }
233 98b568bc A-Konig
                }
234
235 cdf3c217 A-Konig
                // if not in allowed time window -> discard
236
                if (list[i].dateTime < startTime || list[i].dateTime > endTime)
237
                    continue;
238
239 98b568bc A-Konig
                // find index for current instance
240
                index = 0;
241
                for (int k = 1; k < to.Length; k++)
242
                {
243
                    if (to[k] > list[i].dateTime.Hour && to[k - 1] <= list[i].dateTime.Hour)
244
                    {
245
                        index = k;
246
                        break;
247
                    }
248
                }
249
250
                // aggregate data
251
                data[index][0] += list[i].temp;
252
                data[index][1] += list[i].rain;
253
                data[index][2] += list[i].wind;
254
                data[index][3] += list[i].lum * 1000;
255
                count[index]++;
256
257
            }
258
259
            for (int k = 0; k < to.Length; k++)
260
            {
261
                int raincount = 0;
262
                double rainval = 0; ;
263
                for (int l = 0; l <= k; l++)
264
                {
265
                    raincount += count[l];
266
                    rainval += data[l][1];
267
                }
268
269
                DateTime stTime = new DateTime(lastStartTime.Year, lastStartTime.Month, lastStartTime.Day, to[k] - interval, 0, 0);
270
271
                WeatherInfo intervalInfo = new WeatherInfo(stTime, data[k][0] / count[k], (int)((rainval / raincount) * 100), data[k][2] / count[k], data[k][3] / count[k], interval);
272
                if (count[k] != 0)
273 cdf3c217 A-Konig
                    weatherInfo.Add(intervalInfo);
274 98b568bc A-Konig
            }
275
276 cdf3c217 A-Konig
            return weatherInfo;
277 0da0ac88 A-Konig
        }
278 5d9a5bd9 A-Konig
    }
279 98b568bc A-Konig
280 5d9a5bd9 A-Konig
}