Разделить класс ReportMaker по ответственности за оформление отчета и за исчисление показателей: Как угодить NUnitLite ?
15.11.2020, 12:17. Показов 1920. Ответов 1
Задание №1
Петр разработал генератор отчетов в проекте Delegates.Reports, который считает простую статистику о погоде по нескольким параметрам через несколько дней.
Его генератор может создавать два отчета: отчет в HTML, который считает среднее и стандартное отклонение, и отчет в Markdown, который считает медианы.
Однако, что делать, если нужно посчитать медианы и вывести результат в HTML? А если нужен будет третий отчет в HTML?
Текущее решение крайне неудобно для таких ситуаций.
Помогите Петру перевести его код по наследованию на делегирование.
Разделите ответственности за оформление отчета и по исчислению показателей.
В результате сам класс ReportMaker вам, возможно, уже и не понадобится.
Program.cs
C#
Скопировано | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| /*Завдання 1
Петро розробив генератор звітів в проекті Delegates.Reports, який рахує просту статистику про погоду за кількома параметрами за кілька днів.
Його генератор може створювати два звіти: звіт в HTML, який рахує середнє і стандартне відхилення, і звіт в Markdown, який рахує медіани.
Однак, що робити, якщо потрібно порахувати медіани і вивести результат в HTML?
А якщо потрібен буде третій звіт в HTML?
Поточне рішення вкрай незручно для таких ситуацій.
Допоможіть Петру перевести його код з успадкування на делегування.
Розділіть відповідальності за оформлення звіту і по обчисленню показників.
В результаті сам клас ReportMaker вам, можливо, вже й не знадобиться.
*/
using NUnitLite;
namespace _12112020dz
{
class Program
{
static void Main(string[] args)
{
new AutoRun().Execute(args);
}
}
} |
|
MeanAndStd.cs
C#
Скопировано | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| using System.Globalization;
namespace _12112020dz
{
public class MeanAndStd
{
public double Mean { get; set; }
public double Std { get; set; }
public override string ToString()
{
return Mean.ToString(CultureInfo.InvariantCulture) + "±" + Std.ToString(CultureInfo.InvariantCulture); //Возможно проблема тут
}
}
}
/* // оригинал:
using System.Globalization;
namespace _12112020dz
{
public class MeanAndStd
{
public double Mean { get; set; }
public double Std { get; set; }
public override string ToString()
{
return Mean.ToString(CultureInfo.InvariantCulture) + "±" + Std.ToString(CultureInfo.InvariantCulture);
}
}
}
*/ |
|
Measurement.cs
C#
Скопировано | 1
2
3
4
5
6
7
8
| namespace _12112020dz
{
public class Measurement
{
public double Temperature { get; set; }
public double Humidity { get; set; }
}
} |
|
ReportMaker.cs
C#
Скопировано | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
| using System;
using System.Collections.Generic;
using System.Linq;
namespace _12112020dz
{
public static class ReportCalculation
{
public static object MakeStatisticsMeanAndStd(IEnumerable<double> _data)
{
var data = _data.ToList();
var mean = data.Average();
var std = Math.Sqrt(data.Select(z => Math.Pow(z - mean, 2)).Sum() / (data.Count - 1));
return new MeanAndStd { Mean = mean, Std = std };
}
public static object MakeStatisticsMedian(IEnumerable<double> data)
{
var list = data.OrderBy(z => z).ToList();
if (list.Count % 2 == 0)
return (list[list.Count / 2] + list[list.Count / 2 - 1]) / 2;
return list[list.Count / 2];
}
}
public static class WrapperReportMaker
{
public static string HTMLReportMaker(string caption, IEnumerable<Measurement> data, Func<IEnumerable<double>, object> func)
{
var temperature = func(data.Select(e => e.Temperature));
var humidity = func(data.Select(e => e.Humidity));
return $"<h1>{caption}</h1><ul><li><b>Temperature</b>: {temperature}<li><b>Humidity</b>: {humidity}</ul>";
}
public static string MarkdownReportMaker(string caption, IEnumerable<Measurement> data, Func<IEnumerable<double>, object> func)
{
var temperature = func(data.Select(e => e.Temperature));
var humidity = func(data.Select(e => e.Humidity));
return $"## {caption}\n\n * **Temperature**: {temperature}\n\n * **Humidity**: {humidity}\n\n";
}
}
public static class ReportMakerHelper
{
public static string MeanAndStdHtmlReport(IEnumerable<Measurement> data)
{
return WrapperReportMaker.HTMLReportMaker("Mean and Std", data, ReportCalculation.MakeStatisticsMeanAndStd);
}
public static string MedianMarkdownReport(IEnumerable<Measurement> data)
{
return WrapperReportMaker.MarkdownReportMaker("Median", data, ReportCalculation.MakeStatisticsMedian);
}
public static string MeanAndStdMarkdownReport(IEnumerable<Measurement> measurements)
{
return WrapperReportMaker.MarkdownReportMaker("Mean and Std", measurements, ReportCalculation.MakeStatisticsMeanAndStd);
}
public static string MedianHtmlReport(IEnumerable<Measurement> measurements)
{
return WrapperReportMaker.HTMLReportMaker("Median", measurements, ReportCalculation.MakeStatisticsMedian);
}
}
//public abstract class ReportMaker
//{
// protected abstract string MakeCaption(string caption);
// protected abstract string BeginList();
// protected abstract string MakeItem(string valueType, string entry);
// protected abstract string EndList();
// protected abstract object MakeStatistics(IEnumerable<double> data);
// protected abstract string Caption { get; }
// public string MakeReport(IEnumerable<Measurement> measurements)
// {
// var data = measurements.ToList();
// var result = new StringBuilder();
// result.Append(MakeCaption(Caption));
// result.Append(BeginList());
// result.Append(MakeItem("Temperature", MakeStatistics(data.Select(z => z.Temperature)).ToString()));
// result.Append(MakeItem("Humidity", MakeStatistics(data.Select(z => z.Humidity)).ToString()));
// result.Append(EndList());
// return result.ToString();
// }
//}
//public class MeanAndStdHtmlReportMaker : ReportMaker
//{
// protected override string Caption
// {
// get
// {
// return "Mean and Std";
// }
// }
// protected override string MakeCaption(string caption)
// {
// return $"<h1>{caption}</h1>";
// }
// protected override string BeginList()
// {
// return "<ul>";
// }
// protected override string EndList()
// {
// return "</ul>";
// }
// protected override string MakeItem(string valueType, string entry)
// {
// return $"<li><b>{valueType}</b>: {entry}";
// }
// protected override object MakeStatistics(IEnumerable<double> _data)
// {
// var data = _data.ToList();
// var mean = data.Average();
// var std = Math.Sqrt(data.Select(z => Math.Pow(z - mean, 2)).Sum() / (data.Count - 1));
// return new MeanAndStd
// {
// Mean = mean,
// Std = std
// };
// }
//}
//public class MedianMarkdownReportMaker : ReportMaker
//{
// protected override string Caption
// {
// get
// {
// return "Median";
// }
// }
// protected override string BeginList()
// {
// return "";
// }
// protected override string EndList()
// {
// return "";
// }
// protected override string MakeCaption(string caption)
// {
// return $"## {caption}\n\n";
// }
// protected override string MakeItem(string valueType, string entry)
// {
// return $" * **{valueType}**: {entry}\n\n";
// }
// protected override object MakeStatistics(IEnumerable<double> data)
// {
// var list = data.OrderBy(z => z).ToList();
// if (list.Count % 2 == 0)
// return (list[list.Count / 2] + list[list.Count / 2 - 1]) / 2;
// return list[list.Count / 2];
// }
//}
//public static class ReportMakerHelper
//{
// public static string MeanAndStdHtmlReport(IEnumerable<Measurement> data)
// {
// return new MeanAndStdHtmlReportMaker().MakeReport(data);
// }
// public static string MedianMarkdownReport(IEnumerable<Measurement> data)
// {
// return new MedianMarkdownReportMaker().MakeReport(data);
// }
// public static string MeanAndStdMarkdownReport(IEnumerable<Measurement> measurements)
// {
// throw new NotImplementedException();
// }
// public static string MedianHtmlReport(IEnumerable<Measurement> measurements)
// {
// throw new NotImplementedException();
// }
//}
} |
|
ReportMaker_should.cs
C#
Скопировано | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
| using NUnit.Framework;
using System.Collections.Generic;
namespace _12112020dz
{
[TestFixture]
public class ReportMaker_should
{
private readonly List<Measurement> data = new List<Measurement>
{
new Measurement
{
Humidity=1,
Temperature=-10,
},
new Measurement
{
Humidity=2,
Temperature=2,
},
new Measurement
{
Humidity=3,
Temperature=14
},
new Measurement
{
Humidity=2,
Temperature=30
}
};
[Test]
public void MeanAndStdHtml()
{
var expected = @"<h1>Mean and Std</h1><ul><li><b>Temperature</b>: 9±17.0880074906351<li><b>Humidity</b>: 2±0.816496580927726</ul>";
var actual = ReportMakerHelper.MeanAndStdHtmlReport(data);
Assert.AreEqual(expected, actual); // вылетает:
/*NUnit.Framework.AssertionException: ' Expected string length 112 but was 113. Strings differ at index 66.
Expected: "...7.0880074906351<li><b>Humidity</b>: 2±0.816496580927726</ul>"
But was: "...7.08800749063506<li><b>Humidity</b>: 2±0.816496580927726</ul>"
----------------------------^
'
*/
}
[Test]
public void MedianMarkdown()
{
var expected = "## Median\n\n * **Temperature**: 8\n\n * **Humidity**: 2\n\n";
var actual = ReportMakerHelper.MedianMarkdownReport(data);
Assert.AreEqual(expected, actual);
}
[Test(Description = "Новый тест, который нужно сделать рабочим после рефакторинга")]
public void MeanAndStdMarkdown()
{
var expected = "## Mean and Std\n\n * **Temperature**: 9±17.0880074906351\n\n * **Humidity**: 2±0.816496580927726\n\n";
var actual = ReportMakerHelper.MeanAndStdMarkdownReport(data);
Assert.AreEqual(expected, actual); // вылетает:
/*NUnit.Framework.AssertionException: ' Expected string length 95 but was 96. Strings differ at index 54.
Expected: "...: 9±17.0880074906351\n\n * **Humidity**: 2±0.816496580927726\n\n"
But was: "...: 9±17.08800749063506\n\n * **Humidity**: 2±0.816496580927726\n\n"
---------------------------------^
'
*/
}
[Test(Description = "Новый тест, который нужно сделать рабочим после рефакторинга")]
public void MedianHtml()
{
var expected = "<h1>Median</h1><ul><li><b>Temperature</b>: 8<li><b>Humidity</b>: 2</ul>";
var actual = ReportMakerHelper.MedianHtmlReport(data);
Assert.AreEqual(expected, actual);
}
}
} |
|
Вылетает на тестах, в файле ReportMaker_should.cs
Как исправить/угодить NUnitLite ? Кажется, там что-то с округлением:
9±17.0880074906351
9±17.08800749063506
Заранее спасибо за ответы.
0
|