예제 #1
0
        public void SaveBoardAnalysis(BoardAnalysisResult analysisResult)
        {
            var json = JsonConvert.SerializeObject(analysisResult);
            var path = getPath(analysisResult);

            File.WriteAllText(path, json);
        }
예제 #2
0
        public bool TryLoadBoardAnalysis(string boardId, DateTime start, DateTime end, TimeGranularity granularity,
                                         out BoardAnalysisResult analysisResult)
        {
            var path = getPath(boardId, start, end, granularity);

            return(File.Exists(path)
                ? tryLoadAndDeserializeBoardAnalysis(path, out analysisResult)
                : tryLoadLastBoardAnalysis(boardId, start, granularity, out analysisResult));
        }
예제 #3
0
        private bool tryLoadAndDeserializeBoardAnalysis(string path, out BoardAnalysisResult analysisResult)
        {
            var json = File.ReadAllText(path);

            try
            {
                analysisResult = JsonConvert.DeserializeObject <BoardAnalysisResult>(json);
                analysisResult.LinkPeriods();
                return(true);
            }
            catch (Exception ex)
            {
                analysisResult = null;
                return(false);
            }
        }
예제 #4
0
        private bool tryLoadLastBoardAnalysis(string boardId, DateTime start, TimeGranularity granularity,
                                              out BoardAnalysisResult analysisResult)
        {
            analysisResult = null;
            var dir = new DirectoryInfo(RootFolder);

            if (!dir.Exists)
            {
                return(false);
            }

            var files = dir.GetFiles(getFilePattern(boardId, start, granularity)).ToList();

            if (files.Count == 0)
            {
                return(false);
            }

            files.Sort((f1, f2) => string.CompareOrdinal(f1.Name, f2.Name));
            var path = Path.Combine(RootFolder, files.Last().Name);

            return(tryLoadAndDeserializeBoardAnalysis(path, out analysisResult));
        }
예제 #5
0
 private string getPath(BoardAnalysisResult result)
 {
     return(getPath(result.BoardId, result.Start, result.End, result.Granularity));
 }
예제 #6
0
        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();
            }
        }
예제 #7
0
 protected bool Equals(BoardAnalysisResult other)
 {
     return(Equals(other.Start, other.End, other.Granularity));
 }
예제 #8
0
 public PeriodCardsStatus(BoardAnalysisResult boardAnalysis, DateTime start, TimeGranularity granularity)
     : base(start, granularity)
 {
     BoardAnalysis = boardAnalysis;
 }
예제 #9
0
 public void SetParent(BoardAnalysisResult parent)
 {
     BoardAnalysis = parent;
 }