private static void removeFrom(TrelloCard card, params HashSet <TrelloCard>[] sets) { foreach (var hashSet in sets) { if (hashSet.Contains(card)) { hashSet.Remove(card); } } }
public void Set(TrelloCard card, CardStatus status, bool propagateToNext = false) { if (!BoardAnalysis.Cards.Contains(card)) { BoardAnalysis.Cards.Add(card); } switch (status) { case CardStatus.Other: if (Other.Contains(card)) { break; } Other.Add(card); removeFrom(card, Doing, Done); break; case CardStatus.Doing: if (Doing.Contains(card)) { break; } Doing.Add(card); removeFrom(card, Done, Other); break; case CardStatus.Done: if (Done.Contains(card)) { break; } Done.Add(card); removeFrom(card, Other, Doing); break; default: throw new ArgumentOutOfRangeException(nameof(status), status, null); } if (propagateToNext) { ((PeriodCardsStatus)Next(false))?.Set(card, status); } }
public BoardAnalysisResult AnalyzePeriod(DateTime?start = null, DateTime?end = null, TimeGranularity granularity = TimeGranularity.Week) { const string DataFolder = ".\\data"; ensureBoardIsSelected(); ensureProgressListsAreSpecified(); var startDate = start.HasValue && start.Value != default(DateTime) ? start.Value : projectStartTime(); var endDate = end.HasValue && end.Value != default(DateTime) ? end.Value : DateTime.Today.AddDays(1).Subtract(TimeSpan.FromSeconds(1)); if (_boardAnalysis?.Equals(startDate, endDate, granularity) ?? false) { return(_boardAnalysis); } var db = new ApiDatastore(DataFolder); BoardAnalysisResult boardAnalysis; var analysisExists = false; ISince since = new SinceDate(startDate); if (db.TryLoadBoardAnalysis(Board.Id, startDate, endDate, granularity, out boardAnalysis)) { _boardAnalysis = boardAnalysis; since = new SinceDate(boardAnalysis.Timestamp); analysisExists = true; } UI?.Write("Reads cards from Trello ... "); var allCards = _trello.Cards.ForBoard(Board).ToList(); UI?.WriteLine($"DONE (board '{Board.Name}' contains {allCards.Count} cards)"); UI?.WriteLine("Analysing card actions ..."); UI?.ShowBusy(maxValue: allCards.Count); try { Func <CreateCardAction, CardStatus> createStatus = action => { if (_doingListsIds.Any(id => id == action.Data.List.Id)) { return(CardStatus.Doing); } return(_doneListsIds.Any(id => id == action.Data.List.Id) ? CardStatus.Done : CardStatus.Other); }; Func <MoveCardAction, CardStatus> moveStatus = action => { if (_doingListsIds.Any(id => id == action.ListAfter.Id)) { return(CardStatus.Doing); } return(_doneListsIds.Any(id => id == action.ListAfter.Id) ? CardStatus.Done : CardStatus.Other); }; if (!analysisExists) { _boardAnalysis = new BoardAnalysisResult(Board.Id, startDate, endDate, granularity); } // generate all periods ... PeriodCardsStatus lastPeriod; Dictionary <DateTime, PeriodCardsStatus> result; var firstPeriod = generatePeriods(startDate, ref endDate, granularity, analysisExists, out lastPeriod, out result); var progress = 0; ICardActionsProvider cardActionsProvider; if (!analysisExists || !tryQuickAnalyzePeriodThroughActions(out cardActionsProvider)) { cardActionsProvider = new CardActionsReader(_trello, since, endDate); } var analysisWasUpdated = false; foreach (var card in allCards) { UI?.UpdateBusy(progress, $" | Card: '{card.Name}'"); var allActions = cardActionsProvider.GetCardActions(card); if (allActions.Count == 0) { UI?.UpdateBusy(++progress); continue; } var createActions = allActions.OfType <CreateCardAction>().Where(a => a.Date <= endDate).ToList(); var trelloCard = _boardAnalysis.Cards.FirstOrDefault(c => c.Id == card.Id); PeriodCardsStatus period; foreach (var createAction in createActions) { #if DEBUG if (trelloCard != null) { throw new Exception("Huh?"); } #endif analysisWasUpdated = true; var date = createAction.Date; if (date < firstPeriod.Start) { period = firstPeriod; } else if (date > lastPeriod.End) { period = lastPeriod; } else { period = result[new Period(date, granularity).Start]; } var cardStatus = createStatus(createAction); trelloCard = new TrelloCard { Id = card.Id, Name = card.Name }; if (cardStatus == CardStatus.Doing) { trelloCard.DateCommitted = createAction.Date; } period.Set(trelloCard, cardStatus, true); } var moveActions = allActions.OfType <UpdateCardMoveAction>() .Where(a => a.Date <= endDate) .Select(a => new MoveCardAction(a)) .ToList(); moveActions.Sort((a1, a2) => a1.Date <a2.Date ? -1 : a1.Date> a2.Date ? 1 : 0); foreach (var moveAction in moveActions) { analysisWasUpdated = true; var date = moveAction.Date; if (date < firstPeriod.Start) { period = firstPeriod; } else if (date > lastPeriod.End) { period = lastPeriod; } else { period = result[new Period(moveAction.Date, granularity).Start]; } var cardStatus = moveStatus(moveAction); trelloCard = trelloCard ?? new TrelloCard(moveAction.MoveAction.Data.Card); switch (cardStatus) { case CardStatus.Doing: if (!trelloCard.IsCommitted) { trelloCard.DateCommitted = moveAction.Date; } break; case CardStatus.Done: if (!trelloCard.IsDone) { trelloCard.DateDone = moveAction.Date; } break; } period.Set(trelloCard, cardStatus, true); } UI?.UpdateBusy(++progress); } if (!analysisExists || analysisWasUpdated) { db.SaveBoardAnalysis(_boardAnalysis); } return(_boardAnalysis); } finally { UI?.HideBusy(); } }