Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 98b568bc

Přidáno uživatelem Alex Konig před téměř 4 roky(ů)

re #8612 Weather parser in hourly intervals

Zobrazit rozdíly:

Server/ServerApp/Parser/InputData/CsvDataLoader.cs
8 8
    /// <summary>
9 9
    /// Class responsible for loading data from file
10 10
    /// </summary>
11
    static class CsvDataLoader
11
    /// <author>Alex Konig</author>
12
    class CsvDataLoader : DataLoader
12 13
    {
13 14
        /// <summary> Culture info for parsing numbers </summary>
14 15
        static CultureInfo cultureInfo = new CultureInfo("de-DE");
......
18 19
        /// </summary>
19 20
        /// <param name="name">Path to file</param>
20 21
        /// <returns>Array with loaded data</returns>
21
        static string[] LoadCsv(string name)
22
        private string[] LoadCsv(string name)
22 23
        {
23 24
            string[] lines = File.ReadAllLines(name);
24 25
            return lines;
......
29 30
        /// </summary>
30 31
        /// <param name="pathToFile">Path to file</param>
31 32
        /// <returns></returns>
32
        public static List<JisInstance> LoadJisFile(string pathToFile)
33
        public List<JisInstance> LoadJisFile(string pathToFile)
33 34
        {
34 35
            var lines = LoadCsv(pathToFile);
35 36
            List<JisInstance> list = new List<JisInstance>();
......
57 58
        /// </summary>
58 59
        /// <param name="pathToFile">Path to file</param>
59 60
        /// <returns></returns>
60
        public static List<LogInInstance> LoadLoginFile(string pathToFile)
61
        public List<LogInInstance> LoadLoginFile(string pathToFile)
61 62
        {
62 63
            var lines = LoadCsv(pathToFile);
63 64
            List<LogInInstance> list = new List<LogInInstance>();
......
95 96
        /// </summary>
96 97
        /// <param name="pathToFile">Path to file</param>
97 98
        /// <returns></returns>
98
        public static List<WeatherInstance> LoadWeatherFile(string pathToFile)
99
        public List<WeatherInstance> LoadWeatherFile(string pathToFile)
99 100
        {
100 101
            var lines = LoadCsv(pathToFile);
101 102
            
Server/ServerApp/Parser/InputData/DataLoader.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
6

  
7
namespace ServerApp.Parser.InputData
8
{
9
    /// <author>Alex Konig</author>
10
    interface DataLoader
11
    {
12
        /// <summary>
13
        /// Load jis data from file
14
        /// </summary>
15
        /// <param name="pathToFile">Path to file</param>
16
        /// <returns></returns>
17
        List<JisInstance> LoadJisFile(string pathToFile);
18

  
19
        /// <summary>
20
        /// Load login data from file
21
        /// </summary>
22
        /// <param name="pathToFile">Path to file</param>
23
        /// <returns></returns>
24
        List<LogInInstance> LoadLoginFile(string pathToFile);
25
        /// <summary>
26
        /// Load weather data from file
27
        /// </summary>
28
        /// <param name="pathToFile">Path to file</param>
29
        /// <returns></returns>
30
        List<WeatherInstance> LoadWeatherFile(string pathToFile);
31

  
32
    }
33
}
Server/ServerApp/Parser/InputData/JisInstance.cs
13 13
    ///     "A1";"08.04.2018 14:23:15";1
14 14
    ///     [place tag];[date time];[amount]
15 15
    /// </summary>
16
    /// <author>Alex Konig</author>
16 17
    class JisInstance
17 18
    {
18 19
        /// <summary> Place tag  </summary>
Server/ServerApp/Parser/InputData/LogInInstance.cs
20 20
    ///     "27.10.2011 00:00:00";1;7;"13:00";"13:45";"UI";"Laboratoř";"UI-505";"ui505av07-lps"
21 21
    ///     [datum];[amount];[lesson];[lesson start];[lesson end];[building];[room type];[room];[hostname]
22 22
    /// </summary>
23
    /// <author>Alex Konig</author>
23 24
    class LogInInstance
24 25
    {
25 26
        /// <summary> Date time </summary>
Server/ServerApp/Parser/InputData/WeatherInstance.cs
9 9
    ///     "30.04.2019 16:19:01";20.3;5.3;0;19
10 10
    ///     [date time];[temperature];[wind];[rain];[luminance]
11 11
    /// </summary>
12
    /// <author>Alex Konig</author>
12 13
    class WeatherInstance
13 14
    {
14 15
        /// <summary> Date and time </summary>
Server/ServerApp/Parser/OutputInfo/ActivityInfo.cs
6 6
    /// Class representing the number of events in a given time interval a given faculty
7 7
    /// - shortest possible interval is 1h
8 8
    /// </summary>
9
    /// <author>Alex Konig</author>
9 10
    class ActivityInfo
10 11
    {
11 12
        /// <summary> Faculty </summary>
Server/ServerApp/Parser/OutputInfo/WeatherConditions.cs
3 3
    /// <summary>
4 4
    /// Weather conditions in regards to sun level
5 5
    /// </summary>
6
    /// <author>Alex Konig</author>
6 7
    public enum WeatherConditions
7 8
    {
8 9
        Sunny, Cloudy, Overcast, Dark
......
11 12
    /// <summary>
12 13
    /// Transfers lux values to weather conditions and vice versa
13 14
    /// </summary>
15
    /// <author>Alex Konig</author>
14 16
    public static class LuxToConditions
15 17
    {
16 18
        /// <summary>
......
24 26
                return WeatherConditions.Sunny;
25 27

  
26 28
            if (lux > 20_000)
27
                return WeatherConditions.Cloudy;
28

  
29
            if (lux > 10_000)
30 29
                return WeatherConditions.Overcast;
31 30

  
31
            // TODO tohle bylo 10_000, jak mi to má vycházet, zkusit na hourly data
32
            if (lux != 0)
33
                return WeatherConditions.Cloudy;
34

  
32 35
            return WeatherConditions.Dark;
33 36
        }
34 37

  
Server/ServerApp/Parser/OutputInfo/WeatherInfo.cs
6 6
    /// Class representing the weather in a given interval at ZCU
7 7
    /// - shortest possible interval is 1h
8 8
    /// </summary>
9
    /// <author>Alex Konig</author>
9 10
    class WeatherInfo
10 11
    {
11 12
        /// <summary> Temperature in °C </summary>
......
72 73
        /// <returns>interval start temperature probability of rain wind    weather condition</returns>
73 74
        public override string ToString()
74 75
        {
75
            return $"{startTime.ToString()} \t {temp}°C \t {rain}% \t {wind}m/s \t {condition.ToString()}";
76
            return $"{startTime.ToString()} \t {temp}°C \t {rain}% \t {wind}m/s \t {condition.ToString()} \t {lum}";
76 77
        }
77 78

  
78 79
    }
Server/ServerApp/Parser/Parsers/DataParser.cs
1
using ServerApp.Parser.OutputInfo;
1
using ServerApp.Parser.InputData;
2
using ServerApp.Parser.OutputInfo;
2 3
using System;
3 4
using System.Collections.Generic;
4 5
using System.Globalization;
......
10 11
    /// Class parsing data files into instances of ActivityInfo and WeatherInfo divided by given time interval
11 12
    /// Data parsed from 7am (included) to 18pm (included)
12 13
    /// </summary>
14
    /// <author>Alex Konig</author>
13 15
    class DataParser
14 16
    {
15 17
        /// <summary> Path to data folder </summary>
......
31 33
        /// <summary>
32 34
        /// Constructor
33 35
        /// </summary>
34
        public DataParser()
36
        public DataParser(string path)
35 37
        {
36 38
            TagInfo.CreateDictionaries();
37 39

  
38 40
            // TODO ask for data folder?
39
            path = "data/";
41
            this.path = path;
42
            DataLoader loader = new CsvDataLoader();
40 43

  
41
            weatherParser = new WeatherParser();
42
            jisParser = new JisParser();
43
            loginParser = new LogInParser();
44
            weatherParser = new WeatherParser(loader);
45
            jisParser = new JisParser(loader);
46
            loginParser = new LogInParser(loader);
44 47
        }
45 48

  
46 49
        /// <summary>
......
58 61
            string pathJis = path + "jis";
59 62
            string pathLogIn = path + "login";
60 63

  
61
            weatherList = weatherParser.ParseWeatherData(pathWeather, wholeDay, interval);
64
            weatherList = weatherParser.ParseWeatherData(pathWeather, false, 2); // wholeDay, interval);
62 65
            jisList = jisParser.ParseJisData(pathJis, false, 2); // wholeDay, interval);
63 66
            loginList = loginParser.ParseLogInData(pathLogIn, false, 2); // wholeDay, interval);
64 67

  
Server/ServerApp/Parser/Parsers/JisParser.cs
10 10
    /// Class parsing jis files into instances of ActivityInfo divided by given time interval
11 11
    /// Data parsed from 7am (included) to 18pm (included)
12 12
    /// </summary>
13
    /// <author>Alex Konig</author>
13 14
    class JisParser
14 15
    {
15
        
16

  
17
        /// <summary> Datafile loader  </summary>
18
        DataLoader loader;
19

  
20
        /// <summary>
21
        /// Constructor
22
        /// </summary>
23
        /// <param name="loader">Datafile loader</param>
24
        public JisParser(DataLoader loader)
25
        {
26
            this.loader = loader;
27
        }
28

  
16 29
        /// <summary>
17 30
        /// Parses jis data to ActivityInfo instances
18 31
        /// Data parsed from 7am (included) to 18pm (included)
......
52 65
        /// </summary>
53 66
        /// <param name="path">Path ti file</param>
54 67
        /// <returns>List with ActivityInfo instances</returns>
55
        private static List<ActivityInfo> ProcessOneJisFileAsDays(string path)
68
        private List<ActivityInfo> ProcessOneJisFileAsDays(string path)
56 69
        {
57 70
            if (!File.Exists(path))
58 71
                return null;
59 72

  
60 73
            List<ActivityInfo> jisInfo = new List<ActivityInfo>();
61
            List<JisInstance> list =  CsvDataLoader.LoadJisFile(path);
74
            List<JisInstance> list =  loader.LoadJisFile(path);
62 75

  
63 76
            // data for each faculty
64 77
            int[] recordedAmount = new int[TagInfo.faculties.Length];
......
120 133
            return jisInfo;
121 134
        }
122 135

  
123
        private static List<ActivityInfo> ProcessOneJisFileAsIntervals(string path, int interval)
136
        /// <summary>
137
        /// Parses data from one data file as instance per interval length in a day
138
        /// </summary>
139
        /// <param name="path">Path ti file</param>
140
        /// <param name="interval">Interval length</param>
141
        /// <returns>List with ActivityInfo instances</returns>
142
        private List<ActivityInfo> ProcessOneJisFileAsIntervals(string path, int interval)
124 143
        {
125 144
            if (!File.Exists(path))
126 145
                return null;
127 146

  
128 147
            List<ActivityInfo> jisInfo = new List<ActivityInfo>();
129
            List<JisInstance> list = CsvDataLoader.LoadJisFile(path);
148
            List<JisInstance> list = loader.LoadJisFile(path);
130 149

  
131 150
            // data for each faculty
132 151
            int[] recordedAmount = new int[TagInfo.faculties.Length];
Server/ServerApp/Parser/Parsers/LogInParser.cs
10 10
    /// Class parsing login files into instances of ActivityInfo divided by given time interval
11 11
    /// Data parsed from 7am (included) to 18pm (included)
12 12
    /// </summary>
13
    /// <author>Alex Konig</author>
13 14
    class LogInParser
14 15
    {
16
        /// <summary> Datafile loader  </summary>
17
        DataLoader loader;
18

  
19
        /// <summary>
20
        /// Constructor
21
        /// </summary>
22
        /// <param name="loader">Datafile loader</param>
23
        public LogInParser(DataLoader loader)
24
        {
25
            this.loader = loader;
26
        }
27

  
15 28
        /// <summary>
16 29
        /// Parses login data to ActivityInfo instances
17 30
        /// Data parsed from 7am (included) to 18pm (included)
......
51 64
        /// </summary>
52 65
        /// <param name="path">Path ti file</param>
53 66
        /// <returns>List with ActivityInfo instances</returns>
54
        private static List<ActivityInfo> ProcessOneLogInFileAsDays(string path)
67
        private List<ActivityInfo> ProcessOneLogInFileAsDays(string path)
55 68
        {
56 69
            if (!File.Exists(path))
57 70
                return null;
58 71

  
59 72
            List<ActivityInfo> loginInfo = new List<ActivityInfo>();
60
            List<LogInInstance> list = CsvDataLoader.LoadLoginFile(path);
73
            List<LogInInstance> list = loader.LoadLoginFile(path);
61 74

  
62 75
            // data for each faculty
63 76
            int[] recordedAmount = new int[TagInfo.faculties.Length];
......
126 139
            return loginInfo;
127 140
        }
128 141

  
129
        private static List<ActivityInfo> ProcessOneLoginFileAsIntervals(string path, int interval)
142
        /// <summary>
143
        /// Parses data from one data file as one instance per interval length
144
        /// </summary>
145
        /// <param name="path">Path to file</param>
146
        /// <param name="interval">Interval length</param>
147
        /// <returns>List with ActivityInfo instances</returns>
148
        private List<ActivityInfo> ProcessOneLoginFileAsIntervals(string path, int interval)
130 149
        {
131 150
            if (!File.Exists(path))
132 151
                return null;
133 152

  
134 153
            List<ActivityInfo> loignInfo = new List<ActivityInfo>();
135
            List<LogInInstance> list = CsvDataLoader.LoadLoginFile(path);
154
            List<LogInInstance> list = loader.LoadLoginFile(path);
136 155

  
137
            // data for each faculty
138
            int[] recordedAmount = new int[TagInfo.faculties.Length];
139 156
            // min/max hour taken into account
140 157
            int[] minmaxHour = new int[] { 7, 18 };
141 158
            int range = minmaxHour[1] - minmaxHour[0];
Server/ServerApp/Parser/Parsers/TagInfo.cs
2 2

  
3 3
namespace ServerApp.Parser.Parsers
4 4
{
5
    /// <author>Alex Konig</author>
5 6
    class TagInfo
6 7
    {
7 8
        public static string[] faculties;
Server/ServerApp/Parser/Parsers/WeatherParser.cs
10 10
    /// Class parsing weather files into instances of WeatherInfo divided by given time interval
11 11
    /// Data parsed from 7am (included) to 18pm (included)
12 12
    /// </summary>
13
    /// <author>Alex Konig</author>
13 14
    class WeatherParser
14 15
    {
16

  
17
        /// <summary> Datafile loader  </summary>
18
        DataLoader loader;
19

  
20
        /// <summary>
21
        /// Constructor
22
        /// </summary>
23
        /// <param name="loader">Datafile loader</param>
24
        public WeatherParser(DataLoader loader)
25
        {
26
            this.loader = loader;
27
        }
28

  
15 29
        /// <summary>
16 30
        /// Parses weather data to WeatherInfo instances
17 31
        /// Data parsed from 7am (included) to 18pm (included)
......
39 53
                // parse according to interval
40 54
                else
41 55
                {
42
                    // pokud: konec dne nebo konec aktuálního intervalu -> vemu to co sem nasčítal
43
                    throw new NotImplementedException();
56
                    loadedData = ProcessOneWeatherFileAsIntervals(fileName, interval);
44 57
                }
45 58

  
46 59
                list.AddRange(loadedData);
......
54 67
        /// </summary>
55 68
        /// <param name="path">Path ti file</param>
56 69
        /// <returns>List with WeatherInfo instances</returns>
57
        private static List<WeatherInfo> ProcessOneWeatherFileAsDays(string path)
70
        private List<WeatherInfo> ProcessOneWeatherFileAsDays(string path)
58 71
        {
59 72
            if (!File.Exists(path))
60 73
                return null;
61 74

  
62 75
            List<WeatherInfo> weatherInfo = new List<WeatherInfo>();
63
            List<WeatherInstance> list = CsvDataLoader.LoadWeatherFile(path);
76
            List<WeatherInstance> list = loader.LoadWeatherFile(path);
64 77

  
65 78
            // array with data [temp, rain, wind, lum]
66 79
            double[] recordedAmount = new double[4];
......
72 85
            // first day
73 86
            DateTime lastStartDay = new DateTime(list[0].dateTime.Year, list[0].dateTime.Month, list[0].dateTime.Day, minmaxHour[0], 0, 0);
74 87
            // number of values in day
75
            int values = 0;
88
            int values = 0, weatherValues = 0;
76 89
            for (int i = 0; i < list.Count; i++)
77 90
            {
78 91
                int currHour = list[i].dateTime.Hour;
......
83 96
                DateTime date = new DateTime(list[i].dateTime.Year, list[i].dateTime.Month, list[i].dateTime.Day, minmaxHour[0], 0, 0);
84 97
                if (!date.Equals(lastStartDay))
85 98
                {
86
                    WeatherInfo dayInfo = new WeatherInfo(lastStartDay, recordedAmount[0] / values, (int)(recordedAmount[1] / values * 100), recordedAmount[2] / values, recordedAmount[3] / values, range); 
99
                    WeatherInfo dayInfo = new WeatherInfo(lastStartDay, recordedAmount[0] / values, (int)(recordedAmount[1] / values * 100), recordedAmount[2] / values, recordedAmount[3] / weatherValues, range); 
87 100
                    weatherInfo.Add(dayInfo);
88 101

  
89 102
                    recordedAmount = new double[4];
90 103
                    lastStartDay = date;
91 104
                    values = 0;
105
                    weatherValues = 0;
92 106
                }
93 107

  
94 108
                // aggregate data
95 109
                recordedAmount[0] += list[i].temp;
96 110
                recordedAmount[1] += list[i].rain;
97 111
                recordedAmount[2] += list[i].wind;
98
                recordedAmount[3] += list[i].lum * 1000;
112

  
113
                if (LuxToConditions.TransferLuxToConditions(list[i].lum * 1000) != WeatherConditions.Dark)
114
                    recordedAmount[3] += list[i].lum * 1000; weatherValues++;
99 115

  
100 116
                values++;
101 117
            }
......
107 123
            return weatherInfo;
108 124
        }
109 125

  
110
        private static List<ActivityInfo> ProcessOneWeatherFileAsIntervals(string path, int interval)
126
        /// <summary>
127
        /// Parses data from one data file as one instance per interval length
128
        /// </summary>
129
        /// <param name="path">Path to file</param>
130
        /// <param name="interval">Interval length</param>
131
        /// <returns>List with ActivityInfo instances</returns>
132
        private List<WeatherInfo> ProcessOneWeatherFileAsIntervals(string path, int interval)
111 133
        {
112
            throw new NotImplementedException();
134
            if (!File.Exists(path))
135
                return null;
136

  
137
            List<WeatherInfo> loignInfo = new List<WeatherInfo>();
138
            List<WeatherInstance> list = loader.LoadWeatherFile(path);
139

  
140
            // min/max hour taken into account
141
            int[] minmaxHour = new int[] { 7, 18 };
142
            int range = minmaxHour[1] - minmaxHour[0];
143

  
144
            if (interval > range)
145
                return null;
146

  
147
            int indices = (int)Math.Ceiling(range / (double)interval);
148
            int[] to = new int[indices];
149
            double[][] data = new double[indices][];
150
            int[] count = new int[indices];
151
            for (int i = 0; i < to.Length; i++)
152
            {
153
                to[i] = minmaxHour[0] + interval * (i + 1);
154
                data[i] = new double[4];
155
            }
156

  
157
            // first day
158
            DateTime lastStartTime = new DateTime(list[0].dateTime.Year, list[0].dateTime.Month, list[0].dateTime.Day, minmaxHour[0], 0, 0);
159
            int index;
160
            for (int i = 0; i < list.Count; i++)
161
            {
162
                int currHour = list[i].dateTime.Hour;
163
                if (currHour < minmaxHour[0] || currHour > minmaxHour[1])
164
                    continue;
165

  
166
                // start of the day -> make an instance
167
                DateTime date = new DateTime(list[i].dateTime.Year, list[i].dateTime.Month, list[i].dateTime.Day, list[i].dateTime.Hour, 0, 0);
168

  
169
                // end of the day
170
                if (!(date.Year == lastStartTime.Year && date.Month == lastStartTime.Month && date.Day == lastStartTime.Day))
171
                {
172
                    // note down all aggregated data
173
                    for (int k = 0; k < to.Length; k++)
174
                    {
175
                        int raincount = 0;
176
                        double rainval = 0;;
177
                        for (int l = 0; l <= k; l++)
178
                        {
179
                            raincount += count[l];
180
                            rainval += data[l][1];
181
                        }
182

  
183
                        DateTime stTime = new DateTime(lastStartTime.Year, lastStartTime.Month, lastStartTime.Day, to[k] - interval, 0, 0);
184

  
185
                        WeatherInfo intervalInfo = new WeatherInfo(stTime, data[k][0] / count[k], (int)((rainval / raincount) * 100), data[k][2] / count[k], data[k][3] / count[k], interval);
186
                        if (count[k] != 0)
187
                            loignInfo.Add(intervalInfo);
188

  
189
                    }
190

  
191
                    lastStartTime = date;
192
                    count = new int[indices];
193
                    for (int l = 0; l < data.Length; l++)
194
                        data[l] = new double[4];
195
                }
196

  
197
                // find index for current instance
198
                index = 0;
199
                for (int k = 1; k < to.Length; k++)
200
                {
201
                    if (to[k] > list[i].dateTime.Hour && to[k - 1] <= list[i].dateTime.Hour)
202
                    {
203
                        index = k;
204
                        break;
205
                    }
206
                }
207

  
208
                // aggregate data
209
                data[index][0] += list[i].temp;
210
                data[index][1] += list[i].rain;
211
                data[index][2] += list[i].wind;
212
                data[index][3] += list[i].lum * 1000;
213
                count[index]++;
214

  
215
            }
216

  
217
            for (int k = 0; k < to.Length; k++)
218
            {
219
                int raincount = 0;
220
                double rainval = 0; ;
221
                for (int l = 0; l <= k; l++)
222
                {
223
                    raincount += count[l];
224
                    rainval += data[l][1];
225
                }
226

  
227
                DateTime stTime = new DateTime(lastStartTime.Year, lastStartTime.Month, lastStartTime.Day, to[k] - interval, 0, 0);
228

  
229
                WeatherInfo intervalInfo = new WeatherInfo(stTime, data[k][0] / count[k], (int)((rainval / raincount) * 100), data[k][2] / count[k], data[k][3] / count[k], interval);
230
                if (count[k] != 0)
231
                    loignInfo.Add(intervalInfo);
232
            }
233

  
234
            return loignInfo;
113 235
        }
114 236
    }
237

  
115 238
}
Server/ServerApp/Program.cs
7 7
    {
8 8
        static void Main(string[] args)
9 9
        {
10
            DataParser p = new DataParser();
10
            DataParser p = new DataParser("data/");
11 11

  
12 12
            p.Parse();
13 13

  
Server/ServerApp/ServerApp.csproj
45 45
  <ItemGroup>
46 46
    <Compile Include="obj\Debug\.NETFramework,Version=v4.7.2.AssemblyAttributes.cs" />
47 47
    <Compile Include="Parser\InputData\CsvDataLoader.cs" />
48
    <Compile Include="Parser\InputData\DataLoader.cs" />
48 49
    <Compile Include="Parser\InputData\JisInstance.cs" />
49 50
    <Compile Include="Parser\InputData\LogInInstance.cs" />
50 51
    <Compile Include="Parser\InputData\WeatherInstance.cs" />
......
123 124
    <Folder Include="bin\Release\" />
124 125
    <Folder Include="obj\Debug\TempPE\" />
125 126
  </ItemGroup>
127
  <ItemGroup>
128
    <WCFMetadata Include="Connected Services\" />
129
  </ItemGroup>
126 130
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
127 131
</Project>
Server/ServerApp/data/jis/OD_ZCU_JIS_13_2019.CSV
1 1
"M14";"01.12.2019 07:03:03";1
2 2
"L1L2-vchod";"01.12.2019 07:22:38";1
3 3
"L2";"01.12.2019 08:22:53";1
4
"A1";"01.12.2019 09:31:19";1
5
"M14";"01.12.2019 10:35:40";1
4
"A1";"01.12.2019 14:31:19";1
5
"M14";"01.12.2019 14:35:40";1
6 6
"A3";"02.12.2019 07:47:04";1
7 7
"L2";"02.12.2019 10:48:11";1
8 8
"A1";"02.12.2019 11:53:10";1
Server/ServerApp/data/weather/OD_ZCU_POCASI_13_2019.CSV
10 10
"01.06.2019 02:15:44";14.3;.6;0;0
11 11
"01.06.2019 02:30:44";14.2;1.1;0;0
12 12
"01.06.2019 02:45:44";14.2;.1;0;0
13
"01.06.2019 03:00:44";14.4;.3;0;0
14
"02.06.2019 03:15:44";14.3;.3;0;0
15
"02.06.2019 03:30:44";14.3;.1;0;0
16
"02.06.2019 03:45:45";14.2;.2;0;0
17
"02.06.2019 04:00:45";13.9;0;0;0
18
"02.06.2019 04:15:45";13.8;1;0;0
19
"02.06.2019 04:30:45";13.5;.2;0;0
20
"02.06.2019 04:45:45";13.2;0;0;0
21
"02.06.2019 05:00:45";13.4;.2;0;0
22
"02.06.2019 05:15:46";13.4;.3;0;
23
"02.06.2019 05:30:46";13.4;.2;0;5
24
"02.06.2019 05:45:46";13.2;.3;0;3
25
"02.06.2019 06:00:46";13.1;.5;0;8.7
26
"02.06.2019 06:15:46";13.7;0;0;27.5
13
"01.06.2019 07:00:44";14.4;.3;0;0
14
"02.06.2019 07:15:44";14.3;.3;0;0
15
"02.06.2019 08:30:44";14.3;.1;1;0
16
"02.06.2019 09:45:45";14.2;.2;1;0
17
"02.06.2019 10:00:45";13.9;0;0;0
18
"02.06.2019 11:15:45";13.8;1;0;0
19
"02.06.2019 12:30:45";13.5;.2;1;0
20
"02.06.2019 13:45:45";13.2;0;0;0
21
"02.06.2019 14:00:45";13.4;.2;1;0
22
"02.06.2019 15:15:46";13.4;.3;0;
23
"02.06.2019 16:30:46";13.4;.2;1;5
24
"02.06.2019 17:45:46";13.2;.3;0;3
25
"02.06.2019 18:00:46";13.1;.5;1;8.7
26
"02.06.2019 19:15:46";13.7;0;0;27.5
27 27
"03.06.2019 06:30:46";15;0;0;36.6
28 28
"03.06.2019 06:45:46";16.2;.1;0;44.9
29 29
"03.06.2019 07:00:47";16.7;.1;0;46.2

Také k dispozici: Unified diff