public AdvancedStats() { Child = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Spacing = new Vector2(4f), Children = new[] { firstValue = new StatisticRow(), //circle size/key amount hpDrain = new StatisticRow { Title = "HP Drain" }, accuracy = new StatisticRow { Title = "Accuracy" }, approachRate = new StatisticRow { Title = "Approach Rate" }, starDifficulty = new StatisticRow(10, true) { Title = "Star Difficulty" }, }, }; }
private List <StatisticRow> GetDataForDateRange(DateTime startDate, DateTime endDate) { var entityTypeGroupGuid = Rock.SystemGuid.EntityType.GROUP.AsGuid(); var groupEntityType = EntityTypeCache.Read(entityTypeGroupGuid); int entityTypeScheduleEntityId = EntityTypeCache.Read(Rock.SystemGuid.EntityType.SCHEDULE.AsGuid()).Id; var rockContext = new RockContext(); rockContext.Database.CommandTimeout = 2600; var metricService = new MetricService(rockContext); var metricValueService = new MetricValueService(rockContext); var scheduleService = new ScheduleService(rockContext); var groupService = new GroupService(rockContext); var attendanceService = new AttendanceService(rockContext); var attributeService = new AttributeService(rockContext); var attributeValueService = new AttributeValueService(rockContext); var metricCategoryGuidList = GetAttributeValue("Metrics").SplitDelimitedValues().AsGuidList(); var attendanceGroupGuidList = GetAttributeValue("AttendanceGroups").SplitDelimitedValues().AsGuidList(); var parentMetricVolunteerGroupGuids = GetAttributeValue("ServiceVolunteerGroups").SplitDelimitedValues().AsGuidList(); var attendanceGroups = groupService.GetByGuids(attendanceGroupGuidList); var parentMetricVolunteerGroups = groupService.GetByGuids(parentMetricVolunteerGroupGuids); var metrics = metricService.GetByGuids(metricCategoryGuidList).Distinct().ToList(); var datasource = new List <StatisticRow>(); var metricVolunteerGroups = new List <Group>(); foreach (var parentMetricVolunteerGroup in parentMetricVolunteerGroups) { metricVolunteerGroups.Add(parentMetricVolunteerGroup); metricVolunteerGroups.AddRange(groupService.GetAllDescendents(parentMetricVolunteerGroup.Id)); } var metricVolunteerGroupIds = metricVolunteerGroups.Select(g => g.Id).ToList(); var metricVolunteerAttendanceData = attendanceService.Queryable().Where(a => a.GroupId.HasValue && metricVolunteerGroupIds.Contains(a.GroupId.Value) && a.StartDateTime >= startDate && a.StartDateTime <= endDate); foreach (var metric in metrics) { var metricData = metricValueService.Queryable("MetricValuePartitions").Where(mv => mv.MetricValueDateTime >= startDate && mv.MetricValueDateTime <= endDate && mv.MetricId == metric.Id && mv.MetricValuePartitions.FirstOrDefault( mvp => mvp.MetricPartition.EntityTypeId == entityTypeScheduleEntityId).EntityId.HasValue ) .GroupBy( mv => mv.MetricValuePartitions.FirstOrDefault( mvp => mvp.MetricPartition.EntityTypeId == entityTypeScheduleEntityId).EntityId.Value) .ToList() .Select(mv => { var service = scheduleService.Get(mv.Key); return(new StatisticRow { ScheduleDateRanges = GetScheduleDateRanges(service, startDate, endDate), RowId = metric.Id + "-" + mv.Key, SortValue = 0, IsTotal = false, Area = metric.Title, Subarea = "Head Count", StartTime = service.WeeklyTimeOfDay ?? service.StartTimeOfDay, DayOfWeek = service.WeeklyDayOfWeek ?? GetLastDayOfWeek(service, startDate, endDate), Service = service.Name, Count = mv.Sum(a => a.YValue).HasValue ? decimal.ToInt32(mv.Sum(a => a.YValue).Value) : 0, MetricNote = mv.Max(a => a.Note), Value = mv }); }) .ToList(); foreach (var row in metricData) { int volunteers = 0; int total = row.Value.Sum(a => a.YValue).HasValue ? decimal.ToInt32(row.Value.Sum(a => a.YValue).Value) : 0; if (metricVolunteerAttendanceData.Any()) { volunteers += row.ScheduleDateRanges.Sum(dateRange => metricVolunteerAttendanceData.Count(a => (a.DidAttend == null || a.DidAttend.Value) && a.StartDateTime >= dateRange.Start && a.StartDateTime <= dateRange.End)); row.Total = total + volunteers; row.Volunteers = volunteers; } } datasource.AddRange(metricData); if (metricData.Count > 1) { var subTotalRow = new StatisticRow { RowId = metric.Id.ToString(), SortValue = 0, IsTotal = true, Area = metric.Title, Subarea = "Head Count", Service = "Sub-Total", Count = metricData.Sum(mv => mv.Count), Volunteers = metricData.Sum(mv => mv.Volunteers), Total = metricData.Sum(mv => mv.Total) }; datasource.Add(subTotalRow); } } var totalRow = new StatisticRow { RowId = "HeadcountTotal", SortValue = 1, IsTotal = true, Area = "Head Count Total", Subarea = "Head Count", Service = "Total", Count = datasource.Where(row => !row.IsTotal).Sum(row => row.Count), Volunteers = datasource.Where(row => !row.IsTotal).Sum(mv => mv.Volunteers), Total = datasource.Where(row => !row.IsTotal).Sum(mv => mv.Total) }; datasource.Add(totalRow); string attributeKeyString = GetAttributeValue("VolunteerGroupAttributeKey"); var volunteerGroupAttributeIdList = attributeService.Queryable() .Where(a => a.Key == attributeKeyString && a.EntityTypeQualifierColumn == "GroupTypeId" && a.EntityTypeId == groupEntityType.Id).Select(a => a.Id); if (volunteerGroupAttributeIdList.Any()) { // Find the groups that attribute values that have the maaping between group (the entityId) and the place they should be grouped with attending (value) var volunteerGroupMappingList = attributeValueService.Queryable().Where(av => volunteerGroupAttributeIdList.Contains(av.AttributeId) && av.Value != null) .ToList() .Select(av => new { VolunteerAttendanceGroupGuid = av.Value.AsGuid(), VolunteerGroupId = av.EntityId }).ToList(); foreach (var attendanceGroup in attendanceGroups) { foreach (var attendanceChildGroup in attendanceGroup.Groups) { var attendanceChildDescendantGroups = groupService.GetAllDescendents(attendanceChildGroup.Id).ToList(); // Include child group in for cases where attendance needs to be mapped to an area not a specific group (production team isn't for a specific children's group -- it's associated with TC kids as a whole) attendanceChildDescendantGroups.Add(attendanceChildGroup); var attendanceChildDescendantGroupIds = attendanceChildDescendantGroups.Select(g => g.Id); var volunteerGroupIds = volunteerGroupMappingList .Where(vgm => attendanceChildDescendantGroups.Any(g => g.Guid == vgm.VolunteerAttendanceGroupGuid)) .Select(vgm => vgm.VolunteerGroupId).ToList(); var volunteerGroupAttendance = attendanceService.Queryable() .Where(a => volunteerGroupIds.Any(id => id != null && id == a.Group.Id) && a.StartDateTime >= startDate && a.StartDateTime <= endDate) .ToList(); var acg = attendanceChildGroup; var childGroupAttendance = attendanceService.Queryable().Where(a => a.GroupId != null && a.StartDateTime >= startDate && a.StartDateTime <= endDate && (a.GroupId == acg.Id || attendanceChildDescendantGroupIds.Any(id => id == a.GroupId)) && (a.DidAttend == null || a.DidAttend.Value)) .GroupBy(a => a.ScheduleId) .ToList(); // ag is created to prevent a warn "Access to foreach variable in closure." var ag = attendanceGroup; var statisticRows = childGroupAttendance.Select(a => { var attendance = a.FirstOrDefault(); var scheduleDateRanges = GetScheduleDateRanges(attendance.Schedule, startDate, endDate); var row = new StatisticRow(); row.RowId = acg.Id + "-" + a.Key; row.SortValue = 2; row.IsTotal = false; row.Area = ag.Name; row.Subarea = acg.Name; row.Service = attendance.Schedule.Name; row.StartTime = attendance.Schedule.WeeklyTimeOfDay ?? attendance.Schedule.StartTimeOfDay; row.DayOfWeek = attendance.Schedule.WeeklyDayOfWeek ?? GetLastDayOfWeek(attendance.Schedule, startDate, endDate); row.Count = a.Count(); row.Volunteers = volunteerGroupAttendance.Count(b => scheduleDateRanges.Any(s => b.StartDateTime >= s.Start && b.StartDateTime <= s.End)); row.Total = a.Count() + volunteerGroupAttendance.Count(b => scheduleDateRanges.Any(s => b.StartDateTime >= s.Start && b.StartDateTime <= s.End)); return(row); }).ToList(); datasource.AddRange(statisticRows); if (statisticRows.Count > 1) { var subTotalRow = new StatisticRow { RowId = attendanceChildGroup.Id.ToString(), SortValue = 2, IsTotal = true, Area = attendanceGroup.Name, Subarea = attendanceChildGroup.Name, Service = "Sub-Total", Count = statisticRows.Sum(cg => cg.Count), Volunteers = statisticRows.Sum(cg => cg.Volunteers), Total = statisticRows.Sum(cg => cg.Total) }; datasource.Add(subTotalRow); } } } } datasource.Add(new StatisticRow { RowId = "Total", SortValue = 3, IsTotal = true, Area = "Grand Total", Subarea = "Total", Service = "Total", Count = datasource.Where(ds => ds.IsTotal).Sum(cg => cg.Count), Volunteers = datasource.Where(ds => ds.IsTotal).Sum(cg => cg.Volunteers), Total = datasource.Where(ds => ds.IsTotal).Sum(cg => cg.Total) }); return(datasource); }