-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMapping.cpp
100 lines (83 loc) · 2.61 KB
/
Mapping.cpp
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
#include <algorithm>
#include <cstdio>
#include <memory>
#include "common.h"
#include "Logger.h"
#include "Mapping.h"
extern Logger logger;
Result<Mapping>
Mapping::parseFromString(std::string mappingString) {
// e.g. "5:30, 10:60, 40:420"
std::vector<MappingPoint> points;
auto segments = splitString(mappingString, ", ");
for (auto &segment : segments) {
int degreesC;
int seconds;
if (std::sscanf(segment.c_str(), "%d:%d", °reesC, &seconds) != 2) {
return Result<Mapping>::failure(
"Bad mapping point: " + segment);
}
Temperature temperature = Temperature::forDegreesC(degreesC);
if (!(MIN_TEMPERATURE <= temperature
&& temperature <= MAX_TEMPERATURE)) {
return Result<Mapping>::failure(formatString(
"Temperature out of range: %s",
temperature.toString().c_str()));
}
if (!(MIN_DURATION <= seconds && seconds <= MAX_DURATION)) {
return Result<Mapping>::failure(formatString(
"Duration out of range: %d", seconds));
}
if (!points.empty() && temperature <= points.back().temperature) {
return Result<Mapping>::failure(
"Mapping points not in increasing order: " + segment);
}
points.push_back({temperature , seconds });
}
return Result<Mapping>::success(
std::unique_ptr<Mapping>(new Mapping(points)));
}
int
Mapping::mapTemperatureToSeconds(Temperature const &temperature) const {
auto lesserIt = std::find_if(
points.rbegin(), points.rend(), [&] (MappingPoint const &point) {
return point.temperature <= temperature;
});
MappingPoint const *lesser =
lesserIt != points.rend() ? &(*lesserIt) : nullptr;
auto greaterIt = std::find_if(
points.begin(), points.end(), [&] (MappingPoint const &point) {
return point.temperature >= temperature;
});
MappingPoint const *greater =
greaterIt != points.end() ? &(*greaterIt) : nullptr;
if (lesser && greater) {
int temperatureDelta = temperature.degree16thsC
- lesser->temperature.degree16thsC;
int timeSpan = greater->seconds - lesser->seconds;
int temperatureSpan = greater->temperature.degree16thsC
- lesser->temperature.degree16thsC;
int timeDelta = temperatureDelta * timeSpan / temperatureSpan;
return lesser->seconds + timeDelta;
} else if (greater) {
return greater->seconds;
} else if (lesser) {
return lesser->seconds;
} else {
return 0;
}
}
std::string
Mapping::toString() const {
std::string string;
for (auto it = points.begin(); it != points.end(); it++) {
if (it != points.begin()) {
string += ", ";
}
char segment[10];
snprintf(segment, sizeof(segment), "%d:%d",
it->temperature.degreesC(), it->seconds);
string += segment;
}
return string;
}