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); }
public InventoryAggregateRoot(Guid id, string name) { _snapshot = new InventorySnapshot(); Id = id; Version = -1; ApplyChange(new InventoryItemCreated(id, name)); }
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); } }
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() }); }
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); }
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()); }
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); }
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 }); }
private void ProcessSetInitialInventory(InventorySnapshot snapshot, SetInitialInventoryDataEvent dataEvent) { if (!snapshot.HasProcessedInitialInventory) { snapshot.InventoryItems = dataEvent.InventoryItems; snapshot.HasProcessedInitialInventory = true; } }
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()); }
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); } }
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); }
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); }
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 }); }
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); }
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); }
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); }
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; }
public override void LoadSnapshot(string data) { _snapshot = JsonConvert.DeserializeObject <InventorySnapshot>(data); }
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--; } } }
public InventoryAggregateRoot() { _snapshot = new InventorySnapshot(); Version = -1; }
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; } }