예제 #1
0
        /// <summary>
        /// Update the assets table based on the transactions meeting the specified criteria.
        /// </summary>
        /// <param name="charID"></param>
        /// <param name="corpID"></param>
        /// <param name="useCorp"></param>
        /// <param name="minimumTransID"></param>
        /// <param name="includeTransAfter"></param>
        /// <returns></returns>
        private static long UpdateFromTransactions(EMMADataSet.AssetsDataTable assetsData,
            AssetList changes, long charID, long corpID, bool useCorp, long minimumTransID,
            DateTime includeTransAfter)
        {
            long maxID = 0;
            long ownerID = useCorp ? corpID : charID;

            EMMADataSet.TransactionsDataTable transactions = new EMMADataSet.TransactionsDataTable();
            transactions = GetTransactions(charID, corpID, useCorp, minimumTransID, includeTransAfter);

            foreach (EMMADataSet.TransactionsRow trans in transactions)
            {
                // If the ID is greater than 9000000000000000000 then it must have been created by EMMA as part of
                // an item exchange contract. These should be ignored here.
                if (trans.ID < 9000000000000000000)
                {
                    int deltaQuantity = trans.Quantity;
                    if (trans.SellerID == ownerID) { deltaQuantity *= -1; }

                    // Change this to not actually make the change in the database. Instead, use the
                    // asset data table passed in and record the changes made in the 'changes' list.

                    /*ChangeAssets(charID, useCorp, trans.StationID, trans.ItemID, 0, (int)AssetStatus.States.Normal,
                        false, deltaQuantity, (deltaQuantity > 0 ? trans.Price : 0), deltaQuantity > 0);*/
                    long assetID = 0;
                    EMMADataSet.AssetsRow asset = null;

                    AssetExists(assetsData, ownerID, trans.StationID, trans.ItemID,
                        (int)AssetStatus.States.Normal, false, 0, false, false, true, false, true, 0, ref assetID);

                    if (assetID != 0)
                    {
                        // Asset stack already exists in database and/or datatable, modify it
                        // based upon the transaction data.
                        asset = assetsData.FindByID(assetID);
                        asset.Quantity += deltaQuantity;
                        if (deltaQuantity > 0)
                        {
                            Asset logicalAsset = new Asset(asset);
                            asset.CostCalc = true;
                            asset.Cost = (logicalAsset.TotalBuyPrice + (trans.Price * trans.Quantity)) /
                                (logicalAsset.Quantity + trans.Quantity);
                        }
                        Asset chg = new Asset(asset);
                        chg.Quantity = deltaQuantity;
                        changes.Add(chg);
                    }
                    else
                    {
                        // Asset does not exist in database so add it to the datatable.
                        asset = assetsData.NewAssetsRow();
                        asset.Quantity = deltaQuantity;
                        asset.AutoConExclude = false;
                        asset.ContainerID = 0;
                        asset.CorpAsset = useCorp;
                        asset.Cost = trans.Price;
                        asset.CostCalc = true;
                        asset.IsContainer = false;
                        asset.ItemID = trans.ItemID;
                        asset.EveItemID = 0;
                        asset.LocationID = trans.StationID;
                        asset.OwnerID = charID;
                        asset.Processed = true;
                        asset.RegionID = trans.RegionID;
                        asset.ReprocExclude = false;
                        asset.Status = (int)AssetStatus.States.Normal;
                        asset.SystemID = Stations.GetStation(trans.StationID).solarSystemID;
                        asset.BoughtViaContract = false;
                        assetsData.AddAssetsRow(asset);
                        changes.Add(new Asset(asset));
                    }

                    if (trans.ID > maxID) { maxID = trans.ID; }
                }
            }

            return maxID;
        }
예제 #2
0
        /// <summary>
        /// Recursive method to update the supplied assets data table based upon the supplied xml node list.
        /// </summary>
        /// <param name="assetData"></param>
        /// <param name="assetList"></param>
        /// <param name="locationID"></param>
        /// <param name="corc"></param>
        /// <param name="containerID"></param>
        /// <param name="expectedChanges"></param>
        private void UpdateAssets(EMMADataSet.AssetsDataTable assetData, XmlNodeList assetList, long locationID,
            CharOrCorp corc, long containerID, AssetList changes)
        {
            int counter = 0;
            if (containerID == 0)
            {
                UpdateStatus(counter, assetList.Count, "Getting asset data from file", "", false);
            }
            else
            {
                UpdateStatus(-1, -1, "Getting asset data from file", "", false,
                    counter, assetList.Count, "Container progress");
            }

            foreach (XmlNode asset in assetList)
            {
                int itemID;
                long assetID = 0, eveInstanceID, quantity;
                bool isContainer = false, needNewRow = false;

                XmlNode locationNode = asset.SelectSingleNode("@locationID");
                if (locationNode != null)
                {
                    locationID = long.Parse(locationNode.Value);

                    // Translate location ID from a corporate office to a station ID if required.
                    if (locationID >= 66000000 && locationID < 67000000)
                    {
                        // NPC station.
                        locationID -= 6000001;
                    }
                    if (locationID >= 67000000 && locationID < 68000000)
                    {
                        // Conquerable station.
                        locationID -= 6000000;
                    }
                }
                itemID = int.Parse(asset.SelectSingleNode("@typeID").Value,
                    System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
                eveInstanceID = long.Parse(asset.SelectSingleNode("@itemID").Value,
                    System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
                quantity = long.Parse(asset.SelectSingleNode("@quantity").Value,
                    System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
                if (asset.LastChild != null && asset.LastChild.Name.Equals("rowset"))
                {
                    isContainer = true;
                }

                EMMADataSet.AssetsRow assetRow;
                needNewRow = true;

                // Note that if a match is not found for the specific eve instance ID we pass in then
                // EMMA will automatically search for an asset matching all the other parameters.
                if (Assets.AssetExists(assetData, corc == CharOrCorp.Corp ? _corpID : _charID, locationID,
                    itemID, (int)AssetStatus.States.Normal, containerID != 0, containerID, isContainer,
                    false, !isContainer, false, true, eveInstanceID, ref assetID))
                {
                    needNewRow = false;
                }
                else if(!isContainer)
                {
                    // We havn't actually updated the database with anything yet so we may already have a
                    // matching item stack in memory but not in the database. Check for that here.
                    DataRow[] data =
                        assetData.Select("ItemID = " + itemID + " AND OwnerID = " + _charID + " AND CorpAsset = " +
                        (corc == CharOrCorp.Corp ? 1 : 0) + " AND LocationID = " + locationID +
                        " AND Status = " + (int)AssetStatus.States.Normal + " AND ContainerID = " + containerID +
                        " AND EveItemID = " + eveInstanceID);
                    if (data != null && data.Length > 0)
                    {
                        needNewRow = false;
                        assetID = ((EMMADataSet.AssetsRow)data[0]).ID;
                    }
                }

                Asset change = null;
                if (!needNewRow)
                {
                    assetRow = assetData.FindByID(assetID);

                    if (assetRow.Processed)
                    {
                        // Row is already in the database but has been processed so just add the current
                        // quantity to the row.
                        // (i.e. there are multiple stacks of the same item in the same location in-game
                        // EMMA merges these since we don't care how things are stacked and it makes
                        // things a little easier.)
                        assetRow.Quantity = assetRow.Quantity + quantity;
                        // We're stacking multiple eve item instances so just set the eve item ID to zero.
                        assetRow.EveItemID = 0;

                        // Store the changes that are being made to the quantity of
                        // items here.
                        // This means that once the update processing is complete, we
                        // can try and work out where these items came from.
                        #region Remember changes to item quantities
                        changes.ItemFilter = "ID = " + assetRow.ID;
                        if (changes.FiltredItems.Count > 0)
                        {
                            change = (Asset)changes.FiltredItems[0];
                            change.Quantity += quantity;
                            change.EveItemInstanceID = 0;
                            if (change.Quantity == 0) { changes.ItemFilter = ""; changes.Remove(change); }
                        }
                        else
                        {
                            change = new Asset(assetRow);
                            change.Quantity = quantity;
                            change.Processed = false;
                            changes.Add(change);
                        }
                        #endregion
                    }
                    else
                    {
                        if (assetRow.Quantity == quantity)
                        {
                            // The row already exists in the database and quantity is the same so
                            // set the processed flag on the database directly and remove the row
                            // from the dataset without setting it to be deleted when the database
                            // is updated.
                            // Note the processed flag MUST be set on the database for later routines
                            // to work correctly. (e.g. Assets.ProcessSellOrders)
                            if (assetRow.EveItemID != 0)
                            {
                                Assets.SetProcessedFlag(assetID, true);
                                assetData.RemoveAssetsRow(assetRow);
                            }
                            else
                            {
                                // If Eve instance ID is not yet set then set it.
                                Assets.SetProcessedFlag(assetID, true);
                                assetRow.Processed = true;
                                assetRow.EveItemID = eveInstanceID;
                            }
                        }
                        else if (assetRow.Quantity != quantity)
                        {
                            // The row already exists in the database, has not yet been processed
                            // and the quantity does not match what we've got from the XML.

                            // Store the changes that are being made to the quantity of
                            // items here.
                            // This means that once the update processing is complete, we
                            // can try and work out where these items came from.
                            #region Remember changes to item quantities
                            change = new Asset(assetRow);
                            change.Quantity = quantity - assetRow.Quantity;
                            change.EveItemInstanceID = eveInstanceID;
                            change.Processed = false;
                            changes.Add(change);
                            #endregion

                            // All we need to do is update the quantity and set the processed flag.
                            assetRow.Quantity = quantity;
                            assetRow.Processed = true;
                            assetRow.EveItemID = eveInstanceID;
                            // Also set the processed flag on the database directly. This will
                            // stop us from picking up this row later on (e.g. Assets.ProcessSellOrders)
                            Assets.SetProcessedFlag(assetID, true);
                        }
                    }
                }
                else
                {
                    // The row does not currently exist in the database so we need to create it.
                    assetRow = assetData.NewAssetsRow();
                    //assetRow.OwnerID = _charID;
                    assetRow.OwnerID = corc == CharOrCorp.Corp ? _corpID : _charID;
                    assetRow.CorpAsset = corc == CharOrCorp.Corp;
                    assetRow.ItemID = itemID;
                    assetRow.EveItemID = eveInstanceID;
                    assetRow.LocationID = locationID;
                    assetRow.Status = 1;
                    assetRow.Processed = true;
                    assetRow.AutoConExclude = false;
                    assetRow.ReprocExclude = false;
                    assetRow.Cost = 0;
                    assetRow.CostCalc = false;
                    assetRow.BoughtViaContract = false;

                    long systemID = 0, regionID = 0;
                    if (locationID >= 30000000 && locationID < 40000000)
                    {
                        systemID = locationID;
                        EveDataSet.mapSolarSystemsRow system = SolarSystems.GetSystem(locationID);
                        if (system != null)
                        {
                            regionID = system.regionID;
                        }
                        else
                        {
                            new EMMAEveAPIException(ExceptionSeverity.Warning, "Asset row added with unknown " +
                                "solar system ID (" + locationID + ")");
                        }
                    }
                    else
                    {
                        EveDataSet.staStationsRow station = null;
                        try
                        {
                            station = Stations.GetStation(locationID);
                        }
                        catch (EMMADataMissingException) { }

                        if (station != null)
                        {
                            systemID = station.solarSystemID;
                            regionID = station.regionID;
                        }
                        else
                        {
                            new EMMAEveAPIException(ExceptionSeverity.Warning, "Asset row added with unknown " +
                                "station ID (" + locationID + ")");
                        }
                    }
                    assetRow.SystemID = systemID;
                    assetRow.RegionID = regionID;
                    assetRow.Quantity = quantity;
                    assetRow.ContainerID = containerID;
                    assetRow.IsContainer = isContainer;
                    if (isContainer)
                    {
                        // If this asset is a container and has child assets then we must add it to the
                        // database now and get the correct ID number.
                        // (Because IDs are assigned by the database itself)
                        assetID = Assets.AddRowToDatabase(assetRow);
                    }
                    else
                    {
                        // Otherwise, we can just add it to the data table to be stored later along with
                        // everything else.
                        assetData.AddAssetsRow(assetRow);
                    }

                    // Store the changes that are being made to the quantity of
                    // items here.
                    // This means that once the update processing is complete, we
                    // can try and work out where these items came from.
                    #region Remember changes to item quantities
                    change = new Asset(assetRow);
                    if (isContainer) { change.ID = assetID; }
                    change.Quantity = quantity;
                    change.Processed = false;
                    changes.Add(change);
                    #endregion
                }

                if (isContainer)
                {
                    XmlNodeList contained = asset.SelectNodes("rowset/row");
                    UpdateAssets(assetData, contained, locationID, corc, assetID, changes);
                }

                counter++;
                if (containerID == 0)
                {
                    UpdateStatus(counter, assetList.Count, "Getting asset data from file", "", false);
                }
                else
                {
                    UpdateStatus(-1, -1, "Getting asset data from file", "", false,
                        counter, assetList.Count, "Container progress");
                }
            }
        }
예제 #3
0
        /// <summary>
        /// This ensures that items in sell orders appear in the list of the player's assets.
        /// It is called just after new asset XML from the API has been processed but before
        /// the update is applied to the database.
        /// </summary>
        public static void ProcessSellOrders(EMMADataSet.AssetsDataTable assetData, AssetList changes,
            long ownerID)
        {
            List<int> itemIDs = new List<int>();
            itemIDs.Add(0);
            List<long> stationIDs = new List<long>();
            stationIDs.Add(0);
            List<AssetAccessParams> accessParams = new List<AssetAccessParams>();
            accessParams.Add(new AssetAccessParams(ownerID));
            // Get active sell orders
            OrdersList sellOrders = Orders.LoadOrders(accessParams, itemIDs, stationIDs, 999, "Sell");
            EMMADataSet.AssetsRow changedAsset = null;
            // Note that modifiedAssets is indexed first by itemID and second by stationID
            Dictionary<int, Dictionary<long, AssetInfo>> modifiedAssets = new Dictionary<int, Dictionary<long, AssetInfo>>();

            foreach (Order sellOrder in sellOrders)
            {
                bool foundMatch = false;
                long assetID = 0;

                // If there is already an asset row with a state of 'ForSaleViaMarket' in the same location,
                // and with the same item type then check quantity.
                // If it matches then just set to processed and move on.
                // If it does not then record the difference in quantities and go to the next order.
                // If we can't find a match then add a new asset row and record the items gained.
                if (Assets.AssetExists(assetData, ownerID, sellOrder.StationID, sellOrder.ItemID,
                    (int)AssetStatus.States.ForSaleViaMarket, false, 0, false, false, true, true,
                    true, 0, ref assetID))
                {
                    foundMatch = true;
                }
                else
                {
                    DataRow[] data =
                        assetData.Select("ItemID = " + sellOrder.ItemID + " AND OwnerID = " +
                        ownerID.ToString() + " AND LocationID = " + sellOrder.StationID +
                        " AND Status = " + (int)AssetStatus.States.ForSaleViaMarket);
                    if (data != null && data.Length > 0)
                    {
                        foundMatch = true;
                        assetID = ((EMMADataSet.AssetsRow)data[0]).ID;
                    }
                }

                if (foundMatch)
                {
                    changedAsset = assetData.FindByID(assetID);
                    if (changedAsset.Quantity != sellOrder.RemainingVol)
                    {
                        // If the quantities do not match then store how many units we are removing
                        // from the stack, the most likely cause is more than one sell order for
                        // this item in this location and if we know how many units we've removed
                        // We can make sure that the other order(s) quantity matches up.
                        Dictionary<long, AssetInfo> itemDeltaVol = new Dictionary<long, AssetInfo>();
                        if (modifiedAssets.ContainsKey(sellOrder.ItemID))
                        {
                            itemDeltaVol = modifiedAssets[sellOrder.ItemID];
                        }
                        else
                        {
                            modifiedAssets.Add(sellOrder.ItemID, itemDeltaVol);
                        }
                        if (itemDeltaVol.ContainsKey(sellOrder.StationID))
                        {
                            AssetInfo info = itemDeltaVol[sellOrder.StationID];
                            info.quantity += sellOrder.RemainingVol - changedAsset.Quantity;
                            itemDeltaVol[sellOrder.StationID] = info;
                            changedAsset.Quantity += sellOrder.RemainingVol;
                        }
                        else
                        {
                            AssetInfo info = new AssetInfo();
                            info.quantity = sellOrder.RemainingVol - changedAsset.Quantity;
                            info.assetID = changedAsset.ID;
                            itemDeltaVol.Add(sellOrder.StationID, info);
                            changedAsset.Quantity = sellOrder.RemainingVol;
                        }
                    }
                    changedAsset.Processed = true;
                    // Also set it to processed in the database.
                    SetProcessedFlag(changedAsset.ID, true);
                }

                // We havn't managed to match the order to an existing 'ForSaleViaMarket' stack in
                // the database or in memory.
                // As such, we need to create a new one.
                if (!foundMatch)
                {
                    // Create the new asset row..
                    changedAsset = assetData.NewAssetsRow();
                    changedAsset.AutoConExclude = true;
                    changedAsset.ContainerID = 0;
                    changedAsset.CorpAsset = false;
                    // Set cost to zero for now, it will be worked out later when gains/losses are reconciled.
                    changedAsset.Cost = 0;
                    changedAsset.CostCalc = false;
                    changedAsset.IsContainer = false;
                    changedAsset.ItemID = sellOrder.ItemID;
                    changedAsset.EveItemID = 0;
                    changedAsset.LocationID = sellOrder.StationID;
                    changedAsset.OwnerID = sellOrder.OwnerID;
                    changedAsset.Processed = true;
                    changedAsset.Quantity = sellOrder.RemainingVol;
                    changedAsset.RegionID = sellOrder.RegionID;
                    changedAsset.ReprocExclude = true;
                    changedAsset.SystemID = sellOrder.SystemID;
                    changedAsset.BoughtViaContract = false;
                    changedAsset.Status = (int)AssetStatus.States.ForSaleViaMarket;

                    assetData.AddAssetsRow(changedAsset);

                    // Store the changes we are making to quantities
                    Dictionary<long, AssetInfo> itemDeltaVol = new Dictionary<long, AssetInfo>();
                    if (modifiedAssets.ContainsKey(sellOrder.ItemID))
                    {
                        itemDeltaVol = modifiedAssets[sellOrder.ItemID];
                    }
                    else
                    {
                        modifiedAssets.Add(sellOrder.ItemID, itemDeltaVol);
                    }
                    if (itemDeltaVol.ContainsKey(sellOrder.StationID))
                    {
                        AssetInfo info = itemDeltaVol[sellOrder.StationID];
                        info.quantity += sellOrder.RemainingVol;
                        itemDeltaVol[sellOrder.StationID] = info;
                    }
                    else
                    {
                        AssetInfo info = new AssetInfo();
                        info.quantity = sellOrder.RemainingVol;
                        info.assetID = changedAsset.ID;
                        itemDeltaVol.Add(sellOrder.StationID, info);
                    }
                }

            }

            // Once we've finished processing all the orders, store the overall quantity changes.
            Dictionary<int, Dictionary<long, AssetInfo>>.Enumerator enumerator = modifiedAssets.GetEnumerator();
            while (enumerator.MoveNext())
            {
                Dictionary<long, AssetInfo>.Enumerator enumerator2 = enumerator.Current.Value.GetEnumerator();
                while(enumerator2.MoveNext())
                {
                    Asset change = new Asset();
                    change.ID = enumerator2.Current.Value.assetID;
                    change.ItemID = enumerator.Current.Key;
                    change.LocationID = enumerator2.Current.Key;
                    change.Quantity = enumerator2.Current.Value.quantity;
                    change.StatusID = (int)AssetStatus.States.ForSaleViaMarket;
                    change.IsContainer = false;
                    change.Container = null;
                    change.AutoConExclude = true;
                    change.OwnerID = ownerID;
                    change.UnitBuyPrice = 0;
                    change.UnitBuyPricePrecalculated = false;

                    changes.Add(change);
                }
            }
        }