コード例 #1
0
        public void A_normal_items_quality_should_decrease_by_2_after_the_sell_by_date()
        {
            var snapshot            = new InventorySnapshot();
            var setInitialInventory = JsonConvert.SerializeObject(new SetInitialInventoryDataEvent {
                InventoryItems = _initialInventory
            });

            var currentTime = new DateTime(2018, 1, 1, 10, 0, 0);

            _snapshotProcessor.ProcessEvent(snapshot, setInitialInventory, currentTime);

            for (var i = 0; i < 17; i++)
            {
                currentTime = currentTime.AddMinutes(1);

                var advanceDay = JsonConvert.SerializeObject(new AdvanceDayDataEvent());
                _snapshotProcessor.ProcessEvent(snapshot, advanceDay, currentTime);
            }

            var sword = snapshot.InventoryItems.Single(item => string.Equals(item.Name, "Sword", StringComparison.Ordinal));

            // starts at 25
            // -1 x 15
            // -2 x 2
            sword.Quality.ShouldBe(6);
        }
コード例 #2
0
 public InventoryAggregateRoot(Guid id, string name)
 {
     _snapshot = new InventorySnapshot();
     Id        = id;
     Version   = -1;
     ApplyChange(new InventoryItemCreated(id, name));
 }
コード例 #3
0
        public void Sulfuras_quality_should_always_be_80()
        {
            var snapshot            = new InventorySnapshot();
            var setInitialInventory = JsonConvert.SerializeObject(new SetInitialInventoryDataEvent {
                InventoryItems = _initialInventory
            });

            var currentTime = new DateTime(2018, 1, 1, 10, 0, 0);

            _snapshotProcessor.ProcessEvent(snapshot, setInitialInventory, currentTime);

            snapshot.InventoryItems.Single(item => string.Equals(item.Category, "Sulfuras", StringComparison.Ordinal)).Quality
            .ShouldBe(80);

            for (var i = 0; i < 100; i++)
            {
                currentTime = currentTime.AddMinutes(1);

                var advanceDay = JsonConvert.SerializeObject(new AdvanceDayDataEvent());
                _snapshotProcessor.ProcessEvent(snapshot, advanceDay, currentTime);

                snapshot.InventoryItems.Single(item => string.Equals(item.Category, "Sulfuras", StringComparison.Ordinal)).Quality
                .ShouldBe(80);
            }
        }
コード例 #4
0
        public InventorySnapshotDynamics GetDynamics(InventorySnapshot startSnapshot, InventorySnapshot endSnapshot)
        {
            if (startSnapshot == null)
            {
                throw new ArgumentNullException(nameof(startSnapshot));
            }

            if (endSnapshot == null)
            {
                throw new ArgumentNullException(nameof(endSnapshot));
            }

            Dictionary <string, AssetPairInventory> assetPairInventories = GroupAndMerge(
                startSnapshot.AssetPairInventories,
                endSnapshot.AssetPairInventories,
                o => o.AssetPair,
                ComputeAssetPairDynamics);

            Dictionary <string, AssetBalanceInventory> assetInventories = GroupAndMerge(
                startSnapshot.Assets,
                endSnapshot.Assets,
                o => o.AssetId,
                ComputeAssetDynamics);

            return(new InventorySnapshotDynamics
            {
                Source = endSnapshot.Source,
                StartDate = startSnapshot.Timestamp,
                EndDate = endSnapshot.Timestamp,
                Assets = assetInventories.Values.ToList(),
                AssetPairInventories = assetPairInventories.Values.ToList()
            });
        }
コード例 #5
0
        public void Backstage_passes_quality_increases_by_three_per_day_when_there_are_less_than_5_days_left()
        {
            var snapshot            = new InventorySnapshot();
            var setInitialInventory = JsonConvert.SerializeObject(new SetInitialInventoryDataEvent {
                InventoryItems = _initialInventory
            });

            var currentTime = new DateTime(2018, 1, 1, 10, 0, 0);

            _snapshotProcessor.ProcessEvent(snapshot, setInitialInventory, currentTime);

            for (var i = 0; i < 12; i++)
            {
                currentTime = currentTime.AddMinutes(1);

                var advanceDay = JsonConvert.SerializeObject(new AdvanceDayDataEvent());
                _snapshotProcessor.ProcessEvent(snapshot, advanceDay, currentTime);
            }

            // SellIn starts at 15
            // Qualtity starts at 3
            // +1 x 5
            // +2 x 5
            // +3 x 2
            snapshot.InventoryItems.Single(item => string.Equals(item.Category, "Backstage Passes", StringComparison.Ordinal)).Quality
            .ShouldBe(24);
        }
コード例 #6
0
        private static string[] GetExchanges(InventorySnapshot startAssetInventory,
                                             InventorySnapshot endInventorySnapshot)
        {
            IEnumerable <string> startInventorySnapshotBalanceExchanges = startAssetInventory.Assets
                                                                          .SelectMany(x => x.Balances)
                                                                          .Select(x => x.Exchange);

            IEnumerable <string> startInventorySnapshotInventoryExchanges = startAssetInventory.Assets
                                                                            .SelectMany(x => x.Inventories)
                                                                            .Select(x => x.Exchange);

            IEnumerable <string> endInventorySnapshotBalanceExchanges = endInventorySnapshot.Assets
                                                                        .SelectMany(x => x.Balances)
                                                                        .Select(x => x.Exchange);

            IEnumerable <string> endInventorySnapshotInventoryExchanges = endInventorySnapshot.Assets
                                                                          .SelectMany(x => x.Inventories)
                                                                          .Select(x => x.Exchange);

            return(startInventorySnapshotBalanceExchanges
                   .Union(startInventorySnapshotInventoryExchanges)
                   .Union(endInventorySnapshotBalanceExchanges)
                   .Union(endInventorySnapshotInventoryExchanges)
                   .ToArray());
        }
コード例 #7
0
        public void Aged_bries_quality_should_increase_twice_as_fast_after_the_sell_by_date()
        {
            var snapshot            = new InventorySnapshot();
            var setInitialInventory = JsonConvert.SerializeObject(new SetInitialInventoryDataEvent {
                InventoryItems = _initialInventory
            });

            var currentTime = new DateTime(2018, 1, 1, 10, 0, 0);

            _snapshotProcessor.ProcessEvent(snapshot, setInitialInventory, currentTime);

            for (var i = 0; i < 6; i++)
            {
                currentTime = currentTime.AddMinutes(1);

                var advanceDay = JsonConvert.SerializeObject(new AdvanceDayDataEvent());
                _snapshotProcessor.ProcessEvent(snapshot, advanceDay, currentTime);
            }

            var agedBrie = snapshot.InventoryItems.Single(item => string.Equals(item.Name, "Aged Brie", StringComparison.Ordinal));

            // starts at 10
            // +1 x 5
            // +2 x 1
            agedBrie.Quality.ShouldBe(17);
        }
コード例 #8
0
        public static PnLResult GetPnL(InventorySnapshot startInventorySnapshot, InventorySnapshot endInventorySnapshot)
        {
            string[] assets = GetAssets(startInventorySnapshot, endInventorySnapshot);

            string[] exchanges = GetExchanges(startInventorySnapshot, endInventorySnapshot);

            var exchangePnL = new List <ExchangePnL>();

            foreach (string exchange in exchanges)
            {
                var assetsPnL = new List <AssetPnL>();

                foreach (var assetId in assets)
                {
                    AssetPnL assetPnL = CalcPnLByAsset(assetId, exchange, startInventorySnapshot, endInventorySnapshot);

                    assetsPnL.Add(assetPnL);
                }

                exchangePnL.Add(new ExchangePnL
                {
                    Exchange    = exchange,
                    Trading     = assetsPnL.Sum(o => o.Trading),
                    Directional = assetsPnL.Sum(o => o.Directional),
                    AssetsPnLs  = assetsPnL.Where(o => !o.IsEmpty()).ToList()
                });
            }

            return(new PnLResult
            {
                StartDate = startInventorySnapshot.Timestamp,
                EndDate = endInventorySnapshot.Timestamp,
                ExchangePnLs = exchangePnL
            });
        }
コード例 #9
0
 private void ProcessSetInitialInventory(InventorySnapshot snapshot, SetInitialInventoryDataEvent dataEvent)
 {
     if (!snapshot.HasProcessedInitialInventory)
     {
         snapshot.InventoryItems = dataEvent.InventoryItems;
         snapshot.HasProcessedInitialInventory = true;
     }
 }
コード例 #10
0
        private static string[] GetAssets(InventorySnapshot startAssetInventory, InventorySnapshot endInventorySnapshot)
        {
            IEnumerable <string> startInventorySnapshotAssets = startAssetInventory.Assets
                                                                .Select(o => o.AssetId);

            IEnumerable <string> endInventorySnapshotAssets = endInventorySnapshot.Assets
                                                              .Select(o => o.AssetId);

            return(startInventorySnapshotAssets
                   .Union(endInventorySnapshotAssets)
                   .ToArray());
        }
コード例 #11
0
        private async Task <List <InventorySnapshot> > _GetZComInventorySnapshots()
        {
            try
            {
                List <InventorySnapshot> Inventories = new List <InventorySnapshot>();

                using (SqlConnection Con = new SqlConnection(Static.Secrets.ScadaConnectionString))
                {
                    if (Con.State == System.Data.ConnectionState.Closed)
                    {
                        Con.Open();
                    }


                    string str = $@"SELECT s.IDSKLADNIK as Id, s.MaterialNumber as Number, s.NAZWASKLADNIKA as Name, SUM(z.ILOSC_W_ZBIORNIKU) as Size
                                    FROM ZBIORNIKI z 
	                                    LEFT JOIN SKLADNIKI s ON s.IDSKLADNIK=z.IDSKLADNIK
                                    WHERE s.MaterialNumber IS NOT NULL 
                                    GROUP BY s.IDSKLADNIK, s.MaterialNumber, s.NAZWASKLADNIKA";


                    var Command = new SqlCommand(str, Con);

                    var reader = Command.ExecuteReader();


                    if (reader.HasRows)
                    {
                        while (reader.Read())
                        {
                            InventorySnapshot i = new InventorySnapshot();
                            i.InventorySnapshotId = 0;
                            i.ProductId           = Convert.ToInt32(reader["Id"].ToString());
                            i.ProductIndex        = reader["Number"].ToString();
                            i.ProductName         = reader["Name"].ToString();
                            i.Size    = Math.Round(Convert.ToDouble(reader["Size"].ToString()));
                            i.Unit    = "KG";
                            i.Status  = "U";
                            i.TakenOn = DateTime.Now;
                            Inventories.Add(i);
                        }
                    }

                    return(Inventories);
                }
            }
            catch (Exception ex)
            {
                Logger.Error("_GetZComInventorySnapshots: Błąd. Szczegóły: {Message}", ex.ToString());
                throw;
            }
        }
        private async Task ProcessMessageAsync(InventorySnapshot message)
        {
            try
            {
                var model = Mapper.Map <Core.Domain.InventorySnapshots.InventorySnapshot>(message);

                await _inventorySnapshotService.HandleAsync(model);
            }
            catch (Exception exception)
            {
                _log.Error(exception, "An error occurred during processing inventory snapshot", message);
            }
        }
コード例 #13
0
        public async Task InsertAsync(InventorySnapshot inventorySnapshot)
        {
            Guid id = Guid.NewGuid();

            var entity = new InventorySnapshotEntity(GetPartitionKey(inventorySnapshot.Timestamp), GetRowKey(id))
            {
                Time = inventorySnapshot.Timestamp,
                Json = JsonConvert.SerializeObject(inventorySnapshot)
            };

            await _storage.InsertAsync(entity);

            await UpdateIndexes(entity);
        }
        private async Task FillUsdForCreditsAsync(InventorySnapshot inventorySnapshot)
        {
            var balanceRecords = inventorySnapshot.Assets
                                 .SelectMany(x => x.Balances.Select(b => new BalanceRecord(decimal.ToDouble(b.Credit), x.AssetId)))
                                 .ToList();

            var balanceRecordsInUsd = await GetInUsdAsync(balanceRecords);

            var flatListOfBalances = inventorySnapshot.Assets.SelectMany(x => x.Balances).ToList();

            for (int i = 0; i < balanceRecords.Count; i++)
            {
                flatListOfBalances[i].CreditInUsd = (decimal)balanceRecordsInUsd[i].Balance;
            }
        }
        public async Task HandleAsync(InventorySnapshot model)
        {
            try
            {
                await FillUsdForInventoriesAsync(model);
                await FillUsdForBalancesAsync(model);
                await FillUsdForCreditsAsync(model);
            }
            catch (Exception e)
            {
                _log.Error(e, context: $"Snapshot: {model.ToJson()}");
            }

            await _inventorySnapshotRepository.InsertAsync(model);
        }
コード例 #16
0
        public void Aged_bries_quality_should_increase_with_age()
        {
            var snapshot            = new InventorySnapshot();
            var setInitialInventory = JsonConvert.SerializeObject(new SetInitialInventoryDataEvent {
                InventoryItems = _initialInventory
            });

            _snapshotProcessor.ProcessEvent(snapshot, setInitialInventory, new DateTime(2018, 1, 1, 10, 0, 0));

            var advanceDay = JsonConvert.SerializeObject(new AdvanceDayDataEvent());

            _snapshotProcessor.ProcessEvent(snapshot, advanceDay, new DateTime(2018, 1, 1, 10, 1, 0));

            var agedBrie = snapshot.InventoryItems.Single(item => string.Equals(item.Name, "Aged Brie", StringComparison.Ordinal));

            agedBrie.Quality.ShouldBe(11);
        }
コード例 #17
0
        private static AssetPnL CalcPnLByAsset(string assetId, string exchange,
                                               InventorySnapshot startInventorySnapshot, InventorySnapshot endInventorySnapshot)
        {
            AssetBalanceInventory startAssetBalanceInventory = startInventorySnapshot.Assets
                                                               .SingleOrDefault(a => a.AssetId == assetId);

            AssetBalanceInventory endAssetBalanceInventory = endInventorySnapshot.Assets
                                                             .SingleOrDefault(a => a.AssetId == assetId);

            var startAssetBalance = startAssetBalanceInventory == null
                ? BalanceOnDate.Empty
                : new BalanceOnDate(startAssetBalanceInventory.GetBalanceByExchange(exchange));

            var endAssetBalance = endAssetBalanceInventory == null
                ? BalanceOnDate.Empty
                : new BalanceOnDate(endAssetBalanceInventory.GetBalanceByExchange(exchange));

            var startAssetInventory = startAssetBalanceInventory == null
                ? new AssetInventory {
                Exchange = exchange
            }
                : startAssetBalanceInventory.GetInventoryByExchange(exchange);

            var endAssetInventory = endAssetBalanceInventory == null
                ? new AssetInventory {
                Exchange = exchange
            }
                : endAssetBalanceInventory.GetInventoryByExchange(exchange);

            decimal tradingPnL = endAssetBalance.Price * (endAssetInventory.VolumeInUsd - startAssetInventory.VolumeInUsd);

            decimal directionalPnL = startAssetBalance.Balance * (endAssetBalance.Price - startAssetBalance.Price);

            var assetDisplayId = startAssetBalanceInventory?.AssetDisplayId ??
                                 endAssetBalanceInventory?.AssetDisplayId ?? assetId;

            return(new AssetPnL
            {
                Asset = assetDisplayId,
                Exchange = exchange,
                Trading = tradingPnL,
                Directional = directionalPnL,
                StartBalance = startAssetBalance,
                EndBalance = endAssetBalance
            });
        }
コード例 #18
0
        public void Conjured_items_should_degrade_twice_as_fast_as_normal_items()
        {
            var snapshot            = new InventorySnapshot();
            var setInitialInventory = JsonConvert.SerializeObject(new SetInitialInventoryDataEvent {
                InventoryItems = _initialInventory
            });

            var currentTime = new DateTime(2018, 1, 1, 10, 0, 0);

            _snapshotProcessor.ProcessEvent(snapshot, setInitialInventory, currentTime);

            currentTime = currentTime.AddMinutes(1);

            var advanceDay = JsonConvert.SerializeObject(new AdvanceDayDataEvent());

            _snapshotProcessor.ProcessEvent(snapshot, advanceDay, currentTime);

            // 20 - 2 = 18
            snapshot.InventoryItems.Single(item => string.Equals(item.Category, "Conjured", StringComparison.Ordinal)).Quality
            .ShouldBe(18);
        }
コード例 #19
0
        public void Backstage_passes_quality_should_drop_to_zero_after_the_concert()
        {
            var snapshot            = new InventorySnapshot();
            var setInitialInventory = JsonConvert.SerializeObject(new SetInitialInventoryDataEvent {
                InventoryItems = _initialInventory
            });

            var currentTime = new DateTime(2018, 1, 1, 10, 0, 0);

            _snapshotProcessor.ProcessEvent(snapshot, setInitialInventory, currentTime);

            for (var i = 0; i < 16; i++)
            {
                currentTime = currentTime.AddMinutes(1);

                var advanceDay = JsonConvert.SerializeObject(new AdvanceDayDataEvent());
                _snapshotProcessor.ProcessEvent(snapshot, advanceDay, currentTime);
            }

            snapshot.InventoryItems.Single(item => string.Equals(item.Category, "Backstage Passes", StringComparison.Ordinal)).Quality
            .ShouldBe(0);
        }
コード例 #20
0
        public void Aged_bries_quality_should_not_go_above_50()
        {
            var snapshot            = new InventorySnapshot();
            var setInitialInventory = JsonConvert.SerializeObject(new SetInitialInventoryDataEvent {
                InventoryItems = _initialInventory
            });

            var currentTime = new DateTime(2018, 1, 1, 10, 0, 0);

            _snapshotProcessor.ProcessEvent(snapshot, setInitialInventory, currentTime);

            for (var i = 0; i < 100; i++)
            {
                currentTime = currentTime.AddMinutes(1);

                var advanceDay = JsonConvert.SerializeObject(new AdvanceDayDataEvent());
                _snapshotProcessor.ProcessEvent(snapshot, advanceDay, currentTime);
            }

            var agedBrie = snapshot.InventoryItems.Single(item => string.Equals(item.Name, "Aged Brie", StringComparison.Ordinal));

            agedBrie.Quality.ShouldBe(50);
        }
コード例 #21
0
        public void ProcessEvent(InventorySnapshot snapshot, string eventContents, DateTime snapshotFileCreationTime)
        {
            var readableEntity = JsonConvert.DeserializeObject <ReadableEntity>(eventContents);

            if (string.Equals(readableEntity.ContractName, new SetInitialInventoryDataEvent().ContractName, StringComparison.InvariantCultureIgnoreCase))
            {
                ProcessSetInitialInventory(snapshot, JsonConvert.DeserializeObject <SetInitialInventoryDataEvent>(eventContents));
            }
            else if (string.Equals(readableEntity.ContractName, new AdvanceDayDataEvent().ContractName, StringComparison.InvariantCultureIgnoreCase))
            {
                ProcessAdvanceDay(snapshot, JsonConvert.DeserializeObject <AdvanceDayDataEvent>(eventContents));
            }

            // Sulfuras' quality should always be 80.
            if (snapshot?.InventoryItems != null)
            {
                snapshot.InventoryItems.Where(item => string.Equals(item.Category, "Sulfuras", StringComparison.InvariantCultureIgnoreCase))
                .ToList()
                .ForEach(item => item.Quality = 80);
            }

            snapshot.LastFileCreationTimeUtc = snapshotFileCreationTime;
        }
コード例 #22
0
 public override void LoadSnapshot(string data)
 {
     _snapshot = JsonConvert.DeserializeObject <InventorySnapshot>(data);
 }
コード例 #23
0
        private void ProcessAdvanceDay(InventorySnapshot snapshot, AdvanceDayDataEvent dataEvent)
        {
            // Don't advance the day if the initial inventory hasn't been set.
            if (!snapshot.HasProcessedInitialInventory)
            {
                return;
            }

            foreach (var item in snapshot.InventoryItems ?? new List <InventoryItem>())
            {
                // TODO: This needs to move to a ruleset.
                int qualityChange = 0;

                if (string.Equals(item.Name, "Aged Brie", StringComparison.InvariantCultureIgnoreCase))
                {
                    qualityChange = item.SellIn > 0 ? 1 : 2;
                }
                else if (string.Equals(item.Category, "Backstage Passes", StringComparison.InvariantCultureIgnoreCase))
                {
                    // "Backstage passes", like aged brie, increases in Quality as it's SellIn value approaches;
                    // Quality increases by 2 when there are 10 days or less and by 3 when there are 5 days or less but
                    // Quality drops to 0 after the concert
                    if (item.SellIn <= 0)
                    {
                        item.Quality = 0;
                    }
                    else if (item.SellIn <= 5)
                    {
                        qualityChange = 3;
                    }
                    else if (item.SellIn <= 10)
                    {
                        qualityChange = 2;
                    }
                    else
                    {
                        qualityChange = 1;
                    }
                }
                else if (string.Equals(item.Category, "Conjured", StringComparison.InvariantCultureIgnoreCase))
                {
                    qualityChange = item.SellIn > 0 ? -2 : -4;
                }
                else if (string.Equals(item.Category, "Sulfuras", StringComparison.InvariantCultureIgnoreCase))
                {
                }
                else
                {
                    qualityChange = item.SellIn > 0 ? -1 : -2;
                }

                var updatedQuality = item.Quality + qualityChange;

                if (updatedQuality < 0)
                {
                    updatedQuality = 0;
                }
                if (updatedQuality > 50)
                {
                    updatedQuality = 50;
                }

                item.Quality = updatedQuality;

                if (item.SellIn > 0)
                {
                    item.SellIn--;
                }
            }
        }
コード例 #24
0
 public InventoryAggregateRoot()
 {
     _snapshot = new InventorySnapshot();
     Version   = -1;
 }
コード例 #25
0
        private async Task <List <InventorySnapshot> > _GetInventorySnapshots(string query = null)
        {
            try
            {
                List <InventorySnapshot> Inventories = new List <InventorySnapshot>();

                using (SqlConnection Con = new SqlConnection(Static.Secrets.NpdConnectionString))
                {
                    if (Con.State == System.Data.ConnectionState.Closed)
                    {
                        Con.Open();
                    }

                    //make sure takenOn date is always indicated
                    //it should default to last inventory snapshot taken on date
                    if (query != null)
                    {
                        if (!query.Contains("TakenOn"))
                        {
                            query += $" AND (TakenOn = (SELECT TOP(1) TakenOn FROM tbInventorySnapshots ORDER BY TakenOn DESC))";
                        }
                    }
                    else
                    {
                        query = $"(TakenOn = (SELECT TOP(1) TakenOn FROM tbInventorySnapshots ORDER BY TakenOn DESC))";
                    }

                    string str = $@"SELECT z.zfinIndex, z.zfinName, i.*
                                FROM tbInventorySnapshots i LEFT JOIN tbZfin z ON z.zfinId=i.ProductId
                                WHERE {query}";


                    var Command = new SqlCommand(str, Con);

                    var reader = Command.ExecuteReader();


                    if (reader.HasRows)
                    {
                        while (reader.Read())
                        {
                            InventorySnapshot i = new InventorySnapshot();
                            i.InventorySnapshotId = Convert.ToInt32(reader["InventorySnapshotId"].ToString());
                            i.ProductId           = Convert.ToInt32(reader["ProductId"].ToString());
                            i.ProductIndex        = reader["ZfinIndex"].ToString();
                            i.ProductName         = reader["ZfinName"].ToString();
                            i.Size    = Convert.ToDouble(reader["Size"].ToString());
                            i.Unit    = reader["Unit"].ToString();
                            i.Status  = reader["Status"].ToString();
                            i.TakenOn = Convert.ToDateTime(reader["TakenOn"].ToString());
                            Inventories.Add(i);
                        }
                    }

                    return(Inventories);
                }
            }
            catch (Exception ex)
            {
                Logger.Error("_GetInventorySnapshots: Błąd. Szczegóły: {Message}", ex.ToString());
                throw;
            }
        }