From 08c521badd447cf4b00e9b4f89d7873b1c328153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eli=C5=A1ka=20Mourycov=C3=A1?= <eliska.mourycova@seznam.cz> Date: Sat, 12 Jun 2021 20:49:09 +0200 Subject: [PATCH 1/2] Re #9053. Added retrain implementation to the respective admin command. --- Server/ServerApp/User/CommandsAcceptor.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Server/ServerApp/User/CommandsAcceptor.cs b/Server/ServerApp/User/CommandsAcceptor.cs index ba0c7c8..476ebbb 100644 --- a/Server/ServerApp/User/CommandsAcceptor.cs +++ b/Server/ServerApp/User/CommandsAcceptor.cs @@ -204,7 +204,9 @@ namespace ServerApp.User } else if (c.FlagsAndData.ContainsKey("retrain")) { - + Console.WriteLine("Starting to retrain the predictor..."); + model.Train(); + Console.WriteLine("Predictor retrained."); } else if (c.FlagsAndData.ContainsKey("rollback")) { @@ -219,7 +221,7 @@ namespace ServerApp.User Console.WriteLine("No previous version of the predictor exists!"); break; case 2: - Console.WriteLine("Error occured while trying to perform rollback - corrupted or removed Predictor.config file!"); // todo? + Console.WriteLine("Error occured while trying to perform rollback - corrupted or removed Predictor.config file!"); break; default: Console.WriteLine("Unknown error occured when performing rollback."); -- GitLab From f7eb37b3f83305959b28009d56baa8b8847d231f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eli=C5=A1ka=20Mourycov=C3=A1?= <eliska.mourycova@seznam.cz> Date: Sun, 13 Jun 2021 12:45:50 +0200 Subject: [PATCH 2/2] Refactor + logging config modification --- Server/ServerApp/App.config | 1 - .../Connection/ConnectionListener.cs | 184 ++++++++++-------- Server/ServerApp/Program.cs | 88 +++++---- .../XMLComTests/XMLDateTesting.cs | 74 +++++++ 4 files changed, 229 insertions(+), 118 deletions(-) create mode 100644 Server/ServerAppFunctionalTests/XMLComTests/XMLDateTesting.cs diff --git a/Server/ServerApp/App.config b/Server/ServerApp/App.config index a13c70b..ef8b625 100644 --- a/Server/ServerApp/App.config +++ b/Server/ServerApp/App.config @@ -25,7 +25,6 @@ <root> <level value="ALL" /> <appender-ref ref="LogFileAppender" /> - <appender-ref ref="ConsoleAppender" /> </root> </log4net> </configuration> \ No newline at end of file diff --git a/Server/ServerApp/Connection/ConnectionListener.cs b/Server/ServerApp/Connection/ConnectionListener.cs index ee740aa..c28d18a 100644 --- a/Server/ServerApp/Connection/ConnectionListener.cs +++ b/Server/ServerApp/Connection/ConnectionListener.cs @@ -65,7 +65,7 @@ namespace ServerApp.Connection //Console.WriteLine("Listening..."); logger.Info("Started listening at ip: " + ip + ", port: " + PORT); - + Console.WriteLine("Server ready to receive requests."); var result = listener.BeginGetContext(ListenerCallback, listener); // result.AsyncWaitHandle.WaitOne(); // ???? @@ -80,80 +80,80 @@ namespace ServerApp.Connection } - private void HandleRequest(HttpListenerContext context) - { + //private void HandleRequest(HttpListenerContext context) + //{ - //Console.WriteLine("Handling request."); - logger.Debug("Handling request."); - // Obtain a request object. - HttpListenerRequest request = context.Request; - // Obtain a response object. - HttpListenerResponse response = context.Response; + // //Console.WriteLine("Handling request."); + // logger.Debug("Handling request."); + // // Obtain a request object. + // HttpListenerRequest request = context.Request; + // // Obtain a response object. + // HttpListenerResponse response = context.Response; - // add the headers and everything: - response.AddHeader("Access-Control-Allow-Credentials", "true"); - response.AddHeader("Access-Control-Expose-Headers", "ETag"); - response.AddHeader("Access-Control-Allow-Headers", "Accept, X-Access-Token, X-Application-Name, X-Request-Sent-Time"); - response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); - response.AddHeader("Access-Control-Allow-Origin", "*"); + // // add the headers and everything: + // response.AddHeader("Access-Control-Allow-Credentials", "true"); + // response.AddHeader("Access-Control-Expose-Headers", "ETag"); + // response.AddHeader("Access-Control-Allow-Headers", "Accept, X-Access-Token, X-Application-Name, X-Request-Sent-Time"); + // response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); + // response.AddHeader("Access-Control-Allow-Origin", "*"); - string responseString = ""; - // Construct a response. - if (context.Request.HttpMethod == "GET") // when client says download - { - logger.Info("received GET request"); + // string responseString = ""; + // // Construct a response. + // if (context.Request.HttpMethod == "GET") // when client says download + // { + // logger.Info("received GET request"); - string text; - using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding)) - text = reader.ReadToEnd(); - string requestString = HttpUtility.UrlDecode(text); + // string text; + // using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding)) + // text = reader.ReadToEnd(); + // string requestString = HttpUtility.UrlDecode(text); - responseString = ConstructGETResponse(requestString); + // responseString = ConstructGETResponse(requestString); - } - else if (context.Request.HttpMethod == "POST") // when client says upload - { - logger.Info("received POST request"); - string text; - using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding)) - text = reader.ReadToEnd(); - string requestString = HttpUtility.UrlDecode(text); + // } + // else if (context.Request.HttpMethod == "POST") // when client says upload + // { + // logger.Info("received POST request"); + // string text; + // using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding)) + // text = reader.ReadToEnd(); + // string requestString = HttpUtility.UrlDecode(text); - responseString = ConstructPOSTResponse(requestString); + // responseString = ConstructPOSTResponse(requestString); - } - else - { - logger.Warn("received request other than GET or POST"); + // } + // else + // { + // logger.Warn("received request other than GET or POST"); - } + // } - System.IO.Stream output = response.OutputStream; - if (!string.IsNullOrEmpty(responseString)) - { - logger.Debug("Response is not null or empty, sending it to the client."); - byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString); + // System.IO.Stream output = response.OutputStream; + // if (!string.IsNullOrEmpty(responseString)) + // { + // logger.Debug("Response is not null or empty, sending it to the client."); + // byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString); - // Get a response stream and write the response to it. - response.ContentLength64 = buffer.Length; - output.Write(buffer, 0, buffer.Length); - } - else - { - logger.Debug("Response was null or empty, not sending anything."); - } + // // Get a response stream and write the response to it. + // response.ContentLength64 = buffer.Length; + // output.Write(buffer, 0, buffer.Length); + // } + // else + // { + // logger.Debug("Response was null or empty, not sending anything."); + // } - // Close the output stream. - //output.Close(); - response.Close(); + // // Close the output stream. + // //output.Close(); + // response.Close(); - logger.Debug("At the end of HandleRequest"); - } + // logger.Debug("At the end of HandleRequest"); + //} /// <summary> /// The callnack method triggered when client request received @@ -250,20 +250,10 @@ namespace ServerApp.Connection /// <returns>The response string, empty if client's request doesn't follow protocol</returns> private string ConstructGETResponse(string requestString) { - //Console.WriteLine("Constructiing a response for GET request."); - - //int rand = new Random().Next(1, 10); - //string msg = "This is a response from the server :) " + rand; - - //Response xmlResp = Response.Randomize(); - //var xml = XmlCommunication.Serialize(xmlResp); - - //return xml; - logger.Info("Constructing a response for GET request."); - logger.Info("Request string: "); - logger.Info(requestString); + //logger.Info("Request string: "); + //logger.Info(requestString); @@ -288,10 +278,11 @@ namespace ServerApp.Connection logger.Info("Getting the prediction from the predictor."); logger.Debug("Deserialized request is null? : " + requestDeserialized == null); Response responsePrediction = predictionController.Predict(requestDeserialized); + string constructedXml = XmlCommunication.Serialize(responsePrediction); - logger.Info("Constructed response:"); - logger.Info(constructedXml); + //logger.Info("Constructed response:"); + //logger.Info(constructedXml); // build the xml from the prediction: - TODO mbe an exception can happen here as well? - it shouldnt return constructedXml;//XmlCommunication.Serialize(responsePrediction); @@ -307,8 +298,8 @@ namespace ServerApp.Connection private string ConstructPOSTResponse(string requestString) { logger.Info("Constructing a response for POST request."); - logger.Info("Request string: "); - logger.Info(requestString); + //logger.Info("Request string: "); + //logger.Info(requestString); @@ -322,7 +313,7 @@ namespace ServerApp.Connection } catch { - logger.Warn("wrong format of request!"); + logger.Warn("Wrong format of request!"); // don't bother to send anything: return string.Empty; @@ -336,8 +327,8 @@ namespace ServerApp.Connection string constructedXml = XmlCommunication.Serialize(responsePrediction); - logger.Info("Constructed response:"); - logger.Info(constructedXml); + //logger.Info("Constructed response:"); + //logger.Info(constructedXml); // build the xml from the prediction: - TODO mbe an exception can happen here as well? - it shouldnt return constructedXml;//XmlCommunication.Serialize(responsePrediction); @@ -346,6 +337,47 @@ namespace ServerApp.Connection } + + public XMLProtocolHandler.Date CheckTimeSpanModifyEnd(Date startDate, Date endDate, int maxTimeSpan) + { + int comp = startDate.CompareTo(endDate); // -1 if start date lower + + if (comp >= 0) + return endDate; + + // now we're in a situation where startDate is before endDate - check if span too much: + + + DateTime start = new DateTime(); + DateTime end = new DateTime(); + try + { + start = new DateTime(startDate.year, startDate.month, startDate.day); + end = new DateTime(endDate.year, endDate.month, endDate.day); + } + catch(ArgumentOutOfRangeException aore) + { + // hopefully the predictor will know what to do + return endDate; + } + + + int diff = (end - start).Days; + + if(diff > maxTimeSpan) + { + DateTime newEnd = start.AddDays(maxTimeSpan); + endDate.year = newEnd.Year; + endDate.month = newEnd.Month; + endDate.day = newEnd.Day; + + return endDate; + } + + + return endDate; + } + /// <summary> /// Gets the IPv4 IP of the machine /// </summary> diff --git a/Server/ServerApp/Program.cs b/Server/ServerApp/Program.cs index 63deb0a..e4d3040 100644 --- a/Server/ServerApp/Program.cs +++ b/Server/ServerApp/Program.cs @@ -1,4 +1,5 @@ -using log4net.Config; +using log4net; +using log4net.Config; using ServerApp.Connection; using ServerApp.Connection.XMLProtocolHandler; using ServerApp.DataDownload; @@ -27,9 +28,13 @@ namespace ServerApp public class Program { + // logger class instance + private static readonly ILog logger = LogManager.GetLogger(typeof(Program)); - static void Main(string[] args) + static void Main(string[] args) { + Console.WriteLine("Server start."); + // setup logging service XmlConfigurator.Configure(); @@ -41,9 +46,16 @@ namespace ServerApp Console.ReadLine(); return; } + Console.WriteLine("Config parsing successful."); + + //logger.Debug("ahoj"); + //logger.Warn("ahoj2"); + //Console.ReadLine(); - // data download test - DataDownloader dd = DataDownloadAndRetrievalTest(config); + // data download init + Console.WriteLine("Downloading open data..."); + DataDownloader dd = DataDownloaderInit(config); + Console.WriteLine("Data downloaded and saved."); //WeatherAsStringTest(dd); //Console.ReadLine(); @@ -51,17 +63,15 @@ namespace ServerApp // xml building test //XMLTest(); - // PARSE DATA - //DataParser parser = new DataParser(dd); - //parser.Parse(new DateTime()) // json parser test //JSONParserTest(); - // model test - IPredictionController controller = PredictionTest(dd); + // model init + Console.WriteLine("Training the predictor..."); + IPredictionController controller = PredictionControllerInit(dd); + Console.WriteLine("Predictor training finished."); - //parse(new DateTime(2019, 10, 5), , interval = 1, wholeDay = true) // commands accepting test // create a thread for commands accepting: @@ -70,14 +80,13 @@ namespace ServerApp inputThread.Start(); - // connection test - ConnectionTest(controller, config); + // connection init + ConnectionInit(controller, config); - //Console.ReadLine(); } - private static DataDownloader DataDownloadAndRetrievalTest(Config config) + private static DataDownloader DataDownloaderInit(Config config) { //test scenario -data download: DataDownloader dd = new DataDownloader(config.DataRootDir, config.DataWebsite, config.DownloadedFilesNaming, config.WeatherSite); @@ -91,30 +100,30 @@ namespace ServerApp - Console.WriteLine("Saved files: "); - foreach (string s in savedFiles) - { - Console.WriteLine(s); - } + //Console.WriteLine("Saved files: "); + //foreach (string s in savedFiles) + //{ + // Console.WriteLine(s); + //} - Console.WriteLine("subdirectories: "); - foreach (KeyValuePair<DataType, string> kvp in dd.DataSubDirectories) - { - Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value); - } + //Console.WriteLine("subdirectories: "); + //foreach (KeyValuePair<DataType, string> kvp in dd.DataSubDirectories) + //{ + // Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value); + //} - List<string> retrievedData = dd.GetData(dd.DataSubDirectories[DataType.JIS], new DataDownload.Date(10, 2019), new DataDownload.Date(12, 2020)); - Console.WriteLine("Retrieved data: "); - foreach (string s in retrievedData) - { - Console.WriteLine(s); - } - Console.WriteLine("all from directory:"); - retrievedData = dd.GetData(dd.DataSubDirectories[DataType.JIS], null, null); - foreach (string s in retrievedData) - { - Console.WriteLine(s); - } + //List<string> retrievedData = dd.GetData(dd.DataSubDirectories[DataType.JIS], new DataDownload.Date(10, 2019), new DataDownload.Date(12, 2020)); + //Console.WriteLine("Retrieved data: "); + //foreach (string s in retrievedData) + //{ + // Console.WriteLine(s); + //} + //Console.WriteLine("all from directory:"); + //retrievedData = dd.GetData(dd.DataSubDirectories[DataType.JIS], null, null); + //foreach (string s in retrievedData) + //{ + // Console.WriteLine(s); + //} return dd; @@ -166,21 +175,19 @@ namespace ServerApp Console.WriteLine(dd.DownloadWeatherPrediction()); } - private static IPredictionController PredictionTest(DataDownloader dd) + private static IPredictionController PredictionControllerInit(DataDownloader dd) { - // TODO nastavit čas IDataParser p = new DataParser(dd); // FIXME pass the right references to the JsonParser constructor IJsonParser jsonP = new JsonParser(dd, new CsvDataLoader()); IPredictionController predictionController = new PredictionController(jsonP, p); predictionController.Train(); - //var results = predictionController.Predict() return predictionController; } - private static void ConnectionTest(IPredictionController predictionController, Config config) + private static void ConnectionInit(IPredictionController predictionController, Config config) { ConnectionListenerAsync cl = new ConnectionListenerAsync(int.Parse(config.Port), predictionController); cl.StartListening(); @@ -195,7 +202,6 @@ namespace ServerApp Config extractedConfigInfo = new Config(); - Console.WriteLine(Directory.GetCurrentDirectory()); Console.WriteLine("Parsing configuration file..."); if (args.Length != 1) diff --git a/Server/ServerAppFunctionalTests/XMLComTests/XMLDateTesting.cs b/Server/ServerAppFunctionalTests/XMLComTests/XMLDateTesting.cs new file mode 100644 index 0000000..a829a5e --- /dev/null +++ b/Server/ServerAppFunctionalTests/XMLComTests/XMLDateTesting.cs @@ -0,0 +1,74 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ServerApp.Connection; +using ServerApp.Connection.XMLProtocolHandler; +using ServerApp.Predictor; +using ServerApp.DataDownload; +using Date = ServerApp.Connection.XMLProtocolHandler.Date; +using ServerApp.WeatherPredictionParser; +using ServerApp.Parser.InputData; +using ServerApp.Parser.Parsers; + +namespace ServerAppFunctionalTests.XMLComTests +{ + [TestClass] + public class XMLDateTesting + { + + + [TestMethod] + public void ModifyTimeSpanShort() + { + ConnectionListenerAsync conn = new ConnectionListenerAsync(0, null); + + Date startDate = new Date(); + startDate.year = 2019; + startDate.month = 1; + startDate.day = 1; + + + Date endDate = new Date(); + endDate.year = 2019; + endDate.month = 1; + endDate.day = 2; + + Date res = conn.CheckTimeSpanModifyEnd(startDate, endDate, 15); + + Assert.IsNotNull(res); + Assert.AreEqual(endDate.year, res.year); + Assert.AreEqual(endDate.month, res.month); + Assert.AreEqual(endDate.day, res.day); + + } + + + [TestMethod] + public void ModifyTimeSpanLong() + { + ConnectionListenerAsync conn = new ConnectionListenerAsync(0, null); + + Date startDate = new Date(); + startDate.year = 2019; + startDate.month = 1; + startDate.day = 1; + + + Date endDate = new Date(); + endDate.year = 2019; + endDate.month = 1; + endDate.day = 30; + + Date res = conn.CheckTimeSpanModifyEnd(startDate, endDate, 15); + + Assert.IsNotNull(res); + Assert.AreEqual(endDate.year, res.year); + Assert.AreEqual(endDate.month, res.month); + Assert.AreEqual(endDate.day, 16); + + } + } +} -- GitLab