From c9eed50c630173b3863d028acfa2742a07efdae2 Mon Sep 17 00:00:00 2001 From: A-Konig <alex-nebulae@seznam.cz> Date: Fri, 7 May 2021 17:37:19 +0200 Subject: [PATCH 1/5] re #8840 First test --- Server/ServerApp/App.config | 2 +- Server/ServerApp/Parser/Parsers/JsonParser.cs | 66 +++++++++++++++++++ Server/ServerApp/Program.cs | 6 ++ Server/ServerApp/ServerApp.csproj | 27 ++++++-- Server/ServerApp/packages.config | 12 ++-- 5 files changed, 101 insertions(+), 12 deletions(-) create mode 100644 Server/ServerApp/Parser/Parsers/JsonParser.cs diff --git a/Server/ServerApp/App.config b/Server/ServerApp/App.config index 5cffe9b..0a131ae 100644 --- a/Server/ServerApp/App.config +++ b/Server/ServerApp/App.config @@ -7,7 +7,7 @@ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" /> + <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> diff --git a/Server/ServerApp/Parser/Parsers/JsonParser.cs b/Server/ServerApp/Parser/Parsers/JsonParser.cs new file mode 100644 index 0000000..e02eec4 --- /dev/null +++ b/Server/ServerApp/Parser/Parsers/JsonParser.cs @@ -0,0 +1,66 @@ +using ServerApp.DataDownload; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + + +namespace ServerApp.Parser.Parsers +{ + class JsonParser + { + DataDownloader loader; + + public JsonParser(DataDownloader loader) + { + this.loader = loader; + } + + + public void ParsePrediction() + { + // TODO ask DataDownloader for download said file and return path to it + // get file + string file = DownloadWeatherPrediction(); + DateTime now = DateTime.Now; + Console.WriteLine(File.Exists(file)); + + // parse file + string data = File.ReadAllText(file); + + JsonDocument doc = JsonDocument.Parse(data); + JsonElement root = doc.RootElement; + + var users = root.EnumerateObject(); + while (users.MoveNext()) + { + var user = users.Current; + Console.WriteLine(user.Name); + + /* + var props = user.EnumerateObject(); + + while (props.MoveNext()) + { + var prop = props.Current; + Console.WriteLine($"{prop.Name}: {prop.Value}"); + } + */ + } + + } + + private string DownloadWeatherPrediction() + { + DateTime now = DateTime.Now; + WebClient webClient = new WebClient(); + webClient.DownloadFile("http://wttr.in/Plzen,czechia?format=j1", $"data/weather/{now.Year}{now.Month}{now.Day}.json"); + + return $"data/weather/{now.Year}{now.Month}{now.Day}.json"; + } + } +} diff --git a/Server/ServerApp/Program.cs b/Server/ServerApp/Program.cs index c1c0ac7..61a67ce 100644 --- a/Server/ServerApp/Program.cs +++ b/Server/ServerApp/Program.cs @@ -30,6 +30,11 @@ namespace ServerApp static void Main(string[] args) { + JsonParser p = new JsonParser(null); + p.ParsePrediction(); + + /* + Config config = FillConfigInfo(args); if (config == null) { @@ -75,6 +80,7 @@ namespace ServerApp { Console.WriteLine(s); } + */ // test - connection: //ConnectionListener cl = new ConnectionListener(int.Parse(args[0])/*8000*//*int.Parse(config.Port)*/); diff --git a/Server/ServerApp/ServerApp.csproj b/Server/ServerApp/ServerApp.csproj index 2abcf83..f55a34f 100644 --- a/Server/ServerApp/ServerApp.csproj +++ b/Server/ServerApp/ServerApp.csproj @@ -57,6 +57,9 @@ <Prefer32Bit>true</Prefer32Bit> </PropertyGroup> <ItemGroup> + <Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.5.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll</HintPath> + </Reference> <Reference Include="Microsoft.ML, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> <HintPath>..\packages\Microsoft.ML.1.5.5\lib\netstandard2.0\Microsoft.ML.dll</HintPath> </Reference> @@ -88,8 +91,8 @@ <HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> </Reference> <Reference Include="System" /> - <Reference Include="System.Buffers, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> - <HintPath>..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll</HintPath> + <Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath> </Reference> <Reference Include="System.CodeDom, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> <HintPath>..\packages\System.CodeDom.4.4.0\lib\net461\System.CodeDom.dll</HintPath> @@ -106,14 +109,20 @@ <Private>True</Private> </Reference> <Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> - <HintPath>..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll</HintPath> + <HintPath>..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath> </Reference> <Reference Include="System.Numerics" /> - <Reference Include="System.Numerics.Vectors, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <HintPath>..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll</HintPath> + <Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath> + </Reference> + <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll</HintPath> </Reference> - <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath> + <Reference Include="System.Text.Encodings.Web, Version=5.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Text.Encodings.Web.5.0.1\lib\net461\System.Text.Encodings.Web.dll</HintPath> + </Reference> + <Reference Include="System.Text.Json, Version=5.0.0.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Text.Json.5.0.2\lib\net461\System.Text.Json.dll</HintPath> </Reference> <Reference Include="System.Threading.Channels, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> <HintPath>..\packages\System.Threading.Channels.4.7.1\lib\net461\System.Threading.Channels.dll</HintPath> @@ -121,6 +130,9 @@ <Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> <HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath> </Reference> + <Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> + <HintPath>..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath> + </Reference> <Reference Include="System.Web" /> <Reference Include="System.Xml.Linq" /> <Reference Include="System.Data.DataSetExtensions" /> @@ -149,6 +161,7 @@ <Compile Include="Parser\OutputInfo\WindInfo.cs" /> <Compile Include="Parser\Parsers\DataParser.cs" /> <Compile Include="Parser\Parsers\JisParser.cs" /> + <Compile Include="Parser\Parsers\JsonParser.cs" /> <Compile Include="Parser\Parsers\LogInParser.cs" /> <Compile Include="Parser\Parsers\TagInfo.cs" /> <Compile Include="Parser\Parsers\WeatherParser.cs" /> diff --git a/Server/ServerApp/packages.config b/Server/ServerApp/packages.config index de47ae5..c894fd9 100644 --- a/Server/ServerApp/packages.config +++ b/Server/ServerApp/packages.config @@ -1,17 +1,21 @@ <?xml version="1.0" encoding="utf-8"?> <packages> + <package id="Microsoft.Bcl.AsyncInterfaces" version="5.0.0" targetFramework="net472" /> <package id="Microsoft.ML" version="1.5.5" targetFramework="net472" /> <package id="Microsoft.ML.CpuMath" version="1.5.5" targetFramework="net472" /> <package id="Microsoft.ML.DataView" version="1.5.5" targetFramework="net472" /> <package id="Newtonsoft.Json" version="10.0.3" targetFramework="net472" /> - <package id="System.Buffers" version="4.4.0" targetFramework="net472" /> + <package id="System.Buffers" version="4.5.1" targetFramework="net472" /> <package id="System.CodeDom" version="4.4.0" targetFramework="net472" /> <package id="System.Collections.Immutable" version="1.5.0" targetFramework="net472" /> <package id="System.IO.Compression.ZipFile" version="4.3.0" targetFramework="net472" /> - <package id="System.Memory" version="4.5.3" targetFramework="net472" /> - <package id="System.Numerics.Vectors" version="4.4.0" targetFramework="net472" /> + <package id="System.Memory" version="4.5.4" targetFramework="net472" /> + <package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" /> <package id="System.Reflection.Emit.Lightweight" version="4.3.0" targetFramework="net472" /> - <package id="System.Runtime.CompilerServices.Unsafe" version="4.5.3" targetFramework="net472" /> + <package id="System.Runtime.CompilerServices.Unsafe" version="5.0.0" targetFramework="net472" /> + <package id="System.Text.Encodings.Web" version="5.0.1" targetFramework="net472" /> + <package id="System.Text.Json" version="5.0.2" targetFramework="net472" /> <package id="System.Threading.Channels" version="4.7.1" targetFramework="net472" /> <package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net472" /> + <package id="System.ValueTuple" version="4.5.0" targetFramework="net472" /> </packages> \ No newline at end of file -- GitLab From 1407c8ba103a0aa1b54be9d1bea2f9f7acce0e6c Mon Sep 17 00:00:00 2001 From: A-Konig <alex-nebulae@seznam.cz> Date: Mon, 10 May 2021 10:51:03 +0200 Subject: [PATCH 2/5] re #8840 Finishing up Json parser --- Server/ServerApp/Parser/OutputInfo/JisInfo.cs | 29 -- .../ServerApp/Parser/OutputInfo/LogInInfo.cs | 29 -- Server/ServerApp/Parser/OutputInfo/LumInfo.cs | 28 -- .../ServerApp/Parser/OutputInfo/RainInfo.cs | 24 -- .../ServerApp/Parser/OutputInfo/TempInfo.cs | 24 -- .../Parser/OutputInfo/WeatherConditions.cs | 26 +- .../Parser/OutputInfo/WeatherInfo.cs | 15 +- .../ServerApp/Parser/OutputInfo/WindInfo.cs | 24 -- Server/ServerApp/Parser/Parsers/JsonParser.cs | 360 +++++++++++++++++- .../ServerApp/Parser/Parsers/WeatherParser.cs | 2 +- Server/ServerApp/ServerApp.csproj | 6 - 11 files changed, 372 insertions(+), 195 deletions(-) delete mode 100644 Server/ServerApp/Parser/OutputInfo/JisInfo.cs delete mode 100644 Server/ServerApp/Parser/OutputInfo/LogInInfo.cs delete mode 100644 Server/ServerApp/Parser/OutputInfo/LumInfo.cs delete mode 100644 Server/ServerApp/Parser/OutputInfo/RainInfo.cs delete mode 100644 Server/ServerApp/Parser/OutputInfo/TempInfo.cs delete mode 100644 Server/ServerApp/Parser/OutputInfo/WindInfo.cs diff --git a/Server/ServerApp/Parser/OutputInfo/JisInfo.cs b/Server/ServerApp/Parser/OutputInfo/JisInfo.cs deleted file mode 100644 index 849e0d2..0000000 --- a/Server/ServerApp/Parser/OutputInfo/JisInfo.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Parser.OutputInfo -{ - class JisInfo - { - string faculty; - int amount; - DateTime startTime; - int intervalLength; - - public JisInfo(string faculty, int amount, DateTime startTime, int intervalLength) - { - this.faculty = faculty; - this.amount = amount; - this.startTime = startTime; - this.intervalLength = intervalLength; - } - - public override string ToString() - { - return $"{startTime.ToString()} \t {faculty} \t {amount}"; - } - } -} diff --git a/Server/ServerApp/Parser/OutputInfo/LogInInfo.cs b/Server/ServerApp/Parser/OutputInfo/LogInInfo.cs deleted file mode 100644 index a883053..0000000 --- a/Server/ServerApp/Parser/OutputInfo/LogInInfo.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Parser.OutputInfo -{ - class LogInInfo - { - string building; - int amount; - DateTime startTime; - int intervalLength; - - public LogInInfo(string building, int amount, DateTime startTime, int intervalLength) - { - this.building = building; - this.amount = amount; - this.startTime = startTime; - this.intervalLength = intervalLength; - } - - public override string ToString() - { - return $"{startTime} \t {building} \t {amount}"; - } - } -} diff --git a/Server/ServerApp/Parser/OutputInfo/LumInfo.cs b/Server/ServerApp/Parser/OutputInfo/LumInfo.cs deleted file mode 100644 index 0730c99..0000000 --- a/Server/ServerApp/Parser/OutputInfo/LumInfo.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Parser.OutputInfo -{ - class LumInfo - { - // in lux - double value; - DateTime startTime; - int intervalLength; - - public LumInfo(double value, DateTime startTime, int intervalLength) - { - this.value = value; - this.startTime = startTime; - this.intervalLength = intervalLength; - } - - public override string ToString() - { - return $"{startTime.ToString()} \t {value}"; - } - } -} diff --git a/Server/ServerApp/Parser/OutputInfo/RainInfo.cs b/Server/ServerApp/Parser/OutputInfo/RainInfo.cs deleted file mode 100644 index 48d5552..0000000 --- a/Server/ServerApp/Parser/OutputInfo/RainInfo.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; - -namespace Parser.OutputInfo -{ - class RainInfo - { - // probability in % - double value; - DateTime startTime; - int intervalLength; - - public RainInfo(double value, DateTime startTime, int intervalLength) - { - this.value = value; - this.startTime = startTime; - this.intervalLength = intervalLength; - } - - public override string ToString() - { - return $"{startTime.ToString()} \t {value}"; - } - } -} diff --git a/Server/ServerApp/Parser/OutputInfo/TempInfo.cs b/Server/ServerApp/Parser/OutputInfo/TempInfo.cs deleted file mode 100644 index a5e998a..0000000 --- a/Server/ServerApp/Parser/OutputInfo/TempInfo.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; - -namespace Parser.OutputInfo -{ - class TempInfo - { - // in °C - double value; - DateTime startTime; - int intervalLength; - - public TempInfo(double value, DateTime startTime, int intervalLength) - { - this.value = value; - this.startTime = startTime; - this.intervalLength = intervalLength; - } - - public override string ToString() - { - return $"{startTime.ToString()} \t {value}"; - } - } -} diff --git a/Server/ServerApp/Parser/OutputInfo/WeatherConditions.cs b/Server/ServerApp/Parser/OutputInfo/WeatherConditions.cs index 59ebf1e..c73cf37 100644 --- a/Server/ServerApp/Parser/OutputInfo/WeatherConditions.cs +++ b/Server/ServerApp/Parser/OutputInfo/WeatherConditions.cs @@ -13,7 +13,7 @@ /// Transfers lux values to weather conditions and vice versa /// </summary> /// <author>Alex Konig</author> - public static class LuxToConditions + public static class ValueToConditions { /// <summary> /// Lux to weather conditions @@ -26,11 +26,11 @@ return WeatherConditions.Sunny; if (lux > 20_000) - return WeatherConditions.Overcast; + return WeatherConditions.Cloudy; // TODO tohle bylo 10_000, jak mi to má vycházet, zkusit na hourly data if (lux != 0) - return WeatherConditions.Cloudy; + return WeatherConditions.Overcast; return WeatherConditions.Dark; } @@ -43,18 +43,32 @@ internal static double TransferConditionsToLux(WeatherConditions condition) { if (condition == WeatherConditions.Sunny) - return 50_000; + return 60_000; if (condition == WeatherConditions.Cloudy) return 30_000; if (condition == WeatherConditions.Overcast) - return 15_000; + return 10_000; if (condition == WeatherConditions.Dark) - return 5_000; + return 0; return -1; } + + internal static WeatherConditions CloudCoverToConditions(int cloudCover) + { + if (cloudCover >= 66) + return WeatherConditions.Overcast; + + if (cloudCover >= 33) + return WeatherConditions.Cloudy; + + if (cloudCover >= 0) + return WeatherConditions.Sunny; + + return WeatherConditions.Dark; + } } } \ No newline at end of file diff --git a/Server/ServerApp/Parser/OutputInfo/WeatherInfo.cs b/Server/ServerApp/Parser/OutputInfo/WeatherInfo.cs index 027a08d..3db029c 100644 --- a/Server/ServerApp/Parser/OutputInfo/WeatherInfo.cs +++ b/Server/ServerApp/Parser/OutputInfo/WeatherInfo.cs @@ -21,9 +21,14 @@ namespace ServerApp.Parser.OutputInfo public WeatherConditions condition; /// <summary> Start of interval </summary> - DateTime startTime; + public DateTime startTime; /// <summary> Length of interval in hours </summary> - int intervalLength; + public int intervalLength; + + public WeatherInfo() + { + condition = WeatherConditions.Dark; + } /// <summary> /// Constructor @@ -43,7 +48,7 @@ namespace ServerApp.Parser.OutputInfo this.lum = lum; this.intervalLength = intervalLength; - condition = LuxToConditions.TransferLuxToConditions(lum); + condition = ValueToConditions.TransferLuxToConditions(lum); } /// <summary> @@ -64,7 +69,7 @@ namespace ServerApp.Parser.OutputInfo this.condition = condition; this.intervalLength = intervalLength; - lum = LuxToConditions.TransferConditionsToLux(condition); + lum = ValueToConditions.TransferConditionsToLux(condition); } /// <summary> @@ -73,7 +78,7 @@ namespace ServerApp.Parser.OutputInfo /// <returns>interval start temperature probability of rain wind weather condition</returns> public override string ToString() { - return $"{startTime.ToString()} \t {temp}°C \t {rain}% \t {wind}m/s \t {condition.ToString()} \t {lum}"; + return $"{startTime} \t {temp}°C \t {rain}% \t {wind}m/s \t {condition.ToString()} \t {lum}"; } } diff --git a/Server/ServerApp/Parser/OutputInfo/WindInfo.cs b/Server/ServerApp/Parser/OutputInfo/WindInfo.cs deleted file mode 100644 index 0a39423..0000000 --- a/Server/ServerApp/Parser/OutputInfo/WindInfo.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; - -namespace Parser.OutputInfo -{ - class WindInfo - { - // in m/s - double value; - DateTime startTime; - int intervalLength; - - public WindInfo(double value, DateTime startTime, int intervalLength) - { - this.value = value; - this.startTime = startTime; - this.intervalLength = intervalLength; - } - - public override string ToString() - { - return $"{startTime.ToString()} \t {value}"; - } - } -} diff --git a/Server/ServerApp/Parser/Parsers/JsonParser.cs b/Server/ServerApp/Parser/Parsers/JsonParser.cs index e02eec4..a912df4 100644 --- a/Server/ServerApp/Parser/Parsers/JsonParser.cs +++ b/Server/ServerApp/Parser/Parsers/JsonParser.cs @@ -1,66 +1,388 @@ using ServerApp.DataDownload; +using ServerApp.Parser.OutputInfo; using System; using System.Collections.Generic; +using System.Globalization; using System.IO; -using System.Linq; using System.Net; -using System.Text; using System.Text.Json; -using System.Threading.Tasks; - +using static System.Text.Json.JsonElement; namespace ServerApp.Parser.Parsers { + /// <summary> + /// Class representing a parser for json prediction data + /// </summary> + /// <author>A. Konig</author> class JsonParser { + /// <summary> Current weather </summary> + public WeatherInfo current; + /// <summary> Prediction for today, tommorrow and day after tommorrow </summary> + public List<WeatherInfo> predictions; + + /// <summary> Data loader </summary> DataDownloader loader; + /// <summary> Currently parsed day </summary> + DateTime currParsedDay; + /// <summary> Sunrise time of currently parsed day </summary> + DateTime sunriseTime; + /// <summary> Sunset time of currently parsed day </summary> + DateTime sunsetTime; + /// <summary> + /// Constructor + /// </summary> + /// <param name="loader"></param> public JsonParser(DataDownloader loader) { this.loader = loader; } - + /// <summary> + /// Parse weather prediction + /// Results is in attributes current for current weather and pred for weather prediction for today, tommorrow and day after tommorrow + /// </summary> public void ParsePrediction() { // TODO ask DataDownloader for download said file and return path to it + // get file string file = DownloadWeatherPrediction(); DateTime now = DateTime.Now; Console.WriteLine(File.Exists(file)); // parse file - string data = File.ReadAllText(file); + string data = File.ReadAllText(file); JsonDocument doc = JsonDocument.Parse(data); JsonElement root = doc.RootElement; + var weatherP = root.EnumerateObject(); + predictions = new List<WeatherInfo>(); - var users = root.EnumerateObject(); - while (users.MoveNext()) + while (weatherP.MoveNext()) { - var user = users.Current; - Console.WriteLine(user.Name); - - /* - var props = user.EnumerateObject(); + string name = weatherP.Current.Name; + Console.WriteLine(name); - while (props.MoveNext()) + switch (name) { - var prop = props.Current; - Console.WriteLine($"{prop.Name}: {prop.Value}"); + // current weather + case "current_condition": + { + ArrayEnumerator currentWeather = weatherP.Current.Value.EnumerateArray(); + current = ParseCurrentWeather(currentWeather); + + break; + + } + // weather prediction + case "weather": + { + ArrayEnumerator weather = weatherP.Current.Value.EnumerateArray(); + ParseWeatherPredict(weather); + + break; + } } - */ } + // sunrise + sunset into data + EncompassSunRiseSetTimes(); + + TestConsoleOutput(); + } + + private void TestConsoleOutput() + { + Console.WriteLine(current); + foreach (WeatherInfo w in predictions) + Console.WriteLine(w); } + // TODO move to data loader + /// <summary> + /// Downloads json file + /// </summary> + /// <returns> Path to file </returns> private string DownloadWeatherPrediction() { DateTime now = DateTime.Now; WebClient webClient = new WebClient(); - webClient.DownloadFile("http://wttr.in/Plzen,czechia?format=j1", $"data/weather/{now.Year}{now.Month}{now.Day}.json"); + webClient.DownloadFile("http://wttr.in/Plzen,czechia?format=j1", $"data/{now.Year}{now.Month}{now.Day}.json"); + + return $"data/{now.Year}{now.Month}{now.Day}.json"; + } + + /// <summary> + /// Change data in a way that they now reflect sunrise and sunset times + /// If current time under sunrise or over sunset -> WeatherConditions is Dark + /// If prediction time is under sunrise or over sunset and more than half of the interval is under/over said time -> WeatherCondition is Dark + /// </summary> + private void EncompassSunRiseSetTimes() + { + // change current weather + if ((current.startTime.TimeOfDay > sunsetTime.TimeOfDay) || (current.startTime.TimeOfDay < sunriseTime.TimeOfDay)) + current.condition = WeatherConditions.Dark; + + // change prediction + for (int i = 0; i < predictions.Count - 1; i++) + { + // TODO what about when days change -> detect end / start of day and do differently ? + + WeatherInfo w = predictions[i]; + WeatherInfo wNext = predictions[i + 1]; + + int timespan = wNext.startTime.Hour - w.startTime.Hour; + w.intervalLength = timespan; + + // if start under sunset + if (w.startTime.TimeOfDay > sunsetTime.TimeOfDay) + w.condition = WeatherConditions.Dark; + + // if start under sunrise + if (w.startTime.TimeOfDay < sunriseTime.TimeOfDay) + { + double howMuch = ((sunriseTime.Hour * 60 + sunriseTime.Minute) - (w.startTime.Hour * 60 + w.startTime.Minute)) / 60.0; + + if (howMuch >= timespan / 2.0) + w.condition = WeatherConditions.Dark; + } + + // if start under sunrise + TimeSpan endTime = new TimeSpan(w.startTime.TimeOfDay.Hours + timespan, w.startTime.TimeOfDay.Minutes, 0); + if (endTime > sunsetTime.TimeOfDay) + { + double howMuch = ((endTime.Hours * 60 + endTime.Minutes) - (sunsetTime.Hour * 60 + sunsetTime.Minute)) / 60.0; + + if (howMuch >= timespan / 2.0) + w.condition = WeatherConditions.Dark; + } + } + + // last prediction + WeatherInfo wLast = predictions[predictions.Count - 1]; + TimeSpan endTimeW = new TimeSpan(24, 0, 0); + int timespanLast = endTimeW.Hours - wLast.startTime.Hour; + wLast.intervalLength = timespanLast; + + // if start under sunset + if (wLast.startTime.TimeOfDay > sunsetTime.TimeOfDay) + wLast.condition = WeatherConditions.Dark; + + // if start under sunrise + if (wLast.startTime.TimeOfDay < sunriseTime.TimeOfDay) + { + double howMuch = ((sunriseTime.Hour * 60 + sunriseTime.Minute) - (wLast.startTime.Hour * 60 + wLast.startTime.Minute)) / 60.0; + + if (howMuch >= timespanLast / 2.0) + wLast.condition = WeatherConditions.Dark; + } + + // if start under sunrise + if (endTimeW > sunsetTime.TimeOfDay) + { + double howMuch = ((endTimeW.Hours * 60 + endTimeW.Minutes) - (sunsetTime.Hour * 60 + sunsetTime.Minute)) / 60.0; + + if (howMuch >= timespanLast / 2.0) + wLast.condition = WeatherConditions.Dark; + } + } + + /// <summary> + /// Parse weather prediction + /// </summary> + /// <param name="weather"> ArrayEnumerator of weather predictions </param> + private void ParseWeatherPredict(ArrayEnumerator weather) + { + while (weather.MoveNext()) + { + // prediction for one day + var obj = weather.Current.EnumerateObject(); + + while (obj.MoveNext()) + { + switch (obj.Current.Name) + { + case "date": + { + DateTime.TryParseExact(obj.Current.Value.GetString(), "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out currParsedDay); + break; + } + // hourly predictions + case "hourly": + { + ParseHourly(obj.Current.Value.EnumerateArray()); + break; + } + // sunset / sunrise hours + case "astronomy": + { + ParseAstronomy(obj.Current.Value.EnumerateArray()); + break; + } + } + } + } + } + + /// <summary> + /// Parse sunrise and sunset times + /// </summary> + /// <param name="astronomy"> Astronomy array enumerator </param> + private void ParseAstronomy(ArrayEnumerator astronomy) + { + while (astronomy.MoveNext()) + { + var astrInfo = astronomy.Current.EnumerateObject(); + + while (astrInfo.MoveNext()) + { + switch (astrInfo.Current.Name) + { + case "sunrise": + { + DateTime.TryParseExact(astrInfo.Current.Value.GetString(), "hh:mm tt", CultureInfo.InvariantCulture, DateTimeStyles.None, out sunriseTime); + Console.WriteLine("\t sunrise time : " + sunriseTime + " " + astrInfo.Current.Value.GetString()); + break; + } + case "sunset": + { + DateTime.TryParseExact(astrInfo.Current.Value.GetString(), "hh:mm tt", CultureInfo.InvariantCulture, DateTimeStyles.None, out sunsetTime); + Console.WriteLine("\t sunset time : " + sunsetTime + " " + astrInfo.Current.Value.GetString()); + break; + } + } + } + } + } + + /// <summary> + /// Parse hourly predictions + /// </summary> + /// <param name="hourly">Enumerated array of hourly predictions</param> + private void ParseHourly(ArrayEnumerator hourly) + { + while (hourly.MoveNext()) + { + // one hourly prediction + var oneH = hourly.Current.EnumerateObject(); + WeatherInfo weather = new WeatherInfo(); + + while (oneH.MoveNext()) + { + switch (oneH.Current.Name) + { + case "FeelsLikeC": + { + Double.TryParse(oneH.Current.Value.GetString(), out weather.temp); + break; + } + case "cloudcover": + { + int cloudCover; + Int32.TryParse(oneH.Current.Value.GetString(), out cloudCover); + weather.condition = ValueToConditions.CloudCoverToConditions(cloudCover); + break; + } + // take into account highest value from "chanceofrain" and "chaceofsnow" + case "chanceofrain": + { + int rain; + Int32.TryParse(oneH.Current.Value.GetString(), out rain); + weather.rain = rain > weather.rain ? rain : weather.rain; + break; + } + case "chanceofsnow": + { + int snow; + Int32.TryParse(oneH.Current.Value.GetString(), out snow); + weather.rain = snow > weather.rain ? snow : weather.rain; + break; + } + // wind kmph has to be translated to mps + case "WindGustKmph": + { + double windkmh; + Double.TryParse(oneH.Current.Value.GetString(), out windkmh); + weather.wind= windkmh * 1000 / (60.0*60.0); + break; + } + case "time": + { + int h; + Int32.TryParse(oneH.Current.Value.GetString(), out h); + h /= 100; + DateTime time = new DateTime(currParsedDay.Year, currParsedDay.Month, currParsedDay.Day, h, 0, 0); + weather.startTime = time; + break; + } + } + } + + // Console.WriteLine(weather.ToString()); + predictions.Add(weather); + + } - return $"data/weather/{now.Year}{now.Month}{now.Day}.json"; } + + /// <summary> + /// Parse current weather + /// </summary> + /// <param name="currentWeather">Enumerated hour of weather data</param> + /// <returns>WeatherInfo with current weather</returns> + private WeatherInfo ParseCurrentWeather(ArrayEnumerator currentWeather) + { + WeatherInfo res = new WeatherInfo(); + //res.current = true; + + while (currentWeather.MoveNext()) + { + var obj = currentWeather.Current.EnumerateObject(); + + while (obj.MoveNext()) + { + switch (obj.Current.Name) + { + case "localObsDateTime": + { + DateTime.TryParse(obj.Current.Value.GetString(), out res.startTime); + break; + } + case "FeelsLikeC": + { + Double.TryParse(obj.Current.Value.GetString(), out res.temp); + break; + } + case "cloudcover": + { + int cloudCover; + Int32.TryParse(obj.Current.Value.GetString(), out cloudCover); + res.condition = ValueToConditions.CloudCoverToConditions(cloudCover); + break; + } + case "precipMM": + { + double rainMM; + Double.TryParse(obj.Current.Value.GetString(), out rainMM); + res.rain = rainMM > 0 ? 100 : 0; + break; + } + case "windspeedKmph": + { + double wind; + Double.TryParse(obj.Current.Value.GetString(), out wind); + res.wind = wind * 1000 / (60.0 * 60.0); + break; + } + } + } + + } + + return res; + } + } } diff --git a/Server/ServerApp/Parser/Parsers/WeatherParser.cs b/Server/ServerApp/Parser/Parsers/WeatherParser.cs index b3aa0f0..4d39eda 100644 --- a/Server/ServerApp/Parser/Parsers/WeatherParser.cs +++ b/Server/ServerApp/Parser/Parsers/WeatherParser.cs @@ -110,7 +110,7 @@ namespace ServerApp.Parser.Parsers recordedAmount[1] += list[i].rain; recordedAmount[2] += list[i].wind; - if (LuxToConditions.TransferLuxToConditions(list[i].lum * 1000) != WeatherConditions.Dark) + if (ValueToConditions.TransferLuxToConditions(list[i].lum * 1000) != WeatherConditions.Dark) recordedAmount[3] += list[i].lum * 1000; weatherValues++; values++; diff --git a/Server/ServerApp/ServerApp.csproj b/Server/ServerApp/ServerApp.csproj index f55a34f..20bcfd6 100644 --- a/Server/ServerApp/ServerApp.csproj +++ b/Server/ServerApp/ServerApp.csproj @@ -151,14 +151,8 @@ <Compile Include="Parser\InputData\LogInInstance.cs" /> <Compile Include="Parser\InputData\WeatherInstance.cs" /> <Compile Include="Parser\OutputInfo\ActivityInfo.cs" /> - <Compile Include="Parser\OutputInfo\JisInfo.cs" /> - <Compile Include="Parser\OutputInfo\LogInInfo.cs" /> - <Compile Include="Parser\OutputInfo\LumInfo.cs" /> - <Compile Include="Parser\OutputInfo\RainInfo.cs" /> - <Compile Include="Parser\OutputInfo\TempInfo.cs" /> <Compile Include="Parser\OutputInfo\WeatherConditions.cs" /> <Compile Include="Parser\OutputInfo\WeatherInfo.cs" /> - <Compile Include="Parser\OutputInfo\WindInfo.cs" /> <Compile Include="Parser\Parsers\DataParser.cs" /> <Compile Include="Parser\Parsers\JisParser.cs" /> <Compile Include="Parser\Parsers\JsonParser.cs" /> -- GitLab From c0dffb79261167cb3ed9b898a9475f521b3ab79e Mon Sep 17 00:00:00 2001 From: A-Konig <alex-nebulae@seznam.cz> Date: Mon, 10 May 2021 11:05:22 +0200 Subject: [PATCH 3/5] re #8840 Fixing day changes in list of predictions --- Server/ServerApp/Parser/Parsers/JsonParser.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Server/ServerApp/Parser/Parsers/JsonParser.cs b/Server/ServerApp/Parser/Parsers/JsonParser.cs index a912df4..ac3b029 100644 --- a/Server/ServerApp/Parser/Parsers/JsonParser.cs +++ b/Server/ServerApp/Parser/Parsers/JsonParser.cs @@ -128,12 +128,14 @@ namespace ServerApp.Parser.Parsers // change prediction for (int i = 0; i < predictions.Count - 1; i++) { - // TODO what about when days change -> detect end / start of day and do differently ? - WeatherInfo w = predictions[i]; WeatherInfo wNext = predictions[i + 1]; + // if wNext time < than w time then it is prediction from the next day -> add 24 to correctly calculate timespan int timespan = wNext.startTime.Hour - w.startTime.Hour; + if (wNext.startTime.Hour < w.startTime.Hour) + timespan = (wNext.startTime.Hour+24) - w.startTime.Hour; + w.intervalLength = timespan; // if start under sunset -- GitLab From cdf3c217563b42de9a66470b932a0fa637363089 Mon Sep 17 00:00:00 2001 From: A-Konig <alex-nebulae@seznam.cz> Date: Mon, 10 May 2021 20:08:11 +0200 Subject: [PATCH 4/5] re #8841 Fixing errors in start/end time and adding interfaces for DataParser and JsonParser --- .../Parser/InputData/CsvDataLoader.cs | 10 ++- .../{DataLoader.cs => IDataLoader.cs} | 15 ++-- .../ServerApp/Parser/InputData/JisInstance.cs | 8 +- .../Parser/InputData/LogInInstance.cs | 8 +- .../Parser/InputData/WeatherInstance.cs | 8 +- .../Parser/OutputInfo/ActivityInfo.cs | 8 +- .../Parser/OutputInfo/ValueToConditions.cs | 74 +++++++++++++++++++ .../Parser/OutputInfo/WeatherConditions.cs | 71 ++---------------- .../Parser/OutputInfo/WeatherInfo.cs | 8 +- Server/ServerApp/Parser/Parsers/DataParser.cs | 62 ++++++++++------ .../ServerApp/Parser/Parsers/IDataParser.cs | 34 +++++++++ Server/ServerApp/Parser/Parsers/JisParser.cs | 73 +++++++++++------- .../ServerApp/Parser/Parsers/LogInParser.cs | 69 +++++++++++------ Server/ServerApp/Parser/Parsers/TagInfo.cs | 9 ++- .../ServerApp/Parser/Parsers/WeatherParser.cs | 69 +++++++++++------ Server/ServerApp/Program.cs | 31 +++++--- Server/ServerApp/ServerApp.csproj | 32 +++++++- .../WeatherPredictionParser/IJsonParser.cs | 32 ++++++++ .../JsonParser.cs | 34 ++++++--- 19 files changed, 449 insertions(+), 206 deletions(-) rename Server/ServerApp/Parser/InputData/{DataLoader.cs => IDataLoader.cs} (81%) create mode 100644 Server/ServerApp/Parser/OutputInfo/ValueToConditions.cs create mode 100644 Server/ServerApp/Parser/Parsers/IDataParser.cs create mode 100644 Server/ServerApp/WeatherPredictionParser/IJsonParser.cs rename Server/ServerApp/{Parser/Parsers => WeatherPredictionParser}/JsonParser.cs (96%) diff --git a/Server/ServerApp/Parser/InputData/CsvDataLoader.cs b/Server/ServerApp/Parser/InputData/CsvDataLoader.cs index 91b5749..b196784 100644 --- a/Server/ServerApp/Parser/InputData/CsvDataLoader.cs +++ b/Server/ServerApp/Parser/InputData/CsvDataLoader.cs @@ -1,4 +1,8 @@ -using System; +// +// Author: A. Konig +// + +using System; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -8,8 +12,8 @@ namespace ServerApp.Parser.InputData /// <summary> /// Class responsible for loading data from file /// </summary> - /// <author>Alex Konig</author> - class CsvDataLoader : DataLoader + /// <author>A. Konig</author> + class CsvDataLoader : IDataLoader { /// <summary> Culture info for parsing numbers </summary> static CultureInfo cultureInfo = new CultureInfo("de-DE"); diff --git a/Server/ServerApp/Parser/InputData/DataLoader.cs b/Server/ServerApp/Parser/InputData/IDataLoader.cs similarity index 81% rename from Server/ServerApp/Parser/InputData/DataLoader.cs rename to Server/ServerApp/Parser/InputData/IDataLoader.cs index fbf4c47..f0772dd 100644 --- a/Server/ServerApp/Parser/InputData/DataLoader.cs +++ b/Server/ServerApp/Parser/InputData/IDataLoader.cs @@ -1,13 +1,16 @@ -using System; +// +// Author: A. Konig +// + using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ServerApp.Parser.InputData { - /// <author>Alex Konig</author> - interface DataLoader + /// <summary> + /// Interface that every DataLoader should implement + /// </summary> + /// <author>A. Konig</author> + interface IDataLoader { /// <summary> /// Load jis data from file diff --git a/Server/ServerApp/Parser/InputData/JisInstance.cs b/Server/ServerApp/Parser/InputData/JisInstance.cs index 749e693..82af5e9 100644 --- a/Server/ServerApp/Parser/InputData/JisInstance.cs +++ b/Server/ServerApp/Parser/InputData/JisInstance.cs @@ -1,4 +1,8 @@ -using System; +// +// Author: A. Konig +// + +using System; namespace ServerApp.Parser.InputData { @@ -13,7 +17,7 @@ namespace ServerApp.Parser.InputData /// "A1";"08.04.2018 14:23:15";1 /// [place tag];[date time];[amount] /// </summary> - /// <author>Alex Konig</author> + /// <author>A. Konig</author> class JisInstance { /// <summary> Place tag </summary> diff --git a/Server/ServerApp/Parser/InputData/LogInInstance.cs b/Server/ServerApp/Parser/InputData/LogInInstance.cs index 40ef483..7fba2c2 100644 --- a/Server/ServerApp/Parser/InputData/LogInInstance.cs +++ b/Server/ServerApp/Parser/InputData/LogInInstance.cs @@ -1,4 +1,8 @@ -using System; +// +// Author: A. Konig +// + +using System; namespace ServerApp.Parser.InputData { @@ -20,7 +24,7 @@ namespace ServerApp.Parser.InputData /// "27.10.2011 00:00:00";1;7;"13:00";"13:45";"UI";"Laboratoř";"UI-505";"ui505av07-lps" /// [datum];[amount];[lesson];[lesson start];[lesson end];[building];[room type];[room];[hostname] /// </summary> - /// <author>Alex Konig</author> + /// <author>A. Konig</author> class LogInInstance { /// <summary> Date time </summary> diff --git a/Server/ServerApp/Parser/InputData/WeatherInstance.cs b/Server/ServerApp/Parser/InputData/WeatherInstance.cs index cdb4af4..7ee6ef6 100644 --- a/Server/ServerApp/Parser/InputData/WeatherInstance.cs +++ b/Server/ServerApp/Parser/InputData/WeatherInstance.cs @@ -1,4 +1,8 @@ -using System; +// +// Author: A. Konig +// + +using System; namespace ServerApp.Parser.InputData { @@ -9,7 +13,7 @@ namespace ServerApp.Parser.InputData /// "30.04.2019 16:19:01";20.3;5.3;0;19 /// [date time];[temperature];[wind];[rain];[luminance] /// </summary> - /// <author>Alex Konig</author> + /// <author>A. Konig</author> class WeatherInstance { /// <summary> Date and time </summary> diff --git a/Server/ServerApp/Parser/OutputInfo/ActivityInfo.cs b/Server/ServerApp/Parser/OutputInfo/ActivityInfo.cs index 1e287e0..6d17e4f 100644 --- a/Server/ServerApp/Parser/OutputInfo/ActivityInfo.cs +++ b/Server/ServerApp/Parser/OutputInfo/ActivityInfo.cs @@ -1,4 +1,8 @@ -using System; +// +// Author: A. Konig +// + +using System; namespace ServerApp.Parser.OutputInfo { @@ -6,7 +10,7 @@ namespace ServerApp.Parser.OutputInfo /// Class representing the number of events in a given time interval a given faculty /// - shortest possible interval is 1h /// </summary> - /// <author>Alex Konig</author> + /// <author>A. Konig</author> class ActivityInfo { /// <summary> Building </summary> diff --git a/Server/ServerApp/Parser/OutputInfo/ValueToConditions.cs b/Server/ServerApp/Parser/OutputInfo/ValueToConditions.cs new file mode 100644 index 0000000..09c0813 --- /dev/null +++ b/Server/ServerApp/Parser/OutputInfo/ValueToConditions.cs @@ -0,0 +1,74 @@ +// +// Author: A. Konig +// + +namespace ServerApp.Parser.OutputInfo +{ + /// <summary> + /// Transfers various values to weather conditions and vice versa + /// </summary> + /// <author>A. Konig</author> + public static class ValueToConditions + { + /// <summary> + /// Lux to weather conditions + /// </summary> + /// <param name="lux">Lux value</param> + /// <returns>Weather conditions</returns> + public static WeatherConditions TransferLuxToConditions(double lux) + { + if (lux > 40_000) + return WeatherConditions.Sunny; + + if (lux > 20_000) + return WeatherConditions.Cloudy; + + // TODO tohle bylo 10_000, jak mi to má vycházet, zkusit na hourly data + if (lux != 0) + return WeatherConditions.Overcast; + + return WeatherConditions.Dark; + } + + /// <summary> + /// Weather conditions to average lux + /// </summary> + /// <param name="condition">Weather conditions</param> + /// <returns>Lux value</returns> + internal static double TransferConditionsToLux(WeatherConditions condition) + { + if (condition == WeatherConditions.Sunny) + return 60_000; + + if (condition == WeatherConditions.Cloudy) + return 30_000; + + if (condition == WeatherConditions.Overcast) + return 10_000; + + if (condition == WeatherConditions.Dark) + return 0; + + return -1; + } + + /// <summary> + /// Cloud cover value in percentage to weather conditions + /// </summary> + /// <param name="cloudCover">Value expected between 0-100</param> + /// <returns>WeatherConditions</returns> + internal static WeatherConditions CloudCoverToConditions(int cloudCover) + { + if (cloudCover >= 66) + return WeatherConditions.Overcast; + + if (cloudCover >= 33) + return WeatherConditions.Cloudy; + + if (cloudCover >= 0) + return WeatherConditions.Sunny; + + return WeatherConditions.Dark; + } + } +} \ No newline at end of file diff --git a/Server/ServerApp/Parser/OutputInfo/WeatherConditions.cs b/Server/ServerApp/Parser/OutputInfo/WeatherConditions.cs index c73cf37..6c8b760 100644 --- a/Server/ServerApp/Parser/OutputInfo/WeatherConditions.cs +++ b/Server/ServerApp/Parser/OutputInfo/WeatherConditions.cs @@ -1,74 +1,15 @@ -namespace ServerApp.Parser.OutputInfo +// +// Author: A. Konig +// + +namespace ServerApp.Parser.OutputInfo { /// <summary> /// Weather conditions in regards to sun level /// </summary> - /// <author>Alex Konig</author> + /// <author>A. Konig</author> public enum WeatherConditions { Sunny, Cloudy, Overcast, Dark } - - /// <summary> - /// Transfers lux values to weather conditions and vice versa - /// </summary> - /// <author>Alex Konig</author> - public static class ValueToConditions - { - /// <summary> - /// Lux to weather conditions - /// </summary> - /// <param name="lux">Lux value</param> - /// <returns>Weather conditions</returns> - public static WeatherConditions TransferLuxToConditions(double lux) - { - if (lux > 40_000) - return WeatherConditions.Sunny; - - if (lux > 20_000) - return WeatherConditions.Cloudy; - - // TODO tohle bylo 10_000, jak mi to má vycházet, zkusit na hourly data - if (lux != 0) - return WeatherConditions.Overcast; - - return WeatherConditions.Dark; - } - - /// <summary> - /// Weather conditions to average lux - /// </summary> - /// <param name="condition">Weather conditions</param> - /// <returns>Lux value</returns> - internal static double TransferConditionsToLux(WeatherConditions condition) - { - if (condition == WeatherConditions.Sunny) - return 60_000; - - if (condition == WeatherConditions.Cloudy) - return 30_000; - - if (condition == WeatherConditions.Overcast) - return 10_000; - - if (condition == WeatherConditions.Dark) - return 0; - - return -1; - } - - internal static WeatherConditions CloudCoverToConditions(int cloudCover) - { - if (cloudCover >= 66) - return WeatherConditions.Overcast; - - if (cloudCover >= 33) - return WeatherConditions.Cloudy; - - if (cloudCover >= 0) - return WeatherConditions.Sunny; - - return WeatherConditions.Dark; - } - } } \ No newline at end of file diff --git a/Server/ServerApp/Parser/OutputInfo/WeatherInfo.cs b/Server/ServerApp/Parser/OutputInfo/WeatherInfo.cs index 3db029c..52d70cd 100644 --- a/Server/ServerApp/Parser/OutputInfo/WeatherInfo.cs +++ b/Server/ServerApp/Parser/OutputInfo/WeatherInfo.cs @@ -1,4 +1,8 @@ -using System; +// +// Author: A. Konig +// + +using System; namespace ServerApp.Parser.OutputInfo { @@ -6,7 +10,7 @@ namespace ServerApp.Parser.OutputInfo /// Class representing the weather in a given interval at ZCU /// - shortest possible interval is 1h /// </summary> - /// <author>Alex Konig</author> + /// <author>A. Konig</author> class WeatherInfo { /// <summary> Temperature in °C </summary> diff --git a/Server/ServerApp/Parser/Parsers/DataParser.cs b/Server/ServerApp/Parser/Parsers/DataParser.cs index 015ddf3..48bd17a 100644 --- a/Server/ServerApp/Parser/Parsers/DataParser.cs +++ b/Server/ServerApp/Parser/Parsers/DataParser.cs @@ -1,4 +1,9 @@ -using ServerApp.Parser.InputData; +// +// Author: A. Konig +// + +using ServerApp.DataDownload; +using ServerApp.Parser.InputData; using ServerApp.Parser.OutputInfo; using System; using System.Collections.Generic; @@ -11,11 +16,12 @@ namespace ServerApp.Parser.Parsers /// Class parsing data files into instances of ActivityInfo and WeatherInfo divided by given time interval /// Data parsed from 7am (included) to 18pm (included) /// </summary> - /// <author>Alex Konig</author> - class DataParser + /// <author>A. Konig</author> + class DataParser : IDataParser { - /// <summary> Path to data folder </summary> - string path; + /// <summary> Data downloader </summary> + DataDownloader downloader; + /// <summary> Weather data parser </summary> WeatherParser weatherParser; /// <summary> Jis data parser </summary> @@ -25,26 +31,27 @@ namespace ServerApp.Parser.Parsers /// <summary> WeatherInfo </summary> List<WeatherInfo> weatherList; - public List<WeatherInfo> WeatherList { get => weatherList; } + public new List<WeatherInfo> WeatherList { get => weatherList; } /// <summary> ActivityInfo repersenting overall activity </summary> List<ActivityInfo> attendanceList; - public List<ActivityInfo> AttendanceList { get => attendanceList; } + public new List<ActivityInfo> AttendanceList { get => attendanceList; } /// <summary> ActivityInfo representing jis activity </summary> List<ActivityInfo> jisList; /// <summary> ActivityInfo representing login activity</summary> List<ActivityInfo> loginList; + /// <summary> /// Constructor /// </summary> - public DataParser(string path) + public DataParser(DataDownloader downloader) { + this.downloader = downloader; + TagInfo.CreateDictionaries(); - // TODO ask for data folder - this.path = path; - DataLoader loader = new CsvDataLoader(); + IDataLoader loader = new CsvDataLoader(); weatherParser = new WeatherParser(loader); jisParser = new JisParser(loader); @@ -56,26 +63,35 @@ namespace ServerApp.Parser.Parsers /// </summary> /// <param name="interval">Length of an interval</param> /// <param name="wholeDay">Parse data as one instance per day</param> - public bool Parse(DateTime startTime, DateTime endTime, int interval = 1, bool wholeDay = true) + /// <param name="endTime">End time of related data</param> + /// <param name="startTime">Start time of related data</param> + override public bool Parse(DateTime startTime, DateTime endTime, int interval = 1, bool wholeDay = true) { - // 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) var cultureInfo = CultureInfo.GetCultureInfo("en-GB"); Thread.CurrentThread.CurrentCulture = cultureInfo; Thread.CurrentThread.CurrentUICulture = cultureInfo; - string pathWeather = path + "weather"; - string pathJis = path + "jis"; - string pathLogIn = path + "login"; + // get path to folder w/ datafiles + string pathWeather = downloader.DataSubDirectories[DataType.POCASI]; // path + "weather"; + string pathJis = downloader.DataSubDirectories[DataType.JIS]; // path + "jis"; + string pathLogIn = downloader.DataSubDirectories[DataType.STROJE]; // path + "login"; + + // get all files that should be parsed + Date start = new Date((uint)startTime.Month, (uint)startTime.Year); + Date end = new Date((uint)endTime.Month, (uint)endTime.Year); + var weatherFiles = downloader.GetData(pathWeather, start, end); + var jisFiles = downloader.GetData(pathJis, start, end); + var loginFiles = downloader.GetData(pathLogIn, start, end); - weatherList = weatherParser.ParseWeatherData(pathWeather, wholeDay, interval); - jisList = jisParser.ParseJisData(pathJis, wholeDay, interval); - loginList = loginParser.ParseLogInData(pathLogIn, wholeDay, interval); + weatherList = weatherParser.ParseWeatherData(weatherFiles, startTime, endTime, wholeDay, interval); + jisList = jisParser.ParseJisData(jisFiles, startTime, endTime, wholeDay, interval); + loginList = loginParser.ParseLogInData(loginFiles, startTime, endTime, wholeDay, interval); //Console.WriteLine("WEATHER"); //WriteToConsole(weatherList); - //Console.WriteLine("JIS"); - //WriteToConsole(jisList); + Console.WriteLine("JIS"); + WriteToConsole(jisList); //Console.WriteLine("LOGIN"); //WriteToConsole(loginList); @@ -83,8 +99,8 @@ namespace ServerApp.Parser.Parsers MergeAttendance(); - //Console.WriteLine("MERGED IN ONE LIST"); - //WriteToConsole(attendanceList); + Console.WriteLine("MERGED IN ONE LIST"); + WriteToConsole(attendanceList); if (weatherList.Count == 0 || attendanceList.Count == 0) return false; diff --git a/Server/ServerApp/Parser/Parsers/IDataParser.cs b/Server/ServerApp/Parser/Parsers/IDataParser.cs new file mode 100644 index 0000000..a4d7fb8 --- /dev/null +++ b/Server/ServerApp/Parser/Parsers/IDataParser.cs @@ -0,0 +1,34 @@ +// +// Author: A. Konig +// + +using ServerApp.Parser.OutputInfo; +using System; +using System.Collections.Generic; + +namespace ServerApp.Parser.Parsers +{ + /// <summary> + /// Abstract class that every DataParser should inherit from + /// </summary> + /// <author>A. Konig</author> + abstract class IDataParser + { + /// <summary> WeatherInfo </summary> + List<WeatherInfo> weatherList; + public List<WeatherInfo> WeatherList { get => weatherList; } + /// <summary> ActivityInfo repersenting overall activity </summary> + List<ActivityInfo> attendanceList; + public List<ActivityInfo> AttendanceList { get => attendanceList; } + + /// <summary> + /// Parse data + /// </summary> + /// <param name="interval">Length of an interval</param> + /// <param name="wholeDay">Parse data as one instance per day</param> + /// <param name="endTime">End time of related data</param> + /// <param name="startTime">Start time of related data</param> + public abstract bool Parse(DateTime startTime, DateTime endTime, int interval = 1, bool wholeDay = true); + + } +} diff --git a/Server/ServerApp/Parser/Parsers/JisParser.cs b/Server/ServerApp/Parser/Parsers/JisParser.cs index ef13593..1a2914d 100644 --- a/Server/ServerApp/Parser/Parsers/JisParser.cs +++ b/Server/ServerApp/Parser/Parsers/JisParser.cs @@ -1,4 +1,8 @@ -using System; +// +// Author: A. Konig +// + +using System; using System.Collections.Generic; using System.IO; using ServerApp.Parser.InputData; @@ -10,18 +14,18 @@ namespace ServerApp.Parser.Parsers /// Class parsing jis files into instances of ActivityInfo divided by given time interval /// Data parsed from 7am (included) to 18pm (included) /// </summary> - /// <author>Alex Konig</author> + /// <author>A. Konig</author> class JisParser { /// <summary> Datafile loader </summary> - DataLoader loader; + IDataLoader loader; /// <summary> /// Constructor /// </summary> /// <param name="loader">Datafile loader</param> - public JisParser(DataLoader loader) + public JisParser(IDataLoader loader) { this.loader = loader; } @@ -30,29 +34,32 @@ namespace ServerApp.Parser.Parsers /// Parses jis data to ActivityInfo instances /// Data parsed from 7am (included) to 18pm (included) /// </summary> - /// <param name="folder">Folder with login data files</param> + /// <param name="jisFiles">Paths to files with login data files</param> + /// <param name="endTime">End time of related data</param> + /// <param name="startTime">Start time of related data</param> /// <param name="wholeDay">Should data be parsed as one instance per day (if true parameter interval will be ignored)</param> /// <param name="interval">Time interval to divide days by, minimum is 1h</param> /// <returns></returns> - public List<ActivityInfo> ParseJisData(string folder, bool wholeDay = true, int interval = 1) + public List<ActivityInfo> ParseJisData(List<string> jisFiles, DateTime startTime, DateTime endTime, bool wholeDay = true, int interval = 1) { - if (!Directory.Exists(folder)) - return null; - List<ActivityInfo> list = new List<ActivityInfo>(); + if (jisFiles == null || startTime == null || endTime == null || interval <= 0) + return list; + // parse all files - string[] fileEntries = Directory.GetFiles(folder); - foreach (string fileName in fileEntries) + foreach (string fileName in jisFiles) { - List<ActivityInfo> loadedData = null; - + if (!File.Exists(fileName)) + continue; + // parse as one instance per day + List<ActivityInfo> loadedData = null; if (wholeDay) - loadedData = ProcessOneJisFileAsDays(fileName); + loadedData = ProcessOneJisFileAsDays(fileName, startTime, endTime); // parse by interval length else - loadedData = ProcessOneJisFileAsIntervals(fileName, interval); + loadedData = ProcessOneJisFileAsIntervals(fileName, interval, startTime, endTime); list.AddRange(loadedData); } @@ -63,14 +70,17 @@ namespace ServerApp.Parser.Parsers /// <summary> /// Parses data from one data file as one instance per day /// </summary> - /// <param name="path">Path ti file</param> + /// <param name="path">Path to file</param> + /// <param name="endTime">End time of related data</param> + /// <param name="startTime">Start time of related data</param> /// <returns>List with ActivityInfo instances</returns> - private List<ActivityInfo> ProcessOneJisFileAsDays(string path) + private List<ActivityInfo> ProcessOneJisFileAsDays(string path, DateTime startTime, DateTime endTime) { + List<ActivityInfo> jisInfo = new List<ActivityInfo>(); + if (!File.Exists(path)) - return null; + return jisInfo; - List<ActivityInfo> jisInfo = new List<ActivityInfo>(); List<JisInstance> list = loader.LoadJisFile(path); // data for each faculty @@ -104,6 +114,10 @@ namespace ServerApp.Parser.Parsers lastStartTime = date; } + // if not in allowed time window -> discard + if (list[i].dateTime < startTime || list[i].dateTime > endTime) + continue; + // aggregate data if (TagInfo.jisPlaces.ContainsKey(place)) { @@ -138,13 +152,16 @@ namespace ServerApp.Parser.Parsers /// </summary> /// <param name="path">Path ti file</param> /// <param name="interval">Interval length</param> + /// <param name="endTime">End time of related data</param> + /// <param name="startTime">Start time of related data</param> /// <returns>List with ActivityInfo instances</returns> - private List<ActivityInfo> ProcessOneJisFileAsIntervals(string path, int interval) + private List<ActivityInfo> ProcessOneJisFileAsIntervals(string path, int interval, DateTime startTime, DateTime endTime) { + List<ActivityInfo> jisInfo = new List<ActivityInfo>(); + if (!File.Exists(path)) - return null; + return jisInfo; - List<ActivityInfo> jisInfo = new List<ActivityInfo>(); List<JisInstance> list = loader.LoadJisFile(path); // data for each faculty @@ -164,7 +181,7 @@ namespace ServerApp.Parser.Parsers // first day DateTime lastStartTime = new DateTime(list[0].dateTime.Year, list[0].dateTime.Month, list[0].dateTime.Day, minmaxHour[0], 0, 0); int endtime = to[0]; - int startTime = minmaxHour[0]; + int startingTime = minmaxHour[0]; int index = 0; for (int i = 0; i < list.Count; i++) { @@ -188,7 +205,7 @@ namespace ServerApp.Parser.Parsers if ( date.Hour >= endtime || trigger) { // start time of last interval - DateTime stTime = new DateTime(lastStartTime.Year, lastStartTime.Month, lastStartTime.Day, startTime, 0, 0); + DateTime stTime = new DateTime(lastStartTime.Year, lastStartTime.Month, lastStartTime.Day, startingTime, 0, 0); // find end and start time if (!trigger) @@ -198,9 +215,9 @@ namespace ServerApp.Parser.Parsers endtime = to[index]; if (index == 0) - startTime = minmaxHour[0]; + startingTime = minmaxHour[0]; else - startTime = to[index - 1]; + startingTime = to[index - 1]; // data for each faculty separate for (int k = 0; k < TagInfo.buildings.Length; k++) @@ -213,6 +230,10 @@ namespace ServerApp.Parser.Parsers lastStartTime = date; } + // if not in allowed time window -> discard + if (list[i].dateTime < startTime || list[i].dateTime > endTime) + continue; + // aggregate data if (TagInfo.jisPlaces.ContainsKey(place)) { diff --git a/Server/ServerApp/Parser/Parsers/LogInParser.cs b/Server/ServerApp/Parser/Parsers/LogInParser.cs index d78c8a6..32e53a2 100644 --- a/Server/ServerApp/Parser/Parsers/LogInParser.cs +++ b/Server/ServerApp/Parser/Parsers/LogInParser.cs @@ -1,4 +1,8 @@ -using ServerApp.Parser.InputData; +// +// Author: A. Konig +// + +using ServerApp.Parser.InputData; using ServerApp.Parser.OutputInfo; using System; using System.Collections.Generic; @@ -10,17 +14,17 @@ namespace ServerApp.Parser.Parsers /// Class parsing login files into instances of ActivityInfo divided by given time interval /// Data parsed from 7am (included) to 18pm (included) /// </summary> - /// <author>Alex Konig</author> + /// <author>A. Konig</author> class LogInParser { /// <summary> Datafile loader </summary> - DataLoader loader; + IDataLoader loader; /// <summary> /// Constructor /// </summary> /// <param name="loader">Datafile loader</param> - public LogInParser(DataLoader loader) + public LogInParser(IDataLoader loader) { this.loader = loader; } @@ -29,29 +33,32 @@ namespace ServerApp.Parser.Parsers /// Parses login data to ActivityInfo instances /// Data parsed from 7am (included) to 18pm (included) /// </summary> - /// <param name="folder">Folder with login data files</param> + /// <param name="loginFiles">Paths to files with login data files</param> + /// <param name="endTime">End time of related data</param> + /// <param name="startTime">Start time of related data</param> /// <param name="wholeDay">Should data be parsed as one instance per day (if true parameter interval will be ignored)</param> /// <param name="interval">Time interval to divide days by, minimum is 1h</param> /// <returns></returns> - public List<ActivityInfo> ParseLogInData(string folder, bool wholeDay = true, int interval = 1) + public List<ActivityInfo> ParseLogInData(List<string> loginFiles, DateTime startTime, DateTime endTime, bool wholeDay = true, int interval = 1) { - if (!Directory.Exists(folder)) - return null; - List<ActivityInfo> list = new List<ActivityInfo>(); - // get all files in folder - string[] fileEntries = Directory.GetFiles(folder); - foreach (string fileName in fileEntries) + if (loginFiles == null || startTime == null || endTime == null || interval <= 0) + return list; + + // for all files in folder + foreach (string fileName in loginFiles) { - List<ActivityInfo> loadedData = null; + if (!File.Exists(fileName)) + continue; // parse as one instance per day + List<ActivityInfo> loadedData = null; if (wholeDay) - loadedData = ProcessOneLogInFileAsDays(fileName); + loadedData = ProcessOneLogInFileAsDays(fileName, startTime, endTime); // parse by interval length else - loadedData = ProcessOneLoginFileAsIntervals(fileName, interval); + loadedData = ProcessOneLoginFileAsIntervals(fileName, interval, startTime, endTime); list.AddRange(loadedData); } @@ -63,13 +70,16 @@ namespace ServerApp.Parser.Parsers /// Parses data from one data file as one instance per day /// </summary> /// <param name="path">Path ti file</param> + /// <param name="endTime">End time of related data</param> + /// <param name="startTime">Start time of related data</param> /// <returns>List with ActivityInfo instances</returns> - private List<ActivityInfo> ProcessOneLogInFileAsDays(string path) + private List<ActivityInfo> ProcessOneLogInFileAsDays(string path, DateTime startTime, DateTime endTime) { + List<ActivityInfo> loginInfo = new List<ActivityInfo>(); + if (!File.Exists(path)) - return null; + return loginInfo; - List<ActivityInfo> loginInfo = new List<ActivityInfo>(); List<LogInInstance> list = loader.LoadLoginFile(path); // data for each faculty @@ -103,6 +113,10 @@ namespace ServerApp.Parser.Parsers lastStartDay = date; } + // if not in allowed time window -> discard + if (list[i].date < startTime || list[i].date > endTime) + continue; + // aggregate data if (TagInfo.buildingTags.ContainsKey(place)) { @@ -140,13 +154,16 @@ namespace ServerApp.Parser.Parsers /// </summary> /// <param name="path">Path to file</param> /// <param name="interval">Interval length</param> + /// <param name="endTime">End time of related data</param> + /// <param name="startTime">Start time of related data</param> /// <returns>List with ActivityInfo instances</returns> - private List<ActivityInfo> ProcessOneLoginFileAsIntervals(string path, int interval) + private List<ActivityInfo> ProcessOneLoginFileAsIntervals(string path, int interval, DateTime startTime, DateTime endTime) { + List<ActivityInfo> loginInfo = new List<ActivityInfo>(); + if (!File.Exists(path)) - return null; + return loginInfo; - List<ActivityInfo> loignInfo = new List<ActivityInfo>(); List<LogInInstance> list = loader.LoadLoginFile(path); // min/max hour taken into account @@ -190,7 +207,7 @@ namespace ServerApp.Parser.Parsers for (int l = 0; l < TagInfo.buildings.Length; l++) { ActivityInfo dayInfo = new ActivityInfo(TagInfo.buildings[l], data[k][l], stTime, interval); - loignInfo.Add(dayInfo); + loginInfo.Add(dayInfo); } data[k] = new int[TagInfo.buildings.Length]; @@ -198,6 +215,10 @@ namespace ServerApp.Parser.Parsers lastStartTime = date; } + // if not in allowed time window -> discard + if (list[i].date < startTime || list[i].date > endTime) + continue; + // find index for current instance index = 0; for (int k = 1; k < to.Length; k++) @@ -243,11 +264,11 @@ namespace ServerApp.Parser.Parsers for (int l = 0; l < TagInfo.buildings.Length; l++) { ActivityInfo dayInfo = new ActivityInfo(TagInfo.buildings[l], data[k][l], stTime, interval); - loignInfo.Add(dayInfo); + loginInfo.Add(dayInfo); } } - return loignInfo; + return loginInfo; } } diff --git a/Server/ServerApp/Parser/Parsers/TagInfo.cs b/Server/ServerApp/Parser/Parsers/TagInfo.cs index 85c8fc4..da5006b 100644 --- a/Server/ServerApp/Parser/Parsers/TagInfo.cs +++ b/Server/ServerApp/Parser/Parsers/TagInfo.cs @@ -1,9 +1,14 @@ -using System.Collections.Generic; +// +// Author: A. Konig +// -// 30min +using System.Collections.Generic; namespace ServerApp.Parser.Parsers { + /// <summary> + /// Class with Tags used in application + /// </summary> /// <author>Alex Konig</author> class TagInfo { diff --git a/Server/ServerApp/Parser/Parsers/WeatherParser.cs b/Server/ServerApp/Parser/Parsers/WeatherParser.cs index 4d39eda..f8754a1 100644 --- a/Server/ServerApp/Parser/Parsers/WeatherParser.cs +++ b/Server/ServerApp/Parser/Parsers/WeatherParser.cs @@ -1,4 +1,8 @@ -using ServerApp.Parser.InputData; +// +// Author: A. Konig +// + +using ServerApp.Parser.InputData; using ServerApp.Parser.OutputInfo; using System; using System.Collections.Generic; @@ -10,18 +14,18 @@ namespace ServerApp.Parser.Parsers /// Class parsing weather files into instances of WeatherInfo divided by given time interval /// Data parsed from 7am (included) to 18pm (included) /// </summary> - /// <author>Alex Konig</author> + /// <author>A. Konig</author> class WeatherParser { /// <summary> Datafile loader </summary> - DataLoader loader; + IDataLoader loader; /// <summary> /// Constructor /// </summary> /// <param name="loader">Datafile loader</param> - public WeatherParser(DataLoader loader) + public WeatherParser(IDataLoader loader) { this.loader = loader; } @@ -30,30 +34,33 @@ namespace ServerApp.Parser.Parsers /// Parses weather data to WeatherInfo instances /// Data parsed from 7am (included) to 18pm (included) /// </summary> - /// <param name="folder">Folder with weather data files</param> + /// <param name="weatherFiles">Paths to files with weather data files</param> + /// <param name="endTime">End time of related data</param> + /// <param name="startTime">Start time of related data</param> /// <param name="wholeDay">Should data be parsed as one instance per day (if true parameter interval will be ignored)</param> /// <param name="interval">Time interval to divide days by, minimum is 1h</param> /// <returns></returns> - public List<WeatherInfo> ParseWeatherData(string folder, bool wholeDay = true, int interval = 1) + public List<WeatherInfo> ParseWeatherData(List<string> weatherFiles, DateTime startTime, DateTime endTime, bool wholeDay = true, int interval = 1) { - if (!Directory.Exists(folder)) - return null; - List<WeatherInfo> list = new List<WeatherInfo>(); + if (weatherFiles == null || startTime == null || endTime == null || interval <= 0) + return list; + // get all files in folder - string[] fileEntries = Directory.GetFiles(folder); - foreach (string fileName in fileEntries) + foreach (string fileName in weatherFiles) { - List<WeatherInfo> loadedData = null; - + if (!File.Exists(fileName)) + continue; + // parse as one instance per day + List<WeatherInfo> loadedData = null; if (wholeDay) - loadedData = ProcessOneWeatherFileAsDays(fileName); + loadedData = ProcessOneWeatherFileAsDays(fileName, startTime, endTime); // parse according to interval else { - loadedData = ProcessOneWeatherFileAsIntervals(fileName, interval); + loadedData = ProcessOneWeatherFileAsIntervals(fileName, interval, startTime, endTime); } list.AddRange(loadedData); @@ -66,13 +73,16 @@ namespace ServerApp.Parser.Parsers /// Parses data from one data file as one instance per day /// </summary> /// <param name="path">Path ti file</param> + /// <param name="endTime">End time of related data</param> + /// <param name="startTime">Start time of related data</param> /// <returns>List with WeatherInfo instances</returns> - private List<WeatherInfo> ProcessOneWeatherFileAsDays(string path) + private List<WeatherInfo> ProcessOneWeatherFileAsDays(string path, DateTime startTime, DateTime endTime) { + List<WeatherInfo> weatherInfo = new List<WeatherInfo>(); + if (!File.Exists(path)) - return null; + return weatherInfo; - List<WeatherInfo> weatherInfo = new List<WeatherInfo>(); List<WeatherInstance> list = loader.LoadWeatherFile(path); // array with data [temp, rain, wind, lum] @@ -105,6 +115,10 @@ namespace ServerApp.Parser.Parsers weatherValues = 0; } + // if not in allowed time window -> discard + if (list[i].dateTime < startTime|| list[i].dateTime > endTime) + continue; + // aggregate data recordedAmount[0] += list[i].temp; recordedAmount[1] += list[i].rain; @@ -128,13 +142,16 @@ namespace ServerApp.Parser.Parsers /// </summary> /// <param name="path">Path to file</param> /// <param name="interval">Interval length</param> + /// <param name="endTime">End time of related data</param> + /// <param name="startTime">Start time of related data</param> /// <returns>List with ActivityInfo instances</returns> - private List<WeatherInfo> ProcessOneWeatherFileAsIntervals(string path, int interval) + private List<WeatherInfo> ProcessOneWeatherFileAsIntervals(string path, int interval, DateTime startTime, DateTime endTime) { + List<WeatherInfo> weatherInfo = new List<WeatherInfo>(); + if (!File.Exists(path)) - return null; + return weatherInfo; - List<WeatherInfo> loignInfo = new List<WeatherInfo>(); List<WeatherInstance> list = loader.LoadWeatherFile(path); // min/max hour taken into account @@ -184,7 +201,7 @@ namespace ServerApp.Parser.Parsers 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); if (count[k] != 0) - loignInfo.Add(intervalInfo); + weatherInfo.Add(intervalInfo); } @@ -194,6 +211,10 @@ namespace ServerApp.Parser.Parsers data[l] = new double[4]; } + // if not in allowed time window -> discard + if (list[i].dateTime < startTime || list[i].dateTime > endTime) + continue; + // find index for current instance index = 0; for (int k = 1; k < to.Length; k++) @@ -228,10 +249,10 @@ namespace ServerApp.Parser.Parsers 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); if (count[k] != 0) - loignInfo.Add(intervalInfo); + weatherInfo.Add(intervalInfo); } - return loignInfo; + return weatherInfo; } } diff --git a/Server/ServerApp/Program.cs b/Server/ServerApp/Program.cs index 61a67ce..745b356 100644 --- a/Server/ServerApp/Program.cs +++ b/Server/ServerApp/Program.cs @@ -3,6 +3,7 @@ using ServerApp.DataDownload; using ServerApp.Parser.Parsers; using ServerApp.Predictor; using ServerApp.User; +using ServerApp.WeatherPredictionParser; using System; using System.Collections.Generic; using System.IO; @@ -30,10 +31,7 @@ namespace ServerApp static void Main(string[] args) { - JsonParser p = new JsonParser(null); - p.ParsePrediction(); - - /* + // SETUP FOLDERS Config config = FillConfigInfo(args); if (config == null) @@ -42,15 +40,11 @@ namespace ServerApp return; } + /* //create a thread for commands accepting: Thread inputThread = new Thread(CommandsAcceptor.AcceptCommand); inputThread.Start(); - - - - //DataParser p = new DataParser("data/"); - //p.Parse(); - + */ //test scenario -data download: DataDownloader dd = new DataDownloader(config.DataRootDir, config.DataWebsite, config.DownloadedFilesNaming); @@ -60,8 +54,6 @@ namespace ServerApp savedFiles.AddRange(dd.DownloadData(DataType.STROJE, DataFormat.CSV, new Date(1, 2017), new Date(12, 2020))); savedFiles.AddRange(dd.DownloadData(DataType.POCASI, DataFormat.CSV, new Date(1, 2017), new Date(12, 2020))); - - Console.WriteLine("Saved files: "); foreach (string s in savedFiles) { @@ -74,6 +66,8 @@ namespace ServerApp Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value); } + /* + List<string> retrievedData = dd.GetData(dd.DataSubDirectories[DataType.JIS], new Date(10, 2019), new Date(12, 2020)); Console.WriteLine("Retrieved data: "); foreach (string s in retrievedData) @@ -82,6 +76,19 @@ namespace ServerApp } */ + // PARSE DATA + + + JsonParser jsonP = new JsonParser(null); + jsonP.ParsePrediction(); + + // TODO nastavit čas + DataParser p = new DataParser(dd); + DateTime startT = new DateTime(2019, 10, 5); + DateTime endT = new DateTime(2020, 6, 30); + p.Parse(startT, endT, wholeDay: false, interval: 3); + + // test - connection: //ConnectionListener cl = new ConnectionListener(int.Parse(args[0])/*8000*//*int.Parse(config.Port)*/); //cl.StartListening(); diff --git a/Server/ServerApp/ServerApp.csproj b/Server/ServerApp/ServerApp.csproj index 20bcfd6..1ca848d 100644 --- a/Server/ServerApp/ServerApp.csproj +++ b/Server/ServerApp/ServerApp.csproj @@ -16,6 +16,21 @@ <Deterministic>true</Deterministic> <NuGetPackageImportStamp> </NuGetPackageImportStamp> + <PublishUrl>publish\</PublishUrl> + <Install>true</Install> + <InstallFrom>Disk</InstallFrom> + <UpdateEnabled>false</UpdateEnabled> + <UpdateMode>Foreground</UpdateMode> + <UpdateInterval>7</UpdateInterval> + <UpdateIntervalUnits>Days</UpdateIntervalUnits> + <UpdatePeriodically>false</UpdatePeriodically> + <UpdateRequired>false</UpdateRequired> + <MapFileExtensions>true</MapFileExtensions> + <ApplicationRevision>0</ApplicationRevision> + <ApplicationVersion>1.0.0.%2a</ApplicationVersion> + <IsWebBootstrapper>false</IsWebBootstrapper> + <UseApplicationTrust>false</UseApplicationTrust> + <BootstrapperEnabled>true</BootstrapperEnabled> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PlatformTarget>AnyCPU</PlatformTarget> @@ -146,7 +161,7 @@ <Compile Include="DataDownload\DataDownloader.cs" /> <Compile Include="DataDownload\Date.cs" /> <Compile Include="Parser\InputData\CsvDataLoader.cs" /> - <Compile Include="Parser\InputData\DataLoader.cs" /> + <Compile Include="Parser\InputData\IDataLoader.cs" /> <Compile Include="Parser\InputData\JisInstance.cs" /> <Compile Include="Parser\InputData\LogInInstance.cs" /> <Compile Include="Parser\InputData\WeatherInstance.cs" /> @@ -154,8 +169,9 @@ <Compile Include="Parser\OutputInfo\WeatherConditions.cs" /> <Compile Include="Parser\OutputInfo\WeatherInfo.cs" /> <Compile Include="Parser\Parsers\DataParser.cs" /> + <Compile Include="Parser\Parsers\IDataParser.cs" /> <Compile Include="Parser\Parsers\JisParser.cs" /> - <Compile Include="Parser\Parsers\JsonParser.cs" /> + <Compile Include="WeatherPredictionParser\JsonParser.cs" /> <Compile Include="Parser\Parsers\LogInParser.cs" /> <Compile Include="Parser\Parsers\TagInfo.cs" /> <Compile Include="Parser\Parsers\WeatherParser.cs" /> @@ -208,6 +224,18 @@ <ItemGroup> <Folder Include="data\auto\" /> </ItemGroup> + <ItemGroup> + <BootstrapperPackage Include=".NETFramework,Version=v4.7.2"> + <Visible>False</Visible> + <ProductName>Microsoft .NET Framework 4.7.2 %28x86 and x64%29</ProductName> + <Install>true</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1</ProductName> + <Install>false</Install> + </BootstrapperPackage> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <PropertyGroup> diff --git a/Server/ServerApp/WeatherPredictionParser/IJsonParser.cs b/Server/ServerApp/WeatherPredictionParser/IJsonParser.cs new file mode 100644 index 0000000..31c8058 --- /dev/null +++ b/Server/ServerApp/WeatherPredictionParser/IJsonParser.cs @@ -0,0 +1,32 @@ +// +// Author: A. Konig +// + +using ServerApp.Parser.OutputInfo; +using System.Collections.Generic; + +namespace ServerApp.WeatherPredictionParser +{ + /// <summary> + /// Abstract class that every Json parser should inherit from + /// </summary> + abstract class IJsonParser + { + + /// <summary> Current weather </summary> + WeatherInfo current; + public WeatherInfo Current { get => current; } + + /// <summary> Prediction for today, tommorrow and day after tommorrow </summary> + List<WeatherInfo> predictions; + public List<WeatherInfo> Predictions { get => predictions; set => predictions = value; } + + /// <summary> + /// Parse weather prediction + /// Results is in attributes current for current weather and pred for weather prediction for today, tommorrow and day after tommorrow + /// </summary> + abstract public void ParsePrediction(); + + } + +} diff --git a/Server/ServerApp/Parser/Parsers/JsonParser.cs b/Server/ServerApp/WeatherPredictionParser/JsonParser.cs similarity index 96% rename from Server/ServerApp/Parser/Parsers/JsonParser.cs rename to Server/ServerApp/WeatherPredictionParser/JsonParser.cs index ac3b029..e9a7c42 100644 --- a/Server/ServerApp/Parser/Parsers/JsonParser.cs +++ b/Server/ServerApp/WeatherPredictionParser/JsonParser.cs @@ -1,4 +1,8 @@ -using ServerApp.DataDownload; +// +// Author: A. Konig +// + +using ServerApp.DataDownload; using ServerApp.Parser.OutputInfo; using System; using System.Collections.Generic; @@ -8,19 +12,21 @@ using System.Net; using System.Text.Json; using static System.Text.Json.JsonElement; -namespace ServerApp.Parser.Parsers +namespace ServerApp.WeatherPredictionParser { /// <summary> /// Class representing a parser for json prediction data /// </summary> /// <author>A. Konig</author> - class JsonParser + class JsonParser : IJsonParser { /// <summary> Current weather </summary> - public WeatherInfo current; + WeatherInfo current; + public new WeatherInfo Current { get => current; } /// <summary> Prediction for today, tommorrow and day after tommorrow </summary> - public List<WeatherInfo> predictions; - + List<WeatherInfo> predictions; + public new List<WeatherInfo> Predictions { get => predictions; set => predictions = value; } + /// <summary> Data loader </summary> DataDownloader loader; /// <summary> Currently parsed day </summary> @@ -30,6 +36,7 @@ namespace ServerApp.Parser.Parsers /// <summary> Sunset time of currently parsed day </summary> DateTime sunsetTime; + /// <summary> /// Constructor /// </summary> @@ -43,7 +50,7 @@ namespace ServerApp.Parser.Parsers /// Parse weather prediction /// Results is in attributes current for current weather and pred for weather prediction for today, tommorrow and day after tommorrow /// </summary> - public void ParsePrediction() + override public void ParsePrediction() { // TODO ask DataDownloader for download said file and return path to it @@ -52,13 +59,19 @@ namespace ServerApp.Parser.Parsers DateTime now = DateTime.Now; Console.WriteLine(File.Exists(file)); - // parse file + current = new WeatherInfo(); + predictions = new List<WeatherInfo>(); + + if (!File.Exists(file)) + return; + + // read file string data = File.ReadAllText(file); + // parse JsonDocument doc = JsonDocument.Parse(data); JsonElement root = doc.RootElement; var weatherP = root.EnumerateObject(); - predictions = new List<WeatherInfo>(); while (weatherP.MoveNext()) { @@ -93,6 +106,9 @@ namespace ServerApp.Parser.Parsers TestConsoleOutput(); } + /// <summary> + /// Test console output + /// </summary> private void TestConsoleOutput() { Console.WriteLine(current); -- GitLab From 9fb55c71802343d12fe75925472dfbbc6dc21e87 Mon Sep 17 00:00:00 2001 From: A-Konig <alex-nebulae@seznam.cz> Date: Fri, 14 May 2021 16:11:54 +0200 Subject: [PATCH 5/5] re #8840 Update commit - start/endTime in method Parse in DataParser can now be null --- Server/ServerApp/Parser/Parsers/DataParser.cs | 25 +++++++++++-------- Server/ServerApp/ServerApp.csproj | 2 ++ .../WeatherPredictionParser/JsonParser.cs | 3 +-- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/Server/ServerApp/Parser/Parsers/DataParser.cs b/Server/ServerApp/Parser/Parsers/DataParser.cs index 48bd17a..5313953 100644 --- a/Server/ServerApp/Parser/Parsers/DataParser.cs +++ b/Server/ServerApp/Parser/Parsers/DataParser.cs @@ -67,19 +67,24 @@ namespace ServerApp.Parser.Parsers /// <param name="startTime">Start time of related data</param> override public bool Parse(DateTime startTime, DateTime endTime, int interval = 1, bool wholeDay = true) { - var cultureInfo = CultureInfo.GetCultureInfo("en-GB"); Thread.CurrentThread.CurrentCulture = cultureInfo; Thread.CurrentThread.CurrentUICulture = cultureInfo; // get path to folder w/ datafiles - string pathWeather = downloader.DataSubDirectories[DataType.POCASI]; // path + "weather"; - string pathJis = downloader.DataSubDirectories[DataType.JIS]; // path + "jis"; - string pathLogIn = downloader.DataSubDirectories[DataType.STROJE]; // path + "login"; + string pathWeather = downloader.DataSubDirectories[DataType.POCASI]; + string pathJis = downloader.DataSubDirectories[DataType.JIS]; + string pathLogIn = downloader.DataSubDirectories[DataType.STROJE]; // get all files that should be parsed - Date start = new Date((uint)startTime.Month, (uint)startTime.Year); - Date end = new Date((uint)endTime.Month, (uint)endTime.Year); + Date start = null; + Date end = null; + if (startTime != null || endTime != null) + { + start = new Date((uint)startTime.Month, (uint)startTime.Year); + end = new Date((uint)endTime.Month, (uint)endTime.Year); + } + var weatherFiles = downloader.GetData(pathWeather, start, end); var jisFiles = downloader.GetData(pathJis, start, end); var loginFiles = downloader.GetData(pathLogIn, start, end); @@ -90,8 +95,8 @@ namespace ServerApp.Parser.Parsers //Console.WriteLine("WEATHER"); //WriteToConsole(weatherList); - Console.WriteLine("JIS"); - WriteToConsole(jisList); + //Console.WriteLine("JIS"); + //WriteToConsole(jisList); //Console.WriteLine("LOGIN"); //WriteToConsole(loginList); @@ -99,8 +104,8 @@ namespace ServerApp.Parser.Parsers MergeAttendance(); - Console.WriteLine("MERGED IN ONE LIST"); - WriteToConsole(attendanceList); + //Console.WriteLine("MERGED IN ONE LIST"); + //WriteToConsole(attendanceList); if (weatherList.Count == 0 || attendanceList.Count == 0) return false; diff --git a/Server/ServerApp/ServerApp.csproj b/Server/ServerApp/ServerApp.csproj index 1ca848d..ae3f3b6 100644 --- a/Server/ServerApp/ServerApp.csproj +++ b/Server/ServerApp/ServerApp.csproj @@ -166,11 +166,13 @@ <Compile Include="Parser\InputData\LogInInstance.cs" /> <Compile Include="Parser\InputData\WeatherInstance.cs" /> <Compile Include="Parser\OutputInfo\ActivityInfo.cs" /> + <Compile Include="Parser\OutputInfo\ValueToConditions.cs" /> <Compile Include="Parser\OutputInfo\WeatherConditions.cs" /> <Compile Include="Parser\OutputInfo\WeatherInfo.cs" /> <Compile Include="Parser\Parsers\DataParser.cs" /> <Compile Include="Parser\Parsers\IDataParser.cs" /> <Compile Include="Parser\Parsers\JisParser.cs" /> + <Compile Include="WeatherPredictionParser\IJsonParser.cs" /> <Compile Include="WeatherPredictionParser\JsonParser.cs" /> <Compile Include="Parser\Parsers\LogInParser.cs" /> <Compile Include="Parser\Parsers\TagInfo.cs" /> diff --git a/Server/ServerApp/WeatherPredictionParser/JsonParser.cs b/Server/ServerApp/WeatherPredictionParser/JsonParser.cs index e9a7c42..45b912b 100644 --- a/Server/ServerApp/WeatherPredictionParser/JsonParser.cs +++ b/Server/ServerApp/WeatherPredictionParser/JsonParser.cs @@ -87,7 +87,6 @@ namespace ServerApp.WeatherPredictionParser current = ParseCurrentWeather(currentWeather); break; - } // weather prediction case "weather": @@ -103,7 +102,7 @@ namespace ServerApp.WeatherPredictionParser // sunrise + sunset into data EncompassSunRiseSetTimes(); - TestConsoleOutput(); + //TestConsoleOutput(); } /// <summary> -- GitLab