-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTaskDurationDataSet.cs
235 lines (210 loc) · 7.58 KB
/
TaskDurationDataSet.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
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
232
233
234
235
using HarmonyLib;
using System;
using System.Collections.Generic;
using VoxelTycoon.Serialization;
using VoxelTycoon.Tracks;
using VoxelTycoon.Tracks.Tasks;
namespace ScheduleStopwatch
{
[SchemaVersion(3)]
public class TaskDurationDataSet
{
public class DurationData
{
public TimeSpan Duration { get; private set; }
public bool Estimated { get; private set; } //data is not from exact measuring, but are estimated from others vehicles data
public DurationData(TimeSpan duration, bool estimated)
{
Duration = duration;
Estimated = estimated;
}
public static DurationData operator +(DurationData a, DurationData b)
{
return new DurationData(a.Duration + b.Duration, a.Estimated || b.Estimated);
}
public static implicit operator TimeSpan?(DurationData data)
{
if (data == null)
{
return null;
} else
{
return data.Duration;
}
}
public static implicit operator TimeSpan(DurationData data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
else
{
return data.Duration;
}
}
}
private int _bufferSize;
private readonly Dictionary<RootTask, DurationDataSet> _data = new Dictionary<RootTask, DurationDataSet>();
protected DurationDataSet GetOrCreateDataSetForTask(RootTask task)
{
if (!_data.ContainsKey(task))
{
_data.Add(task, new DurationDataSet(_bufferSize));
}
return _data[task];
}
public TaskDurationDataSet(int bufferSize = DurationDataSet.DEFAULT_BUFFER_SIZE)
{
this._bufferSize = bufferSize;
}
public void Add(RootTask task, TimeSpan duration)
{
DurationDataSet dataSet = GetOrCreateDataSetForTask(task);
dataSet.Add(duration);
}
public DurationData GetAverageDuration(RootTask task)
{
if (!_data.TryGetValue(task, out DurationDataSet dataSet))
{
return null;
}
TimeSpan? average = dataSet.Average;
if (!average.HasValue)
{
return null;
}
DurationData durationData = new DurationData(average.Value, dataSet.Estimated);
return durationData;
}
//Gets sum of average duration for all tasks in the list. If some task is missing data, returns null
public DurationData GetAverageDuration(IEnumerable<RootTask> tasks)
{
TimeSpan result = default;
bool estimated = false;
foreach (RootTask task in tasks)
{
DurationData duration = GetAverageDuration(task);
if (duration == null)
{
return null;
}
result += duration.Duration;
estimated |= duration.Estimated;
}
return new DurationData(result, estimated);
}
protected void CopyAverageValues(TaskDurationDataSet newDataSet, Vehicle newVehicle)
{
foreach (KeyValuePair<RootTask, DurationDataSet> pair in _data)
{
TimeSpan? avg = pair.Value.Average;
if (avg != null)
{
newDataSet.Add(newVehicle.Schedule.GetTasks()[pair.Key.GetIndex()], avg.Value);
}
}
}
public TaskDurationDataSet GetCopyWithAverageValues(Vehicle newVehicle, int dataBufferSize = 10)
{
TaskDurationDataSet result = new TaskDurationDataSet(dataBufferSize);
CopyAverageValues(result, newVehicle);
return result;
}
/* Add own average values into the provided dataset */
public void AddAverageValuesToDataSet(TaskDurationDataSet data, Vehicle newVehicle)
{
foreach (KeyValuePair<RootTask, DurationDataSet> pair in _data)
{
TimeSpan? avg = pair.Value.Average;
if (avg != null)
{
data.Add(newVehicle.Schedule.GetTasks()[pair.Key.GetIndex()], avg.Value);
}
}
}
public virtual void OnStationRemoved(VehicleStationLocation station)
{
foreach (RootTask task in _data.Keys)
{
if (task.Destination.VehicleStationLocation == station)
{
_data.Remove(task);
}
}
}
public virtual void Clear()
{
_data.Clear();
}
public virtual void Clear(RootTask task)
{
if (_data.TryGetValue(task, out DurationDataSet dataSet))
{
dataSet.Clear();
}
}
/** marks task data for overwrite with next new data (all old data will be discarded when new data are added) */
public void MarkForOverwrite(RootTask task)
{
if (_data.TryGetValue(task, out DurationDataSet dataSet))
{
dataSet.MarkForOverwrite();
}
}
/** marks all task data for overwrite with next new data (all old data will be discarded when new data are added) */
public void MarkAllForOverwrite()
{
foreach (DurationDataSet dataSet in _data.Values) {
dataSet.MarkForOverwrite();
}
}
/** calculates the running average of all stored data and sets it as the new single record, marks it for overwrite with any new data and reduce number of elements for calculating running average */
public void AdjustDataAfterCopy(int dataBufferSize = 10)
{
foreach (DurationDataSet dataSet in _data.Values)
{
dataSet.ReduceDataToSingleValue();
dataSet.ChangeBufferSize(dataBufferSize);
dataSet.MarkForOverwrite();
}
}
public void ChangeBufferSize(int dataBufferSize = 10)
{
foreach (DurationDataSet dataSet in _data.Values)
{
_bufferSize = dataBufferSize;
dataSet.ChangeBufferSize(dataBufferSize);
}
}
public virtual void Remove(RootTask task)
{
_data.Remove(task);
}
internal virtual void Write(StateBinaryWriter writer)
{
writer.WriteInt(_data.Count);
foreach (var pair in _data)
{
writer.WriteInt(pair.Key.GetIndex());
pair.Value.Write(writer);
}
}
internal static TaskDurationDataSet Read(StateBinaryReader reader, VehicleSchedule schedule)
{
TaskDurationDataSet result = new TaskDurationDataSet();
result.DoRead(reader, schedule);
return result;
}
protected virtual void DoRead(StateBinaryReader reader, VehicleSchedule schedule)
{
int count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
int taskIndex = reader.ReadInt();
RootTask task = schedule.GetTasks()[taskIndex];
_data.Add(task, DurationDataSet.Read(reader));
}
}
}
}