protected override async Task <ResultWithMetrologyProperties <Result> > DoRunAsync(Request request) { var card = await DbContext.CardsInDecks.SingleAsync(card => card.DeckId.Equals(request.DeckId) && card.CardId.Equals(request.CardId)); var lastLearnUtcTime = runDate == null ? DateTime.UtcNow : runDate; if (request.TargetHeap != CardInDeck.UnknownHeap) { if (request.TargetHeap == card.CurrentHeap) { return(new ResultWithMetrologyProperties <Result>(new Result(), ("DeckId", request.DeckId.ToString()), ("CardId", request.CardId.ToString()), ("TargetHeap", request.TargetHeap.ToString()), ("CardWasAlreadyInHeap", true.ToString()))); //This could happen due to connection problems on client side, or to multiple sessions } if (request.TargetHeap < card.CurrentHeap || request.TargetHeap - card.CurrentHeap > 1) { throw new InvalidOperationException($"Invalid move request (request heap: {request.TargetHeap}, current heap: {card.CurrentHeap}, card: {request.CardId}, last learn UTC time: {card.LastLearnUtcTime})"); } var heapingAlgorithm = await HeapingAlgorithm.OfDeckAsync(DbContext, request.DeckId); card.ExpiryUtcTime = heapingAlgorithm.ExpiryUtcDate(request.TargetHeap, lastLearnUtcTime.Value); if (request.TargetHeap > card.BiggestHeapReached) { card.BiggestHeapReached = request.TargetHeap; } } else { card.ExpiryUtcTime = DateTime.MinValue.ToUniversalTime(); //Setting this is useless for normal operations, but would help detect any misuse of this field (bugs) if (card.CurrentHeap != CardInDeck.UnknownHeap) { card.NbTimesInNotLearnedHeap++; } } card.LastLearnUtcTime = lastLearnUtcTime.Value; card.CurrentHeap = request.TargetHeap; await DbContext.SaveChangesAsync(); return(new ResultWithMetrologyProperties <Result>(new Result(), ("DeckId", request.DeckId.ToString()), ("CardId", request.CardId.ToString()), ("TargetHeap", request.TargetHeap.ToString()), ("CardWasAlreadyInHeap", false.ToString()))); }
protected override async Task <ResultWithMetrologyProperties <Result> > DoRunAsync(Request request) { var heapingAlgorithm = await HeapingAlgorithm.OfDeckAsync(DbContext, request.DeckId); var cardsInDecks = DbContext.CardsInDecks.Where(card => card.DeckId.Equals(request.DeckId) && request.CardIds.Any(cardId => cardId == card.CardId)).ToImmutableDictionary(c => c.CardId, c => c); if (request.CardIds.Any(cardId => !cardsInDecks.ContainsKey(cardId))) { throw new InvalidOperationException("One card is not in the deck"); } foreach (var cardInDeck in cardsInDecks.Values) { if (cardInDeck.CurrentHeap != request.TargetHeap) { if (cardInDeck.BiggestHeapReached < request.TargetHeap) { cardInDeck.BiggestHeapReached = request.TargetHeap; } if (request.TargetHeap == CardInDeck.UnknownHeap) { cardInDeck.NbTimesInNotLearnedHeap++; cardInDeck.ExpiryUtcTime = DateTime.MinValue.ToUniversalTime(); //Setting this is useless for normal operations, but would help detect any misuse of this field (bugs) } else { cardInDeck.ExpiryUtcTime = heapingAlgorithm.ExpiryUtcDate(request.TargetHeap, cardInDeck.LastLearnUtcTime); } cardInDeck.CurrentHeap = request.TargetHeap; } } await DbContext.SaveChangesAsync(); return(new ResultWithMetrologyProperties <Result>(new Result(), ("DeckId", request.DeckId.ToString()), ("TargetHeap", request.TargetHeap.ToString()), ("CardCount", request.CardIds.Count().ToString()))); }