WIP
DirectOutput framework for virtual pinball cabinets WIP
Go to:
Overview 
TableElementConditionEffect.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using DirectOutput.Table;
6 using Ciloci.Flee;
7 using System.Xml.Serialization;
8 
9 namespace DirectOutput.FX.ConditionFX
10 {
15  {
16  private string _Condition;
17 
24  public string Condition
25  {
26  get { return _Condition; }
27  set { _Condition = value; }
28  }
29 
30  [XmlIgnore]
31  IGenericExpression<bool> ConditionExpression = null;
32 
33  private List<string> GetVariablesInternal()
34  {
35  List<string> Variables = new List<string>();
36  string C = Condition;
37  if (C.IsNullOrWhiteSpace()) return Variables;
38 
39 
40  ExpressionContext Context = new ExpressionContext();
41  Context.Options.ParseCulture = System.Globalization.CultureInfo.InvariantCulture;
42  Context.Imports.AddType(typeof(Math));
43 
44  VariableCollection VC = Context.Variables;
45  VC.ResolveVariableType += new EventHandler<ResolveVariableTypeEventArgs>(GetVariablesInternal_ResolveVariableType);
46  VC.ResolveVariableValue += new EventHandler<ResolveVariableValueEventArgs>(GetVariablesInternal_ResolveVariableValue);
47 
48  IGenericExpression<bool> Exp = null;
49  try
50  {
51  Exp = Context.CompileGeneric<bool>(Condition.Replace(((char)TableElementTypeEnum.NamedElement).ToString(),"NamedElement_"));
52  }
53  catch {
54  Log.Warning("Cant extract variables from condition {0}.".Build(Condition));
55  Exp = null;
56  }
57  VC.ResolveVariableType -= new EventHandler<ResolveVariableTypeEventArgs>(GetVariablesInternal_ResolveVariableType);
58  VC.ResolveVariableValue -= new EventHandler<ResolveVariableValueEventArgs>(GetVariablesInternal_ResolveVariableValue);
59 
60 
61  if (Exp != null && Exp.Info != null)
62  {
63  Variables = Exp.Info.GetReferencedVariables().ToList();
64  }
65 
66  return Variables;
67  }
68 
69  void GetVariablesInternal_ResolveVariableValue(object sender, ResolveVariableValueEventArgs e)
70  {
71  e.VariableValue = 0;
72  }
73 
74  void GetVariablesInternal_ResolveVariableType(object sender, ResolveVariableTypeEventArgs e)
75  {
76  e.VariableType = typeof(double);
77  }
78 
79 
84  public List<string> GetVariables()
85  {
86  return GetVariablesInternal().Select(Va => (Va.StartsWith("NamedElement_") ? ((char)TableElementTypeEnum.NamedElement).ToString() + Va.Substring("NamedElement_".Length) : Va)).ToList();
87  }
88 
89 
90 
91  private void InitCondition()
92  {
93  string C = Condition.Replace(((char)TableElementTypeEnum.NamedElement).ToString(), "NamedElement_");
94  ConditionExpression = null;
95 
96  if (C.IsNullOrWhiteSpace())
97  {
98  Log.Warning("No condition has been set for {0} named {1}.".Build(this.GetType().Name, Name));
99  return;
100  };
101 
102  List<string> Variables = GetVariablesInternal();
103 
104  ExpressionContext Context = new ExpressionContext();
105  Context.Options.ParseCulture = System.Globalization.CultureInfo.InvariantCulture;
106  try
107  {
108  Context.Imports.AddType(typeof(Math));
109 
110  foreach (string V in Variables)
111  {
112  int P = 0;
113  while (P < C.Length && P >= 0)
114  {
115  P = C.IndexOf(V, P + 1, StringComparison.OrdinalIgnoreCase);
116  if (P < 0) break;
117  if (!C.Substring(P, V.Length + 1).Equals(V + ".", StringComparison.OrdinalIgnoreCase))
118  {
119  C = C.Substring(0, P) + "{0}.Value".Build(V) + C.Substring(P + V.Length);
120  }
121  }
122  // C = C.Replace(V, "{0}.Value".Build(V), StringComparison.OrdinalIgnoreCase);
123 
124  TableElement TE = null;
125 
126  if (V.StartsWith("NamedElement_"))
127  {
128  Table.TableElements.UpdateState(new TableElementData(V.Substring("NamedElement_".Length),0));
129  TE = Table.TableElements[V.Substring("NamedElement_".Length)];
130  }
131  else
132  {
133 
134  Table.TableElements.UpdateState(new TableElementData((TableElementTypeEnum)V[0], V.Substring(1).ToInteger(), 0));
135  TE = Table.TableElements[(TableElementTypeEnum)V[0], V.Substring(1).ToInteger()];
136  }
137 
138 
139  Context.Variables[V] = TE;
140  }
141  }
142  catch (Exception E)
143  {
144  Log.Exception("A exception has occured while setting up the variables for condition {0} of effect {1}.".Build(Condition, Name), E);
145  return;
146 
147  }
148 
149  try
150  {
151  ConditionExpression = Context.CompileGeneric<bool>(C);
152 
153  }
154  catch (Exception E)
155  {
156  Log.Exception("A exception has occured while compiling the condition {0} (internaly translated to {2}) of effect {1}.".Build(Condition, Name, C), E);
157  return;
158  }
159 
160 
161 
162 
163  }
164 
165 
166 
172  {
173  if (ConditionExpression != null)
174  {
175  try
176  {
177  if (ConditionExpression.Evaluate())
178  {
179  TableElementData.Value = 255;
180  }
181  else
182  {
183  TableElementData.Value = 0;
184  }
185  TriggerTargetEffect(TableElementData);
186  }
187  catch (Exception E)
188  {
189 
190  Log.Exception("A exception occured when evaluating the expression {0} of effect {1}. Effect will be deactivated.".Build(ConditionExpression.Text, Name), E);
191  ConditionExpression = null;
192 
193  }
194  }
195  }
196 
197 
198 
199 
200 
206  public override void Init(Table.Table Table)
207  {
208  base.Init(Table);
209  InitCondition();
210  }
211 
212 
217  public override void Finish()
218  {
219  ConditionExpression = null;
220  base.Finish();
221  }
222 
223 
224  }
225 }
This effect evaluates the condition specified in the Condition property.
static void Warning(string Message)
Writes a warning message to the log.
Definition: Log.cs:134
override void Finish()
Finishes the Effect. Releases the references to the target effect, the table object and the expressi...
TableElementTypeEnum
Enum for the different TableElement types.
A simple logger used to record important events and exceptions.
Definition: Log.cs:14
int Value
The value of the table element.
List< string > GetVariables()
Gets a list of all variables in the condition.
TableElementList TableElements
Lists the TableElement objects for the Table. This list is automaticaly extend with new TableElement...
Definition: Table.cs:27
Data representing the state of a table emlement
Base class for effects targeting another effect.
void UpdateState(TableElementData Data)
Method to update the state and/or add a entry to the list
The Table namespace contains all table specific classes like the Table class itself, TableElement and effect assigment classes.
Definition: Table.cs:14
override void Trigger(TableElementData TableElementData)
Triggers the effect with the given TableElementData.
Holds all table specific information and handles all TableElements
Definition: Table.cs:20
Represents a element (e.g. Switch, Solenoid) of a pinball table
Definition: TableElement.cs:12
Table()
Initializes a new instance of the Table class.
Definition: Table.cs:388
override void Init(Table.Table Table)
Initializes the Effect. Resolves the name of the TargetEffect and initializes the condition context...
static void Exception(string Message, Exception E=null)
Writes a exception message to the log.
Definition: Log.cs:144