Antares Simulator
Power System Simulator
modifiers.hxx
1 /*
2  * Copyright 2007-2025, RTE (https://www.rte-france.com)
3  * See AUTHORS.txt
4  * SPDX-License-Identifier: MPL-2.0
5  * This file is part of Antares-Simulator,
6  * Adequacy and Performance assessment for interconnected energy networks.
7  *
8  * Antares_Simulator is free software: you can redistribute it and/or modify
9  * it under the terms of the Mozilla Public Licence 2.0 as published by
10  * the Mozilla Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * Antares_Simulator is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * Mozilla Public Licence 2.0 for more details.
17  *
18  * You should have received a copy of the Mozilla Public Licence 2.0
19  * along with Antares_Simulator. If not, see <https://opensource.org/license/mpl-2-0/>.
20  */
21 #ifndef __ANTARES_TOOLBOX_COMPONENT_DATAGRID_MODIFIERS_HXX__
22 #define __ANTARES_TOOLBOX_COMPONENT_DATAGRID_MODIFIERS_HXX__
23 
24 namespace Antares::Component::Datagrid
25 {
26 namespace // anonymous
27 {
28 enum ModifierSet
29 {
30  modifierValues,
31  modifierDataset,
32  modifierMax
33 };
34 
35 enum OpInputType
36 {
37  opInputText = 0, // default
38  opInputVoid, // nothing
39  opInputDate,
40 };
41 
42 // Forward declaration
43 template<enum ModifierSet ModifierT>
44 struct ModifierOperatorsData;
45 
46 template<enum ModifierSet ModifierT>
47 struct ModifierOperatorsData
48 {
49  // nothing
50 };
51 
52 template<>
53 struct ModifierOperatorsData<modifierValues>
54 {
55  enum Operator
56  {
57  opPlus,
58  opAssign,
59  opMinus,
60  opMult,
61  opDiv,
62  opAbs,
63  opMax
64  };
65 
66  static uint OperatorCount()
67  {
68  return (uint)opMax;
69  }
70 
71  static const wchar_t* Name()
72  {
73  return L"Values";
74  }
75 
76  static const wchar_t* ApplyName(uint)
77  {
78  return L"Apply";
79  }
80 
81  static const wchar_t* OperatorToCString(uint op)
82  {
83  if (op < (uint)opMax)
84  {
85  switch ((Operator)op)
86  {
87  case opPlus:
88  return L"+";
89  case opAssign:
90  return L"=";
91  case opMinus:
92  return L"-";
93  case opMult:
94  return L"*";
95  case opDiv:
96  return L"/";
97  case opAbs:
98  return L"ABS";
99  case opMax:
100  break;
101  }
102  }
103  return L"?";
104  }
105 
106  static OpInputType OperatorInputType(uint op)
107  {
108  if (op == (uint)opAbs)
109  {
110  return opInputVoid;
111  }
112  return opInputText;
113  }
114 
115  static void ApplyChanges(uint op, const YString& value, Renderer::IRenderer*, VGridHelper* grid)
116  {
117  if (op >= (uint)opMax)
118  {
119  return;
120  }
121  double input;
122  if ((Operator)op != opAbs && not value.to(input))
123  {
124  logs.error() << "The value does not seem a valid number";
125  return;
126  }
127  int width = grid->GetNumberCols();
128  int height = grid->GetNumberRows();
129  wxString text;
130 
131  switch ((Operator)op)
132  {
133  case opPlus:
134  {
135  if (not Yuni::Math::Zero(input))
136  {
137  for (int w = 0; w < width; ++w)
138  {
139  for (int h = 0; h < height; ++h)
140  {
141  text.clear();
142  double d = grid->GetNumericValue(h, w);
143  grid->SetValue(h, w, text << (d + input));
144  }
145  }
146  }
147  break;
148  }
149  case opAssign:
150  {
151  text.clear();
152  text << input;
153  for (int w = 0; w < width; ++w)
154  {
155  for (int h = 0; h < height; ++h)
156  {
157  grid->SetValue(h, w, text);
158  }
159  }
160  break;
161  }
162  case opMinus:
163  {
164  if (not Yuni::Math::Zero(input))
165  {
166  for (int w = 0; w < width; ++w)
167  {
168  for (int h = 0; h < height; ++h)
169  {
170  text.clear();
171  double d = grid->GetNumericValue(h, w);
172  grid->SetValue(h, w, text << (d - input));
173  }
174  }
175  }
176  break;
177  }
178  case opMult:
179  {
180  if (Yuni::Math::Zero(input))
181  {
182  text = wxT("0");
183  for (int w = 0; w < width; ++w)
184  {
185  for (int h = 0; h < height; ++h)
186  {
187  grid->SetValue(h, w, text);
188  }
189  }
190  }
191  else
192  {
193  if (not Yuni::Math::Equals(input, 1.))
194  {
195  for (int w = 0; w < width; ++w)
196  {
197  for (int h = 0; h < height; ++h)
198  {
199  text.clear();
200  double d = grid->GetNumericValue(h, w);
201  grid->SetValue(h, w, text << (d * input));
202  }
203  }
204  }
205  }
206  break;
207  }
208  case opDiv:
209  {
210  if (Yuni::Math::Zero(input))
211  {
212  logs.error() << "divide by zero. aborting.";
213  return;
214  }
215  if (not Yuni::Math::Equals(input, 1.))
216  {
217  for (int w = 0; w < width; ++w)
218  {
219  for (int h = 0; h < height; ++h)
220  {
221  text.clear();
222  double d = grid->GetNumericValue(h, w);
223  grid->SetValue(h, w, text << (d / input));
224  }
225  }
226  }
227  break;
228  }
229  case opAbs:
230  {
231  for (int w = 0; w < width; ++w)
232  {
233  for (int h = 0; h < height; ++h)
234  {
235  double d = grid->GetNumericValue(h, w);
236  if (d < 0) // avoid as much as possible grid->SetValue
237  {
238  text.clear();
239  grid->SetValue(h, w, text << (-d));
240  }
241  }
242  }
243  break;
244  }
245  case opMax:
246  break;
247  }
248  }
249 };
250 
251 template<>
252 struct ModifierOperatorsData<modifierDataset>
253 {
254  enum Operator
255  {
256  opResizeColumns,
257  opShiftRows,
258  opMax
259  };
260 
261  static uint OperatorCount()
262  {
263  return (uint)opMax;
264  }
265 
266  static const wchar_t* Name()
267  {
268  return L"Dataset";
269  }
270 
271  static const wchar_t* ApplyName(uint)
272  {
273  return L"Apply";
274  }
275 
276  static const wchar_t* OperatorToCString(uint op)
277  {
278  if (op < (uint)opMax)
279  {
280  switch ((Operator)op)
281  {
282  case opShiftRows:
283  return L"Shift rows until";
284  case opResizeColumns:
285  return L"Resize columns to";
286  case opMax:
287  break;
288  }
289  }
290  return L"?";
291  }
292 
293  static OpInputType OperatorInputType(uint op)
294  {
295  if (op == (uint)opShiftRows)
296  {
297  return opInputDate;
298  }
299  return opInputText;
300  }
301 
302  static void ApplyChanges(uint op,
303  const YString& value,
304  Renderer::IRenderer* renderer,
305  VGridHelper*)
306  {
307  if (op >= (uint)opMax)
308  {
309  return;
310  }
311 
312  switch ((Operator)op)
313  {
314  case opShiftRows:
315  {
316  uint index = 0;
317  uint month = (uint)-1;
318  uint day = 1;
319 
320  value.words(" /-.",
321  [&](AnyString& word) -> bool
322  {
323  switch (index)
324  {
325  case 0:
326  month = word.to<uint>();
327  if (month < 1 || month > 12)
328  {
329  logs.error()
330  << "invalid month: got '" << word << "' => " << month;
331  month = (uint)-1;
332  }
333  break;
334  case 1:
335  if (not word.to(day) || day < 1 || day > 31)
336  {
337  logs.error() << "invalid day";
338  day = (uint)-1;
339  }
340  }
341  ++index;
342  return true;
343  });
344 
345  --month;
346  --day;
347  if (month < 12 && day < 31)
348  {
349  auto monthname = (MonthName)month;
350  if (not renderer->circularShiftRowsUntilDate(monthname, day))
351  {
352  logs.error() << "impossible to perform the row shifting in this dataset";
353  }
354  }
355  break;
356  }
357  case opResizeColumns:
358  {
359  uint maxwidth = (uint)renderer->maxWidthResize();
360  uint newwidth = value.to<uint>();
361 
362  if (newwidth > 0 && newwidth <= maxwidth)
363  {
364  logs.info() << "Resizing the matrix to " << newwidth << " columns";
365  renderer->resizeMatrixToXColumns(newwidth);
366  }
367  else
368  {
369  if (maxwidth > 0)
370  {
371  switch (newwidth)
372  {
373  case 0:
374  logs.error() << "impossible to resize the matrix";
375  break;
376  case 1:
377  logs.error() << "impossible to resize the matrix to 1 column";
378  break;
379  default:
380  logs.error()
381  << "impossible to resize the matrix to " << newwidth << " columns";
382  }
383  }
384  else
385  {
386  logs.error() << "impossible to resize the matrix";
387  }
388  }
389  break;
390  }
391  case opMax:
392  break;
393  }
394  }
395 };
396 
397 struct ModifierOperators
398 {
399  static uint OperatorCount(ModifierSet modifier)
400  {
401  switch (modifier)
402  {
403  case modifierValues:
404  return ModifierOperatorsData<modifierValues>::OperatorCount();
405  case modifierDataset:
406  return ModifierOperatorsData<modifierDataset>::OperatorCount();
407  case modifierMax:
408  break;
409  }
410  return 0;
411  }
412 
413  static const wchar_t* Name(ModifierSet modifier)
414  {
415  switch (modifier)
416  {
417  case modifierValues:
418  return ModifierOperatorsData<modifierValues>::Name();
419  case modifierDataset:
420  return ModifierOperatorsData<modifierDataset>::Name();
421  case modifierMax:
422  break;
423  }
424  return L"?";
425  }
426 
427  static const wchar_t* ApplyName(ModifierSet modifier, uint op)
428  {
429  switch (modifier)
430  {
431  case modifierValues:
432  return ModifierOperatorsData<modifierValues>::ApplyName(op);
433  case modifierDataset:
434  return ModifierOperatorsData<modifierDataset>::ApplyName(op);
435  case modifierMax:
436  break;
437  }
438  return L"?";
439  }
440 
441  static const wchar_t* OperatorToCString(ModifierSet modifier, uint op)
442  {
443  switch (modifier)
444  {
445  case modifierValues:
446  return ModifierOperatorsData<modifierValues>::OperatorToCString(op);
447  case modifierDataset:
448  return ModifierOperatorsData<modifierDataset>::OperatorToCString(op);
449  case modifierMax:
450  break;
451  }
452  return L"?";
453  }
454 
455  static OpInputType OperatorInputType(ModifierSet modifier, uint op)
456  {
457  switch (modifier)
458  {
459  case modifierValues:
460  return ModifierOperatorsData<modifierValues>::OperatorInputType(op);
461  case modifierDataset:
462  return ModifierOperatorsData<modifierDataset>::OperatorInputType(op);
463  case modifierMax:
464  break;
465  }
466  return opInputText;
467  }
468 
469  static void ApplyChanges(ModifierSet modifier,
470  uint op,
471  const YString& value,
472  Renderer::IRenderer* renderer,
473  VGridHelper* grid)
474  {
475  if (!renderer)
476  {
477  return;
478  }
479  switch (modifier)
480  {
481  case modifierValues:
482  ModifierOperatorsData<modifierValues>::ApplyChanges(op, value, renderer, grid);
483  break;
484  case modifierDataset:
485  ModifierOperatorsData<modifierDataset>::ApplyChanges(op, value, renderer, grid);
486  break;
487  case modifierMax:
488  break;
489  }
490  }
491 
492 }; // class ModifierOperators
493 
494 } // anonymous namespace
495 } // namespace Antares::Component::Datagrid
496 
497 #endif // __ANTARES_TOOLBOX_COMPONENT_DATAGRID_MODIFIERS_HXX__