// All properties are set by the model, for now no need to take care about it
 public FlashGlanceRoundItemVO(int id, int cypher, SafeHashCodePoint gridPosition, int rotation, float scale, AvailableColors color)
 {
     Id           = id;
     Cypher       = cypher;
     GridPosition = gridPosition;
     Rotation     = rotation;
     Scale        = scale;
     Color        = color;
 }
        /* adds a single new item on the map. if  */
        private FlashGlanceRoundItemVO AddItem()
        {
            if (_allItems.Count >= MaxItems)
            {
                return(null);                             //map is full
            }
            SafeHashCodePoint      emptyPosition = GetEmptyPosition();
            FlashGlanceRoundItemVO item          = null;

            if (emptyPosition != null)
            {
                _freePositions.Remove(emptyPosition);
                int   rotation = (_random.NextDouble() <= _castedConfig.GetRotationProbabilityByLevel(CurrentDifficulty)) ? Rotation2D.GetRandom(false) : Rotation2D.DEGREE_0;
                float scale    = (float)((_random.NextDouble() <= _castedConfig.GetScalingProbabilityByLevel(CurrentDifficulty)) ? _random.NextDouble() * 0.3f + 0.7f : 1f);
                item = new FlashGlanceRoundItemVO(_lastItemId, _lastCypher, emptyPosition, rotation, scale, _colors[_colorIndex]);
                _allItems.Add(item);
                _solutionChain.Add(item);
                item.IsBusy = true;

                _lastItemId++;

                //generate next cypher
                string     formula = _castedConfig.GetNextItemFormulaByLevel(CurrentDifficulty);
                Expression exp     = _expressionParser.EvaluateExpression(formula);
                if (exp.Parameters.ContainsKey("x"))
                {
                    exp.Parameters["x"].Value = _lastCypher; // set the named parameter "x"
                }
                else
                {
                    exp.Parameters.Add("x", new Parameter("x")
                    {
                        Value = _lastCypher
                    });
                }
                int formulaResult = (int)exp.Value;
                _lastCypher = (formulaResult > 0) ? formulaResult : _lastCypher + 1;
            }

            //_logger.LogMessage(LogLevel.Informational, "New item created: " + item.ToString());

            return(item);
        }
        public override IRoundIndependentUpdateResultVO RoundIndependentUpdate(IRoundIndependentVO data)
        {
            if (data is FlashGlanceEventRequestVO)
            {
                int i;
                switch (((FlashGlanceEventRequestVO)data).EventType)
                {
                case FlashGlanceEventType.ItemSpawning:
                    var spawnConfig = (_castedConfig.GetNewItemtemSpawningByLevel(CurrentDifficulty));
                    if (spawnConfig.Amount > 0 && _allItems.Count < MaxItems)
                    {
                        int itemsToAdd = Math.Min(MaxItems - _allItems.Count, spawnConfig.Amount);
                        for (i = 0; i < itemsToAdd; i++)
                        {
                            var newItem = AddItem();
                            _minItemAmount = newItem == null ? _minItemAmount : _minItemAmount + 1;
                        }
                    }
                    return(new FlashGlanceEventResultVO(CloneItems(_allItems)));

                case FlashGlanceEventType.ItemMovement:
                    var moveConfig = (_castedConfig.GetItemMovingByLevel(CurrentDifficulty));
                    if (moveConfig.Amount > 0 && _allItems.Count < _allPositions.Count)
                    {
                        int itemsToMove = Math.Min(_allPositions.Count - _allItems.Count, moveConfig.Amount);
                        SafeHashCodePoint      freePostion;
                        FlashGlanceRoundItemVO item;
                        for (i = 0; i < itemsToMove; i++)
                        {
                            freePostion = GetEmptyPosition();
                            item        = GetQuiteItem();
                            if (!(freePostion == null || item == null))
                            {
                                _freePositions.Remove(freePostion);
                                _freePositions.Add(item.GridPosition);
                                item.GridPosition = freePostion;
                                item.IsBusy       = true;
                            }
                        }
                    }
                    return(new FlashGlanceEventResultVO(CloneItems(_allItems)));

                case FlashGlanceEventType.ItemSwitching:
                    var switchConfig = (_castedConfig.GetItemSwitchingByLevel(CurrentDifficulty));
                    if (switchConfig.Amount > 0 && _allItems.Count >= (switchConfig.Amount * 2))
                    {
                        int pairsToSwitch = (int)Math.Min(Math.Floor(_allItems.Count / 2f), switchConfig.Amount);
                        FlashGlanceRoundItemVO item1;
                        FlashGlanceRoundItemVO item2;
                        for (i = 0; i < pairsToSwitch; i++)
                        {
                            item1 = GetQuiteItem();
                            item2 = GetQuiteItem(item1);
                            if (!(item1 == null || item2 == null))
                            {
                                SafeHashCodePoint tempPosition = item1.GridPosition;
                                item1.GridPosition = item2.GridPosition;
                                item2.GridPosition = tempPosition;
                                item1.IsBusy       = true;
                                item2.IsBusy       = true;
                            }
                        }
                    }
                    return(new FlashGlanceEventResultVO(CloneItems(_allItems)));
                }
            }

            else if (data is FlashGlanceItemUnlockedVO)
            {
                var itemUnlocked = ((FlashGlanceItemUnlockedVO)data).Item;
                foreach (var item in _allItems)
                {
                    if (item.Id == itemUnlocked.Id)
                    {
                        item.IsBusy = false;
                        //_logger.LogMessage(LogLevel.Informational, "Item unlocked " + item.Cypher);
                        break;
                    }
                }
            }
            else if (data is FlashGlanceItemHiddenVO)
            {
                var itemHidden = ((FlashGlanceItemHiddenVO)data).Item;
                _freePositions.Add(itemHidden.GridPosition);
                _logger.LogMessage(LogLevel.Informational, "Item hidden " + itemHidden.Cypher);
            }
            return(base.RoundIndependentUpdate(data));
        }