protected ModelParameters DetermineParameters(ModelAction action) { try { ModelParameters allparameters = action.Parameters; ModelParameters choosen = new ModelParameters(); //Loop through the method parameters foreach (ParameterInfo info in action.Method.GetParameters()) { //Find the all parameters assoicated with this param ModelParameters parameters = allparameters.Find(info.Name); //Exclude invalid parameters (if not requested) if (!this.InvalidParameters) { parameters = (ModelParameters)parameters.FindFlag((int)ModelItemFlags.Throws, false); } if (parameters.Count <= 0) { throw new ModelException(this, "Unable to find a ModelParameter for method parameter: '" + info.Name + "'"); } //Choose one of the parameters, based upon weight ModelParameter parameter = parameters.Choose(this); parameter.Accessed++; //Note: We cloning the param, since were choosing only one of the values to use this time. parameter = (ModelParameter)parameter.Clone(); //Choose (or generate) one of the values ModelValue value = DetermineParameterValue(parameter); value.Accessed++; //Add it to the array parameter.Value = value; choosen.Add(parameter); } return(choosen); } catch (Exception e) { //Make this easier to debug throw new ModelException(this, "DetermineParameters", e); } }
//Constructor public ModelExpression(ModelFunction func, ModelValue value) : base(null, value) { _func = func; }
protected ModelValue DetermineParameterValue(ModelParameter parameter) { ModelValues values = new ModelValues(); values.Add(parameter.Values); //Parameter values, can be specified in numerous ways: // 1. Value list - simply choose one of them // 2. Expression - generate value that meets the criteria (ie: <, >, !=, etc) // 3. Variable - simply obtain the value by calling a method/field //#3. Variable - simply obtain the value by calling a method/field if (parameter.Variable != null) { object current = parameter.Variable.CachedValue; if (current is IEnumerable && !typeof(IEnumerable).IsAssignableFrom(parameter.Type)) { foreach (object v in (IEnumerable)current) { values.Add(new ModelValue(v)); } } else { values.Add(new ModelValue(current)); } } //First ensure we have a set of values/requirements to choose from if (values.Count <= 0) { throw new ModelException(parameter, "No values specified to choose from"); } //Note: Since we allow the operator on the individual values, this is a little more complex. //Note: We allow multiple operators, not just one, (ie: x > 5, < 10, and != 7). //This gives you great power and flexibility in expressions, but means we have to work a //little hard in determing a value that meets the requirements //#1. Value list - simply choose one of them //Note: Bitmask is already exploded into combinations ModelValues equalvalues = values.FindOperator(ModelValueOperator.Equal); //#2. Expression - generate value that meets the criteria (ie: <, >, !=, etc) //Note: Since we allow the operator on the individual values, this is a little more complex. //Note: We allow multiple operators, not just one, (ie: x > 5, < 10, and != 7). //This gives you great power and flexibility in expressions, but means we have to work a //little hard in determing a value that meets the requirements. int min = Int32.MinValue; int max = Int32.MaxValue; //Adjust our parameter, simplier to loop over all of them foreach (ModelValue value in values.FindOperator(ModelValueOperator.Equal, false).FindOperator(ModelValueOperator.NotEqual, false)) { //To keep this simple, we just support integers (for now). if (!(value.Value is int || value.Value is Nullable <int>)) { throw new ModelException(parameter, "Generated value range must be specified in terms of integers, not '" + value.Type + "'"); } //Simplify our life int v = (int)value.Value; //Adjust Max (if there is one) switch (value.Operator) { case ModelValueOperator.LessThanOrEqual: if (v < max) { max = v; } break; case ModelValueOperator.GreaterThanOrEqual: if (v > min) { min = v; } break; case ModelValueOperator.LessThan: if (v - 1 < max && v > Int32.MinValue /*prevent underflow*/) { max = v - 1; } break; case ModelValueOperator.GreaterThan: if (v + 1 > min && v < Int32.MaxValue /*prevent overflow*/) { min = v + 1; } break; } ; } //Choose a new value, within the specified range //Note: We retry in case it equals one of the existing invalid values (ie: !=) while (true) { ModelValue choice = null; if (equalvalues.Count > 0) { //Simple: Choose one of the specified values choice = new ModelValue(equalvalues.Choose(this).Value); } else { //Otherwise: Choose a value within in the range //Note: Random.Next = min <= x < max (so we have to add one) int index = _options.Random.Next(min, max < Int32.MaxValue ? max + 1 : max); //Prevent overflow choice = new ModelValue(index); } //As soon as we find a value, within the range, (and not in the invalid list), were done bool valid = true; foreach (ModelValue invalid in values.FindOperator(ModelValueOperator.NotEqual)) { if (invalid.Evaluate(choice.Value, ModelValueOperator.Equal)) { valid = false; } } if (valid) { return(choice); } } }
public ModelRequirement(ModelAction action, ModelRequirementAttribute attr, ModelVariable variable, ModelValue value) : base(action != null ? action.Model : null, attr) { //Action _action = action; //Variable if (variable != null) { _variable = variable; if (variable.BitMask) { this.BitMask = true; } } //if(_variable == null) // throw new ModelException(this, "An empty variable is not a valid requirement", null); //Only override the attr, if values are really specified if (value != null) { _values = new ModelValues(value); } //BitMask //TODO: Better place to expand this, (incase values added later). if (this.BitMask) { this.AddBitCombinations(); } //Infer dynamic variable(s) this.InferDynamicVariables(); //Requirements assoicated with actions, are not global. They are tied to that particular //instance of the model, and it's instance of state variables. However if not assoicated //with actions, the default behavior is that their global, they apply to all models //that contain that state variable, unless explicitly indicated otherwise. _global = (action == null); }
public ModelRequirement(ModelAction action, ModelVariable variable, ModelValue value) : this(action, null, variable, value) { //Delegate }