Example #1
0
        internal List <TimelineSegment> Analyze(DateTime startTime, DateTime endTime)
        {
            Func <Event, DynamicEvent> convertEvent = e => new DynamicEvent(e.StartTime, e.EndTime, e.Data, e.Type);

            var events = (from e in this.db.Events
                          where e.EndTime >= startTime
                          where e.StartTime <= endTime
                          select e)
                         .AsEnumerable()
                         .Select(convertEvent)
                         .ToList();

            var times = new SortedSet <DateTime>(new[] { startTime, endTime });

            times.UnionWith(events.Select(e => e.StartTime));
            times.UnionWith(events.Select(e => e.EndTime));
            times = times.GetViewBetween(startTime, endTime);

            var spans = times.Zip(times.Skip(1), (start, end) => new { startTime = start, endTime = end }).ToList();

            var segments = new List <TimelineSegment>();

            var rules = this.db.Rules.ToList();

            for (int i = 0; i < spans.Count; i++)
            {
                var span = spans[i];

                TimelineSegment segment = null;

                Func <Predicate <DynamicEvent>, DynamicEvent> mostRecent = predicate =>
                {
                    return((from e in events
                            where e.StartTime <= span.startTime
                            orderby e.StartTime descending
                            where predicate(e)
                            select e).FirstOrDefault() ??
                           (from e in this.db.Events
                            where e.StartTime <= span.startTime
                            orderby e.StartTime descending
                            select e)
                           .AsEnumerable()
                           .Select(convertEvent)
                           .Where(e => predicate(e))
                           .FirstOrDefault());
                };

                Func <Predicate <DynamicEvent>, DynamicEvent> current = predicate =>
                {
                    return((from e in events
                            where e.StartTime <= span.startTime
                            where e.EndTime >= span.endTime
                            where predicate(e)
                            orderby e.StartTime descending, e.EndTime ascending
                            select e).FirstOrDefault());
                };

                foreach (var rule in rules)
                {
                    var result = RunRule(rule, span.startTime, span.endTime, events, mostRecent, current);

                    if (result != null)
                    {
                        if (result.StartTime > span.startTime)
                        {
                            spans.Add(new { startTime = span.startTime, endTime = result.StartTime });
                        }

                        if (result.EndTime < span.endTime)
                        {
                            spans.Add(new { startTime = result.EndTime, endTime = span.endTime });
                        }

                        segment = result;
                        break;
                    }
                }

                if (segment == null)
                {
                    segment = new TimelineSegment
                    {
                        StartTime      = span.startTime,
                        EndTime        = span.endTime,
                        Description    = "Unclassified",
                        Productivity   = 0,
                        IsUnclassified = true,
                    };
                }

                segments.Add(segment);
            }

            Simplify(segments);
            return(segments);
        }
Example #2
0
        private TimelineSegment RunRule(Rule rule, DateTime startTime, DateTime endTime, IList <DynamicEvent> events, EventFilter mostRecent, EventFilter current)
        {
            var     ruleFunc = ScriptManager.GetScriptFunc(rule.Expression);
            dynamic result;

            try
            {
                result = ruleFunc(startTime, endTime, events, mostRecent, current);
            }
            catch (TargetInvocationException)
            {
                // TODO: This should be bubbled up, so that the user can be notified of which rule cause the error.
                return(null);
            }

            if (result == null)
            {
                return(null);
            }
            else if (result is bool)
            {
                return(!result
                    ? null
                    : new TimelineSegment
                {
                    StartTime = startTime,
                    EndTime = endTime,
                    Description = rule.Description,
                    Productivity = rule.Productivity,
                });
            }
            else if (result is string)
            {
                return(new TimelineSegment
                {
                    StartTime = startTime,
                    EndTime = endTime,
                    Description = result as string,
                    Productivity = rule.Productivity,
                });
            }
            else
            {
                var ruleResult = new TimelineSegment();

                ruleResult.Description  = RetrieveField(result, "Description", rule.Description);
                ruleResult.Productivity = RetrieveField(result, "Productivity", rule.Productivity);
                ruleResult.StartTime    = RetrieveField(result, "StartTime", startTime);
                ruleResult.EndTime      = RetrieveField(result, "EndTime", endTime);

                ruleResult.StartTime   = ruleResult.StartTime.Clamp(startTime, endTime);
                ruleResult.EndTime     = ruleResult.EndTime.Clamp(startTime, endTime);
                ruleResult.Description = ruleResult.Description ?? "";
                if (ruleResult.Productivity.HasValue)
                {
                    ruleResult.Productivity = ruleResult.Productivity.Value.Clamp(0, 100);
                }

                if (ruleResult.StartTime >= ruleResult.EndTime)
                {
                    return(null);
                }

                return(ruleResult);
            }
        }