public ExperimentLibrary()
 {
     AddExperimentCommand = new RelayCommand(async delegate
     {
         Experiment exp = new Experiment();
         ExperimentInformationWindow eiw = new ExperimentInformationWindow("Create Experimet", true) { DataContext = exp };
         List<ParticipantID> selectedReactors = await eiw.ShowAsync();
         if (eiw.Confirmed)
         {
             foreach (ParticipantID selectedReactor in selectedReactors)
                 Directory.CreateDirectory(Path.Combine(experimentsDirectory, exp.DisplayName, selectedReactor.ToString()));
             exp.BaseDirectory = Path.Combine(experimentsDirectory, exp.DisplayName);//this authorizes the experiment to be saved or save itself (when a property changes)
             exp.Save();
         }
     });
     scanTimer.Tick += delegate 
     {
         scanTimer.Stop();
         ScanExperimentsDirectory();
     };
 }
 private async void ScanExperimentsDirectory()
 {
     //in order to preserve the ObservableCollection we only want to add new experiments, or remove experiments where the folder was deleted
     //first get all subdirectories in the experiments directory
     List<string> dirs = Directory.EnumerateDirectories(experimentsDirectory).ToList();
     //remove all dirs which are already loaded and remove experiments that got deleted
     for (int i = 0; i < Experiments.Count; i++)
     {
         if (dirs.Contains(Experiments[i].BaseDirectory))//these experiments are already loaded and can be ignored
         {
             dirs.Remove(Experiments[i].BaseDirectory);
         }
         else//unload/remove experiments where the folder does not exist anymore
         {
             Experiments.RemoveAt(i);
             i--;
         }
     }
     //add new experiments
     foreach (string dir in dirs)
     {
         Experiment exp = Experiment.LoadFromDirectory(dir);
         if (exp != null)
         {
             exp.EditExperimentCommand = new RelayCommand(async delegate
             {
                 Experiment newexp = new Experiment() { Title = exp.Title, Description = exp.Description, Date = exp.Date, Cultivations = exp.Cultivations };
                 ExperimentInformationWindow eiw = new ExperimentInformationWindow("Edit Experimet", false) { DataContext = newexp };
                 await eiw.ShowAsync();
                 if (eiw.Confirmed)
                 {
                     exp.Description = newexp.Description;
                     exp.Save();
                 }
             });
             await LookForConflictsAsync(exp);
             foreach (Cultivation c in exp.Cultivations)
             {
                 ParticipantID reactorInQuestion = c.Reactor.ParticipantID;
                 c.StartStopCultivationCommand = new RelayCommand(async delegate
                 {
                     if (c.IsRunning == false)
                     {
                         int continuationMode = 0;
                         if (c.StartTime != new DateTime())
                         {
                             continuationMode = await CustomMessageBox.ShowAsync(
                                 "Attention!", "This cultivation was running previously. Please select how to proceed.",
                                 System.Windows.MessageBoxImage.Warning, 0, "Just Continue", "Reset the Start Time"
                                 );
                         }
                         Experiment conflictingExperiment;
                         Cultivation conflicting = FindRunningCultivation(c.Reactor.ParticipantID, out conflictingExperiment);
                         if (conflicting == null)
                         {
                             c.IsRunning = true;
                             c.SendSetpointUpdate();
                         }
                         else//ask the user to stop the other cultivation
                         {
                             int result = await CustomMessageBox.ShowAsync(
                                 "Conflict - Reactor already in use",
                                 string.Format("{0} is already in use by {1}\r\n\r\nDo you want to stop the other cultivation?", reactorInQuestion.GetValueName(), conflictingExperiment.ToString()),
                                 System.Windows.MessageBoxImage.Warning,
                                 1,
                                 string.Format("Stop {0}", conflictingExperiment.ToString()),
                                 "Cancel");
                             if (result == 0)//if he wants to proceed and stop the other experiment
                             {
                                 conflicting.IsRunning = false;
                                 conflicting.StopCultivation();
                                 conflicting.Save();
                                 c.IsRunning = true;
                                 c.SendSetpointUpdate();
                             }
                         }
                         if (c.IsRunning)//everything is GO - start the culture and save the time
                             c.StartTime = DateTime.Now;
                         switch (continuationMode)
                         {
                             case 0:
                                 // just continue
                                 break;
                             case 1:
                                 c.StartTime = DateTime.Now;
                                 break;
                             case 2:
                                 //TODO: implement the third option: "delete previous measurements and start"
                                 break;
                         }
                         c.Save();
                     }
                     else
                     {
                         c.IsRunning = false;
                         c.StopCultivation();
                         c.Save();
                     }
                 });
             }
             Experiments.Add(exp);
         }
     }
 }
 public Cultivation FindRunningCultivation(ParticipantID reactor, out Experiment conflictingExperiment)
 {
     foreach (Experiment exp in Experiments)
     {
         foreach (Cultivation culti in exp.Cultivations)
         {
             if (culti.IsRunning && culti.Reactor.ParticipantID == reactor)
             {
                 conflictingExperiment = exp;
                 return culti;
             }
         }
     }
     conflictingExperiment = null;
     return null;
 }
 private async Task LookForConflictsAsync(Experiment exp)
 {
     foreach (Cultivation c in exp.Cultivations)
     {
         ParticipantID reactorInQuestion = c.Reactor.ParticipantID;
         if (c.IsRunning)//the loaded experiment is running -> make sure that there's no conflict
         {
             Experiment conflictingExperiment;
             Cultivation conflicting = FindRunningCultivation(reactorInQuestion, out conflictingExperiment);
             if (conflicting != null)//if we found another experiment that is using the same reactor
             {
                 //ask the user to choose
                 int result = await CustomMessageBox.ShowAsync(
                     "Conflict - Reactor already in use",
                     string.Format("{0} is already in use by {1}\r\n\r\nPlease select the experiment that you want to prioritize.", reactorInQuestion.GetValueName(), conflictingExperiment),
                     System.Windows.MessageBoxImage.Warning,
                     0,
                     conflictingExperiment.ToString(),
                     exp.ToString());
                 if (result == 0)//if he wants to keep the already loaded experiment running
                 {
                     c.IsRunning = false;//stop the new one
                     c.Save();
                 }
                 else//stop the other cultivation and overwrite the reservation
                 {
                     conflicting.IsRunning = false;
                     conflicting.Save();
                 }
             }
         }
         if (c.IsRunning)//a running cultivation was loaded and no conflict was found -> communicate the setpoints to the slaves
             c.SendSetpointUpdate();
         }
 }