-
Notifications
You must be signed in to change notification settings - Fork 0
/
Sauna.cs
160 lines (130 loc) · 4 KB
/
Sauna.cs
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
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
public class Sauna : Room
{
private List<SaunaConfiguration> configurations;
private const int NORMAL_TEMP = 22;
private const int MAX_TEMP = 90;
private const string DATE = "yyyy-MM-dd";
private const string TIME = "HH:mm";
public Sauna() : base()
{
configurations = new List<SaunaConfiguration>();
}
public SaunaConfiguration AddConfiguration(SaunaConfiguration conf)
{
if(conf.Sauna != this.Id)
{
throw new ApplicationException("Configuration vs sauna id mismatch!");
}
if(isDateTimeOverlapped(conf))
{
throw new ApplicationException("The sauna is already configured for the given time!");
}
configurations.Add(conf);
return conf;
}
public SaunaState GetState(DateTime dt)
{
SaunaState state = new SaunaState();
//the sauna is off
state.Sauna = this.Id;
state.DateTime = dt;
state.Stove = "Off";
state.Light = "Off";
state.Temperature = NORMAL_TEMP;
SaunaConfiguration conf = getMatchingConfiguration(dt);
if (conf == null)
{
return state;
}
state.Temperature = getTemperature(conf, dt);
//turn the light on when it's hot enough
state.Light = state.Temperature > 60 ? "On" : "Off";
//turn the stove on / off if it's too cold / hot
state.Stove = state.Temperature < MAX_TEMP ? "On" : "Off";
DateTime offTime = parseTime(conf.Off, dt.ToString(DATE));
if (dt >= offTime)
{
state.Light = "Off";
state.Stove = "Off";
}
return state;
}
private bool isDateTimeOverlapped(SaunaConfiguration conf)
{
foreach(SaunaConfiguration existingConf in configurations.Where(c => c.DayOfWeek == conf.DayOfWeek))
{
if(isTimeOverlapped(conf.On, conf.Off, existingConf.On, existingConf.Off))
{
return true;
}
}
return false;
}
private bool isTimeOverlapped(string t1On, string t1Off, string t2On, string t2Off)
{
DateTime dt1On = parseTime(t1On);
DateTime dt1Off = parseTime(t1Off);
DateTime dt2On = parseTime(t2On);
DateTime dt2Off = parseTime(t2Off);
if(dt1On >= dt2On && dt1On <= dt2Off)
{
return true;
}
if (dt2On >= dt1On && dt2On <= dt1Off)
{
return true;
}
return false;
}
private DateTime parseTime(string time, string date = "2001-01-01")
{
try
{
return DateTime.ParseExact(date + " " + time.Trim(), DATE + " " + TIME, CultureInfo.InvariantCulture); ;
}catch(Exception)
{
throw new ApplicationException("Failed parsing time; time is expected to be in " + TIME + " format.");
}
}
private int getTemperature(SaunaConfiguration conf, DateTime dt)
{
DateTime on = parseTime(conf.On, dt.ToString(DATE));
DateTime off = parseTime(conf.Off, dt.ToString(DATE));
double temp;
if(dt < off)
{
//warming up
temp = NORMAL_TEMP + 2.3 * (dt - on).TotalMinutes;
}
else
{
//cooling down
temp = MAX_TEMP - 0.5 * (dt - off).TotalMinutes;
}
if(temp > MAX_TEMP)
{
temp = MAX_TEMP;
}
if(temp < NORMAL_TEMP)
{
temp = NORMAL_TEMP;
}
return (int)temp;
}
private SaunaConfiguration getMatchingConfiguration(DateTime dt)
{
string time = dt.ToString(TIME);
foreach(SaunaConfiguration conf in configurations.Where(c => c.DayOfWeek == dt.DayOfWeek))
{
if(isTimeOverlapped(time, time, conf.On, conf.Off))
{
return conf;
}
}
return null;
}
}