Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 22211075

Přidáno uživatelem Roman Kalivoda před více než 3 roky(ů)

Revert "Merge branch 'PredictorAPI' into 'master'"

This reverts merge request !20

Zobrazit rozdíly:

Server/ServerApp.sln
7 7
EndProject
8 8
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "TestProject\TestProject.csproj", "{8A09DB8E-64B1-4D55-991E-7F7B21996B45}"
9 9
EndProject
10
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServerAppTests", "ServerAppTests\ServerAppTests.csproj", "{E068474B-98FB-431D-84EB-000AA36D0FC5}"
11
EndProject
12 10
Global
13 11
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 12
		Debug|Any CPU = Debug|Any CPU
......
33 31
		{8A09DB8E-64B1-4D55-991E-7F7B21996B45}.Release|Any CPU.Build.0 = Release|Any CPU
34 32
		{8A09DB8E-64B1-4D55-991E-7F7B21996B45}.Release|x64.ActiveCfg = Release|Any CPU
35 33
		{8A09DB8E-64B1-4D55-991E-7F7B21996B45}.Release|x64.Build.0 = Release|Any CPU
36
		{E068474B-98FB-431D-84EB-000AA36D0FC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37
		{E068474B-98FB-431D-84EB-000AA36D0FC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
38
		{E068474B-98FB-431D-84EB-000AA36D0FC5}.Debug|x64.ActiveCfg = Debug|Any CPU
39
		{E068474B-98FB-431D-84EB-000AA36D0FC5}.Debug|x64.Build.0 = Debug|Any CPU
40
		{E068474B-98FB-431D-84EB-000AA36D0FC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
41
		{E068474B-98FB-431D-84EB-000AA36D0FC5}.Release|Any CPU.Build.0 = Release|Any CPU
42
		{E068474B-98FB-431D-84EB-000AA36D0FC5}.Release|x64.ActiveCfg = Release|Any CPU
43
		{E068474B-98FB-431D-84EB-000AA36D0FC5}.Release|x64.Build.0 = Release|Any CPU
44 34
	EndGlobalSection
45 35
	GlobalSection(SolutionProperties) = preSolution
46 36
		HideSolutionNode = FALSE
Server/ServerApp/Connection/XMLProtocolHandler/Request.cs
1 1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
2 6
using System.Xml.Serialization;
3 7

  
4 8
namespace ServerApp.Connection.XMLProtocolHandler
Server/ServerApp/Parser/Parsers/DataParser.cs
82 82
            var jisFiles = downloader.GetData(pathJis, start, end);
83 83
            var loginFiles = downloader.GetData(pathLogIn, start, end);
84 84

  
85
            WeatherDataUsed = new List<string>();
86
            ActivityDataUsed = new List<string>();
87

  
88
            WeatherDataUsed.AddRange(weatherFiles);
89
            ActivityDataUsed.AddRange(jisFiles);
90
            ActivityDataUsed.AddRange(loginFiles);
91

  
92 85
            WeatherList = weatherParser.ParseWeatherData(weatherFiles, startTime, endTime, wholeDay, interval);
93 86
            jisList = jisParser.ParseJisData(jisFiles, startTime, endTime, wholeDay, interval);
94 87
            loginList = loginParser.ParseLogInData(loginFiles, startTime, endTime, wholeDay, interval);
Server/ServerApp/Parser/Parsers/IDataParser.cs
21 21
        List<ActivityInfo> attendanceList;
22 22
        public List<ActivityInfo> AttendanceList { get => attendanceList; internal set => attendanceList = value; }
23 23

  
24
        /// <summary> List of weather file names the parser was last used on </summary>
25
        List<String> weatherdataUsed;
26
        public List<string> WeatherDataUsed { get => weatherdataUsed; set => weatherdataUsed = value; }
27

  
28
        /// <summary> List of activity file names the parser was last used on </summary>
29
        List<String> activitydataUsed;
30
        public List<string> ActivityDataUsed { get => activitydataUsed; set => activitydataUsed = value; }
31

  
32

  
33 24
        /// <summary>
34 25
        /// Parse data
35 26
        /// </summary>
Server/ServerApp/Predictor/FeatureExtractor.cs
13 13
    /// <summary>
14 14
    /// A class responsible for preparation of features for classifiers.
15 15
    /// </summary>
16
    class FeatureExtractor
16
    public class FeatureExtractor
17 17
    {
18 18
        /// <summary>
19 19
        /// A DataParser instance used to access info objects.
20 20
        /// </summary>
21
        private readonly IDataParser DataParser;
21
        private readonly IDataParser dataParser;
22 22

  
23
        /// <summary>
24
        /// A configuration object of the <c>Predictor</c> package
25
        /// </summary>
26
        private PredictorConfiguration Configuration;
23
        private Dictionary<string, int> buildingsToAreas;
27 24

  
28 25
        /// <summary>
29 26
        /// Instantiates new FeatureExtractor class.
30 27
        /// </summary>
31 28
        /// <param name="dataParser">Data parser used to access training data.</param>
32
        public FeatureExtractor(IDataParser dataParser, PredictorConfiguration configuration)
29
        public FeatureExtractor(IDataParser dataParser, Dictionary<string, int> buildingsToAreas)
33 30
        {
34
            this.DataParser = dataParser;
35
            this.Configuration = configuration;
31
            this.dataParser = dataParser;
32
            this.buildingsToAreas = buildingsToAreas;
36 33
        }
37 34

  
38 35
        /// <summary>
......
44 41
        /// <param name="interval"></param>
45 42
        /// <param name="wholeDay"></param>
46 43
        /// <returns></returns>
47
        public List<ModelInput> PrepareTrainingInput(int area)
44
        public List<ModelInput> PrepareTrainingInput(int area, DateTime startDate, DateTime endDate, int interval = 1, bool wholeDay = true)
48 45
        {
46
            dataParser.Parse(startDate, endDate, interval, wholeDay);
49 47
            List<string> buildings = new List<string>();
50 48

  
51 49
            // find all buildings in area
52
            foreach (KeyValuePair<string, int> kvp in Configuration.BuildingsToAreas)
50
            foreach (KeyValuePair<string, int> kvp in buildingsToAreas)
53 51
            {
54 52
                if (kvp.Value == area)
55 53
                {
......
58 56
            }
59 57

  
60 58
            var res = new List<ModelInput>();
61
            foreach (WeatherInfo val in DataParser.WeatherList)
59
            foreach (WeatherInfo val in dataParser.WeatherList)
62 60
            {
63 61
                res.Add(new ModelInput
64 62
                {
65
                    Time = val.startTime,
66 63
                    Temp = (float)val.temp,
67
                    Hour = val.startTime.Hour,
64
                    Time = val.startTime,
68 65
                    Wind = (float)val.wind,
69 66
                    Rain = (float)val.rain,
70 67
                });
71 68
            }
72 69

  
73
            List<ActivityInfo> attendance = DataParser.AttendanceList;
70
            List<ActivityInfo> attendance = dataParser.AttendanceList;
74 71
            foreach (ModelInput input in res)
75 72
            {
76 73
                List<int> amounts = new List<int>();
77 74
                List<int> maxima = new List<int>();
78 75
                foreach (string building in buildings)
79 76
                {
80
                    List<ActivityInfo> temp = attendance.Where(activity => activity.building.Equals(building)).ToList();
81
                    amounts.Add(temp.Where(activity => activity.startTime.Equals(input.Time)).Select(activity => activity.amount).First());
82
                    maxima.Add(temp.Select(activity => activity.amount).Max());
77

  
78
                    amounts.Add(attendance.Where(activity => activity.building.Equals(building) && activity.startTime.Equals(input.Time)).Select(activity => activity.amount).First());
79
                    maxima.Add(attendance.Where(activity => activity.building.Equals(building)).Select(activity => activity.amount).Max());
83 80
                }
84 81
                double ratio = amounts.Sum() / (double)maxima.Sum();
85 82
                input.Label = RatioToLabel(ratio);
......
93 90
            if (ratio < 0.1f)
94 91
            {
95 92
                return "10%";
96
            }
97
            else if (ratio < 0.2f)
93
            } else if (ratio < 0.2f)
98 94
            {
99 95
                return "20%";
100
            }
101
            else if (ratio < 0.3f)
96
            } else if (ratio < 0.3f)
102 97
            {
103 98
                return "30%";
104
            }
105
            else if (ratio < 0.4f)
99
            } else if (ratio < 0.4f)
106 100
            {
107 101
                return "40%";
108
            }
109
            else if (ratio < 0.5f)
102
            } else if (ratio < 0.5f)
110 103
            {
111 104
                return "50%";
112
            }
113
            else if (ratio < 0.6f)
105
            } else if (ratio < 0.6f)
114 106
            {
115 107
                return "60%";
116
            }
117
            else if (ratio < 0.7f)
118
            {
108
            } else if(ratio < 0.7f) {
119 109
                return "70%";
120
            }
121
            else if (ratio < 0.8f)
110
            } else if (ratio < 0.8f)
122 111
            {
123 112
                return "80%";
124
            }
125
            else if (ratio < 0.9f)
113
            } else if (ratio < 0.9f)
126 114
            {
127 115
                return "90%";
128
            }
129
            else
116
            } else
130 117
            {
131 118
                return "100%";
132 119
            }
133 120
        }
134 121

  
135
        internal double LabelToRatio(string label)
122
        private double LabelToRatio(string label)
136 123
        {
137
            if (label.Equals("10%"))
138
            {
124
            if (label.Equals("10%")) {
139 125
                return 0.1f;
140 126
            }
141
            else if (label.Equals("20%"))
142
            {
127
            else if (label.Equals("20%"))  {
143 128
                return 0.2f;
144 129
            }
145
            else if (label.Equals("30%"))
146
            {
130
            else if (label.Equals("30%")) {
147 131
                return 0.3f;
148 132
            }
149
            else if (label.Equals("40%"))
150
            {
133
            else if (label.Equals("40%")) {
151 134
                return 0.4f;
152 135
            }
153
            else if (label.Equals("50%"))
154
            {
136
            else if (label.Equals("50%")) {
155 137
                return 0.5f;
156 138
            }
157
            else if (label.Equals("60%"))
158
            {
139
            else if (label.Equals("60%")) {
159 140
                return 0.6f;
160 141
            }
161
            else if (label.Equals("70%"))
162
            {
142
            else if (label.Equals("70%")) {
163 143
                return 0.7f;
164 144
            }
165
            else if (label.Equals("80%"))
166
            {
145
            else if (label.Equals("80%")) {
167 146
                return 0.8f;
168 147
            }
169
            else if (label.Equals("90%"))
170
            {
148
            else if (label.Equals("90%")) {
171 149
                return 0.9f;
172 150
            }
173 151
            else
Server/ServerApp/Predictor/IPredictionController.cs
2 2
// Author: Roman Kalivoda
3 3
//
4 4

  
5
using System;
5 6
using System.Collections.Generic;
7
using System.IO;
8
using Microsoft.ML;
6 9
using ServerApp.Connection.XMLProtocolHandler;
10
using ServerApp.Parser.OutputInfo;
7 11

  
8 12
namespace ServerApp.Predictor
9 13
{
......
28 32
        /// </summary>
29 33
        /// <param name="locationKey">A string identifier of the location for which to load a predictor.</param>
30 34
        /// <param name="path">A path to folder with trained prediction model.</param>
31
        void Load(string locationKey = null, string path = null);
35
        void Load(string locationKey = null,string path = null);
32 36

  
33 37
        /// <summary>
34 38
        /// Predicts turnout level at given time supposing given weather conditions.
Server/ServerApp/Predictor/ModelInput.cs
13 13
    /// </summary>
14 14
    public class ModelInput
15 15
    {
16
        /// <summary>
17
        /// Start time of the information.
18
        /// </summary>
19
        public DateTime Time { get; set; }
20

  
21 16
        /// <summary>
22 17
        /// A label of this training input.
23 18
        /// </summary>
......
31 26
        public float Temp { get; set; }
32 27

  
33 28
        /// <summary>
34
        /// Hour of the predicted turnout.
29
        /// Time of the predicted turnout.
35 30
        /// </summary>
36
        [ColumnName("Hour"), LoadColumn(2)]
37
        public int Hour { get; set; }
31
        [ColumnName("Time"), LoadColumn(2)]
32
        public DateTime Time { get; set; }
38 33

  
39 34
        /// <summary>
40
        /// Wind velocity in m/s
35
        /// Wind velocity in ? units
41 36
        /// </summary>
42 37
        [ColumnName("Wind"), LoadColumn(3)]
43 38
        public float Wind { get; set; }
44 39

  
45 40
        /// <summary>
46
        /// Precipitation in %
41
        /// Precipitation
47 42
        /// </summary>
48 43
        [ColumnName("Rain"), LoadColumn(4)]
49 44
        public float Rain { get; set; }
Server/ServerApp/Predictor/ModelOutput.cs
2 2
// Author: Roman Kalivoda
3 3
//
4 4

  
5
using System;
5 6
using Microsoft.ML.Data;
6 7

  
7 8
namespace ServerApp.Predictor
......
15 16
        /// A predicted class.
16 17
        /// </summary>
17 18
        [ColumnName("PredictedLabel")]
18
        public string PredictedLabel { get; set; }
19
        public String Prediction { get; set; }
19 20

  
20 21
    }
21 22
}
Server/ServerApp/Predictor/NaiveBayesClassifier.cs
40 40
        {
41 41
            this._trainingDataView = _mlContext.Data.LoadFromEnumerable(trainInput);
42 42
            var pipeline = _mlContext.Transforms.Conversion.MapValueToKey(nameof(ModelInput.Label))
43
                .Append(_mlContext.Transforms.Conversion.ConvertType(nameof(ModelInput.Hour)))
44
                .Append(_mlContext.Transforms.Concatenate("Features", 
45
                new[] { nameof(ModelInput.Temp), nameof(ModelInput.Rain), nameof(ModelInput.Wind), nameof(ModelInput.Hour) }))
46
                .Append(_mlContext.Transforms.NormalizeMeanVariance("Features", useCdf:false))
43
                .Append(_mlContext.Transforms.Concatenate("Features", new[] { "Temp" }))
44
                .Append(_mlContext.Transforms.NormalizeMinMax("Features", "Features"))
47 45
                .AppendCacheCheckpoint(_mlContext)
48 46
                .Append(_mlContext.MulticlassClassification.Trainers.NaiveBayes())
49
                .Append(_mlContext.Transforms.Conversion.MapKeyToValue(nameof(ModelOutput.PredictedLabel)));
47
                .Append(_mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel")); ;
50 48

  
51
            var cvResults = _mlContext.MulticlassClassification.CrossValidate(this._trainingDataView, pipeline);
52
            foreach (var result in cvResults)
53
            {
54
                var testMetrics = result.Metrics;
55
                Console.WriteLine($"*************************************************************************************************************");
56
                Console.WriteLine($"*       Metrics for Multi-class Classification model - Model #{result.Fold}    ");
57
                Console.WriteLine($"*------------------------------------------------------------------------------------------------------------");
58
                Console.WriteLine($"*       MicroAccuracy:    {testMetrics.MicroAccuracy:0.###}");
59
                Console.WriteLine($"*       MacroAccuracy:    {testMetrics.MacroAccuracy:0.###}");
60
                Console.WriteLine($"*       LogLoss:          {testMetrics.LogLoss:#.###}");
61
                Console.WriteLine($"*       LogLossReduction: {testMetrics.LogLossReduction:#.###}");
62
                Console.WriteLine($"*       Confusion Matrix: {testMetrics.ConfusionMatrix.GetFormattedConfusionTable()}");
63
                Console.WriteLine($"*************************************************************************************************************");
64
            }
65
            this._trainedModel = cvResults.OrderByDescending(fold => fold.Metrics.MicroAccuracy).Select(fold => fold.Model).First();
66
            Console.WriteLine($"Selected the model #{cvResults.OrderByDescending(fold => fold.Metrics.MicroAccuracy).Select(fold => fold.Fold).First()} as the best.");
49
            this._trainedModel = pipeline.Fit(this._trainingDataView);
67 50
            this._predictionEngine = _mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(this._trainedModel);
68 51

  
69 52
        }
70 53

  
71 54
        public string Predict(ModelInput input)
72 55
        {
73
            return this._predictionEngine.Predict(input).PredictedLabel;
56
            return this._predictionEngine.Predict(input).Prediction;
74 57
        }
75 58

  
76 59
        public void Evaluate(IEnumerable<ModelInput> modelInputs)
77 60
        {
78 61
            var testDataView = this._mlContext.Data.LoadFromEnumerable(modelInputs);
79
            var data = _trainedModel.Transform(testDataView);
80
            var testMetrics = _mlContext.MulticlassClassification.Evaluate(data);
62
            var testMetrics = _mlContext.MulticlassClassification.Evaluate(_trainedModel.Transform(testDataView));
81 63

  
82 64
            Console.WriteLine($"*************************************************************************************************************");
83 65
            Console.WriteLine($"*       Metrics for Multi-class Classification model - Test Data     ");
......
86 68
            Console.WriteLine($"*       MacroAccuracy:    {testMetrics.MacroAccuracy:0.###}");
87 69
            Console.WriteLine($"*       LogLoss:          {testMetrics.LogLoss:#.###}");
88 70
            Console.WriteLine($"*       LogLossReduction: {testMetrics.LogLossReduction:#.###}");
89
            Console.WriteLine($"*       Confusion Matrix: {testMetrics.ConfusionMatrix.GetFormattedConfusionTable()}");
90 71
            Console.WriteLine($"*************************************************************************************************************");
91 72
        }
92 73
    }
Server/ServerApp/Predictor/PredictionController.cs
4 4

  
5 5
using System;
6 6
using System.Collections.Generic;
7
using System.IO;
8
using Microsoft.ML;
7 9
using ServerApp.Connection.XMLProtocolHandler;
8
using ServerApp.Parser.Parsers;
9
using Newtonsoft.Json;
10
using ServerApp.WeatherPredictionParser;
11 10
using ServerApp.Parser.OutputInfo;
11
using ServerApp.Parser.Parsers;
12 12

  
13 13
namespace ServerApp.Predictor
14 14
{
15 15
    /// <summary>
16 16
    /// Implentation of the <c>IPredicitionController</c> interface.
17 17
    /// </summary>
18
    public class PredictionController : IPredictionController
18
    class PredictionController : IPredictionController
19 19
    {
20 20
        /// <summary>
21
        /// Configuration of the <c>Predictor</c>
21
        /// A dictionary for storing trained predictors.
22 22
        /// </summary>
23
        private PredictorConfiguration Configuration;
23
        private Dictionary<string, int> buildingsToAreas;
24 24

  
25
        private List<IPredictor> Predictors;
25
        private List<IPredictor> predictors;
26 26

  
27 27
        /// <summary>
28 28
        /// A reference to a data parser.
29 29
        /// </summary>
30
        private IDataParser DataParser;
30
        private IDataParser dataParser;
31 31

  
32 32
        /// <summary>
33 33
        /// A feature extractor instance.
34 34
        /// </summary>
35
        private FeatureExtractor FeatureExtractor;
36

  
37
        /// <summary>
38
        /// A weather prediction parser service
39
        /// </summary>
40
        private IJsonParser weatherService;
35
        private FeatureExtractor featureExtractor;
41 36

  
42 37
        /// <summary>
43 38
        /// Instantiates new prediction controller.
44 39
        /// </summary>
45 40
        /// <param name="dataParser">A data parser used to get training data.</param>
46
        public PredictionController(IJsonParser weatherService, IDataParser dataParser, string pathToConfig = null)
41
        public PredictionController(IDataParser dataParser)
47 42
        {
48
            this.weatherService = weatherService;
49
            // load config or get the default one
50
            if (pathToConfig is null)
51
            {
52
                pathToConfig = PredictorConfiguration.DEFAULT_CONFIG_PATH;
53
            }
54
            try
55
            {
56
                string json = System.IO.File.ReadAllText(pathToConfig);
57
                this.Configuration = JsonConvert.DeserializeObject<PredictorConfiguration>(json);
58
            } catch (System.IO.IOException e)
59
            {
60
                Console.WriteLine(e.ToString());
61
                this.Configuration = PredictorConfiguration.GetDefaultConfig();
62
            }
63

  
64
            this.DataParser = dataParser;
65
            this.Predictors = new List<IPredictor>();
66
            this.FeatureExtractor = new FeatureExtractor(this.DataParser, this.Configuration);
67

  
68
            for (int i = 0; i < this.Configuration.PredictorCount; i++)
43
            this.dataParser = dataParser;
44
            this.predictors = new List<IPredictor>();
45
            this.buildingsToAreas = new Dictionary<string, int>();
46
            this.featureExtractor = new FeatureExtractor(dataParser, buildingsToAreas);
47

  
48
            // fill predictors with all available locationKeys
49
            // TODO Currently all locations use the same predictor. Try dividing locations into subareas with separate predictors.
50
            var locationKeys = TagInfo.buildings;
51
            foreach (string key in locationKeys)
69 52
            {
70
                Predictors.Add(new NaiveBayesClassifier());
53
                buildingsToAreas.Add(key, 0);
71 54
            }
72
            PredictorConfiguration.SaveConfig(PredictorConfiguration.DEFAULT_CONFIG_PATH, Configuration);
55
            IPredictor predictor = new NaiveBayesClassifier();
56
            predictors.Add(predictor);
73 57
        }
74 58
        public List<string> GetPredictors()
75 59
        {
76
            return new List<string>(this.Configuration.BuildingsToAreas.Keys);
60
            return new List<string>(buildingsToAreas.Keys);
77 61
        }
78 62

  
79 63
        public void Load(string locationKey = null, string path = null)
......
90 74

  
91 75
        public Response Predict(Request request)
92 76
        {
93
            DateTime start = new DateTime(year: request.start.year, month: request.start.month, day: request.start.day, hour: request.start.hour, minute: 0, second: 0);
94
            List<Prediction> predictions = new List<Prediction>();
95
            if (request.useEndDate)
96
            {
97
                DateTime end = new DateTime(year: request.end.year, month: request.end.month, day: request.end.day, hour: request.end.hour, minute: 0, second: 0);
98
                DateTime current = start;
99
                while (current < end)
100
                {
101
                    while (current.Hour < Date.MAX_HOUR)
102
                    {
103
                        var prediction = PredictSingle(request, current);
104
                        predictions.Add(prediction);
105
                        current = current.AddHours(this.Configuration.TimeResolution);
106
                    }
107
                    current = current.AddHours(23 - current.Hour + Date.MIN_HOUR);
108
                }
109
            } else
110
            {
111
                if (request.useWeather)
112
                {
113
                    predictions.Add(PredictSingle(request, start));
114
                }
115
            }
116
            var response = new Response();
117
            response.hoursPerSegment = Configuration.TimeResolution;
118
            response.predicitons = predictions.ToArray();
119
            return response;
77
            throw new NotImplementedException();
120 78
        }
121 79

  
122
        private Prediction PredictSingle(Request request, DateTime current)
123
        {
124
            double[] predictedValues = new double[this.Configuration.BuildingsToAreas.Count];
125
            string[] predictedLabels = new string[this.Predictors.Count];
126
            for (int i = 0; i < this.Predictors.Count; i++)
127
            {
128
                if (request.useWeather)
129
                {
130
                    predictedLabels[i] = this.Predictors[i].Predict(new ModelInput
131
                    {
132
                        Rain = (float)request.rain,
133
                        Temp = (float)request.temperature,
134
                        Wind = (float)request.wind,
135
                        Hour = current.Hour,
136
                        Time = current
137
                    });
138
                }
139
                else
140
                {
141
                    List<WeatherInfo> weatherInfos = weatherService.GetPredictionForTime(from: current, to: current.AddHours(this.Configuration.TimeResolution));
142
                    predictedLabels[i] = this.Predictors[i].Predict(new ModelInput
143
                    {
144
                        Rain = weatherInfos[0].rain,
145
                        Temp = (float)weatherInfos[0].temp,
146
                        Wind = (float)weatherInfos[0].wind,
147
                        Hour = current.Hour,
148
                        Time = current
149
                    });
150
                }
151
            }
152
            for (int i = 0; i < predictedValues.Length; i++)
153
            {
154
                predictedValues[i] = this.FeatureExtractor.LabelToRatio(predictedLabels[this.Configuration.BuildingsToAreas[TagInfo.buildings[i]]]) * 100;
155
            }
156

  
157
            Prediction prediction = new Prediction();
158
            prediction.dateTime = new Date
159
            {
160
                year = current.Year,
161
                month = current.Month,
162
                day = current.Day,
163
                hour = current.Hour
164
            };
165
            prediction.predictions = predictedValues;
166
            return prediction;
167
        }
168 80

  
169 81
        public void Train(string locationKey = null)
170 82
        {
171 83
            if (locationKey is null)
172 84
            // train all predictors
173 85
            {
174
                DataParser.Parse(DateTime.MinValue, DateTime.MaxValue, this.Configuration.TimeResolution, wholeDay: false);
175
                for (int i = 0; i < this.Predictors.Count; i++)
86
                // TODO A single predictor is used for all areas, so training is done only once now.
87
                for (int i = 0; i < this.predictors.Count; i++)
176 88
                {
177 89
                    // train on all available data
178
                    List<ModelInput> data = FeatureExtractor.PrepareTrainingInput(i);
179
                    Console.WriteLine("Training predictor with {0} samples.", data.Count);
180
                    this.Predictors[i].Fit(data);
90
                    // TODO the train/test split is used just temporarily for demonstration.
91
                    List<ModelInput> data = featureExtractor.PrepareTrainingInput(i, DateTime.MinValue, DateTime.MaxValue);
92
                    List<ModelInput> trainingData = data.GetRange(index: 0, count: 500);
93
                    List<ModelInput> testData = data.GetRange(index: 500, count: 94);
94
                    Console.WriteLine("Training predictor with {0} samples.", trainingData.Count);
95
                    this.predictors[i].Fit(trainingData);
96

  
97
                    Console.WriteLine("Evaluating predictor with {0} samples.", testData.Count);
98
                    this.predictors[i].Evaluate(testData);
181 99
                }
182
            }
183
            else
100
            } else
184 101
            // train specified predictor only
185 102
            {
186 103
                throw new NotImplementedException();
Server/ServerApp/Predictor/PredictorConfiguration.cs
1
//
2
// Author: Roman Kalivoda
3
//
4

  
5
using System.Collections.Generic;
6
using System;
7
using System.IO;
8
using Newtonsoft.Json;
9

  
10
namespace ServerApp.Predictor
11
{
12
    class PredictorConfiguration
13
    {
14
        public static readonly string DEFAULT_CONFIG_PATH = Path.GetFullPath(Path.GetDirectoryName(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile) + @"\Predictor.config");
15

  
16
        public int TimeResolution { get; set; }
17

  
18
        public Dictionary<string, int> BuildingsToAreas { get; set; }
19

  
20
        public int PredictorCount { get; set; }
21

  
22
        public static PredictorConfiguration LoadConfig(string filename)
23
        {
24
            string json = System.IO.File.ReadAllText(filename);
25
            PredictorConfiguration configuration = JsonConvert.DeserializeObject<PredictorConfiguration>(json);
26
            return configuration;
27
        }
28

  
29
        public static void SaveConfig(string filename, PredictorConfiguration configuration)
30
        {
31
            string json = JsonConvert.SerializeObject(configuration);
32
            System.IO.File.WriteAllText(filename, json);
33
        }
34

  
35
        public static PredictorConfiguration GetDefaultConfig()
36
        {
37
            Dictionary<string, int> dict = new Dictionary<string, int>();
38
            var locationKeys = Parser.Parsers.TagInfo.buildings;
39
            foreach (string key in locationKeys)
40
            {
41
                dict.Add(key, 0);
42
            }
43

  
44
            return new PredictorConfiguration
45
            {
46
                TimeResolution = 3,
47
                PredictorCount = 3,
48
                BuildingsToAreas = new Dictionary<string, int>
49
                {
50
                    { "FST+FEK", 0 },
51
                    { "FDU", 0 },
52
                    { "FAV", 0 },
53
                    { "FEL", 0 },
54
                    { "REK", 0 },
55
                    { "MENZA", 0 },
56
                    { "LIB", 0 },
57
                    { "CIV", 0 },
58
                    { "UNI14", 0 },
59
                    { "DOM", 1 },
60
                    { "HUS", 1 },
61
                    { "CHOD", 1 },
62
                    { "JUNG", 1 },
63
                    { "KLAT", 1 },
64
                    { "KOLL", 1 },
65
                    { "RIEG", 1 },
66
                    { "SADY", 1 },
67
                    { "SED+VEL", 1 },
68
                    { "TES", 1 },
69
                    { "TYL", 1 },
70
                    { "KARMA", 2 },
71
                    { "KBORY", 2 },
72
                    { "KLOCH", 2 },
73
                    { "KKLAT", 2 }
74
                }
75
            };
76
        }
77
    }
78
}
Server/ServerApp/Program.cs
1 1
using ServerApp.Connection;
2 2
using ServerApp.Connection.XMLProtocolHandler;
3 3
using ServerApp.DataDownload;
4
using ServerApp.Parser.OutputInfo;
5 4
using ServerApp.Parser.Parsers;
6 5
using ServerApp.Predictor;
7 6
using ServerApp.User;
......
137 136
            JsonParser jsonP = new JsonParser(null);
138 137
			jsonP.ParsePrediction();
139 138

  
140
			var res = jsonP.GetPredictionForTime(jsonP.Predictions[5].startTime, jsonP.Predictions[20].startTime);
141
			Console.WriteLine("from " + jsonP.Predictions[5].startTime);
142
			Console.WriteLine("end " + jsonP.Predictions[20].startTime);
143
			foreach (WeatherInfo w in res)
144
				Console.WriteLine(w.ToString());
145

  
146

  
147 139
			// TODO nastavit čas
148 140
			IDataParser p = new DataParser(dd);
149
            IPredictionController predictionController = new PredictionController(jsonP, p);
141
            IPredictionController predictionController = new PredictionController(p);
150 142
            predictionController.Train();
151 143
            //var results = predictionController.Predict()
152 144
			
Server/ServerApp/ServerApp.csproj
179 179
    <Compile Include="Parser\Parsers\DataParser.cs" />
180 180
    <Compile Include="Parser\Parsers\IDataParser.cs" />
181 181
    <Compile Include="Parser\Parsers\JisParser.cs" />
182
    <Compile Include="Predictor\PredictorConfiguration.cs" />
183 182
    <Compile Include="Predictor\FeatureExtractor.cs" />
184 183
    <Compile Include="Predictor\IPredictionController.cs" />
185 184
    <Compile Include="Predictor\PredictionController.cs" />
Server/ServerApp/WeatherPredictionParser/IJsonParser.cs
3 3
//
4 4

  
5 5
using ServerApp.Parser.OutputInfo;
6
using System;
7 6
using System.Collections.Generic;
8 7

  
9 8
namespace ServerApp.WeatherPredictionParser
......
11 10
    /// <summary>
12 11
    /// Abstract class that every Json parser should inherit from
13 12
    /// </summary>
14
    public abstract class IJsonParser
13
    abstract class IJsonParser
15 14
    {
16 15

  
17 16
        /// <summary> Current weather </summary>
18 17
        WeatherInfo current;
19
        public WeatherInfo Current { get => current; set => current = value; }
18
        public WeatherInfo Current { get => current; }
20 19

  
21 20
        /// <summary> Prediction for today, tommorrow and day after tommorrow </summary>
22 21
        List<WeatherInfo> predictions;
......
28 27
        /// </summary>
29 28
        abstract public void ParsePrediction();
30 29

  
31
        /// <summary>
32
        /// Get predictions from Predictions that are within specified time span
33
        /// </summary>
34
        /// <param name="from">DateTime from</param>
35
        /// <param name="to">DateTime to</param>
36
        /// <returns>List of predictions that fit specified criteria</returns>
37
        abstract public List<WeatherInfo> GetPredictionForTime(DateTime from, DateTime to);
38

  
39 30
    }
40 31

  
41 32
}
Server/ServerApp/WeatherPredictionParser/JsonParser.cs
20 20
    /// <author>A. Konig</author>
21 21
    class JsonParser : IJsonParser
22 22
    {
23
        /// <summary> Current weather </summary>
24
        WeatherInfo current;
25
        public new WeatherInfo Current { get => current; }
26
        /// <summary> Prediction for today, tommorrow and day after tommorrow </summary>
27
        List<WeatherInfo> predictions;
28
        public new List<WeatherInfo> Predictions { get => predictions; set => predictions = value; }
29

  
23 30
        /// <summary> Data loader </summary>
24 31
        DataDownloader loader;
25 32
        /// <summary> Currently parsed day </summary>
......
39 46
            this.loader = loader;
40 47
        }
41 48

  
42
        /// <summary>
43
        /// Get predictions from Predictions that are within specified time span
44
        /// From-to including
45
        /// If from == null then all until to
46
        /// If to  == null then all starting from from
47
        /// </summary>
48
        /// <param name="from">DateTime from</param>
49
        /// <param name="to">DateTime to</param>
50
        /// <returns>List of predictions that fit specified criteria or null if incorrect input</returns>
51
        public override List<WeatherInfo> GetPredictionForTime(DateTime from, DateTime to)
52
        {
53
            if (Predictions == null)
54
                return null;
55

  
56
            List<WeatherInfo> res = new List<WeatherInfo>();
57

  
58
            if (from == null)
59
                from = Predictions[0].startTime;
60

  
61
            if (to == null)
62
                from = Predictions[Predictions.Count].startTime;
63

  
64
            if (from > to)
65
                return null;
66

  
67
            foreach (WeatherInfo pred in Predictions)
68
            {
69
                int hour = pred.startTime.Hour + pred.intervalLength;
70
                Console.WriteLine(pred.intervalLength);
71
                bool addDay = false;
72
                if (hour >= 24)
73
                {
74
                    hour -= 24;
75
                    addDay = true;
76
                }
77
                DateTime endTime = new DateTime(pred.startTime.Year, pred.startTime.Month, pred.startTime.Day, hour, pred.startTime.Minute, pred.startTime.Second);
78
                if (addDay)
79
                    endTime = endTime.AddDays(1);
80

  
81
                // if both end and start not outside of interval
82
                if (!((pred.startTime < from && endTime <= from) || (pred.startTime > to && endTime >= to)))
83
                    res.Add(pred);
84
            }
85

  
86
            return res;
87
        }
88

  
89 49
        /// <summary>
90 50
        /// Parse weather prediction
91 51
        /// Results is in attributes current for current weather and pred for weather prediction for today, tommorrow and day after tommorrow
......
99 59
            DateTime now = DateTime.Now;
100 60
            Console.WriteLine(File.Exists(file));
101 61

  
102
            Current = new WeatherInfo();
103
            Predictions = new List<WeatherInfo>();
62
            current = new WeatherInfo();
63
            predictions = new List<WeatherInfo>();
104 64

  
105 65
            if (!File.Exists(file))
106 66
                return;
......
124 84
                    case "current_condition":
125 85
                        {
126 86
                            ArrayEnumerator currentWeather = weatherP.Current.Value.EnumerateArray();
127
                            Current = ParseCurrentWeather(currentWeather);
87
                            current = ParseCurrentWeather(currentWeather);
128 88

  
129 89
                            break;
130 90
                        }
......
150 110
        /// </summary>
151 111
        private void TestConsoleOutput()
152 112
        {
153
            Console.WriteLine(Current);
154
            foreach (WeatherInfo w in Predictions)
113
            Console.WriteLine(current);
114
            foreach (WeatherInfo w in predictions)
155 115
                Console.WriteLine(w);
156 116
        }
157 117

  
......
177 137
        private void EncompassSunRiseSetTimes()
178 138
        {
179 139
            // change current weather
180
            if ((Current.startTime.TimeOfDay > sunsetTime.TimeOfDay) || (Current.startTime.TimeOfDay < sunriseTime.TimeOfDay))
181
                Current.condition = WeatherConditions.Dark;
140
            if ((current.startTime.TimeOfDay > sunsetTime.TimeOfDay) || (current.startTime.TimeOfDay < sunriseTime.TimeOfDay))
141
                current.condition = WeatherConditions.Dark;
182 142

  
183 143
            // change prediction
184
            for (int i = 0; i < Predictions.Count - 1; i++)
144
            for (int i = 0; i < predictions.Count - 1; i++)
185 145
            {
186
                WeatherInfo w = Predictions[i];
187
                WeatherInfo wNext = Predictions[i + 1];
146
                WeatherInfo w = predictions[i];
147
                WeatherInfo wNext = predictions[i + 1];
188 148

  
189 149
                // if wNext time < than w time then it is prediction from the next day -> add 24 to correctly calculate timespan
190 150
                int timespan = wNext.startTime.Hour - w.startTime.Hour;
......
218 178
            }
219 179

  
220 180
            // last prediction
221
            WeatherInfo wLast = Predictions[Predictions.Count - 1];
181
            WeatherInfo wLast = predictions[predictions.Count - 1];
222 182
            TimeSpan endTimeW = new TimeSpan(24, 0, 0);
223
            int timespanLast = 24 - wLast.startTime.Hour;
183
            int timespanLast = endTimeW.Hours - wLast.startTime.Hour;
224 184
            wLast.intervalLength = timespanLast;
225 185

  
226 186
            // if start under sunset
......
378 338
                }
379 339

  
380 340
                // Console.WriteLine(weather.ToString());
381
                Predictions.Add(weather);
341
                predictions.Add(weather);
382 342

  
383 343
            }
384 344

  
......
441 401
            return res;
442 402
        }
443 403

  
444
      
445 404
    }
446 405
}
Server/ServerAppTests/Predictor/PredictionControllerTests.cs
1
//
2
// Author: Roman Kalivoda
3
//
4
using Microsoft.VisualStudio.TestTools.UnitTesting;
5
using ServerApp.Predictor;
6
using System;
7
using System.Collections.Generic;
8
using System.Linq;
9
using System.Text;
10
using System.Threading.Tasks;
11

  
12
namespace ServerApp.Predictor.Tests
13
{
14
    [TestClass()]
15
    public class PredictionControllerTests
16
    {
17
        [TestInitialize]
18
        public void SetUp()
19
        {
20

  
21
        }
22

  
23
        [TestMethod()]
24
        public void TrainTest()
25
        {
26
            throw new NotImplementedException();
27
        }
28
    }
29
}
Server/ServerAppTests/Properties/AssemblyInfo.cs
1
using System.Reflection;
2
using System.Runtime.CompilerServices;
3
using System.Runtime.InteropServices;
4

  
5
// General Information about an assembly is controlled through the following 
6
// set of attributes. Change these attribute values to modify the information
7
// associated with an assembly.
8
[assembly: AssemblyTitle("ServerAppTests")]
9
[assembly: AssemblyDescription("")]
10
[assembly: AssemblyConfiguration("")]
11
[assembly: AssemblyCompany("")]
12
[assembly: AssemblyProduct("ServerAppTests")]
13
[assembly: AssemblyCopyright("Copyright ©  2021")]
14
[assembly: AssemblyTrademark("")]
15
[assembly: AssemblyCulture("")]
16

  
17
// Setting ComVisible to false makes the types in this assembly not visible 
18
// to COM components.  If you need to access a type in this assembly from 
19
// COM, set the ComVisible attribute to true on that type.
20
[assembly: ComVisible(false)]
21

  
22
// The following GUID is for the ID of the typelib if this project is exposed to COM
23
[assembly: Guid("e068474b-98fb-431d-84eb-000aa36d0fc5")]
24

  
25
// Version information for an assembly consists of the following four values:
26
//
27
//      Major Version
28
//      Minor Version 
29
//      Build Number
30
//      Revision
31
//
32
// You can specify all the values or you can default the Build and Revision Numbers 
33
// by using the '*' as shown below:
34
// [assembly: AssemblyVersion("1.0.*")]
35
[assembly: AssemblyVersion("1.0.0.0")]
36
[assembly: AssemblyFileVersion("1.0.0.0")]
Server/ServerAppTests/ServerAppTests.csproj
1
<?xml version="1.0" encoding="utf-8"?>
2
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3
  <Import Project="..\packages\MSTest.TestAdapter.2.1.1\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.2.1.1\build\net45\MSTest.TestAdapter.props')" />
4
  <PropertyGroup>
5
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7
    <ProjectGuid>{E068474B-98FB-431D-84EB-000AA36D0FC5}</ProjectGuid>
8
    <OutputType>Library</OutputType>
9
    <AppDesignerFolder>Properties</AppDesignerFolder>
10
    <RootNamespace>ServerAppTests</RootNamespace>
11
    <AssemblyName>ServerAppTests</AssemblyName>
12
    <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
13
    <FileAlignment>512</FileAlignment>
14
    <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
15
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
16
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
17
    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
18
    <IsCodedUITest>False</IsCodedUITest>
19
    <TestProjectType>UnitTest</TestProjectType>
20
    <TargetFrameworkProfile />
21
    <NuGetPackageImportStamp>
22
    </NuGetPackageImportStamp>
23
  </PropertyGroup>
24
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
25
    <DebugSymbols>true</DebugSymbols>
26
    <DebugType>full</DebugType>
27
    <Optimize>false</Optimize>
28
    <OutputPath>bin\Debug\</OutputPath>
29
    <DefineConstants>DEBUG;TRACE</DefineConstants>
30
    <ErrorReport>prompt</ErrorReport>
31
    <WarningLevel>4</WarningLevel>
32
  </PropertyGroup>
33
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
34
    <DebugType>pdbonly</DebugType>
35
    <Optimize>true</Optimize>
36
    <OutputPath>bin\Release\</OutputPath>
37
    <DefineConstants>TRACE</DefineConstants>
38
    <ErrorReport>prompt</ErrorReport>
39
    <WarningLevel>4</WarningLevel>
40
  </PropertyGroup>
41
  <ItemGroup>
42
    <Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
43
      <HintPath>..\packages\Castle.Core.4.4.0\lib\net45\Castle.Core.dll</HintPath>
44
    </Reference>
45
    <Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
46
      <HintPath>..\packages\MSTest.TestFramework.2.1.1\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
47
    </Reference>
48
    <Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
49
      <HintPath>..\packages\MSTest.TestFramework.2.1.1\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
50
    </Reference>
51
    <Reference Include="Moq, Version=4.16.0.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
52
      <HintPath>..\packages\Moq.4.16.1\lib\net45\Moq.dll</HintPath>
53
    </Reference>
54
    <Reference Include="System" />
55
    <Reference Include="System.Configuration" />
56
    <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
57
      <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
58
    </Reference>
59
    <Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
60
      <HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath>
61
    </Reference>
62
  </ItemGroup>
63
  <Choose>
64
    <When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
65
      <ItemGroup>
66
        <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
67
      </ItemGroup>
68
    </When>
69
    <Otherwise />
70
  </Choose>
71
  <ItemGroup>
72
    <Compile Include="Predictor\PredictionControllerTests.cs" />
73
    <Compile Include="Properties\AssemblyInfo.cs" />
74
  </ItemGroup>
75
  <ItemGroup>
76
    <None Include="app.config" />
77
    <None Include="packages.config" />
78
  </ItemGroup>
79
  <ItemGroup>
80
    <ProjectReference Include="..\ServerApp\ServerApp.csproj">
81
      <Project>{18FCFB20-B860-4147-8E7C-8A0DD84C55D4}</Project>
82
      <Name>ServerApp</Name>
83
    </ProjectReference>
84
  </ItemGroup>
85
  <Choose>
86
    <When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
87
      <ItemGroup>
88
        <Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
89
          <Private>False</Private>
90
        </Reference>
91
        <Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
92
          <Private>False</Private>
93
        </Reference>
94
        <Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
95
          <Private>False</Private>
96
        </Reference>
97
        <Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
98
          <Private>False</Private>
99
        </Reference>
100
      </ItemGroup>
101
    </When>
102
  </Choose>
103
  <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
104
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
105
  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
106
    <PropertyGroup>
107
      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
108
    </PropertyGroup>
109
    <Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.1.1\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.1.1\build\net45\MSTest.TestAdapter.props'))" />
110
    <Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.1.1\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.1.1\build\net45\MSTest.TestAdapter.targets'))" />
111
  </Target>
112
  <Import Project="..\packages\MSTest.TestAdapter.2.1.1\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.2.1.1\build\net45\MSTest.TestAdapter.targets')" />
113
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
114
       Other similar extension points exist, see Microsoft.Common.targets.
115
  <Target Name="BeforeBuild">
116
  </Target>
117
  <Target Name="AfterBuild">
118
  </Target>
119
  -->
120
</Project>
Server/ServerAppTests/app.config
1
<?xml version="1.0" encoding="utf-8"?>
2
<configuration>
3
  <runtime>
4
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
5
      <dependentAssembly>
6
        <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
7
        <bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" />
8
      </dependentAssembly>
9
    </assemblyBinding>
10
  </runtime>
11
</configuration>
Server/ServerAppTests/packages.config
1
<?xml version="1.0" encoding="utf-8"?>
2
<packages>
3
  <package id="Castle.Core" version="4.4.0" targetFramework="net472" />
4
  <package id="Moq" version="4.16.1" targetFramework="net472" />
5
  <package id="MSTest.TestAdapter" version="2.1.1" targetFramework="net472" />
6
  <package id="MSTest.TestFramework" version="2.1.1" targetFramework="net472" />
7
  <package id="System.Runtime.CompilerServices.Unsafe" version="4.5.3" targetFramework="net472" />
8
  <package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net472" />
9
</packages>

Také k dispozici: Unified diff