예제 #1
0
        public virtual void                    AddBitCombinations()
        {
            //AutoExpand enum into bit combinations
            //Note: We do this to make choosing the parameters easier and faster (ie: one time hit)
            //In addition we do this inorder to keep track of each combinations coverage

            //Must be an Enumerable type
            if (this.Type == null || !this.Type.IsEnum)
            {
                throw new ModelException(this, "BitMask can only be specified on a Enumerable type", null);
            }

            //Note: A simple (ripple) counter is the easiest solution
            //	For example, Given 3 bits { A, B, C } the combinations are simply:
            //						A, B, C		  Value
            //						-------------------
            //						0, 0, 0,	= 0 (invalid, no bits on)
            //						0, 0, 1,	= 1
            //						0, 1, 0,	= 2
            //						0, 1, 1,	= 3
            //						1, 0, 0,	= 4
            //						1, 0, 1,	= 5
            //						1, 1, 0,	= 6
            //						1, 1, 1,	= 7

            ModelValues values = this.Values;
            Hashtable   hash   = new Hashtable();                               //Automatic Dup collapsing

            int bits  = values.Count;                                           //bits
            int total = (int)Math.Pow(2, bits);                                 //2^n

            for (int i = 1; i < total; i++)
            {
                int value = 0;

                //Calculate which bits are on
                for (int bit = 0; bit < bits; bit++)
                {
                    int mask = 0x00000001 << bit;
                    if ((i & mask) != 0)
                    {
                        value |= (int)values[bit].Value;
                    }
                }

                //Note: We have to covert it back to the enum, inorder to call the method
                hash[value] = Enum.ToObject(this.Type, value);                  //Since 0 is skipped
            }

            //Update our list of values
            values.Clear();
            foreach (object value in hash.Values)
            {
                values.Add(new ModelValue(value));
            }
        }
예제 #2
0
        ///<summary>Finds all the model values except those that match the operator specified</summary>
        public virtual ModelValues      FindOperator(ModelValueOperator op, bool include)
        {
            ModelValues found = new ModelValues();

            foreach (ModelValue item in _list)
            {
                if ((item.Operator == op) == include)
                {
                    found.Add(item);
                }
            }
            return(found);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
                }
            }
        }