-
Notifications
You must be signed in to change notification settings - Fork 1
/
User.java
231 lines (214 loc) · 5.43 KB
/
User.java
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
import java.util.ArrayList;
import java.util.List;
/**
* A class to represent a user.
*
* @version 0.2
*/
public class User {
private List<HistoryData> history;
private HistoryData currentValues;
private History historyStore;
private int age;
private int weight;
private double position;
/* Cache variables: these should be the sums of all the values in
* this.history; to get usable data while running, add in the values in
* currentValues. */
private double timeElapsedCache;
private double totalDistanceCache;
/** Half the length of the treadmill, in feet. */
private static final double HALF_TM_LENGTH = 2.5;
/**
* Default constructor. Uses default values of 30 years and 150 lbs.
*
* @param hist history tab that we'll update
*/
public User(History hist) {
this(hist, 30, 150);
}
/**
* User constructor.
*
* @param hist history tab that we'll update
* @param age age in years
* @param weight weight in lbs
*/
public User(History hist, int age, int weight) {
historyStore = hist;
this.age = age;
this.weight = weight;
reset();
}
/**
* Forgets the history data. Resets as if to a newly-created object.
*/
public void reset() {
reorient();
timeElapsedCache = 0.0;
totalDistanceCache = 0.0;
/* Pre-allocate memory for 50 */
history = new ArrayList<HistoryData>(50);
currentValues = new HistoryData(0, 0);
}
/**
* Puts the runner back in the middle of the treadmill. This should be
* called, e.g., when the treadmill is paused or stopped.
*/
public void reorient() {
position = 0;
}
/**
* Updates the speed and position of the runner based on the speed of
* the treadmill.
*
* @param timeSpan number of seconds since last update
* @param treadmillSpeed speed of the treadmill in tenths of a mph
* @return if the user is safely on the treadmill
*/
public boolean update(double timeSpan, int treadmillSpeed) {
// feet = 10*mph * s / (s/hr) * (feet/mile / 10)
position += (currentValues.getSpeed() - treadmillSpeed) * timeSpan / 3600.0 * 528.0;
timeElapsedCache += timeSpan;
currentValues.update(timeSpan);
return (position >= -HALF_TM_LENGTH) && (position <= HALF_TM_LENGTH);
}
/**
* Sets a new speed for the runner.
*
* @param sp new speed in tenths of a mile per hour
*/
public void setSpeed(int sp) {
if (currentValues.getSpeed() == sp) return;
int inclineSetting = currentValues.getIncline();
if (currentValues.getTime() > 0.0) {
saveHistoryData();
}
currentValues = new HistoryData(sp, inclineSetting);
}
/**
* Sets a new inclination for the runner.
*
* @param inc new inclination in percent
*/
public void setIncline(int inc) {
if (currentValues.getIncline() == inc) return;
int speedSetting = currentValues.getSpeed();
if (currentValues.getTime() > 0.0) {
saveHistoryData();
}
currentValues = new HistoryData(speedSetting, inc);
}
/**
* Speed of the runner.
*
* @return current speed in mph
*/
public double getSpeed() {
return currentValues.getSpeed() / 10.0;
}
/**
* Average speed throughout the session.
*
* @return average speed in mph
*/
public double getAverageSpeed() {
if (timeElapsedCache > 0.0) {
return getDistance() * 3600.0 / timeElapsedCache;
} else {
return 0.0;
}
}
/**
* Total distance run.
*
* @return distance run in miles
*/
public double getDistance() {
return totalDistanceCache + currentValues.getDistance();
}
/**
* Total time spent running
*
* @return time run in seconds
*/
public double getTimeElapsed() {
return timeElapsedCache;
}
/**
* Calories burnt.
*
* @return calories burnt while running
*/
public int getCalories() {
double cal = currentValues.getCalories(age, weight);
for (HistoryData curHist : history) {
cal += curHist.getCalories(age, weight);
}
return (int)cal;
}
/**
* Returns the relative position of the user.
*
* @return Distance from center of treadmill in feet
*/
public double getPosition() { return position; }
/**
* Returns the weight of the user.
*
* @return Weight of the user in lbs
*/
public int getWeight() { return weight; }
/**
* Returns the age of the user.
*
* @return Age of the user in years
*/
public int getAge() { return age; }
/**
* Sets the weight of the user.
*
* @param weight weight of the user in lbs
*/
public void setWeight(int weight) {
this.weight = weight;
/* We need to update the history; calories are calculated based
* on the weight. */
recalculateHistory();
}
/**
* Sets the age of the user.
*
* @param age age of the user in years
*/
public void setAge(int age) { this.age = age; }
/**
* Saves the history data. Call this when you want to put
* <tt>currentValues</tt> into the <tt>history</tt> data store.
*/
private void saveHistoryData() {
totalDistanceCache += currentValues.getDistance();
history.add(currentValues);
addHistoryLine(currentValues);
}
/**
* Adds a single line to the History tab.
*
* @param which HistoryData value to add
*/
private void addHistoryLine(HistoryData which) {
/* We only do this if the time is >= 1s because otherwise the
* user was probably just scrolling. */
if (which.getTime() < 1.0) return;
historyStore.updateHistory(which.toString(age, weight));
}
/**
* Recalculates the entire history tab from scratch.
*/
public void recalculateHistory() {
historyStore.resetHistory();
for (HistoryData curHist : history) {
addHistoryLine(curHist);
}
}
}