49{
50 CheckForCoffeeMachine(yourDevice);
51 }
52
53 public virtual void PreValidate()
54 {
55 }
56
57 public virtual void PostValidate()
58 {
59 }
60
61 public abstract void Execute();
62 public abstract string GetTaskAction();
63
65 }
66
71 {
72 public CoffeeCategory(int ranking) : base(ranking)
73 {
74 }
75
79 public override string Name => LocalizeMockPlugin.CoffeeCategory_Name_Coffee;
80 }
81
89 [CoffeeCategory(1)]
90 [ScheduleDiagramColor("Sienna")]
92 {
97 {
98 mDevice.ShowTheMessage(Message);
99 RegisterCoffeeConsumption();
100 }
101
103 {
104 RegisterCoffeeConsumption();
105 }
106
110 private void RegisterCoffeeConsumption()
111 {
113 }
114
120 {
121 return LocalizeMockPlugin.BrewCoffee_GetTaskAction_Send_a_message_to_my_device;
122 }
123
127 public string Message { get; set; } = LocalizeMockPlugin.BrewCoffee_mMessage_Do_you_want_sugar_;
128 }
129
139 [CoffeeCategory(2)]
141 {
146 public enum CreamType
147 {
148 Normal,
149 LowFat,
150 Vegan
151 }
152
156 [Editor(typeof(CompositionEditor), typeof(UITypeEditor))]
157 public class CompositionData
158 {
159 [XmlIgnore]
161
162 public CreamType Cream
163 {
164 get;
165 set;
166 }
167
168 public bool MuchIce { get; set; }
169
170 public bool DeCaffeinated { get; set; }
171
172 public uint Volume { get; set; }
173
177 public CompositionData()
178 {
179 Cream = CreamType.LowFat;
180 MuchIce = false;
181 DeCaffeinated = false;
182 Volume = 250;
183 }
184
189 public override string ToString()
190 {
191 return String.Format(LocalizeMockPlugin.CompositionData_ToString_Cream___0___MuchIce___1___Decaffeinated___2___Size___3__mL,
192 Cream, MuchIce, DeCaffeinated, Volume);
193 }
194 }
195
196 #region Component model UI type editor
197
201 public class CompositionEditor : UITypeEditor
202 {
208 public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
209 {
210
211 return UITypeEditorEditStyle.Modal;
212 }
213
221 public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
222 {
223 var editProvider = (IWindowsFormsEditorService)provider?.GetService(typeof(IWindowsFormsEditorService));
224
225 var compData = (CompositionData)value;
226
227 using (var myEditor = new FrappuccinoCompositionEditor(compData))
228 {
229
230 editProvider?.ShowDialog(myEditor);
231 }
232 return value;
233 }
234 }
235
236 #endregion Component model UI type editor
237
238 private CompositionData mComposition;
239
244 public CompositionData Composition
245 {
246 get
247 {
248 if (mComposition != null && mComposition.DevInEditor == null)
249 {
250 mComposition.DevInEditor = mDevInEditor;
251 }
252 return mComposition;
253 }
254 set
255 {
256 mComposition = value;
257 if (mComposition != null)
258 {
259 mComposition.DevInEditor = mDevInEditor;
260 }
261 RaiseVolumeChanged();
262 }
263 }
264
266 {
267 return LocalizeMockPlugin.BrewFrappuccino_GetTaskAction_Brew_a_frappuccino__composition__ + Composition;
268 }
269
270
271 [DefaultUnit(Units.MilliLiter)]
272 public uint Volume
273 {
274 get => mComposition.Volume;
275 set
276 {
277 if(mComposition.Volume == value) return;
278 mComposition.Volume = value;
279 RaiseVolumeChanged();
280 }
281 }
282 internal void RaiseVolumeChanged()
283 {
284 PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(nameof(Volume)));
285 }
286 [DefaultUnit("mL")]
287 public uint CupSize
288 {
289 get;
290 set;
291 }
292
293 public BrewFrappuccino()
294 {
295 Composition = new CompositionData();
296 CupSize = 250;
297 }
298
303 {
304 mDevice.BrewFrappuccino(Composition);
305 RegisterConsumption(Composition);
306 }
307
309 {
310 RegisterConsumption(Composition);
311 }
312
317 private void RegisterConsumption(CompositionData composition)
318 {
319 var sizeFactor = composition.Volume / 125.0;
321 string creamName;
322 switch (composition.Cream)
323 {
324 case CreamType.LowFat:
325
326 creamName = "Low Fat Milk";
327 break;
328 case CreamType.Normal:
329 creamName = MockConsumablesForCoffeeMakerDevice.Milk.Name;
330 break;
331 case CreamType.Vegan:
332 creamName = MockConsumablesForCoffeeMakerDevice.VeganCream.Name;
333 break;
334 default:
335 creamName = "";
336 break;
337 }
339 }
340
352 {
353 if (propName == nameof(Volume))
354 {
355
356 if (propValue is uint u)
357 {
358 Volume = u;
359 }
360 else
361 {
362 var conv = TypeDescriptor.GetConverter(Volume, true);
363 if (conv.IsValid(propValue))
364 {
365
366 Volume = (uint)conv.ConvertFrom(null, System.Globalization.CultureInfo.InvariantCulture, propValue);
367 }
368 }
369 }
370 else if (propName == "Autosampler")
371 {
372 mDevInEditor =
MockDevice.Instances.FirstOrDefault(someDev => someDev.Name == propValue?.ToString());
373 if (mComposition != null)
374 {
375 mComposition.DevInEditor = mDevInEditor;
376 }
377 }
378 }
379
381
382 public event PropertyChangedEventHandler PropertyChanged;
383
384 #region Implementation of IGiveARuntimeHint
385
389 public int? CalculatedRuntime
390 {
391 get
392 {
393 if (Volume > 250)
394 {
395 return 30;
396 }
397
398 if (Volume > 100)
399 {
400 return 15;
401 }
402
403 return 10;
404 }
405 }
406
407 #endregion
408 }
409
413 [CoffeeCategory(3)]
414
415 public class PretendCoffeeMachineIsBroken : CoffeeMachineBaseTask,
ITaskForDevice
416 {
417 public bool SoftStop { get; set; }
419 {
420 mDevice.TriggerAbort(LocalizeMockPlugin
421 .PretendCoffeeMachineIsBroken_Execute_The_coffee_machine_s_heater_failed_,SoftStop);
422 }
423
425 {
426 return String.Format(LocalizeMockPlugin.PretendCoffeeMachineIsBroken_GetTaskAction_Will_make_the_device_abort_the_schedule_after_a_few_seconds_,SoftStop);
427 }
428 }
432 [CoffeeCategory(4)]
433 public class CoffeeMachineDoesNotWorkProperly : CoffeeMachineBaseTask,
ITaskForDevice
434 {
435 public string ErrorDescription { get; set; } = "Some random error message that is shown to the user";
440 public bool ResolvedAfterHandling { get; set; } = false;
442 {
443 mDevice.RaiseError(ErrorDescription,
ErrorType, ResolvedAfterHandling);
444 }
445
447 {
448 return $"Raising error type {ErrorType} with description \"{ErrorDescription}\"";
449 }
450 }
451}
ErrorType
Lets a device implementing IHaveInteractiveErrorHandling specify which kind of error occurred.
Helps you manipulate the desired consumable, or works as a dummy.
void Execute()
Do whatever you have to do with your parameters.
void PostValidate()
Called after the schedule construction is completed.
string GetTaskAction()
Description of the tasks's action (for hints/time table)
To be implemented if the task needs to access a device ("Autosampler" property in Chronos)
If you can calculate your runtime, you should implement this interface.
Implement this interface in your task if you want the method editor to notify it of changed propertie...
void PropertyEdited(string propName, object propValue)
This will be called as soon as a property was changed in the method editor.
Use this if none of the predefined categories fit and you have a better idea than "Misc".
Keeps track of all consumables that are associated to our mock coffee machine.
static string GetLocationIdentifier(MockDevice dev, string ingredientName)
A chronos plugin implementation for a fake device. We pretend we are controlling a mixture of coffee ...
Just provide a TypeConverter, and Chronos is happy.