Esempio n. 1
0
File: Bag.cs Progetto: e2wugui/zeze
        /// <summary>
        /// 加入物品:优先堆叠到已有的格子里面;然后如果很多,自动拆分。
        /// 失败处理:如果外面调用者在失败时回滚事务,那么所有的添加都会被回滚。
        ///           如果没有回滚,那么就会完成部分添加。此时返回剩余number,逻辑可能需要把剩余数量的物品转到其他系统(比如邮件中)。
        ///           另外如果想回滚全部添加,但是又不回滚整个事务,应该使用嵌套事务。
        ///           在嵌套事务中尝试添加,失败的话回滚嵌套事务,然后继续把所有物品转到其他系统。
        /// </summary>
        /// <param name="item"></param>
        public int Add(int positionHint, BItem itemAdd)
        {
            if (itemAdd.Number <= 0)
            {
                throw new ArgumentException();
            }

            int pileMax = GetItemPileMax(itemAdd.Id);

            // 优先加到提示格子
            if (positionHint >= 0 && positionHint < bag.Capacity)
            {
                if (bag.Items.TryGetValue(positionHint, out var bItemHint))
                {
                    if (bItemHint.Id == itemAdd.Id)
                    {
                        int numberNew = bItemHint.Number + itemAdd.Number;
                        if (numberNew <= pileMax)
                        {
                            bItemHint.Number = numberNew;
                            return(0); // all pile done
                        }
                        bItemHint.Number = pileMax;
                        itemAdd.Number   = numberNew - pileMax;
                        // continue to add
                    }
                    // continue to add
                }
                else
                {
                    bag.Items.Add(positionHint, itemAdd); // in managed
                    if (itemAdd.Number <= pileMax)
                    {
                        return(0);
                    }

                    int remain = itemAdd.Number - pileMax;
                    itemAdd.Number = pileMax;
                    itemAdd        = itemAdd.Copy(); // current itemAdd has in mananged.
                    itemAdd.Number = remain;
                    // ready to continue add
                }
            }

            foreach (var item in bag.Items)
            {
                if (item.Value.Id == itemAdd.Id)
                {
                    int numberNew = item.Value.Number + itemAdd.Number;
                    if (numberNew > pileMax)
                    {
                        item.Value.Number = pileMax;
                        itemAdd.Number    = numberNew - pileMax;
                        continue;
                    }
                    item.Value.Number = numberNew;
                    return(0); // all pile done
                }
            }
            while (itemAdd.Number > pileMax)
            {
                int pos = GetEmptyPosition();
                if (pos == -1)
                {
                    return(itemAdd.Number);
                }

                BItem itemNew = itemAdd.Copy();
                itemNew.Number  = pileMax;
                itemAdd.Number -= pileMax;
                bag.Items.Add(pos, itemNew);
            }
            if (itemAdd.Number > 0)
            {
                int pos = GetEmptyPosition();
                if (pos == -1)
                {
                    return(itemAdd.Number);
                }
                bag.Items.Add(pos, itemAdd);
            }
            return(0);
        }