commit 60a60164a07fe5f8f188574c10b36bac72696e7a
Author: Roman Kalivoda <kalivodaroman@gmail.com>
Date:   Mon May 17 19:17:04 2021 +0200

    Re #8955 refactoring

diff --git a/Server/ServerApp/Connection/XMLProtocolHandler/Request.cs b/Server/ServerApp/Connection/XMLProtocolHandler/Request.cs
index 41f228e..0f314aa 100644
--- a/Server/ServerApp/Connection/XMLProtocolHandler/Request.cs
+++ b/Server/ServerApp/Connection/XMLProtocolHandler/Request.cs
@@ -1,8 +1,4 @@
 ﻿using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 using System.Xml.Serialization;
 
 namespace ServerApp.Connection.XMLProtocolHandler
diff --git a/Server/ServerApp/Predictor/FeatureExtractor.cs b/Server/ServerApp/Predictor/FeatureExtractor.cs
index 4c7ccaa..9264135 100644
--- a/Server/ServerApp/Predictor/FeatureExtractor.cs
+++ b/Server/ServerApp/Predictor/FeatureExtractor.cs
@@ -60,8 +60,9 @@ namespace ServerApp.Predictor
             {
                 res.Add(new ModelInput
                 {
-                    Temp = (float)val.temp,
                     Time = val.startTime,
+                    Temp = (float)val.temp,
+                    Hour = val.startTime.Hour,
                     Wind = (float)val.wind,
                     Rain = (float)val.rain,
                 });
@@ -90,30 +91,40 @@ namespace ServerApp.Predictor
             if (ratio < 0.1f)
             {
                 return "10%";
-            } else if (ratio < 0.2f)
+            }
+            else if (ratio < 0.2f)
             {
                 return "20%";
-            } else if (ratio < 0.3f)
+            }
+            else if (ratio < 0.3f)
             {
                 return "30%";
-            } else if (ratio < 0.4f)
+            }
+            else if (ratio < 0.4f)
             {
                 return "40%";
-            } else if (ratio < 0.5f)
+            }
+            else if (ratio < 0.5f)
             {
                 return "50%";
-            } else if (ratio < 0.6f)
+            }
+            else if (ratio < 0.6f)
             {
                 return "60%";
-            } else if(ratio < 0.7f) {
+            }
+            else if (ratio < 0.7f)
+            {
                 return "70%";
-            } else if (ratio < 0.8f)
+            }
+            else if (ratio < 0.8f)
             {
                 return "80%";
-            } else if (ratio < 0.9f)
+            }
+            else if (ratio < 0.9f)
             {
                 return "90%";
-            } else
+            }
+            else
             {
                 return "100%";
             }
@@ -121,31 +132,40 @@ namespace ServerApp.Predictor
 
         private double LabelToRatio(string label)
         {
-            if (label.Equals("10%")) {
+            if (label.Equals("10%"))
+            {
                 return 0.1f;
             }
-            else if (label.Equals("20%"))  {
+            else if (label.Equals("20%"))
+            {
                 return 0.2f;
             }
-            else if (label.Equals("30%")) {
+            else if (label.Equals("30%"))
+            {
                 return 0.3f;
             }
-            else if (label.Equals("40%")) {
+            else if (label.Equals("40%"))
+            {
                 return 0.4f;
             }
-            else if (label.Equals("50%")) {
+            else if (label.Equals("50%"))
+            {
                 return 0.5f;
             }
-            else if (label.Equals("60%")) {
+            else if (label.Equals("60%"))
+            {
                 return 0.6f;
             }
-            else if (label.Equals("70%")) {
+            else if (label.Equals("70%"))
+            {
                 return 0.7f;
             }
-            else if (label.Equals("80%")) {
+            else if (label.Equals("80%"))
+            {
                 return 0.8f;
             }
-            else if (label.Equals("90%")) {
+            else if (label.Equals("90%"))
+            {
                 return 0.9f;
             }
             else
diff --git a/Server/ServerApp/Predictor/IPredictionController.cs b/Server/ServerApp/Predictor/IPredictionController.cs
index 023e3d8..a434a2b 100644
--- a/Server/ServerApp/Predictor/IPredictionController.cs
+++ b/Server/ServerApp/Predictor/IPredictionController.cs
@@ -2,12 +2,8 @@
 // Author: Roman Kalivoda
 //
 
-using System;
 using System.Collections.Generic;
-using System.IO;
-using Microsoft.ML;
 using ServerApp.Connection.XMLProtocolHandler;
-using ServerApp.Parser.OutputInfo;
 
 namespace ServerApp.Predictor
 {
@@ -32,7 +28,7 @@ namespace ServerApp.Predictor
         /// </summary>
         /// <param name="locationKey">A string identifier of the location for which to load a predictor.</param>
         /// <param name="path">A path to folder with trained prediction model.</param>
-        void Load(string locationKey = null,string path = null);
+        void Load(string locationKey = null, string path = null);
 
         /// <summary>
         /// Predicts turnout level at given time supposing given weather conditions.
diff --git a/Server/ServerApp/Predictor/ModelInput.cs b/Server/ServerApp/Predictor/ModelInput.cs
index b7e1e6d..12da9ae 100644
--- a/Server/ServerApp/Predictor/ModelInput.cs
+++ b/Server/ServerApp/Predictor/ModelInput.cs
@@ -13,6 +13,11 @@ namespace ServerApp.Predictor
     /// </summary>
     public class ModelInput
     {
+        /// <summary>
+        /// Start time of the information.
+        /// </summary>
+        public DateTime Time { get; set; }
+
         /// <summary>
         /// A label of this training input.
         /// </summary>
@@ -26,19 +31,19 @@ namespace ServerApp.Predictor
         public float Temp { get; set; }
 
         /// <summary>
-        /// Time of the predicted turnout.
+        /// Hour of the predicted turnout.
         /// </summary>
-        [ColumnName("Time"), LoadColumn(2)]
-        public DateTime Time { get; set; }
+        [ColumnName("Hour"), LoadColumn(2)]
+        public int Hour { get; set; }
 
         /// <summary>
-        /// Wind velocity in ? units
+        /// Wind velocity in m/s
         /// </summary>
         [ColumnName("Wind"), LoadColumn(3)]
         public float Wind { get; set; }
 
         /// <summary>
-        /// Precipitation
+        /// Precipitation in %
         /// </summary>
         [ColumnName("Rain"), LoadColumn(4)]
         public float Rain { get; set; }
diff --git a/Server/ServerApp/Predictor/ModelOutput.cs b/Server/ServerApp/Predictor/ModelOutput.cs
index ace5084..5d8984b 100644
--- a/Server/ServerApp/Predictor/ModelOutput.cs
+++ b/Server/ServerApp/Predictor/ModelOutput.cs
@@ -2,7 +2,6 @@
 // Author: Roman Kalivoda
 //
 
-using System;
 using Microsoft.ML.Data;
 
 namespace ServerApp.Predictor
@@ -16,7 +15,7 @@ namespace ServerApp.Predictor
         /// A predicted class.
         /// </summary>
         [ColumnName("PredictedLabel")]
-        public String Prediction { get; set; }
+        public string PredictedLabel { get; set; }
 
     }
 }
diff --git a/Server/ServerApp/Predictor/NaiveBayesClassifier.cs b/Server/ServerApp/Predictor/NaiveBayesClassifier.cs
index 31ce1d2..b8ddc27 100644
--- a/Server/ServerApp/Predictor/NaiveBayesClassifier.cs
+++ b/Server/ServerApp/Predictor/NaiveBayesClassifier.cs
@@ -40,11 +40,11 @@ namespace ServerApp.Predictor
         {
             this._trainingDataView = _mlContext.Data.LoadFromEnumerable(trainInput);
             var pipeline = _mlContext.Transforms.Conversion.MapValueToKey(nameof(ModelInput.Label))
-                .Append(_mlContext.Transforms.Concatenate("Features", new[] { "Temp" }))
+                .Append(_mlContext.Transforms.Concatenate("Features", new[] { nameof(ModelInput.Temp), nameof(ModelInput.Rain), nameof(ModelInput.Wind) }))
                 .Append(_mlContext.Transforms.NormalizeMinMax("Features", "Features"))
                 .AppendCacheCheckpoint(_mlContext)
                 .Append(_mlContext.MulticlassClassification.Trainers.NaiveBayes())
-                .Append(_mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel")); ;
+                .Append(_mlContext.Transforms.Conversion.MapKeyToValue(nameof(ModelOutput.PredictedLabel)));
 
             this._trainedModel = pipeline.Fit(this._trainingDataView);
             this._predictionEngine = _mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(this._trainedModel);
@@ -53,13 +53,14 @@ namespace ServerApp.Predictor
 
         public string Predict(ModelInput input)
         {
-            return this._predictionEngine.Predict(input).Prediction;
+            return this._predictionEngine.Predict(input).PredictedLabel;
         }
 
         public void Evaluate(IEnumerable<ModelInput> modelInputs)
         {
             var testDataView = this._mlContext.Data.LoadFromEnumerable(modelInputs);
-            var testMetrics = _mlContext.MulticlassClassification.Evaluate(_trainedModel.Transform(testDataView));
+            var data = _trainedModel.Transform(testDataView);
+            var testMetrics = _mlContext.MulticlassClassification.Evaluate(data);
 
             Console.WriteLine($"*************************************************************************************************************");
             Console.WriteLine($"*       Metrics for Multi-class Classification model - Test Data     ");
diff --git a/Server/ServerApp/Predictor/PredictionController.cs b/Server/ServerApp/Predictor/PredictionController.cs
index 9349326..378e4df 100644
--- a/Server/ServerApp/Predictor/PredictionController.cs
+++ b/Server/ServerApp/Predictor/PredictionController.cs
@@ -4,10 +4,7 @@
 
 using System;
 using System.Collections.Generic;
-using System.IO;
-using Microsoft.ML;
 using ServerApp.Connection.XMLProtocolHandler;
-using ServerApp.Parser.OutputInfo;
 using ServerApp.Parser.Parsers;
 
 namespace ServerApp.Predictor
@@ -43,7 +40,7 @@ namespace ServerApp.Predictor
             this.dataParser = dataParser;
             this.predictors = new List<IPredictor>();
             this.buildingsToAreas = new Dictionary<string, int>();
-            this.featureExtractor = new FeatureExtractor(dataParser, buildingsToAreas);
+            this.featureExtractor = new FeatureExtractor(this.dataParser, buildingsToAreas);
 
             // fill predictors with all available locationKeys
             // TODO Currently all locations use the same predictor. Try dividing locations into subareas with separate predictors.
@@ -97,7 +94,8 @@ namespace ServerApp.Predictor
                     Console.WriteLine("Evaluating predictor with {0} samples.", testData.Count);
                     this.predictors[i].Evaluate(testData);
                 }
-            } else
+            }
+            else
             // train specified predictor only
             {
                 throw new NotImplementedException();
