Digital Twin - GUI
MainWindow.cs
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Threading.Tasks;
9 using System.Windows.Forms;
10 using GUI.IO_Modules;
11 using GUI.Datatypes;
12 using System.IO;
13 using Mosel;
14 
15 namespace GUI
16 {
20  public partial class MainWindow : Form
21  {
23  String[] locationNames;
27  Dictionary<String, int> locationDictionary = new Dictionary<String, int>();
29  List<MachineCB>[] machinesAtLocation;
31  List<ProductCB>[] productsAtMachine;
33  FlowLayoutPanel[] LocationFlowLayouts;
35  FlowLayoutPanel[] MachineFlowLayouts;
37  FlowLayoutPanel[] ProductFlowLayouts;
38 
40 
41  // 86bit
42  //string resourcesFolder = Directory.GetParent(Directory.GetParent(Directory.GetCurrentDirectory()).ToString()) + "\\Resources";
43  // 64bit
44  string resourcesFolder = Directory.GetParent(Directory.GetParent(Directory.GetParent(Directory.GetCurrentDirectory()).ToString()).ToString()) + "\\Resources";
45 
47 
48  //86bit
49  //string excelFileFolder = Directory.GetParent(Directory.GetParent(Directory.GetCurrentDirectory()).ToString()) + "\\Resources";
50  //64bit
51  string excelFilePath = Directory.GetParent(Directory.GetParent(Directory.GetParent(Directory.GetCurrentDirectory()).ToString()).ToString()) + "\\Resources\\Dataset.xlsx";
52 
54  DateTime startTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Hour, 0, 0);
56  DateTime endTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Hour, 0, 0).AddHours(1);
58  bool ExcelFileReadIn = false;
59 
61  private ModelData md;
62 
64  private int width = 145;
65 
69  public MainWindow()
70  {
71  InitializeComponent(); // needed
72  setup(); // create all the elements that the GUI needs
73  }
74 
79  public void setup()
80  {
81  numericUpDown2.Value = DateTime.Now.Hour;
82  numericUpDown1.Value = DateTime.Now.Hour;
83 
84  CheckboxCreator creator = new CheckboxCreator(excelFilePath);
85  try
86  {
87  // Try to extract Location/Machine/Product Data from Excel file
88  creator.Create();
89  }
90  catch (Exception e)
91  {
92  // if that fails, show the Exception thrown
93  ThreadExceptionDialog ted = new ThreadExceptionDialog(e);
94  ted.ShowDialog();
95  }
96 
97  // get all the Data from the CheckboxCreator
98  locationDictionary = creator.GetLocationDict();
99  locations = creator.GetAllLocations();
100  locationNames = creator.GetLocationNames();
101  machinesAtLocation = creator.GetAllMachines();
102  productsAtMachine = creator.GetAllProducts();
103 
104  // Have a FlowLayoutPanel for each Location, which then will be added to a wrapping FlowLayoutPanel (flowLayoutPanelLocations)
105  LocationFlowLayouts = new FlowLayoutPanel[locations.Length];
106  for (int i = 0; i < locations.Length; i++)
107  {
108  // adjust design of the location checkboxes
109  locations[i].MinimumSize = new Size(width, 0); //adjust width
110  locations[i].CheckStateChanged += new EventHandler(LocationCheckBoxChanged); // add custom EventHandler to each Checkbox
111  locations[i].Click += new EventHandler(LocationCheckBoxClicked); // if Checkbox is clicked, show TimeslotDialog
112  LocationFlowLayouts[i] = new FlowLayoutPanel();
113  LocationFlowLayouts[i].Padding = new Padding(0, 3, 0, 3);
114  LocationFlowLayouts[i].Size = new Size(width, flowLayoutPanelLocations.Size.Height - flowLayoutPanelLocations.Padding.Top - flowLayoutPanelLocations.Padding.Bottom - 6);
115  LocationFlowLayouts[i].Controls.Add(locations[i]); //add Checkbox to FlowLayoutPanel
116  flowLayoutPanelLocations.Controls.Add(LocationFlowLayouts[i]);
117  }
118 
119  // Mostly the same as for the Locations
120  MachineFlowLayouts = new FlowLayoutPanel[locations.Length];
121  for (int i = 0; i < locations.Length; i++)
122  {
123  MachineFlowLayouts[i] = new FlowLayoutPanel();
124  MachineFlowLayouts[i].Padding = new Padding(0, 3, 0, 3);
125  MachineFlowLayouts[i].Size = new Size(width, flowLayoutPanelMachines.Size.Height - flowLayoutPanelMachines.Padding.Top - flowLayoutPanelMachines.Padding.Bottom - 6);
126  MachineFlowLayouts[i].FlowDirection = FlowDirection.TopDown;
127  MachineFlowLayouts[i].AutoScroll = true; // if too much Machines are in one Panel, add scrollbar
128  MachineFlowLayouts[i].WrapContents = false;
129  MachineFlowLayouts[i].MaximumSize = new Size(width, 10000);
130  flowLayoutPanelMachines.Controls.Add(MachineFlowLayouts[i]);
131  foreach (MachineCB mac in machinesAtLocation[i])
132  {
133  mac.CheckStateChanged += new EventHandler(MachineCheckBoxChanged);
134  mac.Click += new EventHandler(MachineCheckBoxClicked);
135  MachineFlowLayouts[i].Controls.Add(mac);
136  }
137  }
138 
139  // Mostly the same as for the Locations
140  ProductFlowLayouts = new FlowLayoutPanel[locations.Length];
141  for (int i = 0; i < locations.Length; i++)
142  {
143  ProductFlowLayouts[i] = new FlowLayoutPanel();
144  ProductFlowLayouts[i].Padding = new Padding(0, 3, 0, 3);
145  ProductFlowLayouts[i].Size = new Size(width, flowLayoutPanelProducts.Size.Height - flowLayoutPanelProducts.Padding.Top - flowLayoutPanelProducts.Padding.Bottom - 6);
146  ProductFlowLayouts[i].FlowDirection = FlowDirection.TopDown;
147  ProductFlowLayouts[i].AutoScroll = true;
148  ProductFlowLayouts[i].WrapContents = false;
149  ProductFlowLayouts[i].MaximumSize = new Size(width, 10000);
150  flowLayoutPanelProducts.Controls.Add(ProductFlowLayouts[i]);
151  foreach (MachineCB mac in machinesAtLocation[i])
152  {
153  ProductFlowLayouts[i].Controls.Add(new Label() { Text = mac.Name });
154  foreach (ProductCB prod in mac.getProducts())
155  {
156  prod.CheckStateChanged += new EventHandler(ProductCheckBoxChanged);
157  ProductFlowLayouts[i].Controls.Add(prod);
158  }
159  }
160  }
161 
162  // make the folder Textbox readonly and display that excelFileFoler String
163  textBox1.ReadOnly = true;
164  textBox1.Text = excelFilePath;
165  }
166 
172 
176  private void LocationCheckBoxChanged(object sender, EventArgs e)
177  {
178  // logic for LocationCheckboxes (mark all of the machines if location is checked, etc.)
179  LocationCB loc = (LocationCB)sender;
180  if (loc.CheckState.Equals(CheckState.Checked))
181  {
182  loc.checkAllMachines();
183  }
184 
185  if (loc.CheckState.Equals(CheckState.Unchecked))
186  {
187  loc.uncheckAllMachines();
188  }
189 
190  if (loc.CheckState.Equals(CheckState.Indeterminate))
191  {
192  if (loc.allChildrenChecked() == 2.00000)
193  {
194  loc.CheckState = CheckState.Unchecked;
195  }
196  else
197  {
198  if (loc.allChildrenChecked() == 0.00000)
199  {
200  loc.CheckState = CheckState.Checked;
201  }
202  }
203  }
204 
205  }
206 
212 
216  private void MachineCheckBoxChanged(object sender, EventArgs e)
217  {
218  // logic for MachineCheckboxes (mark all of the products if machine is checked, etc.)
219  MachineCB mac = (MachineCB)sender;
220  if (mac.CheckState.Equals(CheckState.Checked))
221  {
222  mac.checkAllProducts();
223  if (mac.getLocation().allChildrenChecked()== 2.00000)
224  {
225  mac.getLocation().CheckState = CheckState.Checked;
226  }
227  else
228  {
229  mac.getLocation().CheckState = CheckState.Indeterminate;
230  }
231  }
232 
233  if (mac.CheckState.Equals(CheckState.Unchecked))
234  {
235  mac.uncheckAllProducts();
236  if (mac.getLocation().allChildrenChecked() == 0.00000)
237  {
238  mac.getLocation().CheckState = CheckState.Unchecked;
239  }
240  else
241  {
242  mac.getLocation().CheckState = CheckState.Indeterminate;
243  }
244  }
245 
246  if (mac.CheckState.Equals(CheckState.Indeterminate))
247  {
248  if (mac.allChildrenChecked() == 2.00000)
249  {
250  mac.CheckState = CheckState.Unchecked;
251  }
252  else
253  {
254  if (mac.allChildrenChecked() == 0.00000)
255  {
256  mac.CheckState = CheckState.Checked;
257  }
258  else
259  {
260  mac.getLocation().CheckState = CheckState.Indeterminate;
261  }
262  }
263  }
264  }
265 
271 
275  private void MachineCheckBoxClicked(object sender, EventArgs e)
276  {
277  // if clicked, show the TimeSlotDialog for the corresponding Machine
278  MachineCB mac = (MachineCB)sender;
279  if (mac.CheckState.Equals(CheckState.Checked))
280  {
281  var form2 = new TimeslotDialog(mac, startTime, endTime);
282  form2.ShowDialog();
283  }
284  }
285 
291 
295  private void LocationCheckBoxClicked(object sender, EventArgs e)
296  {
297  // if clicked, show the TimeSlotDialog for the corresponding Location
298  LocationCB c = (LocationCB)sender;
299  if (c.CheckState.Equals(CheckState.Checked))
300  {
301  var form2 = new TimeslotDialog(c, startTime, endTime);
302  form2.ShowDialog();
303  }
304  }
305 
311 
315  private void ProductCheckBoxChanged(object sender, EventArgs e)
316  {
317  // logic for LocationCheckboxes
318  ProductCB p = (ProductCB)sender;
319  if (p.CheckState == CheckState.Checked)
320  {
321  if (p.getMachine().allChildrenChecked() == 2.00000)
322  {
323  p.getMachine().CheckState = CheckState.Checked;
324  }
325  else
326  {
327  p.getMachine().CheckState = CheckState.Indeterminate;
328  }
329  }
330 
331  if (p.CheckState == CheckState.Unchecked)
332  {
333  if (p.getMachine().allChildrenChecked() == 0.00000)
334  {
335  p.getMachine().CheckState = CheckState.Unchecked;
336  }
337  else
338  {
339  p.getMachine().CheckState = CheckState.Indeterminate;
340  }
341  }
342  }
343 
349 
352  private void button1_Click(object sender, EventArgs e)
353  {
354  // if "Durchsuchen" is clicked, let the user browse for a folder that contains "Dataset.xlsx"
355  while (true) {
356  OpenFileDialog ofd = new OpenFileDialog();
357  ofd.Filter = "Exceldateien | *.xlsx";
358  DialogResult result = ofd.ShowDialog();
359  string s = "";
360 
361  if (result == DialogResult.Cancel)
362  {
363  // abort
364  break;
365  }
366 
367  if (result == DialogResult.OK)
368  {
369  s = ofd.FileName;
370  }
371 
372  if (s.EndsWith("TestDatei.xlsx"))
373  {
374  // if so, make the selected folder the one we operate on
375  excelFilePath = s;
376  textBox1.Text = s;
377  // clear Layout and create new Checkboxes etc.
378  clear();
379  setup();
380  break;
381  }
382  else
383  {
384  // if not, let user know and make them select another folder (or abort)
385  MessageBox.Show("Datei muss auf *Dataset.xlsx enden.");
386  }
387  }
388  }
389 
393  public void clear()
394  {
395  // clear all elements
396  locationDictionary.Clear();
397  locationNames = null;
398  locations = null;
399  machinesAtLocation = null;
400  productsAtMachine = null;
401  ExcelFileReadIn = false;
402 
403 
404  foreach (FlowLayoutPanel f in LocationFlowLayouts)
405  {
406  f.Dispose();
407  }
408 
409  foreach (FlowLayoutPanel f in MachineFlowLayouts)
410  {
411  f.Dispose();
412  }
413 
414  foreach (FlowLayoutPanel f in ProductFlowLayouts)
415  {
416  f.Dispose();
417  }
418 
419  // activate Garbage Collector
420  GC.Collect();
421  }
422 
426  private void UpdateStartTime()
427  {
428  DateTime sd = new DateTime(dateTimePicker1.Value.Year, dateTimePicker1.Value.Month, dateTimePicker1.Value.Day, (int)numericUpDown1.Value, 0, 0);
429  startTime = sd;
430  // if the start time is at the same time or after the end time, we update the endtime and the display of end time
431  //We update it so that the endTime is the startTime + 1 hour
432  if (sd.CompareTo(endTime) >= 0)
433  {
434  endTime = startTime.AddHours(1);
435  numericUpDown2.Value = endTime.Hour;
436  dateTimePicker2.Value = new DateTime(endTime.Year, endTime.Month, endTime.Day);
437  }
438 
439  //update number of timeslots for each machine and Location
441  }
442 
448  private void numericUpDown1_ValueChanged(object sender, EventArgs e)
449  {
450  UpdateStartTime();
451  }
452 
458  private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
459  {
460  UpdateStartTime();
461  }
462 
466  private void UpdateEndtime()
467  {
468  DateTime et = new DateTime(dateTimePicker2.Value.Year, dateTimePicker2.Value.Month, dateTimePicker2.Value.Day, (int)numericUpDown2.Value, 0, 0);
469  //If the end time asked in the GUI is valid, we update the attribute endTime
470  if (et.CompareTo(startTime)>0)
471  {
472  endTime = et;
473  }
474  //Else, we set the end time and the display to the start time + 1 hour
475  else
476  {
477  endTime = startTime.AddHours(1);
478  numericUpDown2.Value = endTime.Hour;
479  dateTimePicker2.Value = new DateTime(endTime.Year, endTime.Month, endTime.Day);
480  }
481 
482  //update number of timeslots for each machine and Location
484  }
485 
491  private void numericUpDown2_ValueChanged(object sender, EventArgs e)
492  {
493  UpdateEndtime();
494  }
495 
501  private void dateTimePicker2_ValueChanged(object sender, EventArgs e)
502  {
503  UpdateEndtime();
504  }
505 
509  private void UpdateNumberOfTimeslots()
510  {
511  int num = (int)Math.Ceiling(endTime.Subtract(startTime).TotalHours);
512  if (machinesAtLocation != null)
513  {
514  foreach (List<MachineCB> l in machinesAtLocation)
515  {
516  foreach (MachineCB m in l)
517  {
518  m.setNumberOfTimeslots(num);
519  }
520  }
521  }
522 
523  if (locations != null)
524  {
525  for (int i = 0; i < locations.Length; i++)
526  {
527  locations[i].setNumberOfTimeslots(num);
528  }
529  }
530  }
531 
537  private void button2_Click(object sender, EventArgs e)
538  {
539  //read in ModelData from Excel file (once!)
540  if (!ExcelFileReadIn)
541  {
542  md = new ModelData(excelFilePath, locationNames, locations, locationDictionary);
543  ExcelFileReadIn = true;
544  }
545 
546  // reformulate data so that it matches the .dat format we need for the model
547  DatFileCreator dfc = new DatFileCreator(md, startTime, endTime);
548  double d = 1;
549  if (dfc.createDatFile(d))
550  {
551  // if there was no problem writing the Datafile, i.e. maxN>0
552 
553  // Initialize Mosel
554  XPRM mosel = XPRM.Init();
555 
556  // Compile and load the Mosel model
557  XPRMModel model = mosel.CompileAndLoad(resourcesFolder + "\\Test.mos");
558 
559  // Bind a stream based on the BurglarDat data to the name 'BurglarIni'
560  // where the model will expect to find its initialization data
561  model.Bind("ModelIni", new StringReader(dfc.Data));
562  model.Bind("ModelIniSecond", new StringReader(dfc.Data));
563 
564  // Redirect the model’s output to a custom TextWriter
565  MoselTextWriter modelOut = new MoselTextWriter();
566  model.SetDefaultStream(XPRMStreamType.F_OUTPUT, modelOut);
567  // Redirect the error output to a custom TextWriter
568  MoselTextWriter errorOut = new MoselTextWriter();
569  model.SetDefaultStream(XPRMStreamType.F_ERROR, errorOut);
570 
571 
572  // Pass data location as a parameter to the model
573  // Initializations block in .mos is separated into two blocks, therefore we have to hand two StreamReader to it.
574  model.SetExecParam("DATAFILE", "dotnet:ModelIni");
575  model.SetExecParam("SECONDDATAFILE", "dotnet:ModelIniSecond");
576  model.Run();
577 
578  if (errorOut.sb.Length > 0)
579  {
580  MessageBox.Show(errorOut.sb.ToString(), "ERROR in Mosel");
581  }
582  else
583  {
584  MessageBox.Show(modelOut.sb.ToString(), "Mosel Output");
585  }
586 #if DEBUG
587  dfc.export();
588 #endif
589  }
590  else
591  {
592  // if not show user what went wrong
593  MessageBox.Show("Es muss mindestens eine Bestellung im Planungshorizont liegen.");
594  }
595  }
596  }
597 }
598 
void numericUpDown2_ValueChanged(object sender, EventArgs e)
Called whenever the user change the hour for the endTime.
Definition: MainWindow.cs:491
void MachineCheckBoxClicked(object sender, EventArgs e)
Eventhandler that is called when the machine checkbox has been clicked.
Definition: MainWindow.cs:275
void UpdateNumberOfTimeslots()
Update number of timeslots for each machine and Location every time endTime or startTime change...
Definition: MainWindow.cs:509
void UpdateStartTime()
Function which updates the startTime, and updates the endTime if necessary.
Definition: MainWindow.cs:426
MachineCB getMachine()
Grants access to the machine this product is meant to be produced on.
Definition: ProductCB.cs:53
double allChildrenChecked()
Check if every machine belonging to the location is checked.
Definition: LocationCB.cs:98
This class reads all the important data out of an Excel file and creates all the Checkboxes we need...
This is the main window, where the locations, machines and products are shown.
Definition: MainWindow.cs:20
FlowLayoutPanel[] LocationFlowLayouts
Each Location is wrapped by a Location FlowLayout.
Definition: MainWindow.cs:33
List< ProductCB >[] productsAtMachine
All products at a specific location. Indexed by location&#39;s indexed, so that they can be aligned verti...
Definition: MainWindow.cs:31
LocationCB[] GetAllLocations()
Grants access to the location array.
void InitializeComponent()
Erforderliche Methode für die Designerunterstützung. Der Inhalt der Methode darf nicht mit dem Code-E...
A class that lets us catch the output Stream of Mosel.
DateTime startTime
Starttime of planning horizon.
Definition: MainWindow.cs:54
void setNumberOfTimeslots(int num)
Sets the number of timeslots to a certain amount.
Definition: MachineCB.cs:185
void checkAllProducts()
Check all the product Checkboxes that belong to this machine.
Definition: MachineCB.cs:90
StringBuilder sb
Save every incoming message to the StringBuilder.
int width
Number to easily adjust width of all elements.
Definition: MainWindow.cs:64
void uncheckAllProducts()
Uncheck all the product Checkboxes that belong to this machine.
Definition: MachineCB.cs:105
LocationCB getLocation()
Grants access to the location where the machine is located.
Definition: MachineCB.cs:78
void dateTimePicker1_ValueChanged(object sender, EventArgs e)
Called whenever the user change the date for the startTime.
Definition: MainWindow.cs:458
void Create()
Reads all the Data from Dir + "\\Dataset.xlsx".
DateTime endTime
Endtime of planning horizon.
Definition: MainWindow.cs:56
List< MachineCB >[] machinesAtLocation
All machines at a specific location. Indexed by location&#39;s indexed, so that they can be aligned verti...
Definition: MainWindow.cs:29
void button2_Click(object sender, EventArgs e)
Function that is called when the "Compute" Button is clicked. Reads in the rest of the model data and...
Definition: MainWindow.cs:537
List< MachineCB >[] GetAllMachines()
Grants access to the machine checkboxes.
List< ProductCB > getProducts()
Grants access to the list of products that belong to the machine.
Definition: MachineCB.cs:69
A wrapper class for products.
Definition: ProductCB.cs:18
void LocationCheckBoxChanged(object sender, EventArgs e)
Eventhandler that is called when the Checkstate of a location has changed.
Definition: MainWindow.cs:176
Dialog that lets users choose which timeslots are available.
A wrapper class for locations.
Definition: LocationCB.cs:19
void UpdateEndtime()
Function which updates the endTime, provided that the end time is at least the startTime + 1 hour...
Definition: MainWindow.cs:466
List< ProductCB >[] GetAllProducts()
Grants access to the product checkboxes.
void LocationCheckBoxClicked(object sender, EventArgs e)
Eventhandler that is called when the location checkbox has been clicked.
Definition: MainWindow.cs:295
FlowLayoutPanel[] ProductFlowLayouts
Each block of products is wrapped by a Location FlowLayout.
Definition: MainWindow.cs:37
void setup()
Reads in data from a user defined folder (or the standard one) and sets the interface up with all its...
Definition: MainWindow.cs:79
ModelData md
Object that contains additional model data.
Definition: MainWindow.cs:61
void button1_Click(object sender, EventArgs e)
Eventhandler that is called when the "Durchsuchen..." button is clicked.
Definition: MainWindow.cs:352
void clear()
Deletes every object on the interface.
Definition: MainWindow.cs:393
void MachineCheckBoxChanged(object sender, EventArgs e)
Eventhandler that is called when the Checkstate of a machine has changed.
Definition: MainWindow.cs:216
Dictionary< String, int > locationDictionary
Dictionary that maps a location&#39;s name to its position in the locations array.
Definition: MainWindow.cs:27
void setNumberOfTimeslots(int num)
Sets the number of timeslots to a certain amount.
Definition: LocationCB.cs:161
void dateTimePicker2_ValueChanged(object sender, EventArgs e)
Called whenever the user change the date for the endTime.
Definition: MainWindow.cs:501
double allChildrenChecked()
Check if every procuct belonging to the machine is checked.
Definition: MachineCB.cs:121
string resourcesFolder
Folder directory where the model related files are located.
Definition: MainWindow.cs:44
LocationCB[] locations
Array that stores all locations.
Definition: MainWindow.cs:25
void uncheckAllMachines()
Uncheck all the machine Checkboxes that belong to this location.
Definition: LocationCB.cs:81
void numericUpDown1_ValueChanged(object sender, EventArgs e)
Called whenever the user change the hour for the startTime.
Definition: MainWindow.cs:448
string excelFilePath
Folder directory where the Excel input file is located.
Definition: MainWindow.cs:51
void ProductCheckBoxChanged(object sender, EventArgs e)
Eventhandler that is called when the Checkstate of a product has changed.
Definition: MainWindow.cs:315
A wrapper class for machines.
Definition: MachineCB.cs:18
Dictionary< String, int > GetLocationDict()
Grants access to the location dictionary.
This class reads all the important data out of an Excel file related to the model.
Definition: ModelData.cs:16
bool ExcelFileReadIn
Check if Excel file has been read in before.
Definition: MainWindow.cs:58
MainWindow()
Constructor.
Definition: MainWindow.cs:69
String[] locationNames
Array that contains all of the locations&#39; names.
Definition: MainWindow.cs:23
void checkAllMachines()
Check all the machine Checkboxes that belong to this location.
Definition: LocationCB.cs:65
String[] GetLocationNames()
Grants access to the all the location names.
FlowLayoutPanel[] MachineFlowLayouts
Each block of machines is wrapped by a Location FlowLayout.
Definition: MainWindow.cs:35