Revize cdf3c217
Přidáno uživatelem Alex Konig před více než 3 roky(ů)
Server/ServerApp/Parser/InputData/CsvDataLoader.cs | ||
---|---|---|
1 |
using System; |
|
1 |
// |
|
2 |
// Author: A. Konig |
|
3 |
// |
|
4 |
|
|
5 |
using System; |
|
2 | 6 |
using System.Collections.Generic; |
3 | 7 |
using System.Globalization; |
4 | 8 |
using System.IO; |
... | ... | |
8 | 12 |
/// <summary> |
9 | 13 |
/// Class responsible for loading data from file |
10 | 14 |
/// </summary> |
11 |
/// <author>Alex Konig</author>
|
|
12 |
class CsvDataLoader : DataLoader |
|
15 |
/// <author>A. Konig</author>
|
|
16 |
class CsvDataLoader : IDataLoader
|
|
13 | 17 |
{ |
14 | 18 |
/// <summary> Culture info for parsing numbers </summary> |
15 | 19 |
static CultureInfo cultureInfo = new CultureInfo("de-DE"); |
Server/ServerApp/Parser/InputData/DataLoader.cs | ||
---|---|---|
1 |
using System; |
|
2 |
using System.Collections.Generic; |
|
3 |
using System.Linq; |
|
4 |
using System.Text; |
|
5 |
using System.Threading.Tasks; |
|
6 |
|
|
7 |
namespace ServerApp.Parser.InputData |
|
8 |
{ |
|
9 |
/// <author>Alex Konig</author> |
|
10 |
interface DataLoader |
|
11 |
{ |
|
12 |
/// <summary> |
|
13 |
/// Load jis data from file |
|
14 |
/// </summary> |
|
15 |
/// <param name="pathToFile">Path to file</param> |
|
16 |
/// <returns></returns> |
|
17 |
List<JisInstance> LoadJisFile(string pathToFile); |
|
18 |
|
|
19 |
/// <summary> |
|
20 |
/// Load login data from file |
|
21 |
/// </summary> |
|
22 |
/// <param name="pathToFile">Path to file</param> |
|
23 |
/// <returns></returns> |
|
24 |
List<LogInInstance> LoadLoginFile(string pathToFile); |
|
25 |
/// <summary> |
|
26 |
/// Load weather data from file |
|
27 |
/// </summary> |
|
28 |
/// <param name="pathToFile">Path to file</param> |
|
29 |
/// <returns></returns> |
|
30 |
List<WeatherInstance> LoadWeatherFile(string pathToFile); |
|
31 |
|
|
32 |
} |
|
33 |
} |
Server/ServerApp/Parser/InputData/IDataLoader.cs | ||
---|---|---|
1 |
// |
|
2 |
// Author: A. Konig |
|
3 |
// |
|
4 |
|
|
5 |
using System.Collections.Generic; |
|
6 |
|
|
7 |
namespace ServerApp.Parser.InputData |
|
8 |
{ |
|
9 |
/// <summary> |
|
10 |
/// Interface that every DataLoader should implement |
|
11 |
/// </summary> |
|
12 |
/// <author>A. Konig</author> |
|
13 |
interface IDataLoader |
|
14 |
{ |
|
15 |
/// <summary> |
|
16 |
/// Load jis data from file |
|
17 |
/// </summary> |
|
18 |
/// <param name="pathToFile">Path to file</param> |
|
19 |
/// <returns></returns> |
|
20 |
List<JisInstance> LoadJisFile(string pathToFile); |
|
21 |
|
|
22 |
/// <summary> |
|
23 |
/// Load login data from file |
|
24 |
/// </summary> |
|
25 |
/// <param name="pathToFile">Path to file</param> |
|
26 |
/// <returns></returns> |
|
27 |
List<LogInInstance> LoadLoginFile(string pathToFile); |
|
28 |
/// <summary> |
|
29 |
/// Load weather data from file |
|
30 |
/// </summary> |
|
31 |
/// <param name="pathToFile">Path to file</param> |
|
32 |
/// <returns></returns> |
|
33 |
List<WeatherInstance> LoadWeatherFile(string pathToFile); |
|
34 |
|
|
35 |
} |
|
36 |
} |
Server/ServerApp/Parser/InputData/JisInstance.cs | ||
---|---|---|
1 |
using System; |
|
1 |
// |
|
2 |
// Author: A. Konig |
|
3 |
// |
|
4 |
|
|
5 |
using System; |
|
2 | 6 |
|
3 | 7 |
namespace ServerApp.Parser.InputData |
4 | 8 |
{ |
... | ... | |
13 | 17 |
/// "A1";"08.04.2018 14:23:15";1 |
14 | 18 |
/// [place tag];[date time];[amount] |
15 | 19 |
/// </summary> |
16 |
/// <author>Alex Konig</author>
|
|
20 |
/// <author>A. Konig</author>
|
|
17 | 21 |
class JisInstance |
18 | 22 |
{ |
19 | 23 |
/// <summary> Place tag </summary> |
Server/ServerApp/Parser/InputData/LogInInstance.cs | ||
---|---|---|
1 |
using System; |
|
1 |
// |
|
2 |
// Author: A. Konig |
|
3 |
// |
|
4 |
|
|
5 |
using System; |
|
2 | 6 |
|
3 | 7 |
namespace ServerApp.Parser.InputData |
4 | 8 |
{ |
... | ... | |
20 | 24 |
/// "27.10.2011 00:00:00";1;7;"13:00";"13:45";"UI";"Laboratoř";"UI-505";"ui505av07-lps" |
21 | 25 |
/// [datum];[amount];[lesson];[lesson start];[lesson end];[building];[room type];[room];[hostname] |
22 | 26 |
/// </summary> |
23 |
/// <author>Alex Konig</author>
|
|
27 |
/// <author>A. Konig</author>
|
|
24 | 28 |
class LogInInstance |
25 | 29 |
{ |
26 | 30 |
/// <summary> Date time </summary> |
Server/ServerApp/Parser/InputData/WeatherInstance.cs | ||
---|---|---|
1 |
using System; |
|
1 |
// |
|
2 |
// Author: A. Konig |
|
3 |
// |
|
4 |
|
|
5 |
using System; |
|
2 | 6 |
|
3 | 7 |
namespace ServerApp.Parser.InputData |
4 | 8 |
{ |
... | ... | |
9 | 13 |
/// "30.04.2019 16:19:01";20.3;5.3;0;19 |
10 | 14 |
/// [date time];[temperature];[wind];[rain];[luminance] |
11 | 15 |
/// </summary> |
12 |
/// <author>Alex Konig</author>
|
|
16 |
/// <author>A. Konig</author>
|
|
13 | 17 |
class WeatherInstance |
14 | 18 |
{ |
15 | 19 |
/// <summary> Date and time </summary> |
Server/ServerApp/Parser/OutputInfo/ActivityInfo.cs | ||
---|---|---|
1 |
using System; |
|
1 |
// |
|
2 |
// Author: A. Konig |
|
3 |
// |
|
4 |
|
|
5 |
using System; |
|
2 | 6 |
|
3 | 7 |
namespace ServerApp.Parser.OutputInfo |
4 | 8 |
{ |
... | ... | |
6 | 10 |
/// Class representing the number of events in a given time interval a given faculty |
7 | 11 |
/// - shortest possible interval is 1h |
8 | 12 |
/// </summary> |
9 |
/// <author>Alex Konig</author>
|
|
13 |
/// <author>A. Konig</author>
|
|
10 | 14 |
class ActivityInfo |
11 | 15 |
{ |
12 | 16 |
/// <summary> Building </summary> |
Server/ServerApp/Parser/OutputInfo/ValueToConditions.cs | ||
---|---|---|
1 |
// |
|
2 |
// Author: A. Konig |
|
3 |
// |
|
4 |
|
|
5 |
namespace ServerApp.Parser.OutputInfo |
|
6 |
{ |
|
7 |
/// <summary> |
|
8 |
/// Transfers various values to weather conditions and vice versa |
|
9 |
/// </summary> |
|
10 |
/// <author>A. Konig</author> |
|
11 |
public static class ValueToConditions |
|
12 |
{ |
|
13 |
/// <summary> |
|
14 |
/// Lux to weather conditions |
|
15 |
/// </summary> |
|
16 |
/// <param name="lux">Lux value</param> |
|
17 |
/// <returns>Weather conditions</returns> |
|
18 |
public static WeatherConditions TransferLuxToConditions(double lux) |
|
19 |
{ |
|
20 |
if (lux > 40_000) |
|
21 |
return WeatherConditions.Sunny; |
|
22 |
|
|
23 |
if (lux > 20_000) |
|
24 |
return WeatherConditions.Cloudy; |
|
25 |
|
|
26 |
// TODO tohle bylo 10_000, jak mi to má vycházet, zkusit na hourly data |
|
27 |
if (lux != 0) |
|
28 |
return WeatherConditions.Overcast; |
|
29 |
|
|
30 |
return WeatherConditions.Dark; |
|
31 |
} |
|
32 |
|
|
33 |
/// <summary> |
|
34 |
/// Weather conditions to average lux |
|
35 |
/// </summary> |
|
36 |
/// <param name="condition">Weather conditions</param> |
|
37 |
/// <returns>Lux value</returns> |
|
38 |
internal static double TransferConditionsToLux(WeatherConditions condition) |
|
39 |
{ |
|
40 |
if (condition == WeatherConditions.Sunny) |
|
41 |
return 60_000; |
|
42 |
|
|
43 |
if (condition == WeatherConditions.Cloudy) |
|
44 |
return 30_000; |
|
45 |
|
|
46 |
if (condition == WeatherConditions.Overcast) |
|
47 |
return 10_000; |
|
48 |
|
|
49 |
if (condition == WeatherConditions.Dark) |
|
50 |
return 0; |
|
51 |
|
|
52 |
return -1; |
|
53 |
} |
|
54 |
|
|
55 |
/// <summary> |
|
56 |
/// Cloud cover value in percentage to weather conditions |
|
57 |
/// </summary> |
|
58 |
/// <param name="cloudCover">Value expected between 0-100</param> |
|
59 |
/// <returns>WeatherConditions</returns> |
|
60 |
internal static WeatherConditions CloudCoverToConditions(int cloudCover) |
|
61 |
{ |
|
62 |
if (cloudCover >= 66) |
|
63 |
return WeatherConditions.Overcast; |
|
64 |
|
|
65 |
if (cloudCover >= 33) |
|
66 |
return WeatherConditions.Cloudy; |
|
67 |
|
|
68 |
if (cloudCover >= 0) |
|
69 |
return WeatherConditions.Sunny; |
|
70 |
|
|
71 |
return WeatherConditions.Dark; |
|
72 |
} |
|
73 |
} |
|
74 |
} |
Server/ServerApp/Parser/OutputInfo/WeatherConditions.cs | ||
---|---|---|
1 |
namespace ServerApp.Parser.OutputInfo |
|
1 |
// |
|
2 |
// Author: A. Konig |
|
3 |
// |
|
4 |
|
|
5 |
namespace ServerApp.Parser.OutputInfo |
|
2 | 6 |
{ |
3 | 7 |
/// <summary> |
4 | 8 |
/// Weather conditions in regards to sun level |
5 | 9 |
/// </summary> |
6 |
/// <author>Alex Konig</author>
|
|
10 |
/// <author>A. Konig</author>
|
|
7 | 11 |
public enum WeatherConditions |
8 | 12 |
{ |
9 | 13 |
Sunny, Cloudy, Overcast, Dark |
10 | 14 |
} |
11 |
|
|
12 |
/// <summary> |
|
13 |
/// Transfers lux values to weather conditions and vice versa |
|
14 |
/// </summary> |
|
15 |
/// <author>Alex Konig</author> |
|
16 |
public static class ValueToConditions |
|
17 |
{ |
|
18 |
/// <summary> |
|
19 |
/// Lux to weather conditions |
|
20 |
/// </summary> |
|
21 |
/// <param name="lux">Lux value</param> |
|
22 |
/// <returns>Weather conditions</returns> |
|
23 |
public static WeatherConditions TransferLuxToConditions(double lux) |
|
24 |
{ |
|
25 |
if (lux > 40_000) |
|
26 |
return WeatherConditions.Sunny; |
|
27 |
|
|
28 |
if (lux > 20_000) |
|
29 |
return WeatherConditions.Cloudy; |
|
30 |
|
|
31 |
// TODO tohle bylo 10_000, jak mi to má vycházet, zkusit na hourly data |
|
32 |
if (lux != 0) |
|
33 |
return WeatherConditions.Overcast; |
|
34 |
|
|
35 |
return WeatherConditions.Dark; |
|
36 |
} |
|
37 |
|
|
38 |
/// <summary> |
|
39 |
/// Weather conditions to average lux |
|
40 |
/// </summary> |
|
41 |
/// <param name="condition">Weather conditions</param> |
|
42 |
/// <returns>Lux value</returns> |
|
43 |
internal static double TransferConditionsToLux(WeatherConditions condition) |
|
44 |
{ |
|
45 |
if (condition == WeatherConditions.Sunny) |
|
46 |
return 60_000; |
|
47 |
|
|
48 |
if (condition == WeatherConditions.Cloudy) |
|
49 |
return 30_000; |
|
50 |
|
|
51 |
if (condition == WeatherConditions.Overcast) |
|
52 |
return 10_000; |
|
53 |
|
|
54 |
if (condition == WeatherConditions.Dark) |
|
55 |
return 0; |
|
56 |
|
|
57 |
return -1; |
|
58 |
} |
|
59 |
|
|
60 |
internal static WeatherConditions CloudCoverToConditions(int cloudCover) |
|
61 |
{ |
|
62 |
if (cloudCover >= 66) |
|
63 |
return WeatherConditions.Overcast; |
|
64 |
|
|
65 |
if (cloudCover >= 33) |
|
66 |
return WeatherConditions.Cloudy; |
|
67 |
|
|
68 |
if (cloudCover >= 0) |
|
69 |
return WeatherConditions.Sunny; |
|
70 |
|
|
71 |
return WeatherConditions.Dark; |
|
72 |
} |
|
73 |
} |
|
74 | 15 |
} |
Server/ServerApp/Parser/OutputInfo/WeatherInfo.cs | ||
---|---|---|
1 |
using System; |
|
1 |
// |
|
2 |
// Author: A. Konig |
|
3 |
// |
|
4 |
|
|
5 |
using System; |
|
2 | 6 |
|
3 | 7 |
namespace ServerApp.Parser.OutputInfo |
4 | 8 |
{ |
... | ... | |
6 | 10 |
/// Class representing the weather in a given interval at ZCU |
7 | 11 |
/// - shortest possible interval is 1h |
8 | 12 |
/// </summary> |
9 |
/// <author>Alex Konig</author>
|
|
13 |
/// <author>A. Konig</author>
|
|
10 | 14 |
class WeatherInfo |
11 | 15 |
{ |
12 | 16 |
/// <summary> Temperature in °C </summary> |
Server/ServerApp/Parser/Parsers/DataParser.cs | ||
---|---|---|
1 |
using ServerApp.Parser.InputData; |
|
1 |
// |
|
2 |
// Author: A. Konig |
|
3 |
// |
|
4 |
|
|
5 |
using ServerApp.DataDownload; |
|
6 |
using ServerApp.Parser.InputData; |
|
2 | 7 |
using ServerApp.Parser.OutputInfo; |
3 | 8 |
using System; |
4 | 9 |
using System.Collections.Generic; |
... | ... | |
11 | 16 |
/// Class parsing data files into instances of ActivityInfo and WeatherInfo divided by given time interval |
12 | 17 |
/// Data parsed from 7am (included) to 18pm (included) |
13 | 18 |
/// </summary> |
14 |
/// <author>Alex Konig</author>
|
|
15 |
class DataParser |
|
19 |
/// <author>A. Konig</author>
|
|
20 |
class DataParser : IDataParser
|
|
16 | 21 |
{ |
17 |
/// <summary> Path to data folder </summary> |
|
18 |
string path; |
|
22 |
/// <summary> Data downloader </summary> |
|
23 |
DataDownloader downloader; |
|
24 |
|
|
19 | 25 |
/// <summary> Weather data parser </summary> |
20 | 26 |
WeatherParser weatherParser; |
21 | 27 |
/// <summary> Jis data parser </summary> |
... | ... | |
25 | 31 |
|
26 | 32 |
/// <summary> WeatherInfo </summary> |
27 | 33 |
List<WeatherInfo> weatherList; |
28 |
public List<WeatherInfo> WeatherList { get => weatherList; } |
|
34 |
public new List<WeatherInfo> WeatherList { get => weatherList; }
|
|
29 | 35 |
/// <summary> ActivityInfo repersenting overall activity </summary> |
30 | 36 |
List<ActivityInfo> attendanceList; |
31 |
public List<ActivityInfo> AttendanceList { get => attendanceList; } |
|
37 |
public new List<ActivityInfo> AttendanceList { get => attendanceList; }
|
|
32 | 38 |
|
33 | 39 |
/// <summary> ActivityInfo representing jis activity </summary> |
34 | 40 |
List<ActivityInfo> jisList; |
35 | 41 |
/// <summary> ActivityInfo representing login activity</summary> |
36 | 42 |
List<ActivityInfo> loginList; |
37 | 43 |
|
44 |
|
|
38 | 45 |
/// <summary> |
39 | 46 |
/// Constructor |
40 | 47 |
/// </summary> |
41 |
public DataParser(string path)
|
|
48 |
public DataParser(DataDownloader downloader)
|
|
42 | 49 |
{ |
50 |
this.downloader = downloader; |
|
51 |
|
|
43 | 52 |
TagInfo.CreateDictionaries(); |
44 | 53 |
|
45 |
// TODO ask for data folder |
|
46 |
this.path = path; |
|
47 |
DataLoader loader = new CsvDataLoader(); |
|
54 |
IDataLoader loader = new CsvDataLoader(); |
|
48 | 55 |
|
49 | 56 |
weatherParser = new WeatherParser(loader); |
50 | 57 |
jisParser = new JisParser(loader); |
... | ... | |
56 | 63 |
/// </summary> |
57 | 64 |
/// <param name="interval">Length of an interval</param> |
58 | 65 |
/// <param name="wholeDay">Parse data as one instance per day</param> |
59 |
public bool Parse(DateTime startTime, DateTime endTime, int interval = 1, bool wholeDay = true) |
|
66 |
/// <param name="endTime">End time of related data</param> |
|
67 |
/// <param name="startTime">Start time of related data</param> |
|
68 |
override public bool Parse(DateTime startTime, DateTime endTime, int interval = 1, bool wholeDay = true) |
|
60 | 69 |
{ |
61 |
// TODO start and end time -> ask for files from this span, plus validate if the data really is from this span (issue with 00 files) |
|
62 | 70 |
|
63 | 71 |
var cultureInfo = CultureInfo.GetCultureInfo("en-GB"); |
64 | 72 |
Thread.CurrentThread.CurrentCulture = cultureInfo; |
65 | 73 |
Thread.CurrentThread.CurrentUICulture = cultureInfo; |
66 | 74 |
|
67 |
string pathWeather = path + "weather"; |
|
68 |
string pathJis = path + "jis"; |
|
69 |
string pathLogIn = path + "login"; |
|
75 |
// get path to folder w/ datafiles |
|
76 |
string pathWeather = downloader.DataSubDirectories[DataType.POCASI]; // path + "weather"; |
|
77 |
string pathJis = downloader.DataSubDirectories[DataType.JIS]; // path + "jis"; |
|
78 |
string pathLogIn = downloader.DataSubDirectories[DataType.STROJE]; // path + "login"; |
|
79 |
|
|
80 |
// get all files that should be parsed |
|
81 |
Date start = new Date((uint)startTime.Month, (uint)startTime.Year); |
|
82 |
Date end = new Date((uint)endTime.Month, (uint)endTime.Year); |
|
83 |
var weatherFiles = downloader.GetData(pathWeather, start, end); |
|
84 |
var jisFiles = downloader.GetData(pathJis, start, end); |
|
85 |
var loginFiles = downloader.GetData(pathLogIn, start, end); |
|
70 | 86 |
|
71 |
weatherList = weatherParser.ParseWeatherData(pathWeather, wholeDay, interval);
|
|
72 |
jisList = jisParser.ParseJisData(pathJis, wholeDay, interval);
|
|
73 |
loginList = loginParser.ParseLogInData(pathLogIn, wholeDay, interval);
|
|
87 |
weatherList = weatherParser.ParseWeatherData(weatherFiles, startTime, endTime, wholeDay, interval);
|
|
88 |
jisList = jisParser.ParseJisData(jisFiles, startTime, endTime, wholeDay, interval);
|
|
89 |
loginList = loginParser.ParseLogInData(loginFiles, startTime, endTime, wholeDay, interval);
|
|
74 | 90 |
|
75 | 91 |
//Console.WriteLine("WEATHER"); |
76 | 92 |
//WriteToConsole(weatherList); |
77 |
//Console.WriteLine("JIS");
|
|
78 |
//WriteToConsole(jisList);
|
|
93 |
Console.WriteLine("JIS"); |
|
94 |
WriteToConsole(jisList); |
|
79 | 95 |
//Console.WriteLine("LOGIN"); |
80 | 96 |
//WriteToConsole(loginList); |
81 | 97 |
|
... | ... | |
83 | 99 |
|
84 | 100 |
MergeAttendance(); |
85 | 101 |
|
86 |
//Console.WriteLine("MERGED IN ONE LIST");
|
|
87 |
//WriteToConsole(attendanceList);
|
|
102 |
Console.WriteLine("MERGED IN ONE LIST"); |
|
103 |
WriteToConsole(attendanceList); |
|
88 | 104 |
|
89 | 105 |
if (weatherList.Count == 0 || attendanceList.Count == 0) |
90 | 106 |
return false; |
Server/ServerApp/Parser/Parsers/IDataParser.cs | ||
---|---|---|
1 |
// |
|
2 |
// Author: A. Konig |
|
3 |
// |
|
4 |
|
|
5 |
using ServerApp.Parser.OutputInfo; |
|
6 |
using System; |
|
7 |
using System.Collections.Generic; |
|
8 |
|
|
9 |
namespace ServerApp.Parser.Parsers |
|
10 |
{ |
|
11 |
/// <summary> |
|
12 |
/// Abstract class that every DataParser should inherit from |
|
13 |
/// </summary> |
|
14 |
/// <author>A. Konig</author> |
|
15 |
abstract class IDataParser |
|
16 |
{ |
|
17 |
/// <summary> WeatherInfo </summary> |
|
18 |
List<WeatherInfo> weatherList; |
|
19 |
public List<WeatherInfo> WeatherList { get => weatherList; } |
|
20 |
/// <summary> ActivityInfo repersenting overall activity </summary> |
|
21 |
List<ActivityInfo> attendanceList; |
|
22 |
public List<ActivityInfo> AttendanceList { get => attendanceList; } |
|
23 |
|
|
24 |
/// <summary> |
|
25 |
/// Parse data |
|
26 |
/// </summary> |
|
27 |
/// <param name="interval">Length of an interval</param> |
|
28 |
/// <param name="wholeDay">Parse data as one instance per day</param> |
|
29 |
/// <param name="endTime">End time of related data</param> |
|
30 |
/// <param name="startTime">Start time of related data</param> |
|
31 |
public abstract bool Parse(DateTime startTime, DateTime endTime, int interval = 1, bool wholeDay = true); |
|
32 |
|
|
33 |
} |
|
34 |
} |
Server/ServerApp/Parser/Parsers/JisParser.cs | ||
---|---|---|
1 |
using System; |
|
1 |
// |
|
2 |
// Author: A. Konig |
|
3 |
// |
|
4 |
|
|
5 |
using System; |
|
2 | 6 |
using System.Collections.Generic; |
3 | 7 |
using System.IO; |
4 | 8 |
using ServerApp.Parser.InputData; |
... | ... | |
10 | 14 |
/// Class parsing jis files into instances of ActivityInfo divided by given time interval |
11 | 15 |
/// Data parsed from 7am (included) to 18pm (included) |
12 | 16 |
/// </summary> |
13 |
/// <author>Alex Konig</author>
|
|
17 |
/// <author>A. Konig</author>
|
|
14 | 18 |
class JisParser |
15 | 19 |
{ |
16 | 20 |
|
17 | 21 |
/// <summary> Datafile loader </summary> |
18 |
DataLoader loader; |
|
22 |
IDataLoader loader;
|
|
19 | 23 |
|
20 | 24 |
/// <summary> |
21 | 25 |
/// Constructor |
22 | 26 |
/// </summary> |
23 | 27 |
/// <param name="loader">Datafile loader</param> |
24 |
public JisParser(DataLoader loader) |
|
28 |
public JisParser(IDataLoader loader)
|
|
25 | 29 |
{ |
26 | 30 |
this.loader = loader; |
27 | 31 |
} |
... | ... | |
30 | 34 |
/// Parses jis data to ActivityInfo instances |
31 | 35 |
/// Data parsed from 7am (included) to 18pm (included) |
32 | 36 |
/// </summary> |
33 |
/// <param name="folder">Folder with login data files</param> |
|
37 |
/// <param name="jisFiles">Paths to files with login data files</param> |
|
38 |
/// <param name="endTime">End time of related data</param> |
|
39 |
/// <param name="startTime">Start time of related data</param> |
|
34 | 40 |
/// <param name="wholeDay">Should data be parsed as one instance per day (if true parameter interval will be ignored)</param> |
35 | 41 |
/// <param name="interval">Time interval to divide days by, minimum is 1h</param> |
36 | 42 |
/// <returns></returns> |
37 |
public List<ActivityInfo> ParseJisData(string folder, bool wholeDay = true, int interval = 1)
|
|
43 |
public List<ActivityInfo> ParseJisData(List<string> jisFiles, DateTime startTime, DateTime endTime, bool wholeDay = true, int interval = 1)
|
|
38 | 44 |
{ |
39 |
if (!Directory.Exists(folder)) |
|
40 |
return null; |
|
41 |
|
|
42 | 45 |
List<ActivityInfo> list = new List<ActivityInfo>(); |
43 | 46 |
|
47 |
if (jisFiles == null || startTime == null || endTime == null || interval <= 0) |
|
48 |
return list; |
|
49 |
|
|
44 | 50 |
// parse all files |
45 |
string[] fileEntries = Directory.GetFiles(folder); |
|
46 |
foreach (string fileName in fileEntries) |
|
51 |
foreach (string fileName in jisFiles) |
|
47 | 52 |
{ |
48 |
List<ActivityInfo> loadedData = null; |
|
49 |
|
|
53 |
if (!File.Exists(fileName)) |
|
54 |
continue; |
|
55 |
|
|
50 | 56 |
// parse as one instance per day |
57 |
List<ActivityInfo> loadedData = null; |
|
51 | 58 |
if (wholeDay) |
52 |
loadedData = ProcessOneJisFileAsDays(fileName); |
|
59 |
loadedData = ProcessOneJisFileAsDays(fileName, startTime, endTime);
|
|
53 | 60 |
// parse by interval length |
54 | 61 |
else |
55 |
loadedData = ProcessOneJisFileAsIntervals(fileName, interval); |
|
62 |
loadedData = ProcessOneJisFileAsIntervals(fileName, interval, startTime, endTime);
|
|
56 | 63 |
|
57 | 64 |
list.AddRange(loadedData); |
58 | 65 |
} |
... | ... | |
63 | 70 |
/// <summary> |
64 | 71 |
/// Parses data from one data file as one instance per day |
65 | 72 |
/// </summary> |
66 |
/// <param name="path">Path ti file</param> |
|
73 |
/// <param name="path">Path to file</param> |
|
74 |
/// <param name="endTime">End time of related data</param> |
|
75 |
/// <param name="startTime">Start time of related data</param> |
|
67 | 76 |
/// <returns>List with ActivityInfo instances</returns> |
68 |
private List<ActivityInfo> ProcessOneJisFileAsDays(string path) |
|
77 |
private List<ActivityInfo> ProcessOneJisFileAsDays(string path, DateTime startTime, DateTime endTime)
|
|
69 | 78 |
{ |
79 |
List<ActivityInfo> jisInfo = new List<ActivityInfo>(); |
|
80 |
|
|
70 | 81 |
if (!File.Exists(path)) |
71 |
return null;
|
|
82 |
return jisInfo;
|
|
72 | 83 |
|
73 |
List<ActivityInfo> jisInfo = new List<ActivityInfo>(); |
|
74 | 84 |
List<JisInstance> list = loader.LoadJisFile(path); |
75 | 85 |
|
76 | 86 |
// data for each faculty |
... | ... | |
104 | 114 |
lastStartTime = date; |
105 | 115 |
} |
106 | 116 |
|
117 |
// if not in allowed time window -> discard |
|
118 |
if (list[i].dateTime < startTime || list[i].dateTime > endTime) |
|
119 |
continue; |
|
120 |
|
|
107 | 121 |
// aggregate data |
108 | 122 |
if (TagInfo.jisPlaces.ContainsKey(place)) |
109 | 123 |
{ |
... | ... | |
138 | 152 |
/// </summary> |
139 | 153 |
/// <param name="path">Path ti file</param> |
140 | 154 |
/// <param name="interval">Interval length</param> |
155 |
/// <param name="endTime">End time of related data</param> |
|
156 |
/// <param name="startTime">Start time of related data</param> |
|
141 | 157 |
/// <returns>List with ActivityInfo instances</returns> |
142 |
private List<ActivityInfo> ProcessOneJisFileAsIntervals(string path, int interval) |
|
158 |
private List<ActivityInfo> ProcessOneJisFileAsIntervals(string path, int interval, DateTime startTime, DateTime endTime)
|
|
143 | 159 |
{ |
160 |
List<ActivityInfo> jisInfo = new List<ActivityInfo>(); |
|
161 |
|
|
144 | 162 |
if (!File.Exists(path)) |
145 |
return null;
|
|
163 |
return jisInfo;
|
|
146 | 164 |
|
147 |
List<ActivityInfo> jisInfo = new List<ActivityInfo>(); |
|
148 | 165 |
List<JisInstance> list = loader.LoadJisFile(path); |
149 | 166 |
|
150 | 167 |
// data for each faculty |
... | ... | |
164 | 181 |
// first day |
165 | 182 |
DateTime lastStartTime = new DateTime(list[0].dateTime.Year, list[0].dateTime.Month, list[0].dateTime.Day, minmaxHour[0], 0, 0); |
166 | 183 |
int endtime = to[0]; |
167 |
int startTime = minmaxHour[0]; |
|
184 |
int startingTime = minmaxHour[0];
|
|
168 | 185 |
int index = 0; |
169 | 186 |
for (int i = 0; i < list.Count; i++) |
170 | 187 |
{ |
... | ... | |
188 | 205 |
if ( date.Hour >= endtime || trigger) |
189 | 206 |
{ |
190 | 207 |
// start time of last interval |
191 |
DateTime stTime = new DateTime(lastStartTime.Year, lastStartTime.Month, lastStartTime.Day, startTime, 0, 0); |
|
208 |
DateTime stTime = new DateTime(lastStartTime.Year, lastStartTime.Month, lastStartTime.Day, startingTime, 0, 0);
|
|
192 | 209 |
|
193 | 210 |
// find end and start time |
194 | 211 |
if (!trigger) |
... | ... | |
198 | 215 |
|
199 | 216 |
endtime = to[index]; |
200 | 217 |
if (index == 0) |
201 |
startTime = minmaxHour[0]; |
|
218 |
startingTime = minmaxHour[0];
|
|
202 | 219 |
else |
203 |
startTime = to[index - 1]; |
|
220 |
startingTime = to[index - 1];
|
|
204 | 221 |
|
205 | 222 |
// data for each faculty separate |
206 | 223 |
for (int k = 0; k < TagInfo.buildings.Length; k++) |
... | ... | |
213 | 230 |
lastStartTime = date; |
214 | 231 |
} |
215 | 232 |
|
233 |
// if not in allowed time window -> discard |
|
234 |
if (list[i].dateTime < startTime || list[i].dateTime > endTime) |
|
235 |
continue; |
|
236 |
|
|
216 | 237 |
// aggregate data |
217 | 238 |
if (TagInfo.jisPlaces.ContainsKey(place)) |
218 | 239 |
{ |
Server/ServerApp/Parser/Parsers/JsonParser.cs | ||
---|---|---|
1 |
using ServerApp.DataDownload; |
|
2 |
using ServerApp.Parser.OutputInfo; |
|
3 |
using System; |
|
4 |
using System.Collections.Generic; |
|
5 |
using System.Globalization; |
|
6 |
using System.IO; |
|
7 |
using System.Net; |
|
8 |
using System.Text.Json; |
|
9 |
using static System.Text.Json.JsonElement; |
|
10 |
|
|
11 |
namespace ServerApp.Parser.Parsers |
|
12 |
{ |
|
13 |
/// <summary> |
|
14 |
/// Class representing a parser for json prediction data |
|
15 |
/// </summary> |
|
16 |
/// <author>A. Konig</author> |
|
17 |
class JsonParser |
|
18 |
{ |
|
19 |
/// <summary> Current weather </summary> |
|
20 |
public WeatherInfo current; |
|
21 |
/// <summary> Prediction for today, tommorrow and day after tommorrow </summary> |
|
22 |
public List<WeatherInfo> predictions; |
|
23 |
|
|
24 |
/// <summary> Data loader </summary> |
|
25 |
DataDownloader loader; |
|
26 |
/// <summary> Currently parsed day </summary> |
|
27 |
DateTime currParsedDay; |
|
28 |
/// <summary> Sunrise time of currently parsed day </summary> |
|
29 |
DateTime sunriseTime; |
|
30 |
/// <summary> Sunset time of currently parsed day </summary> |
|
31 |
DateTime sunsetTime; |
|
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 |
public void ParsePrediction() |
|
47 |
{ |
|
48 |
// TODO ask DataDownloader for download said file and return path to it |
|
49 |
|
|
50 |
// get file |
|
51 |
string file = DownloadWeatherPrediction(); |
|
52 |
DateTime now = DateTime.Now; |
|
53 |
Console.WriteLine(File.Exists(file)); |
|
54 |
|
|
55 |
// parse file |
|
56 |
string data = File.ReadAllText(file); |
|
57 |
|
|
58 |
JsonDocument doc = JsonDocument.Parse(data); |
|
59 |
JsonElement root = doc.RootElement; |
|
60 |
var weatherP = root.EnumerateObject(); |
|
61 |
predictions = new List<WeatherInfo>(); |
|
62 |
|
|
63 |
while (weatherP.MoveNext()) |
|
64 |
{ |
|
65 |
string name = weatherP.Current.Name; |
|
66 |
Console.WriteLine(name); |
|
67 |
|
|
68 |
switch (name) |
|
69 |
{ |
|
70 |
// current weather |
|
71 |
case "current_condition": |
|
72 |
{ |
|
73 |
ArrayEnumerator currentWeather = weatherP.Current.Value.EnumerateArray(); |
|
74 |
current = ParseCurrentWeather(currentWeather); |
|
75 |
|
|
76 |
break; |
|
77 |
|
|
78 |
} |
|
79 |
// weather prediction |
|
80 |
case "weather": |
|
81 |
{ |
|
82 |
ArrayEnumerator weather = weatherP.Current.Value.EnumerateArray(); |
|
83 |
ParseWeatherPredict(weather); |
|
84 |
|
|
85 |
break; |
|
86 |
} |
|
87 |
} |
|
88 |
} |
|
89 |
|
|
90 |
// sunrise + sunset into data |
|
91 |
EncompassSunRiseSetTimes(); |
|
92 |
|
|
93 |
TestConsoleOutput(); |
|
94 |
} |
|
95 |
|
|
96 |
private void TestConsoleOutput() |
|
97 |
{ |
|
98 |
Console.WriteLine(current); |
|
99 |
foreach (WeatherInfo w in predictions) |
|
100 |
Console.WriteLine(w); |
|
101 |
} |
|
102 |
|
|
103 |
// TODO move to data loader |
|
104 |
/// <summary> |
|
105 |
/// Downloads json file |
|
106 |
/// </summary> |
|
107 |
/// <returns> Path to file </returns> |
|
108 |
private string DownloadWeatherPrediction() |
|
109 |
{ |
|
110 |
DateTime now = DateTime.Now; |
|
111 |
WebClient webClient = new WebClient(); |
|
112 |
webClient.DownloadFile("http://wttr.in/Plzen,czechia?format=j1", $"data/{now.Year}{now.Month}{now.Day}.json"); |
|
113 |
|
|
114 |
return $"data/{now.Year}{now.Month}{now.Day}.json"; |
|
115 |
} |
|
116 |
|
|
117 |
/// <summary> |
|
118 |
/// Change data in a way that they now reflect sunrise and sunset times |
|
119 |
/// If current time under sunrise or over sunset -> WeatherConditions is Dark |
|
120 |
/// If prediction time is under sunrise or over sunset and more than half of the interval is under/over said time -> WeatherCondition is Dark |
|
121 |
/// </summary> |
|
122 |
private void EncompassSunRiseSetTimes() |
|
123 |
{ |
|
124 |
// change current weather |
|
125 |
if ((current.startTime.TimeOfDay > sunsetTime.TimeOfDay) || (current.startTime.TimeOfDay < sunriseTime.TimeOfDay)) |
|
126 |
current.condition = WeatherConditions.Dark; |
|
127 |
|
|
128 |
// change prediction |
|
129 |
for (int i = 0; i < predictions.Count - 1; i++) |
|
130 |
{ |
|
131 |
WeatherInfo w = predictions[i]; |
|
132 |
WeatherInfo wNext = predictions[i + 1]; |
|
133 |
|
|
134 |
// if wNext time < than w time then it is prediction from the next day -> add 24 to correctly calculate timespan |
|
135 |
int timespan = wNext.startTime.Hour - w.startTime.Hour; |
|
136 |
if (wNext.startTime.Hour < w.startTime.Hour) |
|
137 |
timespan = (wNext.startTime.Hour+24) - w.startTime.Hour; |
|
138 |
|
|
139 |
w.intervalLength = timespan; |
|
140 |
|
|
141 |
// if start under sunset |
|
142 |
if (w.startTime.TimeOfDay > sunsetTime.TimeOfDay) |
|
143 |
w.condition = WeatherConditions.Dark; |
|
144 |
|
|
145 |
// if start under sunrise |
|
146 |
if (w.startTime.TimeOfDay < sunriseTime.TimeOfDay) |
|
147 |
{ |
|
148 |
double howMuch = ((sunriseTime.Hour * 60 + sunriseTime.Minute) - (w.startTime.Hour * 60 + w.startTime.Minute)) / 60.0; |
|
149 |
|
|
150 |
if (howMuch >= timespan / 2.0) |
|
151 |
w.condition = WeatherConditions.Dark; |
|
152 |
} |
|
153 |
|
|
154 |
// if start under sunrise |
|
155 |
TimeSpan endTime = new TimeSpan(w.startTime.TimeOfDay.Hours + timespan, w.startTime.TimeOfDay.Minutes, 0); |
|
156 |
if (endTime > sunsetTime.TimeOfDay) |
|
157 |
{ |
|
158 |
double howMuch = ((endTime.Hours * 60 + endTime.Minutes) - (sunsetTime.Hour * 60 + sunsetTime.Minute)) / 60.0; |
|
159 |
|
|
160 |
if (howMuch >= timespan / 2.0) |
|
161 |
w.condition = WeatherConditions.Dark; |
|
162 |
} |
|
163 |
} |
|
164 |
|
|
165 |
// last prediction |
|
166 |
WeatherInfo wLast = predictions[predictions.Count - 1]; |
|
167 |
TimeSpan endTimeW = new TimeSpan(24, 0, 0); |
|
168 |
int timespanLast = endTimeW.Hours - wLast.startTime.Hour; |
|
169 |
wLast.intervalLength = timespanLast; |
|
170 |
|
|
171 |
// if start under sunset |
|
172 |
if (wLast.startTime.TimeOfDay > sunsetTime.TimeOfDay) |
|
173 |
wLast.condition = WeatherConditions.Dark; |
|
174 |
|
|
175 |
// if start under sunrise |
|
176 |
if (wLast.startTime.TimeOfDay < sunriseTime.TimeOfDay) |
|
177 |
{ |
|
178 |
double howMuch = ((sunriseTime.Hour * 60 + sunriseTime.Minute) - (wLast.startTime.Hour * 60 + wLast.startTime.Minute)) / 60.0; |
|
179 |
|
|
180 |
if (howMuch >= timespanLast / 2.0) |
|
181 |
wLast.condition = WeatherConditions.Dark; |
|
182 |
} |
|
183 |
|
|
184 |
// if start under sunrise |
|
185 |
if (endTimeW > sunsetTime.TimeOfDay) |
|
186 |
{ |
|
187 |
double howMuch = ((endTimeW.Hours * 60 + endTimeW.Minutes) - (sunsetTime.Hour * 60 + sunsetTime.Minute)) / 60.0; |
|
188 |
|
|
189 |
if (howMuch >= timespanLast / 2.0) |
|
190 |
wLast.condition = WeatherConditions.Dark; |
|
191 |
} |
|
192 |
} |
|
193 |
|
|
194 |
/// <summary> |
|
195 |
/// Parse weather prediction |
|
196 |
/// </summary> |
|
197 |
/// <param name="weather"> ArrayEnumerator of weather predictions </param> |
|
198 |
private void ParseWeatherPredict(ArrayEnumerator weather) |
|
199 |
{ |
|
200 |
while (weather.MoveNext()) |
|
201 |
{ |
|
202 |
// prediction for one day |
|
203 |
var obj = weather.Current.EnumerateObject(); |
|
204 |
|
|
205 |
while (obj.MoveNext()) |
|
206 |
{ |
|
207 |
switch (obj.Current.Name) |
|
208 |
{ |
|
209 |
case "date": |
|
210 |
{ |
|
211 |
DateTime.TryParseExact(obj.Current.Value.GetString(), "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out currParsedDay); |
|
212 |
break; |
|
213 |
} |
|
214 |
// hourly predictions |
|
215 |
case "hourly": |
|
216 |
{ |
|
217 |
ParseHourly(obj.Current.Value.EnumerateArray()); |
|
218 |
break; |
|
219 |
} |
|
220 |
// sunset / sunrise hours |
|
221 |
case "astronomy": |
|
222 |
{ |
|
223 |
ParseAstronomy(obj.Current.Value.EnumerateArray()); |
|
224 |
break; |
|
225 |
} |
|
226 |
} |
|
227 |
} |
|
228 |
} |
|
229 |
} |
|
230 |
|
|
231 |
/// <summary> |
|
232 |
/// Parse sunrise and sunset times |
|
233 |
/// </summary> |
|
234 |
/// <param name="astronomy"> Astronomy array enumerator </param> |
|
235 |
private void ParseAstronomy(ArrayEnumerator astronomy) |
|
236 |
{ |
|
237 |
while (astronomy.MoveNext()) |
|
238 |
{ |
|
239 |
var astrInfo = astronomy.Current.EnumerateObject(); |
|
240 |
|
|
241 |
while (astrInfo.MoveNext()) |
|
242 |
{ |
|
243 |
switch (astrInfo.Current.Name) |
|
244 |
{ |
|
245 |
case "sunrise": |
|
246 |
{ |
|
247 |
DateTime.TryParseExact(astrInfo.Current.Value.GetString(), "hh:mm tt", CultureInfo.InvariantCulture, DateTimeStyles.None, out sunriseTime); |
|
248 |
Console.WriteLine("\t sunrise time : " + sunriseTime + " " + astrInfo.Current.Value.GetString()); |
|
249 |
break; |
|
250 |
} |
|
251 |
case "sunset": |
|
252 |
{ |
|
253 |
DateTime.TryParseExact(astrInfo.Current.Value.GetString(), "hh:mm tt", CultureInfo.InvariantCulture, DateTimeStyles.None, out sunsetTime); |
|
254 |
Console.WriteLine("\t sunset time : " + sunsetTime + " " + astrInfo.Current.Value.GetString()); |
|
255 |
break; |
|
256 |
} |
|
257 |
} |
|
258 |
} |
|
259 |
} |
|
260 |
} |
|
261 |
|
|
262 |
/// <summary> |
|
263 |
/// Parse hourly predictions |
|
264 |
/// </summary> |
|
265 |
/// <param name="hourly">Enumerated array of hourly predictions</param> |
|
266 |
private void ParseHourly(ArrayEnumerator hourly) |
|
267 |
{ |
|
268 |
while (hourly.MoveNext()) |
|
269 |
{ |
|
270 |
// one hourly prediction |
|
271 |
var oneH = hourly.Current.EnumerateObject(); |
|
272 |
WeatherInfo weather = new WeatherInfo(); |
|
273 |
|
|
274 |
while (oneH.MoveNext()) |
|
275 |
{ |
|
276 |
switch (oneH.Current.Name) |
|
277 |
{ |
|
278 |
case "FeelsLikeC": |
|
279 |
{ |
|
280 |
Double.TryParse(oneH.Current.Value.GetString(), out weather.temp); |
|
281 |
break; |
|
282 |
} |
|
283 |
case "cloudcover": |
|
284 |
{ |
|
285 |
int cloudCover; |
|
286 |
Int32.TryParse(oneH.Current.Value.GetString(), out cloudCover); |
|
287 |
weather.condition = ValueToConditions.CloudCoverToConditions(cloudCover); |
|
288 |
break; |
|
289 |
} |
|
290 |
// take into account highest value from "chanceofrain" and "chaceofsnow" |
|
291 |
case "chanceofrain": |
|
292 |
{ |
|
293 |
int rain; |
|
294 |
Int32.TryParse(oneH.Current.Value.GetString(), out rain); |
|
295 |
weather.rain = rain > weather.rain ? rain : weather.rain; |
|
296 |
break; |
|
297 |
} |
|
298 |
case "chanceofsnow": |
|
299 |
{ |
|
300 |
int snow; |
|
301 |
Int32.TryParse(oneH.Current.Value.GetString(), out snow); |
|
302 |
weather.rain = snow > weather.rain ? snow : weather.rain; |
|
303 |
break; |
|
304 |
} |
|
305 |
// wind kmph has to be translated to mps |
|
306 |
case "WindGustKmph": |
|
307 |
{ |
|
308 |
double windkmh; |
|
309 |
Double.TryParse(oneH.Current.Value.GetString(), out windkmh); |
|
310 |
weather.wind= windkmh * 1000 / (60.0*60.0); |
|
311 |
break; |
|
312 |
} |
|
313 |
case "time": |
|
314 |
{ |
|
315 |
int h; |
|
316 |
Int32.TryParse(oneH.Current.Value.GetString(), out h); |
|
317 |
h /= 100; |
|
318 |
DateTime time = new DateTime(currParsedDay.Year, currParsedDay.Month, currParsedDay.Day, h, 0, 0); |
|
319 |
weather.startTime = time; |
|
320 |
break; |
|
321 |
} |
|
322 |
} |
|
323 |
} |
|
324 |
|
|
325 |
// Console.WriteLine(weather.ToString()); |
|
326 |
predictions.Add(weather); |
|
327 |
|
|
328 |
} |
|
329 |
|
|
330 |
} |
|
331 |
|
|
332 |
/// <summary> |
|
333 |
/// Parse current weather |
|
334 |
/// </summary> |
|
335 |
/// <param name="currentWeather">Enumerated hour of weather data</param> |
|
336 |
/// <returns>WeatherInfo with current weather</returns> |
|
337 |
private WeatherInfo ParseCurrentWeather(ArrayEnumerator currentWeather) |
|
338 |
{ |
|
339 |
WeatherInfo res = new WeatherInfo(); |
|
340 |
//res.current = true; |
|
341 |
|
|
342 |
while (currentWeather.MoveNext()) |
|
343 |
{ |
|
344 |
var obj = currentWeather.Current.EnumerateObject(); |
|
345 |
|
|
346 |
while (obj.MoveNext()) |
|
347 |
{ |
|
348 |
switch (obj.Current.Name) |
|
349 |
{ |
|
350 |
case "localObsDateTime": |
|
351 |
{ |
|
352 |
DateTime.TryParse(obj.Current.Value.GetString(), out res.startTime); |
|
353 |
break; |
|
354 |
} |
|
355 |
case "FeelsLikeC": |
|
356 |
{ |
|
357 |
Double.TryParse(obj.Current.Value.GetString(), out res.temp); |
|
358 |
break; |
|
359 |
} |
|
360 |
case "cloudcover": |
|
361 |
{ |
|
362 |
int cloudCover; |
|
363 |
Int32.TryParse(obj.Current.Value.GetString(), out cloudCover); |
|
364 |
res.condition = ValueToConditions.CloudCoverToConditions(cloudCover); |
|
365 |
break; |
|
366 |
} |
|
367 |
case "precipMM": |
|
368 |
{ |
|
369 |
double rainMM; |
|
370 |
Double.TryParse(obj.Current.Value.GetString(), out rainMM); |
|
371 |
res.rain = rainMM > 0 ? 100 : 0; |
|
372 |
break; |
|
373 |
} |
|
374 |
case "windspeedKmph": |
|
375 |
{ |
|
376 |
double wind; |
|
377 |
Double.TryParse(obj.Current.Value.GetString(), out wind); |
|
378 |
res.wind = wind * 1000 / (60.0 * 60.0); |
|
379 |
break; |
|
380 |
} |
|
381 |
} |
|
382 |
} |
|
383 |
|
|
384 |
} |
|
385 |
|
|
386 |
return res; |
|
387 |
} |
|
388 |
|
|
389 |
} |
|
390 |
} |
Server/ServerApp/Parser/Parsers/LogInParser.cs | ||
---|---|---|
1 |
using ServerApp.Parser.InputData; |
|
1 |
// |
|
2 |
// Author: A. Konig |
|
3 |
// |
|
4 |
|
|
5 |
using ServerApp.Parser.InputData; |
|
2 | 6 |
using ServerApp.Parser.OutputInfo; |
3 | 7 |
using System; |
4 | 8 |
using System.Collections.Generic; |
... | ... | |
10 | 14 |
/// Class parsing login files into instances of ActivityInfo divided by given time interval |
11 | 15 |
/// Data parsed from 7am (included) to 18pm (included) |
12 | 16 |
/// </summary> |
13 |
/// <author>Alex Konig</author>
|
|
17 |
/// <author>A. Konig</author>
|
|
14 | 18 |
class LogInParser |
15 | 19 |
{ |
16 | 20 |
/// <summary> Datafile loader </summary> |
17 |
DataLoader loader; |
|
21 |
IDataLoader loader;
|
|
18 | 22 |
|
19 | 23 |
/// <summary> |
20 | 24 |
/// Constructor |
21 | 25 |
/// </summary> |
22 | 26 |
/// <param name="loader">Datafile loader</param> |
23 |
public LogInParser(DataLoader loader) |
|
27 |
public LogInParser(IDataLoader loader)
|
|
24 | 28 |
{ |
25 | 29 |
this.loader = loader; |
26 | 30 |
} |
... | ... | |
29 | 33 |
/// Parses login data to ActivityInfo instances |
30 | 34 |
/// Data parsed from 7am (included) to 18pm (included) |
31 | 35 |
/// </summary> |
32 |
/// <param name="folder">Folder with login data files</param> |
|
36 |
/// <param name="loginFiles">Paths to files with login data files</param> |
|
37 |
/// <param name="endTime">End time of related data</param> |
|
38 |
/// <param name="startTime">Start time of related data</param> |
|
33 | 39 |
/// <param name="wholeDay">Should data be parsed as one instance per day (if true parameter interval will be ignored)</param> |
34 | 40 |
/// <param name="interval">Time interval to divide days by, minimum is 1h</param> |
35 | 41 |
/// <returns></returns> |
36 |
public List<ActivityInfo> ParseLogInData(string folder, bool wholeDay = true, int interval = 1)
|
|
42 |
public List<ActivityInfo> ParseLogInData(List<string> loginFiles, DateTime startTime, DateTime endTime, bool wholeDay = true, int interval = 1)
|
|
37 | 43 |
{ |
38 |
if (!Directory.Exists(folder)) |
|
39 |
return null; |
|
40 |
|
|
41 | 44 |
List<ActivityInfo> list = new List<ActivityInfo>(); |
42 | 45 |
|
43 |
// get all files in folder |
|
44 |
string[] fileEntries = Directory.GetFiles(folder); |
|
45 |
foreach (string fileName in fileEntries) |
|
46 |
if (loginFiles == null || startTime == null || endTime == null || interval <= 0) |
|
47 |
return list; |
|
48 |
|
|
49 |
// for all files in folder |
|
50 |
foreach (string fileName in loginFiles) |
|
46 | 51 |
{ |
47 |
List<ActivityInfo> loadedData = null; |
|
52 |
if (!File.Exists(fileName)) |
|
53 |
continue; |
|
48 | 54 |
|
49 | 55 |
// parse as one instance per day |
56 |
List<ActivityInfo> loadedData = null; |
|
50 | 57 |
if (wholeDay) |
51 |
loadedData = ProcessOneLogInFileAsDays(fileName); |
|
58 |
loadedData = ProcessOneLogInFileAsDays(fileName, startTime, endTime);
|
|
52 | 59 |
// parse by interval length |
53 | 60 |
else |
54 |
loadedData = ProcessOneLoginFileAsIntervals(fileName, interval); |
|
61 |
loadedData = ProcessOneLoginFileAsIntervals(fileName, interval, startTime, endTime);
|
|
55 | 62 |
|
56 | 63 |
list.AddRange(loadedData); |
57 | 64 |
} |
... | ... | |
63 | 70 |
/// Parses data from one data file as one instance per day |
64 | 71 |
/// </summary> |
65 | 72 |
/// <param name="path">Path ti file</param> |
73 |
/// <param name="endTime">End time of related data</param> |
|
74 |
/// <param name="startTime">Start time of related data</param> |
|
66 | 75 |
/// <returns>List with ActivityInfo instances</returns> |
67 |
private List<ActivityInfo> ProcessOneLogInFileAsDays(string path) |
|
76 |
private List<ActivityInfo> ProcessOneLogInFileAsDays(string path, DateTime startTime, DateTime endTime)
|
|
68 | 77 |
{ |
78 |
List<ActivityInfo> loginInfo = new List<ActivityInfo>(); |
|
79 |
|
|
69 | 80 |
if (!File.Exists(path)) |
70 |
return null;
|
|
81 |
return loginInfo;
|
|
71 | 82 |
|
72 |
List<ActivityInfo> loginInfo = new List<ActivityInfo>(); |
|
73 | 83 |
List<LogInInstance> list = loader.LoadLoginFile(path); |
74 | 84 |
|
75 | 85 |
// data for each faculty |
... | ... | |
103 | 113 |
lastStartDay = date; |
104 | 114 |
} |
105 | 115 |
|
116 |
// if not in allowed time window -> discard |
|
117 |
if (list[i].date < startTime || list[i].date > endTime) |
|
118 |
continue; |
|
119 |
|
|
106 | 120 |
// aggregate data |
107 | 121 |
if (TagInfo.buildingTags.ContainsKey(place)) |
108 | 122 |
{ |
... | ... | |
140 | 154 |
/// </summary> |
141 | 155 |
/// <param name="path">Path to file</param> |
142 | 156 |
/// <param name="interval">Interval length</param> |
157 |
/// <param name="endTime">End time of related data</param> |
|
158 |
/// <param name="startTime">Start time of related data</param> |
|
143 | 159 |
/// <returns>List with ActivityInfo instances</returns> |
144 |
private List<ActivityInfo> ProcessOneLoginFileAsIntervals(string path, int interval) |
|
160 |
private List<ActivityInfo> ProcessOneLoginFileAsIntervals(string path, int interval, DateTime startTime, DateTime endTime)
|
|
145 | 161 |
{ |
162 |
List<ActivityInfo> loginInfo = new List<ActivityInfo>(); |
|
163 |
|
|
146 | 164 |
if (!File.Exists(path)) |
147 |
return null;
|
|
165 |
return loginInfo;
|
|
148 | 166 |
|
149 |
List<ActivityInfo> loignInfo = new List<ActivityInfo>(); |
|
150 | 167 |
List<LogInInstance> list = loader.LoadLoginFile(path); |
151 | 168 |
|
152 | 169 |
// min/max hour taken into account |
... | ... | |
190 | 207 |
for (int l = 0; l < TagInfo.buildings.Length; l++) |
191 | 208 |
{ |
192 | 209 |
ActivityInfo dayInfo = new ActivityInfo(TagInfo.buildings[l], data[k][l], stTime, interval); |
193 |
loignInfo.Add(dayInfo);
|
|
210 |
loginInfo.Add(dayInfo);
|
|
194 | 211 |
} |
195 | 212 |
|
196 | 213 |
data[k] = new int[TagInfo.buildings.Length]; |
... | ... | |
198 | 215 |
lastStartTime = date; |
199 | 216 |
} |
200 | 217 |
|
218 |
// if not in allowed time window -> discard |
|
219 |
if (list[i].date < startTime || list[i].date > endTime) |
|
220 |
continue; |
|
221 |
|
|
201 | 222 |
// find index for current instance |
202 | 223 |
index = 0; |
203 | 224 |
for (int k = 1; k < to.Length; k++) |
... | ... | |
243 | 264 |
for (int l = 0; l < TagInfo.buildings.Length; l++) |
244 | 265 |
{ |
245 | 266 |
ActivityInfo dayInfo = new ActivityInfo(TagInfo.buildings[l], data[k][l], stTime, interval); |
246 |
loignInfo.Add(dayInfo);
|
|
267 |
loginInfo.Add(dayInfo);
|
|
247 | 268 |
} |
248 | 269 |
} |
249 | 270 |
|
250 |
return loignInfo;
|
|
271 |
return loginInfo;
|
|
251 | 272 |
} |
252 | 273 |
|
253 | 274 |
} |
Server/ServerApp/Parser/Parsers/TagInfo.cs | ||
---|---|---|
1 |
using System.Collections.Generic; |
|
1 |
// |
|
2 |
// Author: A. Konig |
|
3 |
// |
|
2 | 4 |
|
3 |
// 30min
|
|
5 |
using System.Collections.Generic;
|
|
4 | 6 |
|
5 | 7 |
namespace ServerApp.Parser.Parsers |
6 | 8 |
{ |
9 |
/// <summary> |
|
10 |
/// Class with Tags used in application |
|
11 |
/// </summary> |
|
7 | 12 |
/// <author>Alex Konig</author> |
8 | 13 |
class TagInfo |
9 | 14 |
{ |
Server/ServerApp/Parser/Parsers/WeatherParser.cs | ||
---|---|---|
1 |
using ServerApp.Parser.InputData; |
|
1 |
// |
|
2 |
// Author: A. Konig |
|
3 |
// |
|
4 |
|
|
5 |
using ServerApp.Parser.InputData; |
|
2 | 6 |
using ServerApp.Parser.OutputInfo; |
3 | 7 |
using System; |
4 | 8 |
using System.Collections.Generic; |
... | ... | |
10 | 14 |
/// Class parsing weather files into instances of WeatherInfo divided by given time interval |
11 | 15 |
/// Data parsed from 7am (included) to 18pm (included) |
12 | 16 |
/// </summary> |
13 |
/// <author>Alex Konig</author>
|
|
17 |
/// <author>A. Konig</author>
|
|
14 | 18 |
class WeatherParser |
15 | 19 |
{ |
16 | 20 |
|
17 | 21 |
/// <summary> Datafile loader </summary> |
18 |
DataLoader loader; |
|
22 |
IDataLoader loader;
|
|
19 | 23 |
|
20 | 24 |
/// <summary> |
21 | 25 |
/// Constructor |
22 | 26 |
/// </summary> |
23 | 27 |
/// <param name="loader">Datafile loader</param> |
24 |
public WeatherParser(DataLoader loader) |
|
28 |
public WeatherParser(IDataLoader loader)
|
|
25 | 29 |
{ |
26 | 30 |
this.loader = loader; |
27 | 31 |
} |
... | ... | |
30 | 34 |
/// Parses weather data to WeatherInfo instances |
31 | 35 |
/// Data parsed from 7am (included) to 18pm (included) |
32 | 36 |
/// </summary> |
33 |
/// <param name="folder">Folder with weather data files</param> |
|
37 |
/// <param name="weatherFiles">Paths to files with weather data files</param> |
|
38 |
/// <param name="endTime">End time of related data</param> |
|
39 |
/// <param name="startTime">Start time of related data</param> |
|
34 | 40 |
/// <param name="wholeDay">Should data be parsed as one instance per day (if true parameter interval will be ignored)</param> |
35 | 41 |
/// <param name="interval">Time interval to divide days by, minimum is 1h</param> |
36 | 42 |
/// <returns></returns> |
37 |
public List<WeatherInfo> ParseWeatherData(string folder, bool wholeDay = true, int interval = 1)
|
|
43 |
public List<WeatherInfo> ParseWeatherData(List<string> weatherFiles, DateTime startTime, DateTime endTime, bool wholeDay = true, int interval = 1)
|
|
38 | 44 |
{ |
39 |
if (!Directory.Exists(folder)) |
|
40 |
return null; |
|
41 |
|
|
42 | 45 |
List<WeatherInfo> list = new List<WeatherInfo>(); |
43 | 46 |
|
47 |
if (weatherFiles == null || startTime == null || endTime == null || interval <= 0) |
|
48 |
return list; |
|
49 |
|
|
44 | 50 |
// get all files in folder |
45 |
string[] fileEntries = Directory.GetFiles(folder); |
|
46 |
foreach (string fileName in fileEntries) |
|
51 |
foreach (string fileName in weatherFiles) |
|
47 | 52 |
{ |
48 |
List<WeatherInfo> loadedData = null; |
|
49 |
|
|
53 |
if (!File.Exists(fileName)) |
|
54 |
continue; |
|
55 |
|
|
50 | 56 |
// parse as one instance per day |
57 |
List<WeatherInfo> loadedData = null; |
|
51 | 58 |
if (wholeDay) |
52 |
loadedData = ProcessOneWeatherFileAsDays(fileName); |
|
59 |
loadedData = ProcessOneWeatherFileAsDays(fileName, startTime, endTime);
|
|
53 | 60 |
// parse according to interval |
54 | 61 |
else |
55 | 62 |
{ |
56 |
loadedData = ProcessOneWeatherFileAsIntervals(fileName, interval); |
|
63 |
loadedData = ProcessOneWeatherFileAsIntervals(fileName, interval, startTime, endTime);
|
|
57 | 64 |
} |
58 | 65 |
|
59 | 66 |
list.AddRange(loadedData); |
... | ... | |
66 | 73 |
/// Parses data from one data file as one instance per day |
67 | 74 |
/// </summary> |
68 | 75 |
/// <param name="path">Path ti file</param> |
76 |
/// <param name="endTime">End time of related data</param> |
|
77 |
/// <param name="startTime">Start time of related data</param> |
|
69 | 78 |
/// <returns>List with WeatherInfo instances</returns> |
70 |
private List<WeatherInfo> ProcessOneWeatherFileAsDays(string path) |
|
79 |
private List<WeatherInfo> ProcessOneWeatherFileAsDays(string path, DateTime startTime, DateTime endTime)
|
|
71 | 80 |
{ |
81 |
List<WeatherInfo> weatherInfo = new List<WeatherInfo>(); |
|
82 |
|
|
72 | 83 |
if (!File.Exists(path)) |
73 |
return null;
|
|
84 |
return weatherInfo;
|
|
74 | 85 |
|
75 |
List<WeatherInfo> weatherInfo = new List<WeatherInfo>(); |
|
76 | 86 |
List<WeatherInstance> list = loader.LoadWeatherFile(path); |
77 | 87 |
|
78 | 88 |
// array with data [temp, rain, wind, lum] |
... | ... | |
105 | 115 |
weatherValues = 0; |
106 | 116 |
} |
107 | 117 |
|
118 |
// if not in allowed time window -> discard |
|
119 |
if (list[i].dateTime < startTime|| list[i].dateTime > endTime) |
|
120 |
continue; |
|
121 |
|
|
108 | 122 |
// aggregate data |
109 | 123 |
recordedAmount[0] += list[i].temp; |
110 | 124 |
recordedAmount[1] += list[i].rain; |
... | ... | |
128 | 142 |
/// </summary> |
129 | 143 |
/// <param name="path">Path to file</param> |
130 | 144 |
/// <param name="interval">Interval length</param> |
145 |
/// <param name="endTime">End time of related data</param> |
|
146 |
/// <param name="startTime">Start time of related data</param> |
|
131 | 147 |
/// <returns>List with ActivityInfo instances</returns> |
132 |
private List<WeatherInfo> ProcessOneWeatherFileAsIntervals(string path, int interval) |
|
148 |
private List<WeatherInfo> ProcessOneWeatherFileAsIntervals(string path, int interval, DateTime startTime, DateTime endTime)
|
|
133 | 149 |
{ |
150 |
List<WeatherInfo> weatherInfo = new List<WeatherInfo>(); |
|
151 |
|
|
134 | 152 |
if (!File.Exists(path)) |
135 |
return null;
|
|
153 |
return weatherInfo;
|
|
136 | 154 |
|
137 |
List<WeatherInfo> loignInfo = new List<WeatherInfo>(); |
|
138 | 155 |
List<WeatherInstance> list = loader.LoadWeatherFile(path); |
139 | 156 |
|
140 | 157 |
// min/max hour taken into account |
... | ... | |
184 | 201 |
|
185 | 202 |
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); |
186 | 203 |
if (count[k] != 0) |
187 |
loignInfo.Add(intervalInfo);
|
|
204 |
weatherInfo.Add(intervalInfo);
|
|
188 | 205 |
|
189 | 206 |
} |
190 | 207 |
|
... | ... | |
194 | 211 |
data[l] = new double[4]; |
195 | 212 |
} |
196 | 213 |
|
214 |
// if not in allowed time window -> discard |
|
215 |
if (list[i].dateTime < startTime || list[i].dateTime > endTime) |
|
216 |
continue; |
|
217 |
|
|
197 | 218 |
// find index for current instance |
198 | 219 |
index = 0; |
199 | 220 |
for (int k = 1; k < to.Length; k++) |
... | ... | |
228 | 249 |
|
229 | 250 |
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); |
230 | 251 |
if (count[k] != 0) |
231 |
loignInfo.Add(intervalInfo);
|
|
252 |
weatherInfo.Add(intervalInfo);
|
|
232 | 253 |
} |
233 | 254 |
|
234 |
return loignInfo;
|
|
255 |
return weatherInfo;
|
|
235 | 256 |
} |
236 | 257 |
} |
237 | 258 |
|
Server/ServerApp/Program.cs | ||
---|---|---|
3 | 3 |
using ServerApp.Parser.Parsers; |
4 | 4 |
using ServerApp.Predictor; |
5 | 5 |
using ServerApp.User; |
6 |
using ServerApp.WeatherPredictionParser; |
|
6 | 7 |
using System; |
7 | 8 |
using System.Collections.Generic; |
8 | 9 |
using System.IO; |
... | ... | |
30 | 31 |
static void Main(string[] args) |
31 | 32 |
{ |
32 | 33 |
|
33 |
JsonParser p = new JsonParser(null); |
|
34 |
p.ParsePrediction(); |
|
35 |
|
|
36 |
/* |
|
34 |
// SETUP FOLDERS |
|
37 | 35 |
|
38 | 36 |
Config config = FillConfigInfo(args); |
39 | 37 |
if (config == null) |
Také k dispozici: Unified diff
re #8841 Fixing errors in start/end time and adding interfaces for DataParser and JsonParser