예제 #1
0
        // A sell order was found so the deal is done instantly
        public void FulfillBuyOrderInstantly(Character buyer, bool useBuyerCorporationWallet, MarketOrder marketSellOrder, double pricePerPiece, int duration, int quantity, PublicContainer publicContainer, long?forMembersOf)
        {
            var forCorporation = forMembersOf != null;
            var seller         = Character.GetByEid(marketSellOrder.submitterEID);

            Item itemOnMarket;

            if (!marketSellOrder.isVendorItem)
            {
                //the seller is NOT a vendor
                itemOnMarket = GetItemByMarketOrder(marketSellOrder);

                seller.ThrowIfEqual(null, ErrorCodes.CharacterNotFound);

                if (itemOnMarket.Quantity > quantity)
                {
                    // unstack a fraction
                    var fractionItem = itemOnMarket.Unstack(quantity);
                    fractionItem.Owner = buyer.Eid;

                    // save the remaining item
                    itemOnMarket.Save();

                    // add to public container and change owner
                    publicContainer.AddItem(fractionItem, true);

                    //the remaining amount
                    marketSellOrder.quantity = itemOnMarket.Quantity;

                    // update remaining amount
                    _orderRepository.UpdateQuantity(marketSellOrder);

                    //cash in
                    _marketHelper.CashIn(buyer, useBuyerCorporationWallet, marketSellOrder.price, marketSellOrder.itemDefinition, quantity, TransactionType.marketBuy);

                    //pay out
                    this.PayOutToSeller(seller, marketSellOrder.useCorporationWallet, itemOnMarket.Definition, marketSellOrder.price, quantity, TransactionType.marketSell, marketSellOrder.IsAffectsAverage(), forCorporation);
                }
                else if (itemOnMarket.Quantity == quantity)
                {
                    itemOnMarket.Owner = buyer.Eid;

                    // add to public container and change owner
                    publicContainer.AddItem(itemOnMarket, true);

                    //delete the sell order coz it's done
                    _orderRepository.Delete(marketSellOrder);

                    //cash in
                    _marketHelper.CashIn(buyer, useBuyerCorporationWallet, marketSellOrder.price, marketSellOrder.itemDefinition, quantity, TransactionType.marketBuy);

                    //pay out
                    this.PayOutToSeller(seller, marketSellOrder.useCorporationWallet, itemOnMarket.Definition, marketSellOrder.price, quantity, TransactionType.marketSell, marketSellOrder.IsAffectsAverage(), forCorporation);

                    marketSellOrder.quantity = 0; //signal the sell order delete to the client
                }
                else if (itemOnMarket.Quantity < quantity)
                {
                    //a part of the buy order is fulfilled immediately
                    itemOnMarket.Owner = buyer.Eid;

                    // add to public container and change owner
                    publicContainer.AddItem(itemOnMarket, true);

                    _orderRepository.Delete(marketSellOrder);

                    // create a buy order for the rest of the quantity
                    var newBuyOrder = CreateBuyOrder(buyer, marketSellOrder.itemDefinition, duration, pricePerPiece, quantity - itemOnMarket.Quantity, marketSellOrder.useCorporationWallet, forMembersOf);

                    // cash in for the actual transaction
                    _marketHelper.CashIn(buyer, useBuyerCorporationWallet, marketSellOrder.price, marketSellOrder.itemDefinition, itemOnMarket.Quantity, TransactionType.marketBuy);

                    // cash in for the deposit - for the rest of the quantity
                    _marketHelper.CashIn(buyer, useBuyerCorporationWallet, pricePerPiece, marketSellOrder.itemDefinition, quantity - itemOnMarket.Quantity, TransactionType.buyOrderDeposit);

                    AddCentralBank(TransactionType.buyOrderDeposit, pricePerPiece * (quantity - itemOnMarket.Quantity));

                    //pay out for the current market item
                    this.PayOutToSeller(seller, marketSellOrder.useCorporationWallet, itemOnMarket.Definition, marketSellOrder.price, itemOnMarket.Quantity, TransactionType.marketSell, marketSellOrder.IsAffectsAverage(), forCorporation);

                    marketSellOrder.quantity = 0; //signal to the client

                    //the item he just bought, the sell order update

                    //the new buy order
                    Message.Builder.SetCommand(Commands.MarketBuyOrderCreated)
                    .WithData(new Dictionary <string, object> {
                        { k.buyOrder, newBuyOrder.ToDictionary() }
                    })
                    .ToCharacter(buyer)
                    .Send();
                }

                Market.SendMarketItemBoughtMessage(buyer, itemOnMarket);

                Message.Builder.SetCommand(Commands.MarketSellOrderUpdate)
                .WithData(new Dictionary <string, object> {
                    { k.sellOrder, marketSellOrder.ToDictionary() }
                })
                .ToCharacters(seller, buyer)
                .Send();

                return;
            }

            //check VENDOR sell order's quantity
            if (marketSellOrder.quantity > 0)
            {
                //finite order cases

                var boughtQuantity = quantity;

                if (marketSellOrder.quantity == quantity)
                {
                    _orderRepository.Delete(marketSellOrder);
                    marketSellOrder.quantity = 0; //signal client
                }
                else if (marketSellOrder.quantity > quantity)
                {
                    marketSellOrder.quantity -= quantity; //signal client
                    _orderRepository.UpdateQuantity(marketSellOrder);
                }
                else if (marketSellOrder.quantity < quantity)
                {
                    _orderRepository.Delete(marketSellOrder);
                    boughtQuantity = marketSellOrder.quantity;

                    //create buyorder for the rest of the quantity
                    var buyOrder = CreateBuyOrder(buyer, marketSellOrder.itemDefinition, duration, pricePerPiece, quantity - marketSellOrder.quantity, marketSellOrder.useCorporationWallet, forMembersOf);

                    Message.Builder.SetCommand(Commands.MarketBuyOrderCreated)
                    .WithData(new Dictionary <string, object> {
                        { k.item, buyOrder.ToDictionary() }
                    })
                    .ToCharacter(buyer)
                    .Send();

                    marketSellOrder.quantity = 0; //signal client

                    //cash in deposit
                    _marketHelper.CashIn(buyer, useBuyerCorporationWallet, pricePerPiece, marketSellOrder.itemDefinition, quantity - boughtQuantity, TransactionType.buyOrderDeposit);

                    AddCentralBank(TransactionType.buyOrderDeposit, pricePerPiece * (quantity - boughtQuantity));
                }

                //take the money for the quantity bought
                _marketHelper.CashIn(buyer, useBuyerCorporationWallet, marketSellOrder.price, marketSellOrder.itemDefinition, boughtQuantity, TransactionType.marketBuy);

                Message.Builder.SetCommand(Commands.MarketSellOrderUpdate)
                .WithData(new Dictionary <string, object> {
                    { k.sellOrder, marketSellOrder.ToDictionary() }
                })
                .ToCharacter(buyer)
                .Send();

                // vendor stuff
                itemOnMarket = publicContainer.CreateAndAddItem(marketSellOrder.itemDefinition, false, item =>
                {
                    item.Owner    = buyer.Eid;
                    item.Quantity = boughtQuantity;
                });

                Market.SendMarketItemBoughtMessage(buyer, itemOnMarket);

                //average price
                _marketHandler.InsertAveragePrice(this, marketSellOrder.itemDefinition, boughtQuantity * marketSellOrder.price, boughtQuantity);

                AddCentralBank(TransactionType.marketBuy, boughtQuantity * pricePerPiece); //vendor income
                return;
            }

            //infinite quantity case
            _marketHelper.CashIn(buyer, useBuyerCorporationWallet, marketSellOrder.price, marketSellOrder.itemDefinition, quantity, TransactionType.marketBuy);

            itemOnMarket = publicContainer.CreateAndAddItem(marketSellOrder.itemDefinition, false, item =>
            {
                item.Owner    = buyer.Eid;
                item.Quantity = quantity;
            });

            Market.SendMarketItemBoughtMessage(buyer, itemOnMarket);

            //average price
            _marketHandler.InsertAveragePrice(this, marketSellOrder.itemDefinition, quantity * marketSellOrder.price, quantity);

            AddCentralBank(TransactionType.marketBuy, quantity * pricePerPiece); //vendor income
        }
        public void HandleRequest(IRequest request)
        {
            using (var scope = Db.CreateTransaction())
            {
                var buyer                = request.Session.Character;
                var marketItemId         = request.Data.GetOrDefault <int>(k.marketItemID);
                var useCorporationWallet = request.Data.GetOrDefault <int>(k.useCorporationWallet) == 1;
                var quantity             = request.Data.GetOrDefault <int>(k.quantity);

                quantity.ThrowIfLessOrEqual(0, ErrorCodes.WTFErrorMedicalAttentionSuggested);
                buyer.IsDocked.ThrowIfFalse(ErrorCodes.CharacterHasToBeDocked);
                buyer.CheckPrivilegedTransactionsAndThrowIfFailed();

                var market = buyer.GetCurrentDockingBase().GetMarketOrThrow();

                var sellOrder = _marketOrderRepository.Get(marketItemId).ThrowIfNull(ErrorCodes.ItemNotFound);

                sellOrder.submitterEID.ThrowIfEqual(buyer.Eid, ErrorCodes.CannotBuyFromYourself);

                var corporationEid = buyer.CorporationEid;

                if (sellOrder.forMembersOf != null)
                {
                    corporationEid.ThrowIfNotEqual((long)sellOrder.forMembersOf, ErrorCodes.AccessDenied);
                }

                var publicContainer = buyer.GetPublicContainerWithItems();

                var sellerEid = sellOrder.submitterEID;
                var seller    = Character.GetByEid(sellerEid);

                if (!sellOrder.isVendorItem)
                {
                    //nem vendor, hanem player az aki eladja a cuccot

                    var forCorporation = sellOrder.forMembersOf != null;

                    var boughtQuantity = quantity;

                    seller.ThrowIfEqual(null, ErrorCodes.CharacterNotFound);

                    // the item as entity
                    var itemOnMarket = market.GetItemByMarketOrder(sellOrder);

                    var resultItem = itemOnMarket;
                    if (sellOrder.quantity == quantity)
                    {
                        //delete the sell order coz it's done
                        _marketOrderRepository.Delete(sellOrder);
                        sellOrder.quantity = 0;
                    }
                    else if (sellOrder.quantity > quantity)
                    {
                        sellOrder.quantity = sellOrder.quantity - quantity;
                        _marketOrderRepository.UpdateQuantity(sellOrder);

                        resultItem = itemOnMarket.Unstack(quantity);
                        itemOnMarket.Save();
                    }
                    else if (sellOrder.quantity < quantity)
                    {
                        //bought quantity => marketitem.quantity
                        boughtQuantity = sellOrder.quantity;

                        //delete the sell order coz it's done
                        _marketOrderRepository.Delete(sellOrder);
                        sellOrder.quantity = 0;
                    }

                    resultItem.Owner = buyer.Eid;

                    // add to public container
                    publicContainer.AddItem(resultItem, false);
                    publicContainer.Save();

                    //take money
                    _marketHelper.CashIn(buyer, useCorporationWallet, sellOrder.price, sellOrder.itemDefinition, boughtQuantity, TransactionType.marketBuy);
                    //pay out
                    market.PayOutToSeller(seller, sellOrder.useCorporationWallet, resultItem.Definition, sellOrder.price, boughtQuantity, TransactionType.marketSell, sellOrder.IsAffectsAverage(), forCorporation);


                    Market.SendMarketItemBoughtMessage(buyer, resultItem);

                    Message.Builder.SetCommand(Commands.MarketSellOrderUpdate)
                    .WithData(new Dictionary <string, object> {
                        { k.sellOrder, sellOrder.ToDictionary() }
                    })
                    .ToCharacters(seller, buyer)
                    .Send();
                }
                else
                {
                    // the item is a vendor sell order
                    if (sellOrder.quantity < 0)
                    {
                        //infinite quantity case
                        _marketHelper.CashIn(buyer, useCorporationWallet, sellOrder.price, sellOrder.itemDefinition, quantity, TransactionType.marketBuy);

                        var boughtItem = publicContainer.CreateAndAddItem(sellOrder.itemDefinition, false, item =>
                        {
                            item.Owner    = buyer.Eid;
                            item.Quantity = quantity;
                        });
                        Market.SendMarketItemBoughtMessage(buyer, boughtItem);

                        //average price
                        _marketHandler.InsertAveragePrice(market, sellOrder.itemDefinition, quantity * sellOrder.price, quantity);
                        market.AddCentralBank(TransactionType.marketBuy, quantity * sellOrder.price); //vendor income
                    }
                    else
                    {
                        // vendor finite
                        var boughtQuantity = quantity;

                        if (sellOrder.quantity == quantity)
                        {
                            sellOrder.quantity = 0; //signal order delete
                            //all sold
                            _marketOrderRepository.Delete(sellOrder);
                        }
                        else if (sellOrder.quantity < quantity)
                        {
                            boughtQuantity     = sellOrder.quantity; //clip the amount
                            sellOrder.quantity = 0;                  //signal order delete
                            //all sold
                            _marketOrderRepository.Delete(sellOrder);
                        }
                        else if (sellOrder.quantity > quantity)
                        {
                            sellOrder.quantity -= quantity;
                            //update entry
                            _marketOrderRepository.UpdateQuantity(sellOrder);
                        }

                        _marketHelper.CashIn(buyer, useCorporationWallet, sellOrder.price, sellOrder.itemDefinition, boughtQuantity, TransactionType.marketBuy);

                        //average price
                        _marketHandler.InsertAveragePrice(market, sellOrder.itemDefinition, boughtQuantity * sellOrder.price, boughtQuantity);
                        market.AddCentralBank(TransactionType.marketBuy, boughtQuantity * sellOrder.price); //vendor income

                        var boughtItem = publicContainer.CreateAndAddItem(sellOrder.itemDefinition, false, item =>
                        {
                            item.Owner    = buyer.Eid;
                            item.Quantity = boughtQuantity;
                        });
                        Market.SendMarketItemBoughtMessage(buyer, boughtItem);

                        Message.Builder.SetCommand(Commands.MarketSellOrderUpdate)
                        .WithData(new Dictionary <string, object> {
                            { k.sellOrder, sellOrder.ToDictionary() }
                        })
                        .ToCharacter(buyer)
                        .Send();
                    }
                }

                publicContainer.Save();

                Message.Builder.SetCommand(Commands.ListContainer)
                .WithData(publicContainer.ToDictionary())
                .ToCharacter(buyer)
                .Send();

                scope.Complete();
            }
        }