From 3eda579bdf4c82abdd7d83f5b2798be3bb29c6c8 Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 11 Feb 2024 21:53:11 +1100 Subject: [PATCH 1/6] Issue-33: Refactor milestone report --- Model/Milestone/GetMilestoneResultModel.cs | 24 +--- Topo/Services/MilestoneService.cs | 156 +++++++++++++++------ Topo/Shared/NavMenu.razor | 2 +- 3 files changed, 116 insertions(+), 66 deletions(-) diff --git a/Model/Milestone/GetMilestoneResultModel.cs b/Model/Milestone/GetMilestoneResultModel.cs index 93c0904..9631ae8 100644 --- a/Model/Milestone/GetMilestoneResultModel.cs +++ b/Model/Milestone/GetMilestoneResultModel.cs @@ -25,28 +25,12 @@ public class MilestoneResult public class Event_Count { - public Participant participant { get; set; } = new Participant(); - public Assistant assistant { get; set; } = new Assistant(); - public Leader leader { get; set; } = new Leader(); + public PALEventCount participant { get; set; } = new PALEventCount(); + public PALEventCount assistant { get; set; } = new PALEventCount(); + public PALEventCount leader { get; set; } = new PALEventCount(); } - public class Participant - { - public float community { get; set; } - public float outdoors { get; set; } - public float creative { get; set; } - public float personal_growth { get; set; } - } - - public class Assistant - { - public float community { get; set; } - public float outdoors { get; set; } - public float creative { get; set; } - public float personal_growth { get; set; } - } - - public class Leader + public class PALEventCount { public float community { get; set; } public float outdoors { get; set; } diff --git a/Topo/Services/MilestoneService.cs b/Topo/Services/MilestoneService.cs index b8cfa2a..6801e49 100644 --- a/Topo/Services/MilestoneService.cs +++ b/Topo/Services/MilestoneService.cs @@ -10,70 +10,136 @@ public interface IMilestoneService public class MilestoneService : IMilestoneService { private readonly ITerrainAPIService _terrainAPIService; + private readonly IMembersService _membersService; + private readonly StorageService _storageService; - public MilestoneService(ITerrainAPIService terrainAPIService) + public MilestoneService(ITerrainAPIService terrainAPIService, IMembersService membersService, StorageService storageService) { _terrainAPIService = terrainAPIService; + _membersService = membersService; + _storageService = storageService; } public async Task> GetMilestoneSummaries(string selectedUnitId) { var unitMilestoneSummary = new List(); - var getGroupLifeResultModel = await _terrainAPIService.GetGroupLifeForUnit(selectedUnitId); - foreach (var result in getGroupLifeResultModel.results) + var members = await _membersService.GetMembersAsync(selectedUnitId); + foreach (var member in members.Where(m => m.isAdultLeader == 0)) { - var milestone1 = result.milestones.Where(m => m.milestone == 1).FirstOrDefault(); - var milestone1Awarded = result.milestone.milestone > 1 && (milestone1?.awarded ?? false); - var milestone1Skipped = result.milestone.milestone > 1 && !(milestone1?.awarded ?? false); - var milestone2 = result.milestones.Where(m => m.milestone == 2).FirstOrDefault(); - var milestone2Awarded = result.milestone.milestone > 2 && (milestone2?.awarded ?? false); - var milestone2Skipped = result.milestone.milestone > 2 && !(milestone2?.awarded ?? false); - var milestone3 = result.milestones.Where(m => m.milestone == 3).FirstOrDefault(); - var milestone3Awarded = milestone3?.awarded ?? false; + var memberMilestones = await _terrainAPIService.GetMilestoneResultsForMember(member.id); + MilestoneResult milestone1 = new MilestoneResult(); + MilestoneResult milestone2 = new MilestoneResult(); + MilestoneResult milestone3 = new MilestoneResult(); + bool milestone1Awarded = false; + bool milestone2Awarded = false; + bool milestone3Awarded = false; + bool milestone1Skipped = false; + bool milestone2Skipped = false; + bool milestone3Skipped = false; + int currentLevel = 1; + foreach (var milestoneResult in memberMilestones.results.Where(r => r.section == _storageService.Section).OrderBy(r => r.achievement_meta.stage)) + { + switch (milestoneResult.achievement_meta.stage) + { + case 1: + milestone1 = milestoneResult; + milestone1Awarded = milestone1.status == "awarded"; + milestone1Skipped = milestone1.status == "not_required"; + currentLevel = (milestone1Awarded || milestone1Skipped) ? 2 : 1; + break; + case 2: + milestone2 = milestoneResult; + milestone2Awarded = milestone2.status == "awarded"; + milestone2Skipped = milestone2.status == "not_required"; + currentLevel = (milestone1Awarded || milestone1Skipped) && (milestone2Awarded || milestone2Skipped) ? 3 : currentLevel; + break; + case 3: + milestone3 = milestoneResult; + milestone3Awarded = milestone3.status == "awarded"; + milestone3Skipped = milestone3.status == "not_required"; + break; + } + } + int percentComplete = 0; + switch (currentLevel) + { + case 1: + percentComplete = CalculateMilestonePercentComplete(1, milestone1.event_count); + break; + case 2: + percentComplete = CalculateMilestonePercentComplete(2, milestone2.event_count); + break; + case 3: + percentComplete = CalculateMilestonePercentComplete(3, milestone3.event_count); + break; + } unitMilestoneSummary.Add( new MilestoneSummaryListModel { - memberName = result.name, - currentLevel = result.milestone.milestone, - percentComplete = CalculateMilestonePercentComplete(result.milestone), - milestone1ParticipateCommunity = milestone1Skipped ? -1 : (milestone1Awarded ? 6 : milestone1?.participates.Where(p => p.challenge_area == "community").FirstOrDefault()?.total ?? 0), - milestone1ParticipateOutdoors = milestone1Skipped ? -1 : (milestone1Awarded ? 6 : milestone1?.participates.Where(p => p.challenge_area == "outdoors").FirstOrDefault()?.total ?? 0), - milestone1ParticipateCreative = milestone1Skipped ? -1 : (milestone1Awarded ? 6 : milestone1?.participates.Where(p => p.challenge_area == "creative").FirstOrDefault()?.total ?? 0), - milestone1ParticipatePersonalGrowth = milestone1Skipped ? -1 : (milestone1Awarded ? 6 : milestone1?.participates.Where(p => p.challenge_area == "personal_growth").FirstOrDefault()?.total ?? 0), - milestone1Assist = milestone1Skipped ? -1 : (milestone1Awarded ? 2 : milestone1?.total_assists ?? 0), - milestone1Lead = milestone1Skipped ? -1 : (milestone1Awarded ? 1 : milestone1?.total_leads ?? 0), - milestone2ParticipateCommunity = milestone2Skipped ? -1 : (milestone2Awarded ? 5 : milestone2?.participates.Where(p => p.challenge_area == "community").FirstOrDefault()?.total ?? 0), - milestone2ParticipateOutdoors = milestone2Skipped ? -1 : (milestone2Awarded ? 5 : milestone2?.participates.Where(p => p.challenge_area == "outdoors").FirstOrDefault()?.total ?? 0), - milestone2ParticipateCreative = milestone2Skipped ? -1 : (milestone2Awarded ? 5 : milestone2?.participates.Where(p => p.challenge_area == "creative").FirstOrDefault()?.total ?? 0), - milestone2ParticipatePersonalGrowth = milestone2Skipped ? -1 : (milestone2Awarded ? 5 : milestone2?.participates.Where(p => p.challenge_area == "personal_growth").FirstOrDefault()?.total ?? 0), - milestone2Assist = milestone2Skipped ? -1 : (milestone2Awarded ? 3 : milestone2?.total_assists ?? 0), - milestone2Lead = milestone2Skipped ? -1 : (milestone2Awarded ? 2 : milestone2?.total_leads ?? 0), - milestone3ParticipateCommunity = milestone3Awarded ? 4 : milestone3?.participates.Where(p => p.challenge_area == "community").FirstOrDefault()?.total ?? 0, - milestone3ParticipateOutdoors = milestone3Awarded ? 4 : milestone3?.participates.Where(p => p.challenge_area == "outdoors").FirstOrDefault()?.total ?? 0, - milestone3ParticipateCreative = milestone3Awarded ? 4 : milestone3?.participates.Where(p => p.challenge_area == "creative").FirstOrDefault()?.total ?? 0, - milestone3ParticipatePersonalGrowth = milestone3Awarded ? 4 : milestone3?.participates.Where(p => p.challenge_area == "personal_growth").FirstOrDefault()?.total ?? 0, - milestone3Assist = milestone3Awarded ? 4 : milestone3?.total_assists ?? 0, - milestone3Lead = milestone3Awarded ? 4 : milestone3?.total_leads ?? 0 + memberName = $"{member.first_name} {member.last_name}", + currentLevel = currentLevel, + percentComplete = percentComplete, + milestone1ParticipateCommunity = milestone1Skipped ? -1 : (milestone1Awarded ? 6 : (int)milestone1.event_count.participant.community), + milestone1ParticipateOutdoors = milestone1Skipped ? -1 : (milestone1Awarded ? 6 : (int)milestone1.event_count.participant.outdoors), + milestone1ParticipateCreative = milestone1Skipped ? -1 : (milestone1Awarded ? 6 : (int)milestone1.event_count.participant.creative), + milestone1ParticipatePersonalGrowth = milestone1Skipped ? -1 : (milestone1Awarded ? 6 : (int)milestone1.event_count.participant.personal_growth), + milestone1Assist = milestone1Skipped ? -1 : (milestone1Awarded ? 2 : (int)milestone1.event_count.assistant.community + + (int)milestone1.event_count.assistant.outdoors + + (int)milestone1.event_count.assistant.creative + + (int)milestone1.event_count.assistant.personal_growth), + milestone1Lead = milestone1Skipped ? -1 : (milestone1Awarded ? 1 : (int)milestone1.event_count.leader.community + + (int)milestone1.event_count.leader.outdoors + + (int)milestone1.event_count.leader.creative + + (int)milestone1.event_count.leader.personal_growth), + milestone2ParticipateCommunity = milestone2Skipped ? -1 : (milestone2Awarded ? 5 : (int)milestone2.event_count.participant.community), + milestone2ParticipateOutdoors = milestone2Skipped ? -1 : (milestone2Awarded ? 5 : (int)milestone2.event_count.participant.outdoors), + milestone2ParticipateCreative = milestone2Skipped ? -1 : (milestone2Awarded ? 5 : (int)milestone2.event_count.participant.creative), + milestone2ParticipatePersonalGrowth = milestone2Skipped ? -1 : (milestone2Awarded ? 5 : (int)milestone2.event_count.participant.personal_growth), + milestone2Assist = milestone2Skipped ? -1 : (milestone2Awarded ? 3 : (int)milestone2.event_count.assistant.community + + (int)milestone2.event_count.assistant.outdoors + + (int)milestone2.event_count.assistant.creative + + (int)milestone2.event_count.assistant.personal_growth), + milestone2Lead = milestone2Skipped ? -1 : (milestone2Awarded ? 2 : (int)milestone2.event_count.leader.community + + (int)milestone2.event_count.leader.outdoors + + (int)milestone2.event_count.leader.creative + + (int)milestone2.event_count.leader.personal_growth), + milestone3ParticipateCommunity = milestone3Skipped ? -1 : (milestone3Awarded ? 4 : (int)milestone3.event_count.participant.community), + milestone3ParticipateOutdoors = milestone3Skipped ? -1 : (milestone3Awarded ? 4 : (int)milestone3.event_count.participant.outdoors), + milestone3ParticipateCreative = milestone3Skipped ? -1 : (milestone3Awarded ? 4 : (int)milestone3.event_count.participant.creative), + milestone3ParticipatePersonalGrowth = milestone3Skipped ? -1 : (milestone3Awarded ? 4 : (int)milestone3.event_count.participant.personal_growth), + milestone3Assist = milestone3Awarded ? 4 : (int)milestone3.event_count.assistant.community + + (int)milestone3.event_count.assistant.outdoors + + (int)milestone3.event_count.assistant.creative + + (int)milestone3.event_count.assistant.personal_growth, + milestone3Lead = milestone3Awarded ? 4 : (int)milestone3.event_count.leader.community + + (int)milestone3.event_count.leader.outdoors + + (int)milestone3.event_count.leader.creative + + (int)milestone3.event_count.leader.personal_growth, }); } return unitMilestoneSummary; } - private int CalculateMilestonePercentComplete(Milestone milestone) + private int CalculateMilestonePercentComplete(int currentLevel, Event_Count eventCount) { - int participateTotal = 0; int target = 0; - foreach (var participate in milestone.participates) - { - participateTotal += milestone.milestone == 3 - ? Math.Min(4, participate.total) - : participate.total; - } - participateTotal += milestone.milestone == 3 - ? Math.Min(4, milestone.total_assists) + Math.Min(4, milestone.total_leads) - : milestone.total_assists + milestone.total_leads; + int participantTotal = (int)((currentLevel == 3 ? Math.Min(4.0, eventCount.participant.community) : eventCount.participant.community) + + (currentLevel == 3 ? Math.Min(4.0, eventCount.participant.outdoors) : eventCount.participant.outdoors) + + (currentLevel == 3 ? Math.Min(4.0, eventCount.participant.creative) : eventCount.participant.creative) + + (currentLevel == 3 ? Math.Min(4.0, eventCount.participant.personal_growth) : eventCount.participant.personal_growth)); + int assistantTotal = (int)(eventCount.assistant.community + + eventCount.assistant.creative + + eventCount.assistant.outdoors + + eventCount.assistant.personal_growth); + int leaderTotal = (int)(eventCount.leader.community + + eventCount.leader.creative + + eventCount.leader.outdoors + + eventCount.leader.personal_growth); + var total = currentLevel == 3 + ? participantTotal + Math.Min(4, assistantTotal) + Math.Min(4, leaderTotal) + : participantTotal + assistantTotal + leaderTotal; - switch (milestone.milestone) + switch (currentLevel) { case 1: target = 27; @@ -86,7 +152,7 @@ private int CalculateMilestonePercentComplete(Milestone milestone) break; } - var percentComplete = participateTotal * 100 / target; + var percentComplete = total * 100 / target; return percentComplete; } diff --git a/Topo/Shared/NavMenu.razor b/Topo/Shared/NavMenu.razor index d68713a..aff624b 100644 --- a/Topo/Shared/NavMenu.razor +++ b/Topo/Shared/NavMenu.razor @@ -110,7 +110,7 @@ } From 5ea1e6e659a5ab7933a6cc800dd73ec7ae2421ae Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 11 Feb 2024 21:54:49 +1100 Subject: [PATCH 2/6] Issue-33: Handle failing GroupLIfe request --- Topo/Controller/LogoutController.cs | 2 +- ...ySpinnerAutomaticallyHttpMessageHandler.cs | 18 ++++++++++---- Topo/Services/StorageService.cs | 6 +++-- Topo/Services/TerrainAPIService.cs | 24 ++++++++++++++----- 4 files changed, 36 insertions(+), 14 deletions(-) diff --git a/Topo/Controller/LogoutController.cs b/Topo/Controller/LogoutController.cs index ff298f0..dad09fe 100644 --- a/Topo/Controller/LogoutController.cs +++ b/Topo/Controller/LogoutController.cs @@ -11,7 +11,7 @@ public class LogoutController : ComponentBase [Inject] public NavigationManager NavigationManager { get; set; } - protected override async Task OnInitializedAsync() + protected override void OnInitialized() { _storageService.Logout(); NavigationManager.NavigateTo("index"); diff --git a/Topo/DisplaySpinnerAutomaticallyHttpMessageHandler.cs b/Topo/DisplaySpinnerAutomaticallyHttpMessageHandler.cs index 1187af9..7f65ab8 100644 --- a/Topo/DisplaySpinnerAutomaticallyHttpMessageHandler.cs +++ b/Topo/DisplaySpinnerAutomaticallyHttpMessageHandler.cs @@ -11,11 +11,19 @@ public DisplaySpinnerAutomaticallyHttpMessageHandler(SpinnerService spinnerServi } protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { - _spinnerService.Show(); - // await Task.Delay(1000); - var response = await base.SendAsync(request, cancellationToken); - _spinnerService.Hide(); - return response; + try + { + _spinnerService.Show(); + // await Task.Delay(1000); + var response = await base.SendAsync(request, cancellationToken); + _spinnerService.Hide(); + return response; + } + catch (Exception ex) + { + _spinnerService.Hide(); + throw; + } } } } diff --git a/Topo/Services/StorageService.cs b/Topo/Services/StorageService.cs index 4a09131..39876ea 100644 --- a/Topo/Services/StorageService.cs +++ b/Topo/Services/StorageService.cs @@ -47,8 +47,8 @@ public Dictionary Units { return GetProfilesResult?.profiles? .Where(p => p.unit != null) - .Where(p => p.group.name == GroupName) - .Where(p => p.member.name == MemberName) + .Where(p => p.group.name == (GroupName ?? "")) + .Where(p => p.member.name == (MemberName ?? "")) .Select(p => p.unit) .ToDictionary(u => u?.id?.ToString() ?? "", u => u?.name ?? ""); } @@ -91,6 +91,8 @@ public void Logout() IsAuthenticated = false; GroupName = ""; CachedMembers = new List>>(); + _unitId = ""; + GetProfilesResult = null; } public bool IsYouthMember { diff --git a/Topo/Services/TerrainAPIService.cs b/Topo/Services/TerrainAPIService.cs index c4172cd..011ca61 100644 --- a/Topo/Services/TerrainAPIService.cs +++ b/Topo/Services/TerrainAPIService.cs @@ -504,12 +504,24 @@ private async Task SendRequest(HttpMethod httpMethod, string requestUri, httpRequest.Headers.Add("accept", "application/json, text/plain, */*"); //httpRequest.Headers.Add("X-Amz-User-Agent", "aws-amplify/0.1.x js"); - var response = await _httpClient.SendAsync(httpRequest); - var responseContent = response.Content.ReadAsStringAsync(); - var result = responseContent.Result; - _logger.LogInformation($"Request: {requestUri}"); - _logger.LogInformation($"Response: {result}"); - return result; + var response = new HttpResponseMessage(); + try + { + response = await _httpClient.SendAsync(httpRequest); + var responseContent = response.Content.ReadAsStringAsync(); + var result = responseContent.Result; + _logger.LogInformation($"Request: {requestUri}"); + _logger.LogInformation($"Response: {result}"); + return result; + } + catch( Exception ex ) + { + _logger.LogInformation($"Request: {requestUri}"); + _logger.LogInformation($"StatusCode: {response.StatusCode}"); + _logger.LogInformation($"Exception: {ex}"); + return ""; + } + } private T DeserializeObject(string result) From a391c30d561e96e76bfed1dc3aa923b5744bddaf Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 15 Feb 2024 21:34:35 +1100 Subject: [PATCH 3/6] Issue-33: Set UnitName when only one unit available --- Topo/Controller/MilestoneController.cs | 1 + Topo/Controller/OasController.cs | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Topo/Controller/MilestoneController.cs b/Topo/Controller/MilestoneController.cs index 8f78b2a..0945279 100644 --- a/Topo/Controller/MilestoneController.cs +++ b/Topo/Controller/MilestoneController.cs @@ -38,6 +38,7 @@ protected override void OnInitialized() model.GroupName = _storageService.GroupNameDisplay; model.Units = _storageService.Units; model.UnitId = _storageService.UnitId; + model.UnitName = _storageService.UnitName; } internal async Task UnitChange(ChangeEventArgs e) diff --git a/Topo/Controller/OasController.cs b/Topo/Controller/OasController.cs index 128e786..88cd77e 100644 --- a/Topo/Controller/OasController.cs +++ b/Topo/Controller/OasController.cs @@ -47,12 +47,21 @@ protected override async Task OnInitializedAsync() model.GroupName = _storageService.GroupNameDisplay; model.Units = _storageService.Units; model.Stages = await _oasService.GetOASStagesList(); - model.UnitId = _storageService.UnitId; + if (!string.IsNullOrEmpty(_storageService.UnitId)) + { + await UnitChange(_storageService.UnitId); + } + } internal async Task UnitChange(ChangeEventArgs e) { var unitId = e.Value?.ToString() ?? ""; + await UnitChange(unitId); + } + + internal async Task UnitChange(string unitId) + { model.UnitId = unitId; _storageService.UnitId = model.UnitId; if (_storageService.Units != null) From 56ced7e63ab9f38d378f576cb5cd63310474fbb1 Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 16 Feb 2024 13:27:23 +1100 Subject: [PATCH 4/6] Issue-33: Refactor wallchart report to not use GroupLife --- Model/Wallchart/WallchartItemModel.cs | 1 + Model/Wallchart/WallchartPageViewModel.cs | 1 + Topo/Controller/WallchartController.cs | 17 + Topo/Pages/Wallchart.razor | 4 + Topo/Services/MembersService.cs | 8 + Topo/Services/WallchartService.cs | 393 +++++++++++++++++----- 6 files changed, 342 insertions(+), 82 deletions(-) diff --git a/Model/Wallchart/WallchartItemModel.cs b/Model/Wallchart/WallchartItemModel.cs index 506e443..be45609 100644 --- a/Model/Wallchart/WallchartItemModel.cs +++ b/Model/Wallchart/WallchartItemModel.cs @@ -3,6 +3,7 @@ public class WallchartItemModel { public string MemberName { get; set; } = string.Empty; + public string MemberPatrol { get; set; } = string.Empty; public DateTime? IntroToScouting { get; set; } public DateTime? IntroToSection { get; set; } public int Milestone1Community { get; set; } diff --git a/Model/Wallchart/WallchartPageViewModel.cs b/Model/Wallchart/WallchartPageViewModel.cs index fd17416..eb91425 100644 --- a/Model/Wallchart/WallchartPageViewModel.cs +++ b/Model/Wallchart/WallchartPageViewModel.cs @@ -10,5 +10,6 @@ public class WallchartPageViewModel public string UnitId { get; set; } = string.Empty; public string UnitName { get; set; } = string.Empty; public string GroupName { get; set; } = string.Empty; + public string ErrorMessage { get; set; } = string.Empty; } } diff --git a/Topo/Controller/WallchartController.cs b/Topo/Controller/WallchartController.cs index a62ad8a..e192614 100644 --- a/Topo/Controller/WallchartController.cs +++ b/Topo/Controller/WallchartController.cs @@ -4,6 +4,7 @@ using Topo.Model.Wallchart; using Topo.Model.ReportGeneration; using Topo.Services; +using System.Reflection; namespace Topo.Controller { @@ -37,6 +38,7 @@ protected override void OnInitialized() model.GroupName = _storageService.GroupNameDisplay; model.Units = _storageService.Units; model.UnitId = _storageService.UnitId; + model.UnitName = _storageService.UnitName; } internal async Task UnitChange(ChangeEventArgs e) @@ -55,6 +57,11 @@ internal async Task WallchartReportPdfClick() return; byte[] report = await WallchartReport(OutputType.PDF); + if (report.Length == 0) + { + model.ErrorMessage = "Group life request took too long. Please try Group Life for unit in Terrain first."; + return; + } var fileName = $"Wallchart_{model.UnitName.Replace(' ', '_')}.pdf"; // Send the data to JS to actually download the file @@ -67,6 +74,11 @@ internal async Task WallchartReportXlsxClick() return; byte[] report = await WallchartReport(OutputType.Excel); + if (report.Length == 0) + { + model.ErrorMessage = "Group life request took too long. Please try Group Life for unit in Terrain first."; + return; + } var fileName = $"Wallchart_{model.UnitName.Replace(' ', '_')}.xlsx"; // Send the data to JS to actually download the file @@ -75,7 +87,12 @@ internal async Task WallchartReportXlsxClick() private async Task WallchartReport(OutputType outputType = OutputType.PDF) { + model.ErrorMessage = ""; var wallchartItems = await _wallchartService.GetWallchartItems(model.UnitId); + if (wallchartItems.Count == 0) + { + return new byte[0]; + } var groupName = _storageService.GroupName ?? ""; var unitName = _storageService.UnitName ?? ""; diff --git a/Topo/Pages/Wallchart.razor b/Topo/Pages/Wallchart.razor index 024441a..0d9284c 100644 --- a/Topo/Pages/Wallchart.razor +++ b/Topo/Pages/Wallchart.razor @@ -34,4 +34,8 @@ +
+ +
+ diff --git a/Topo/Services/MembersService.cs b/Topo/Services/MembersService.cs index f7cfaf0..ec72deb 100644 --- a/Topo/Services/MembersService.cs +++ b/Topo/Services/MembersService.cs @@ -7,6 +7,7 @@ public interface IMembersService { public Task> GetMembersAsync(string unitId); public void ClearMemberCache(string unitId); + public Task GetMember(string unitId, string memberId); } public class MembersService : IMembersService @@ -80,6 +81,13 @@ public async Task> GetMembersAsync(string unitId) return memberList; } + public async Task GetMember(string unitId, string memberId) + { + var members = await GetMembersAsync(unitId); + var member = members.Where(m => m.id == memberId).FirstOrDefault(); + return member ?? new MemberListModel(); + } + private string GetAgeFromBirthdate(string dateOfBirth) { var birthday = DateTime.ParseExact(dateOfBirth, "yyyy-MM-dd", CultureInfo.InvariantCulture); // Date in AU format diff --git a/Topo/Services/WallchartService.cs b/Topo/Services/WallchartService.cs index d7446c9..67c79c3 100644 --- a/Topo/Services/WallchartService.cs +++ b/Topo/Services/WallchartService.cs @@ -1,5 +1,9 @@ -using Topo.Model.Approvals; +using System.Globalization; +using Topo.Model.Approvals; +using Topo.Model.Milestone; +using Topo.Model.Progress; using Topo.Model.Wallchart; +using Topo.Pages; namespace Topo.Services { @@ -12,13 +16,15 @@ public class WallchartService : IWallchartService private readonly StorageService _storageService; private readonly ITerrainAPIService _terrainAPIService; private readonly IApprovalsService _approvalService; + private readonly IMembersService _membersService; private List approvals = new List(); - public WallchartService(StorageService storageService, ITerrainAPIService terrainAPIService, IApprovalsService approvalService) + public WallchartService(StorageService storageService, ITerrainAPIService terrainAPIService, IApprovalsService approvalService, IMembersService membersService) { _storageService = storageService; _terrainAPIService = terrainAPIService; _approvalService = approvalService; + _membersService = membersService; } public async Task> GetWallchartItems(string selectedUnitId) @@ -32,117 +38,292 @@ public async Task> GetWallchartItems(string selectedUni await _terrainAPIService.RevokeAssumedProfiles(); var wallchartItems = new List(); - var getGroupLifeResultModel = await _terrainAPIService.GetGroupLifeForUnit(selectedUnitId); - foreach (var result in getGroupLifeResultModel.results) + var members = await _membersService.GetMembersAsync(selectedUnitId); + foreach (var member in members.Where(m => m.isAdultLeader == 0).OrderBy(m => m.last_name).ThenBy(m => m.first_name)) { - await _terrainAPIService.AssumeProfile(result.member_id); - var getMemberLogbookMetrics = await _terrainAPIService.GetMemberLogbookMetrics(result.member_id); - var totalNightsCamped = getMemberLogbookMetrics.results.Where(r => r.name == "total_nights_camped").FirstOrDefault()?.value ?? 0; - var totalNightsCampedInSection = getMemberLogbookMetrics.results.Where(r => r.name == "total_nights_camped" && r.last_updated >= result.intro_to_section).FirstOrDefault()?.value ?? 0; - var totalKmsHiked = (getMemberLogbookMetrics.results.Where(r => r.name == "total_distance_hiked").FirstOrDefault()?.value ?? 0) / 1000.0f; - var wallchartItem = new WallchartItemModel(); - wallchartItem.MemberName = result.name; - wallchartItem.IntroToScouting = result.intro_to_scouts; - wallchartItem.IntroToSection = result.intro_to_section; - var currentMilestone = result.milestone.milestone; - foreach (var milestone in result.milestones.OrderBy(m => m.milestone)) + + // Get Milestone for member + var memberMilestones = await _terrainAPIService.GetMilestoneResultsForMember(member.id); + foreach (var milestoneResult in memberMilestones.results.Where(r => r.section == _storageService.Section).OrderBy(r => r.achievement_meta.stage)) { - if (milestone.milestone == 1) + switch (milestoneResult.achievement_meta.stage) { - if (milestone.awarded) - { - wallchartItem.Milestone1Community = 6; - wallchartItem.Milestone1Creative = 6; - wallchartItem.Milestone1Outdoors = 6; - wallchartItem.Milestone1PersonalGrowth = 6; - wallchartItem.Milestone1Assist = 2; - wallchartItem.Milestone1Lead = 1; - wallchartItem.Milestone1Awarded = milestone.status_updated; - wallchartItem.Milestone1Presented = GetPresentedDate(result.member_id, "Milestone 1"); - } - else - { - wallchartItem.Milestone1Community = milestone.participates.Where(p => p.challenge_area == "community").FirstOrDefault()?.total ?? 0; - wallchartItem.Milestone1Creative = milestone.participates.Where(p => p.challenge_area == "creative").FirstOrDefault()?.total ?? 0; - wallchartItem.Milestone1Outdoors = milestone.participates.Where(p => p.challenge_area == "outdoors").FirstOrDefault()?.total ?? 0; - wallchartItem.Milestone1PersonalGrowth = milestone.participates.Where(p => p.challenge_area == "personal_growth").FirstOrDefault()?.total ?? 0; - wallchartItem.Milestone1Assist = milestone.total_assists; - wallchartItem.Milestone1Lead = milestone.total_leads; - } - } - if (milestone.milestone == 2) - { - if (milestone.awarded) - { - wallchartItem.Milestone2Community = 5; - wallchartItem.Milestone2Creative = 5; - wallchartItem.Milestone2Outdoors = 5; - wallchartItem.Milestone2PersonalGrowth = 5; - wallchartItem.Milestone2Assist = 3; - wallchartItem.Milestone2Lead = 2; - wallchartItem.Milestone2Awarded = milestone.status_updated; - wallchartItem.Milestone2Presented = GetPresentedDate(result.member_id, "Milestone 2"); - } - else - { - wallchartItem.Milestone2Community = milestone.participates.Where(p => p.challenge_area == "community").FirstOrDefault()?.total ?? 0; - wallchartItem.Milestone2Creative = milestone.participates.Where(p => p.challenge_area == "creative").FirstOrDefault()?.total ?? 0; - wallchartItem.Milestone2Outdoors = milestone.participates.Where(p => p.challenge_area == "outdoors").FirstOrDefault()?.total ?? 0; - wallchartItem.Milestone2PersonalGrowth = milestone.participates.Where(p => p.challenge_area == "personal_growth").FirstOrDefault()?.total ?? 0; - wallchartItem.Milestone2Assist = milestone.total_assists; - wallchartItem.Milestone2Lead = milestone.total_leads; - } - } - if (milestone.milestone == 3) - { - wallchartItem.Milestone3Community = milestone.participates.Where(p => p.challenge_area == "community").FirstOrDefault()?.total ?? 0; - wallchartItem.Milestone3Creative = milestone.participates.Where(p => p.challenge_area == "creative").FirstOrDefault()?.total ?? 0; - wallchartItem.Milestone3Outdoors = milestone.participates.Where(p => p.challenge_area == "outdoors").FirstOrDefault()?.total ?? 0; - wallchartItem.Milestone3PersonalGrowth = milestone.participates.Where(p => p.challenge_area == "personal_growth").FirstOrDefault()?.total ?? 0; - wallchartItem.Milestone3Assist = milestone.total_assists; - wallchartItem.Milestone3Lead = milestone.total_leads; - wallchartItem.Milestone3Awarded = milestone.awarded ? milestone.status_updated : null; - wallchartItem.Milestone3Presented = GetPresentedDate(result.member_id, "Milestone 3"); + case 1: + if (milestoneResult.status == "awarded") + { + wallchartItem.Milestone1Community = 6; + wallchartItem.Milestone1Creative = 6; + wallchartItem.Milestone1Outdoors = 6; + wallchartItem.Milestone1PersonalGrowth = 6; + wallchartItem.Milestone1Assist = 2; + wallchartItem.Milestone1Lead = 1; + wallchartItem.Milestone1Awarded = milestoneResult.status_updated; + wallchartItem.Milestone1Presented = GetPresentedDate(member.id, "Milestone 1"); + } + else + { + wallchartItem.Milestone1Community = (int)milestoneResult.event_count.participant.community; + wallchartItem.Milestone1Creative = (int)milestoneResult.event_count.participant.creative; + wallchartItem.Milestone1Outdoors = (int)milestoneResult.event_count.participant.outdoors; + wallchartItem.Milestone1PersonalGrowth = (int)milestoneResult.event_count.participant.personal_growth; + wallchartItem.Milestone1Assist = PALEventCountTotal(milestoneResult.event_count.assistant); + wallchartItem.Milestone1Lead = PALEventCountTotal(milestoneResult.event_count.leader); + } + break; + case 2: + if (milestoneResult.status == "awarded") + { + wallchartItem.Milestone2Community = 5; + wallchartItem.Milestone2Creative = 5; + wallchartItem.Milestone2Outdoors = 5; + wallchartItem.Milestone2PersonalGrowth = 5; + wallchartItem.Milestone2Assist = 3; + wallchartItem.Milestone2Lead = 2; + wallchartItem.Milestone2Awarded = milestoneResult.status_updated; + wallchartItem.Milestone2Presented = GetPresentedDate(member.id, "Milestone 2"); + } + else + { + wallchartItem.Milestone2Community = (int)milestoneResult.event_count.participant.community; + wallchartItem.Milestone2Creative = (int)milestoneResult.event_count.participant.creative; + wallchartItem.Milestone2Outdoors = (int)milestoneResult.event_count.participant.outdoors; + wallchartItem.Milestone2PersonalGrowth = (int)milestoneResult.event_count.participant.personal_growth; + wallchartItem.Milestone2Assist = PALEventCountTotal(milestoneResult.event_count.assistant); + wallchartItem.Milestone2Lead = PALEventCountTotal(milestoneResult.event_count.leader); + } + break; + case 3: + wallchartItem.Milestone3Community = (int)milestoneResult.event_count.participant.community; + wallchartItem.Milestone3Creative = (int)milestoneResult.event_count.participant.creative; + wallchartItem.Milestone3Outdoors = (int)milestoneResult.event_count.participant.outdoors; + wallchartItem.Milestone3PersonalGrowth = (int)milestoneResult.event_count.participant.personal_growth; + wallchartItem.Milestone3Assist = PALEventCountTotal(milestoneResult.event_count.assistant); + wallchartItem.Milestone3Lead = PALEventCountTotal(milestoneResult.event_count.leader); + wallchartItem.Milestone3Awarded = milestoneResult.status == "awarded" ? milestoneResult.status_updated : null; + wallchartItem.Milestone3Presented = GetPresentedDate(member.id, "Milestone 3"); + break; } } - foreach (var oas in result.oas.highest.OrderBy(h => h.stream).ThenBy(h => h.stage)) + // Get OAS for member + var oasResults = await _terrainAPIService.GetOASResultsForMember(member.id); + foreach (var oasResult in oasResults.results.Where(o => o.status == "awarded").OrderBy(o => o.achievement_meta.stream).ThenBy(o => o.achievement_meta.stage)) { - switch (oas.stream) + switch (oasResult.achievement_meta.stream) { case "bushcraft": - wallchartItem.OASBushcraftStage = oas.stage; + wallchartItem.OASBushcraftStage = oasResult.achievement_meta.stage; break; case "bushwalking": - wallchartItem.OASBushwalkingStage = oas.stage; + wallchartItem.OASBushwalkingStage = oasResult.achievement_meta.stage; break; case "camping": - wallchartItem.OASCampingStage = oas.stage; + wallchartItem.OASCampingStage = oasResult.achievement_meta.stage; break; case "alpine": - wallchartItem.OASAlpineStage = oas.stage; + wallchartItem.OASAlpineStage = oasResult.achievement_meta.stage; break; case "cycling": - wallchartItem.OASCyclingStage = oas.stage; + wallchartItem.OASCyclingStage = oasResult.achievement_meta.stage; break; case "vertical": - wallchartItem.OASVerticalStage = oas.stage; + wallchartItem.OASVerticalStage = oasResult.achievement_meta.stage; break; case "aquatics": - wallchartItem.OASAquaticsStage = oas.stage; + wallchartItem.OASAquaticsStage = oasResult.achievement_meta.stage; break; case "boating": - wallchartItem.OASBoatingStage = oas.stage; + wallchartItem.OASBoatingStage = oasResult.achievement_meta.stage; break; case "paddling": - wallchartItem.OASPaddlingStage = oas.stage; + wallchartItem.OASPaddlingStage = oasResult.achievement_meta.stage; break; } } + wallchartItem.OASStageProgressions = oasResults.results.Where(o => o.status == "awarded" && o.section == _storageService.Section).Count(); + // Member + wallchartItem.MemberName = $"{member.first_name} {member.last_name}"; + wallchartItem.MemberPatrol = member.patrol_name; + wallchartItem.IntroToScouting = await GetIntroToScouting(member.id); + wallchartItem.IntroToSection = await GetIntroToSection(member.id); + // Logbook + await _terrainAPIService.AssumeProfile(member.id); + var getMemberLogbookMetrics = await _terrainAPIService.GetMemberLogbookMetrics(member.id); + await _terrainAPIService.RevokeAssumedProfiles(); + var totalNightsCamped = getMemberLogbookMetrics.results.Where(r => r.name == "total_nights_camped").FirstOrDefault()?.value ?? 0; + var totalNightsCampedInSection = totalNightsCamped; + var totalKmsHiked = (getMemberLogbookMetrics.results.Where(r => r.name == "total_distance_hiked").FirstOrDefault()?.value ?? 0) / 1000.0f; wallchartItem.NightsCamped = (int)totalNightsCamped; wallchartItem.NightsCampedInSection = (int)totalNightsCampedInSection; wallchartItem.KMsHiked = (int)totalKmsHiked; - wallchartItem.OASStageProgressions = result.oas.total_progressions; + // SIA + var siaResultModel = await _terrainAPIService.GetSIAResultsForMember(member.id); + var awardedSIAProjects = siaResultModel.results.Where(r => r.section == section && r.status == "awarded"); + var awardedSIAProjectsByArea = awardedSIAProjects.GroupBy(p => p.answers.special_interest_area_selection); + foreach (var area in awardedSIAProjectsByArea) + { + switch (area.Key) + { + case "sia_adventure_sport": + wallchartItem.SIAAdventureSport = area.Count(); + break; + case "sia_art_literature": + wallchartItem.SIAArtsLiterature = area.Count(); + break; + case "sia_environment": + wallchartItem.SIAEnvironment = area.Count(); + break; + case "sia_stem_innovation": + wallchartItem.SIAStemInnovation = area.Count(); + break; + case "sia_growth_development": + wallchartItem.SIAGrowthDevelopment = area.Count(); + break; + case "sia_better_world": + wallchartItem.SIACreatingABetterWorld = area.Count(); + break; + } + } + // Peak Award + var courseReflectionResultModel = await _terrainAPIService.GetCourseReflectionResultsForMember(member.id); + wallchartItem.LeadershipCourse = courseReflectionResultModel.results + .Where(r => r.status == "awarded" && r.section == _storageService.Section) + .FirstOrDefault()?.status_updated; + + var adventurousJourneyResultModel = await _terrainAPIService.GetAdventurousJourneyResultsForMember(member.id); + wallchartItem.AdventurousJourney = adventurousJourneyResultModel.results + .Where(r => r.status == "awarded" && r.section == _storageService.Section) + .FirstOrDefault()?.status_updated; + + var personalReflectionResultModel = await _terrainAPIService.GetPersonalReflectionResultsForMember(member.id); + wallchartItem.PersonalReflection = personalReflectionResultModel.results + .Where(r => r.status == "awarded" && r.section == _storageService.Section) + .FirstOrDefault()?.status_updated; + + wallchartItem.PeakAward = 0; + wallchartItems.Add(wallchartItem); + } + _storageService.CachedWallchartItems.Add(new KeyValuePair>(selectedUnitId, wallchartItems)); + return wallchartItems; + + + var getGroupLifeResultModel = await _terrainAPIService.GetGroupLifeForUnit(selectedUnitId); + if (getGroupLifeResultModel.results.Length == 0) + { + return new List(); + } + foreach (var result in getGroupLifeResultModel.results) + { + //await _terrainAPIService.AssumeProfile(result.member_id); + //var getMemberLogbookMetrics = await _terrainAPIService.GetMemberLogbookMetrics(result.member_id); + //var totalNightsCamped = getMemberLogbookMetrics.results.Where(r => r.name == "total_nights_camped").FirstOrDefault()?.value ?? 0; + //var totalNightsCampedInSection = getMemberLogbookMetrics.results.Where(r => r.name == "total_nights_camped" && r.last_updated >= result.intro_to_section).FirstOrDefault()?.value ?? 0; + //var totalKmsHiked = (getMemberLogbookMetrics.results.Where(r => r.name == "total_distance_hiked").FirstOrDefault()?.value ?? 0) / 1000.0f; + //var member = await _membersService.GetMember(selectedUnitId, result.member_id); + + var wallchartItem = new WallchartItemModel(); + //wallchartItem.MemberName = result.name; + //wallchartItem.MemberPatrol = member.patrol_name; + //wallchartItem.IntroToScouting = result.intro_to_scouts; + //wallchartItem.IntroToSection = result.intro_to_section; + //var currentMilestone = result.milestone.milestone; + //foreach (var milestone in result.milestones.OrderBy(m => m.milestone)) + //{ + // if (milestone.milestone == 1) + // { + // if (milestone.awarded) + // { + // wallchartItem.Milestone1Community = 6; + // wallchartItem.Milestone1Creative = 6; + // wallchartItem.Milestone1Outdoors = 6; + // wallchartItem.Milestone1PersonalGrowth = 6; + // wallchartItem.Milestone1Assist = 2; + // wallchartItem.Milestone1Lead = 1; + // wallchartItem.Milestone1Awarded = milestone.status_updated; + // wallchartItem.Milestone1Presented = GetPresentedDate(result.member_id, "Milestone 1"); + // } + // else + // { + // wallchartItem.Milestone1Community = milestone.participates.Where(p => p.challenge_area == "community").FirstOrDefault()?.total ?? 0; + // wallchartItem.Milestone1Creative = milestone.participates.Where(p => p.challenge_area == "creative").FirstOrDefault()?.total ?? 0; + // wallchartItem.Milestone1Outdoors = milestone.participates.Where(p => p.challenge_area == "outdoors").FirstOrDefault()?.total ?? 0; + // wallchartItem.Milestone1PersonalGrowth = milestone.participates.Where(p => p.challenge_area == "personal_growth").FirstOrDefault()?.total ?? 0; + // wallchartItem.Milestone1Assist = milestone.total_assists; + // wallchartItem.Milestone1Lead = milestone.total_leads; + // } + // } + // if (milestone.milestone == 2) + // { + // if (milestone.awarded) + // { + // wallchartItem.Milestone2Community = 5; + // wallchartItem.Milestone2Creative = 5; + // wallchartItem.Milestone2Outdoors = 5; + // wallchartItem.Milestone2PersonalGrowth = 5; + // wallchartItem.Milestone2Assist = 3; + // wallchartItem.Milestone2Lead = 2; + // wallchartItem.Milestone2Awarded = milestone.status_updated; + // wallchartItem.Milestone2Presented = GetPresentedDate(result.member_id, "Milestone 2"); + // } + // else + // { + // wallchartItem.Milestone2Community = milestone.participates.Where(p => p.challenge_area == "community").FirstOrDefault()?.total ?? 0; + // wallchartItem.Milestone2Creative = milestone.participates.Where(p => p.challenge_area == "creative").FirstOrDefault()?.total ?? 0; + // wallchartItem.Milestone2Outdoors = milestone.participates.Where(p => p.challenge_area == "outdoors").FirstOrDefault()?.total ?? 0; + // wallchartItem.Milestone2PersonalGrowth = milestone.participates.Where(p => p.challenge_area == "personal_growth").FirstOrDefault()?.total ?? 0; + // wallchartItem.Milestone2Assist = milestone.total_assists; + // wallchartItem.Milestone2Lead = milestone.total_leads; + // } + // } + // if (milestone.milestone == 3) + // { + // wallchartItem.Milestone3Community = milestone.participates.Where(p => p.challenge_area == "community").FirstOrDefault()?.total ?? 0; + // wallchartItem.Milestone3Creative = milestone.participates.Where(p => p.challenge_area == "creative").FirstOrDefault()?.total ?? 0; + // wallchartItem.Milestone3Outdoors = milestone.participates.Where(p => p.challenge_area == "outdoors").FirstOrDefault()?.total ?? 0; + // wallchartItem.Milestone3PersonalGrowth = milestone.participates.Where(p => p.challenge_area == "personal_growth").FirstOrDefault()?.total ?? 0; + // wallchartItem.Milestone3Assist = milestone.total_assists; + // wallchartItem.Milestone3Lead = milestone.total_leads; + // wallchartItem.Milestone3Awarded = milestone.awarded ? milestone.status_updated : null; + // wallchartItem.Milestone3Presented = GetPresentedDate(result.member_id, "Milestone 3"); + // } + //} + //foreach (var oas in result.oas.highest.OrderBy(h => h.stream).ThenBy(h => h.stage)) + //{ + // switch (oas.stream) + // { + // case "bushcraft": + // wallchartItem.OASBushcraftStage = oas.stage; + // break; + // case "bushwalking": + // wallchartItem.OASBushwalkingStage = oas.stage; + // break; + // case "camping": + // wallchartItem.OASCampingStage = oas.stage; + // break; + // case "alpine": + // wallchartItem.OASAlpineStage = oas.stage; + // break; + // case "cycling": + // wallchartItem.OASCyclingStage = oas.stage; + // break; + // case "vertical": + // wallchartItem.OASVerticalStage = oas.stage; + // break; + // case "aquatics": + // wallchartItem.OASAquaticsStage = oas.stage; + // break; + // case "boating": + // wallchartItem.OASBoatingStage = oas.stage; + // break; + // case "paddling": + // wallchartItem.OASPaddlingStage = oas.stage; + // break; + // } + //} + //wallchartItem.NightsCamped = (int)totalNightsCamped; + //wallchartItem.NightsCampedInSection = (int)totalNightsCampedInSection; + //wallchartItem.KMsHiked = (int)totalKmsHiked; + //wallchartItem.OASStageProgressions = result.oas.total_progressions; var siaResultModel = await _terrainAPIService.GetSIAResultsForMember(result.member_id); var awardedSIAProjects = siaResultModel.results.Where(r => r.section == section && r.status == "awarded"); var awardedSIAProjectsByArea = awardedSIAProjects.GroupBy(p => p.answers.special_interest_area_selection); @@ -182,10 +363,58 @@ public async Task> GetWallchartItems(string selectedUni return wallchartItems; } + private async Task GetIntroToScouting(string memberId) + { + var introToScouting = await _terrainAPIService.GetIntroductionToScoutingResultsForMember(memberId); + var result = introToScouting.results.Where(r => r.status == "awarded").FirstOrDefault(); + if (result != null) + { + if (!string.IsNullOrEmpty(result.imported.date_awarded)) + { + return ConvertStringToDate(result.imported.date_awarded, "yyyy-MM-dd"); + } + else + { + return result.status_updated; + } + } + + return null; + } + + private async Task GetIntroToSection(string memberId) + { + var introToSection = await _terrainAPIService.GetIntroductionToSectionResultsForMember(memberId); + var result = introToSection.results.Where(r => r.section == _storageService.Section && r.status == "awarded").FirstOrDefault(); + if (result != null) + { + if (!string.IsNullOrEmpty(result.imported.date_awarded)) + { + return ConvertStringToDate(result.imported.date_awarded, "yyyy-MM-dd"); + } + else + { + return result.status_updated; + } + } + + return null; + } + + private DateTime ConvertStringToDate(string dateString, string dateFormat) + { + return DateTime.ParseExact(dateString, dateFormat, CultureInfo.InvariantCulture); + } + private DateTime? GetPresentedDate(string member_id, string achievement_name) { var approval = approvals.Where(a => a.member_id == member_id && a.achievement_name == achievement_name).FirstOrDefault(); return approval?.presented_date; } + + private int PALEventCountTotal(PALEventCount eventCount) + { + return (int)(eventCount.community + eventCount.creative + eventCount.outdoors + eventCount.personal_growth); + } } } From 0a4065faa560025ba9dde6ff89f6bf8fe8374494 Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 17 Feb 2024 16:20:56 +1100 Subject: [PATCH 5/6] Issue-33: Add help link to main menu --- Topo/Shared/NavMenu.razor | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Topo/Shared/NavMenu.razor b/Topo/Shared/NavMenu.razor index aff624b..37e2a12 100644 --- a/Topo/Shared/NavMenu.razor +++ b/Topo/Shared/NavMenu.razor @@ -108,6 +108,12 @@ } + + +
+
+ + +
+
+
+
+
diff --git a/Topo/Services/ReportService.cs b/Topo/Services/ReportService.cs index ed10ed8..ceca132 100644 --- a/Topo/Services/ReportService.cs +++ b/Topo/Services/ReportService.cs @@ -17,7 +17,7 @@ public interface IReportService public Task GetSIAReport(string groupName, string section, string unitName, OutputType outputType, string serialisedReportData); public Task GetMilestoneReport(string groupName, string section, string unitName, OutputType outputType, string serialisedReportData); public Task GetLogbookReport(string groupName, string section, string unitName, OutputType outputType, string serialisedReportData); - public Task GetWallchartReport(string groupName, string section, string unitName, OutputType outputType, string serialisedWallchartItems); + public Task GetWallchartReport(string groupName, string section, string unitName, OutputType outputType, string serialisedWallchartItems, bool breakByPatrol); public Task GetAdditionalAwardsReport(string groupName, string section, string unitName, OutputType outputType, string serialisedReportData); public Task GetApprovalsReport(string groupName, string section, string unitName, OutputType outputType, string serialisedReportData, DateTime fromDate, DateTime toDate, bool groupByMember); public Task GetProgressReport(string groupName, string section, string unitName, OutputType outputType, string serialisedReportData); @@ -182,7 +182,7 @@ public async Task GetMilestoneReport(string groupName, string section, s return report; } - public async Task GetWallchartReport(string groupName, string section, string unitName, OutputType outputType, string serialisedWallchartItems) + public async Task GetWallchartReport(string groupName, string section, string unitName, OutputType outputType, string serialisedWallchartItems, bool breakByPatrol = false) { var reportGenerationRequest = new ReportGenerationRequest() { @@ -191,7 +191,8 @@ public async Task GetWallchartReport(string groupName, string section, s Section = section, UnitName = unitName, OutputType = outputType, - ReportData = serialisedWallchartItems + ReportData = serialisedWallchartItems, + BreakByPatrol = breakByPatrol }; var report = await CallReportGeneratorFunction(reportGenerationRequest); diff --git a/TopoReportFunction/Function.cs b/TopoReportFunction/Function.cs index 5082a45..5262cee 100644 --- a/TopoReportFunction/Function.cs +++ b/TopoReportFunction/Function.cs @@ -269,7 +269,7 @@ private IWorkbook GenerateWallchartWorkbook(ReportGenerationRequest reportGenera if (reportData != null) { var workbook = reportService.GenerateWallchartWorkbook(reportData, reportGenerationRequest.GroupName, reportGenerationRequest.Section - , reportGenerationRequest.UnitName, reportGenerationRequest.OutputType == OutputType.PDF); + , reportGenerationRequest.UnitName, reportGenerationRequest.OutputType == OutputType.PDF, reportGenerationRequest.BreakByPatrol); return workbook; } return reportService.CreateWorkbookWithSheets(1); diff --git a/TopoReportFunctionTest/Wallchart.cs b/TopoReportFunctionTest/Wallchart.cs new file mode 100644 index 0000000..4e7dede --- /dev/null +++ b/TopoReportFunctionTest/Wallchart.cs @@ -0,0 +1,98 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Topo.Model.ReportGeneration; +using TopoReportFunction; + +namespace TopoReportFunctionTest +{ + [TestClass] + public class Wallchart + { + private ReportGenerationRequest _reportGenerationRequest; + private Function _function; + + [TestInitialize] + public void SetUp() + { + _function = new Function(); + _reportGenerationRequest = new ReportGenerationRequest() + { + ReportType = ReportType.Wallchart, + GroupName = "Epping Scout Group", + Section = "scout", + UnitName = "Scout Unit", + OutputType = OutputType.PDF, + BreakByPatrol = false, + ReportData = "[{\"MemberName\":\"James Alchin\",\"MemberPatrol\":\"Platypus\",\"IntroToScouting\":\"2023-02-17T14:38:23.905267+11:00\",\"IntroToSection\":\"2023-02-14T18:40:16.267965+11:00\",\"Milestone1Community\":6,\"Milestone1Outdoors\":6,\"Milestone1Creative\":6,\"Milestone1PersonalGrowth\":6,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":2,\"Milestone2Outdoors\":5,\"Milestone2Creative\":5,\"Milestone2PersonalGrowth\":3,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":1,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":0,\"OASBushwalkingStage\":0,\"OASCampingStage\":0,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":0,\"OASAquaticsStage\":3,\"OASBoatingStage\":0,\"OASPaddlingStage\":0,\"NightsCamped\":0,\"NightsCampedInSection\":0,\"KMsHiked\":10,\"OASStageProgressions\":3,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Hayley Au\",\"MemberPatrol\":\"Drop Bear\",\"IntroToScouting\":\"2022-05-31T12:34:01.643408+10:00\",\"IntroToSection\":null,\"Milestone1Community\":4,\"Milestone1Outdoors\":5,\"Milestone1Creative\":1,\"Milestone1PersonalGrowth\":3,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":0,\"Milestone2Outdoors\":0,\"Milestone2Creative\":0,\"Milestone2PersonalGrowth\":0,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":3,\"OASBushwalkingStage\":3,\"OASCampingStage\":3,\"OASAlpineStage\":2,\"OASCyclingStage\":2,\"OASVerticalStage\":1,\"OASAquaticsStage\":2,\"OASBoatingStage\":2,\"OASPaddlingStage\":2,\"NightsCamped\":14,\"NightsCampedInSection\":14,\"KMsHiked\":49,\"OASStageProgressions\":0,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"James Brunsdon\",\"MemberPatrol\":\"Lyrebird\",\"IntroToScouting\":\"2023-05-11T19:36:55.269057+10:00\",\"IntroToSection\":\"2023-02-19T21:11:42.709965+11:00\",\"Milestone1Community\":6,\"Milestone1Outdoors\":5,\"Milestone1Creative\":6,\"Milestone1PersonalGrowth\":6,\"Milestone1Assist\":1,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":1,\"Milestone2Outdoors\":0,\"Milestone2Creative\":2,\"Milestone2PersonalGrowth\":4,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":0,\"OASBushwalkingStage\":0,\"OASCampingStage\":0,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":0,\"OASAquaticsStage\":3,\"OASBoatingStage\":0,\"OASPaddlingStage\":0,\"NightsCamped\":0,\"NightsCampedInSection\":0,\"KMsHiked\":2,\"OASStageProgressions\":3,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Toby Cain\",\"MemberPatrol\":\"Platypus\",\"IntroToScouting\":\"2023-11-18T16:42:21.909571+11:00\",\"IntroToSection\":\"2023-12-03T13:56:03.114497+11:00\",\"Milestone1Community\":0,\"Milestone1Outdoors\":0,\"Milestone1Creative\":0,\"Milestone1PersonalGrowth\":0,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":0,\"Milestone2Outdoors\":0,\"Milestone2Creative\":0,\"Milestone2PersonalGrowth\":0,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":4,\"Milestone3Outdoors\":4,\"Milestone3Creative\":2,\"Milestone3PersonalGrowth\":4,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":0,\"OASBushwalkingStage\":0,\"OASCampingStage\":0,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":0,\"OASAquaticsStage\":1,\"OASBoatingStage\":0,\"OASPaddlingStage\":0,\"NightsCamped\":5,\"NightsCampedInSection\":5,\"KMsHiked\":20,\"OASStageProgressions\":1,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Miles (Yu Qi) Chen\",\"MemberPatrol\":\"Drop Bear\",\"IntroToScouting\":\"2023-03-20T16:53:32.58117+11:00\",\"IntroToSection\":null,\"Milestone1Community\":0,\"Milestone1Outdoors\":0,\"Milestone1Creative\":0,\"Milestone1PersonalGrowth\":1,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":0,\"Milestone2Outdoors\":0,\"Milestone2Creative\":0,\"Milestone2PersonalGrowth\":0,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":0,\"OASBushwalkingStage\":1,\"OASCampingStage\":0,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":0,\"OASAquaticsStage\":1,\"OASBoatingStage\":0,\"OASPaddlingStage\":1,\"NightsCamped\":1,\"NightsCampedInSection\":1,\"KMsHiked\":7,\"OASStageProgressions\":0,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Jeremy Chim\",\"MemberPatrol\":\"Magpie\",\"IntroToScouting\":\"2019-08-05T00:00:00\",\"IntroToSection\":\"2023-05-17T22:30:16.823284+10:00\",\"Milestone1Community\":6,\"Milestone1Outdoors\":6,\"Milestone1Creative\":6,\"Milestone1PersonalGrowth\":6,\"Milestone1Assist\":2,\"Milestone1Lead\":1,\"Milestone1Awarded\":\"2023-12-13T22:40:30.395398+11:00\",\"Milestone1Presented\":\"2023-12-06T21:34:17.734537+11:00\",\"Milestone2Community\":5,\"Milestone2Outdoors\":5,\"Milestone2Creative\":2,\"Milestone2PersonalGrowth\":5,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":4,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":2,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":3,\"OASBushwalkingStage\":3,\"OASCampingStage\":3,\"OASAlpineStage\":1,\"OASCyclingStage\":1,\"OASVerticalStage\":2,\"OASAquaticsStage\":3,\"OASBoatingStage\":0,\"OASPaddlingStage\":1,\"NightsCamped\":18,\"NightsCampedInSection\":18,\"KMsHiked\":48,\"OASStageProgressions\":1,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":\"2023-11-01T07:34:26.914165+11:00\",\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Eddy Chin\",\"MemberPatrol\":\"Magpie\",\"IntroToScouting\":\"2018-04-05T00:00:00\",\"IntroToSection\":\"2023-12-04T20:52:23.723509+11:00\",\"Milestone1Community\":4,\"Milestone1Outdoors\":6,\"Milestone1Creative\":5,\"Milestone1PersonalGrowth\":5,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":0,\"Milestone2Outdoors\":2,\"Milestone2Creative\":0,\"Milestone2PersonalGrowth\":0,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":0,\"OASBushwalkingStage\":0,\"OASCampingStage\":0,\"OASAlpineStage\":0,\"OASCyclingStage\":1,\"OASVerticalStage\":0,\"OASAquaticsStage\":0,\"OASBoatingStage\":0,\"OASPaddlingStage\":1,\"NightsCamped\":6,\"NightsCampedInSection\":6,\"KMsHiked\":4,\"OASStageProgressions\":0,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Lukas Dunn\",\"MemberPatrol\":\"Lyrebird\",\"IntroToScouting\":\"2017-07-31T00:00:00\",\"IntroToSection\":\"2023-04-05T19:50:01.39087+10:00\",\"Milestone1Community\":6,\"Milestone1Outdoors\":6,\"Milestone1Creative\":6,\"Milestone1PersonalGrowth\":6,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":1,\"Milestone2Outdoors\":5,\"Milestone2Creative\":4,\"Milestone2PersonalGrowth\":3,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":1,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":2,\"OASBushwalkingStage\":2,\"OASCampingStage\":1,\"OASAlpineStage\":0,\"OASCyclingStage\":1,\"OASVerticalStage\":1,\"OASAquaticsStage\":3,\"OASBoatingStage\":1,\"OASPaddlingStage\":1,\"NightsCamped\":2,\"NightsCampedInSection\":2,\"KMsHiked\":66,\"OASStageProgressions\":1,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Adrian Gaebel\",\"MemberPatrol\":\"Lyrebird\",\"IntroToScouting\":\"2018-06-25T00:00:00\",\"IntroToSection\":null,\"Milestone1Community\":4,\"Milestone1Outdoors\":0,\"Milestone1Creative\":0,\"Milestone1PersonalGrowth\":2,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":0,\"Milestone2Outdoors\":0,\"Milestone2Creative\":0,\"Milestone2PersonalGrowth\":0,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":3,\"OASBushwalkingStage\":3,\"OASCampingStage\":3,\"OASAlpineStage\":0,\"OASCyclingStage\":1,\"OASVerticalStage\":0,\"OASAquaticsStage\":2,\"OASBoatingStage\":1,\"OASPaddlingStage\":2,\"NightsCamped\":21,\"NightsCampedInSection\":21,\"KMsHiked\":50,\"OASStageProgressions\":0,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Allegra Gold\",\"MemberPatrol\":\"Platypus\",\"IntroToScouting\":\"2023-05-23T17:02:59.884715+10:00\",\"IntroToSection\":null,\"Milestone1Community\":1,\"Milestone1Outdoors\":2,\"Milestone1Creative\":1,\"Milestone1PersonalGrowth\":3,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":0,\"Milestone2Outdoors\":0,\"Milestone2Creative\":0,\"Milestone2PersonalGrowth\":0,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":1,\"OASBushwalkingStage\":0,\"OASCampingStage\":0,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":0,\"OASAquaticsStage\":0,\"OASBoatingStage\":0,\"OASPaddlingStage\":1,\"NightsCamped\":0,\"NightsCampedInSection\":0,\"KMsHiked\":2,\"OASStageProgressions\":0,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Zimo Gu\",\"MemberPatrol\":\"Lyrebird\",\"IntroToScouting\":\"2021-03-28T18:16:35.621181+11:00\",\"IntroToSection\":null,\"Milestone1Community\":2,\"Milestone1Outdoors\":3,\"Milestone1Creative\":1,\"Milestone1PersonalGrowth\":3,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":0,\"Milestone2Outdoors\":0,\"Milestone2Creative\":0,\"Milestone2PersonalGrowth\":0,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":2,\"OASBushwalkingStage\":2,\"OASCampingStage\":3,\"OASAlpineStage\":0,\"OASCyclingStage\":1,\"OASVerticalStage\":1,\"OASAquaticsStage\":0,\"OASBoatingStage\":0,\"OASPaddlingStage\":1,\"NightsCamped\":5,\"NightsCampedInSection\":5,\"KMsHiked\":17,\"OASStageProgressions\":0,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Jacob Hong\",\"MemberPatrol\":\"Platypus\",\"IntroToScouting\":\"2022-05-31T12:33:36.834444+10:00\",\"IntroToSection\":null,\"Milestone1Community\":0,\"Milestone1Outdoors\":0,\"Milestone1Creative\":0,\"Milestone1PersonalGrowth\":0,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":0,\"Milestone2Outdoors\":0,\"Milestone2Creative\":0,\"Milestone2PersonalGrowth\":0,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":2,\"OASBushwalkingStage\":2,\"OASCampingStage\":3,\"OASAlpineStage\":0,\"OASCyclingStage\":1,\"OASVerticalStage\":0,\"OASAquaticsStage\":0,\"OASBoatingStage\":0,\"OASPaddlingStage\":1,\"NightsCamped\":10,\"NightsCampedInSection\":10,\"KMsHiked\":12,\"OASStageProgressions\":0,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Andy Huang\",\"MemberPatrol\":\"Magpie\",\"IntroToScouting\":\"2022-05-30T20:49:58.138856+10:00\",\"IntroToSection\":\"2023-02-19T21:11:53.452204+11:00\",\"Milestone1Community\":6,\"Milestone1Outdoors\":6,\"Milestone1Creative\":6,\"Milestone1PersonalGrowth\":6,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":4,\"Milestone2Outdoors\":5,\"Milestone2Creative\":4,\"Milestone2PersonalGrowth\":1,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":2,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":2,\"OASBushwalkingStage\":1,\"OASCampingStage\":2,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":0,\"OASAquaticsStage\":0,\"OASBoatingStage\":0,\"OASPaddlingStage\":0,\"NightsCamped\":9,\"NightsCampedInSection\":9,\"KMsHiked\":29,\"OASStageProgressions\":0,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Brian Huang\",\"MemberPatrol\":\"Drop Bear\",\"IntroToScouting\":\"2023-03-14T00:00:00\",\"IntroToSection\":null,\"Milestone1Community\":2,\"Milestone1Outdoors\":2,\"Milestone1Creative\":1,\"Milestone1PersonalGrowth\":1,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":0,\"Milestone2Outdoors\":0,\"Milestone2Creative\":0,\"Milestone2PersonalGrowth\":0,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":0,\"OASBushwalkingStage\":1,\"OASCampingStage\":1,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":0,\"OASAquaticsStage\":1,\"OASBoatingStage\":0,\"OASPaddlingStage\":1,\"NightsCamped\":2,\"NightsCampedInSection\":2,\"KMsHiked\":9,\"OASStageProgressions\":0,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Joshua Jones\",\"MemberPatrol\":\"Drop Bear\",\"IntroToScouting\":\"2022-05-25T22:24:08.769329+10:00\",\"IntroToSection\":\"2022-06-08T22:15:01.305961+10:00\",\"Milestone1Community\":6,\"Milestone1Outdoors\":6,\"Milestone1Creative\":6,\"Milestone1PersonalGrowth\":6,\"Milestone1Assist\":1,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":5,\"Milestone2Outdoors\":5,\"Milestone2Creative\":5,\"Milestone2PersonalGrowth\":5,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":3,\"Milestone3Outdoors\":4,\"Milestone3Creative\":4,\"Milestone3PersonalGrowth\":4,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":3,\"OASBushwalkingStage\":2,\"OASCampingStage\":0,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":2,\"OASAquaticsStage\":3,\"OASBoatingStage\":0,\"OASPaddlingStage\":1,\"NightsCamped\":12,\"NightsCampedInSection\":12,\"KMsHiked\":20,\"OASStageProgressions\":10,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Matthew Last\",\"MemberPatrol\":\"Lyrebird\",\"IntroToScouting\":\"2022-10-19T22:42:03.673239+11:00\",\"IntroToSection\":\"2022-10-19T22:42:42.388491+11:00\",\"Milestone1Community\":6,\"Milestone1Outdoors\":6,\"Milestone1Creative\":6,\"Milestone1PersonalGrowth\":6,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":3,\"Milestone2Outdoors\":5,\"Milestone2Creative\":5,\"Milestone2PersonalGrowth\":4,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":2,\"Milestone3Creative\":2,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":0,\"OASBushwalkingStage\":0,\"OASCampingStage\":0,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":2,\"OASAquaticsStage\":3,\"OASBoatingStage\":0,\"OASPaddlingStage\":0,\"NightsCamped\":2,\"NightsCampedInSection\":2,\"KMsHiked\":18,\"OASStageProgressions\":5,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Isabella Lawrence\",\"MemberPatrol\":\"Platypus\",\"IntroToScouting\":\"2022-05-30T20:49:41.749638+10:00\",\"IntroToSection\":null,\"Milestone1Community\":0,\"Milestone1Outdoors\":0,\"Milestone1Creative\":0,\"Milestone1PersonalGrowth\":1,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":0,\"Milestone2Outdoors\":0,\"Milestone2Creative\":0,\"Milestone2PersonalGrowth\":0,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":1,\"OASBushwalkingStage\":1,\"OASCampingStage\":0,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":0,\"OASAquaticsStage\":1,\"OASBoatingStage\":0,\"OASPaddlingStage\":0,\"NightsCamped\":1,\"NightsCampedInSection\":1,\"KMsHiked\":5,\"OASStageProgressions\":0,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"James Li\",\"MemberPatrol\":\"Lyrebird\",\"IntroToScouting\":\"2015-10-12T00:00:00\",\"IntroToSection\":\"2021-06-23T19:50:24.758358+10:00\",\"Milestone1Community\":6,\"Milestone1Outdoors\":6,\"Milestone1Creative\":6,\"Milestone1PersonalGrowth\":6,\"Milestone1Assist\":2,\"Milestone1Lead\":1,\"Milestone1Awarded\":\"2023-11-22T21:59:08.616021+11:00\",\"Milestone1Presented\":\"2023-11-21T12:21:43.982338+11:00\",\"Milestone2Community\":5,\"Milestone2Outdoors\":5,\"Milestone2Creative\":5,\"Milestone2PersonalGrowth\":5,\"Milestone2Assist\":1,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":1,\"Milestone3Outdoors\":4,\"Milestone3Creative\":3,\"Milestone3PersonalGrowth\":4,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":2,\"OASBushwalkingStage\":0,\"OASCampingStage\":2,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":1,\"OASAquaticsStage\":4,\"OASBoatingStage\":0,\"OASPaddlingStage\":0,\"NightsCamped\":20,\"NightsCampedInSection\":20,\"KMsHiked\":55,\"OASStageProgressions\":3,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":\"2023-09-06T22:48:54.283816+10:00\",\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Jinbo Li\",\"MemberPatrol\":\"Lyrebird\",\"IntroToScouting\":\"2022-05-31T12:33:05.351808+10:00\",\"IntroToSection\":null,\"Milestone1Community\":1,\"Milestone1Outdoors\":3,\"Milestone1Creative\":1,\"Milestone1PersonalGrowth\":1,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":0,\"Milestone2Outdoors\":0,\"Milestone2Creative\":0,\"Milestone2PersonalGrowth\":0,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":2,\"OASBushwalkingStage\":2,\"OASCampingStage\":2,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":0,\"OASAquaticsStage\":0,\"OASBoatingStage\":0,\"OASPaddlingStage\":1,\"NightsCamped\":1,\"NightsCampedInSection\":1,\"KMsHiked\":29,\"OASStageProgressions\":0,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Jonathan Li\",\"MemberPatrol\":\"Platypus\",\"IntroToScouting\":\"2019-05-06T00:00:00\",\"IntroToSection\":\"2021-06-23T19:50:19.102767+10:00\",\"Milestone1Community\":6,\"Milestone1Outdoors\":6,\"Milestone1Creative\":6,\"Milestone1PersonalGrowth\":6,\"Milestone1Assist\":2,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":5,\"Milestone2Outdoors\":5,\"Milestone2Creative\":5,\"Milestone2PersonalGrowth\":5,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":2,\"Milestone3Outdoors\":4,\"Milestone3Creative\":2,\"Milestone3PersonalGrowth\":4,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":2,\"OASBushwalkingStage\":2,\"OASCampingStage\":2,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":1,\"OASAquaticsStage\":3,\"OASBoatingStage\":0,\"OASPaddlingStage\":1,\"NightsCamped\":18,\"NightsCampedInSection\":18,\"KMsHiked\":61,\"OASStageProgressions\":6,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Zoe Lloyd\",\"MemberPatrol\":\"Magpie\",\"IntroToScouting\":\"2019-03-25T00:00:00\",\"IntroToSection\":\"2022-06-01T22:02:00.305238+10:00\",\"Milestone1Community\":6,\"Milestone1Outdoors\":6,\"Milestone1Creative\":6,\"Milestone1PersonalGrowth\":6,\"Milestone1Assist\":1,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":3,\"Milestone2Outdoors\":5,\"Milestone2Creative\":5,\"Milestone2PersonalGrowth\":5,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":4,\"Milestone3Creative\":4,\"Milestone3PersonalGrowth\":1,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":2,\"OASBushwalkingStage\":2,\"OASCampingStage\":2,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":2,\"OASAquaticsStage\":3,\"OASBoatingStage\":0,\"OASPaddlingStage\":0,\"NightsCamped\":16,\"NightsCampedInSection\":16,\"KMsHiked\":39,\"OASStageProgressions\":8,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":\"2022-11-15T10:52:59.905394+11:00\",\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"James Luong\",\"MemberPatrol\":\"Drop Bear\",\"IntroToScouting\":\"2022-05-12T00:00:00\",\"IntroToSection\":null,\"Milestone1Community\":0,\"Milestone1Outdoors\":0,\"Milestone1Creative\":0,\"Milestone1PersonalGrowth\":1,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":0,\"Milestone2Outdoors\":0,\"Milestone2Creative\":0,\"Milestone2PersonalGrowth\":0,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":0,\"OASBushwalkingStage\":0,\"OASCampingStage\":0,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":0,\"OASAquaticsStage\":0,\"OASBoatingStage\":0,\"OASPaddlingStage\":0,\"NightsCamped\":0,\"NightsCampedInSection\":0,\"KMsHiked\":0,\"OASStageProgressions\":0,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Barnaby Peake\",\"MemberPatrol\":\"Drop Bear\",\"IntroToScouting\":\"2023-05-11T19:37:01.260306+10:00\",\"IntroToSection\":\"2023-02-19T21:11:47.714079+11:00\",\"Milestone1Community\":4,\"Milestone1Outdoors\":6,\"Milestone1Creative\":6,\"Milestone1PersonalGrowth\":6,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":0,\"Milestone2Outdoors\":3,\"Milestone2Creative\":2,\"Milestone2PersonalGrowth\":0,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":0,\"OASBushwalkingStage\":0,\"OASCampingStage\":0,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":0,\"OASAquaticsStage\":3,\"OASBoatingStage\":0,\"OASPaddlingStage\":0,\"NightsCamped\":1,\"NightsCampedInSection\":1,\"KMsHiked\":20,\"OASStageProgressions\":3,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Chloe Small\",\"MemberPatrol\":\"Drop Bear\",\"IntroToScouting\":\"2022-05-25T22:23:48.372823+10:00\",\"IntroToSection\":\"2022-06-01T22:02:10.597961+10:00\",\"Milestone1Community\":6,\"Milestone1Outdoors\":6,\"Milestone1Creative\":6,\"Milestone1PersonalGrowth\":6,\"Milestone1Assist\":1,\"Milestone1Lead\":1,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":5,\"Milestone2Outdoors\":5,\"Milestone2Creative\":5,\"Milestone2PersonalGrowth\":5,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":3,\"Milestone3Outdoors\":4,\"Milestone3Creative\":4,\"Milestone3PersonalGrowth\":4,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":0,\"OASBushwalkingStage\":2,\"OASCampingStage\":0,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":2,\"OASAquaticsStage\":3,\"OASBoatingStage\":0,\"OASPaddlingStage\":0,\"NightsCamped\":5,\"NightsCampedInSection\":5,\"KMsHiked\":9,\"OASStageProgressions\":6,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Nivaan Wagh\",\"MemberPatrol\":\"Platypus\",\"IntroToScouting\":\"2023-03-21T12:27:26.651269+11:00\",\"IntroToSection\":null,\"Milestone1Community\":0,\"Milestone1Outdoors\":0,\"Milestone1Creative\":0,\"Milestone1PersonalGrowth\":1,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":0,\"Milestone2Outdoors\":0,\"Milestone2Creative\":0,\"Milestone2PersonalGrowth\":0,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":1,\"OASBushwalkingStage\":0,\"OASCampingStage\":3,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":0,\"OASAquaticsStage\":0,\"OASBoatingStage\":0,\"OASPaddlingStage\":1,\"NightsCamped\":6,\"NightsCampedInSection\":6,\"KMsHiked\":0,\"OASStageProgressions\":0,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Larry Wen\",\"MemberPatrol\":\"Magpie\",\"IntroToScouting\":\"2022-05-30T20:49:50.380907+10:00\",\"IntroToSection\":null,\"Milestone1Community\":5,\"Milestone1Outdoors\":4,\"Milestone1Creative\":1,\"Milestone1PersonalGrowth\":3,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":0,\"Milestone2Outdoors\":0,\"Milestone2Creative\":0,\"Milestone2PersonalGrowth\":0,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":2,\"OASBushwalkingStage\":2,\"OASCampingStage\":3,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":0,\"OASAquaticsStage\":1,\"OASBoatingStage\":0,\"OASPaddlingStage\":1,\"NightsCamped\":7,\"NightsCampedInSection\":7,\"KMsHiked\":16,\"OASStageProgressions\":0,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Zara Williams\",\"MemberPatrol\":\"Drop Bear\",\"IntroToScouting\":\"2019-06-24T00:00:00\",\"IntroToSection\":\"2021-06-23T19:50:12.262955+10:00\",\"Milestone1Community\":6,\"Milestone1Outdoors\":6,\"Milestone1Creative\":6,\"Milestone1PersonalGrowth\":6,\"Milestone1Assist\":2,\"Milestone1Lead\":1,\"Milestone1Awarded\":\"2022-06-11T11:43:44.730105+10:00\",\"Milestone1Presented\":\"2022-06-11T11:34:50.186406+10:00\",\"Milestone2Community\":5,\"Milestone2Outdoors\":5,\"Milestone2Creative\":5,\"Milestone2PersonalGrowth\":5,\"Milestone2Assist\":3,\"Milestone2Lead\":2,\"Milestone2Awarded\":\"2023-07-20T09:23:59.187815+10:00\",\"Milestone2Presented\":\"2023-07-19T18:10:59.667893+10:00\",\"Milestone3Community\":4,\"Milestone3Outdoors\":4,\"Milestone3Creative\":3,\"Milestone3PersonalGrowth\":4,\"Milestone3Assist\":4,\"Milestone3Lead\":2,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":4,\"OASBushwalkingStage\":2,\"OASCampingStage\":4,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":2,\"OASAquaticsStage\":4,\"OASBoatingStage\":4,\"OASPaddlingStage\":1,\"NightsCamped\":22,\"NightsCampedInSection\":22,\"KMsHiked\":67,\"OASStageProgressions\":12,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":1,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":\"2022-11-15T10:53:33.143125+11:00\",\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Zoe Williams\",\"MemberPatrol\":\"Platypus\",\"IntroToScouting\":\"2019-06-24T00:00:00\",\"IntroToSection\":\"2021-06-23T19:50:10.400473+10:00\",\"Milestone1Community\":6,\"Milestone1Outdoors\":6,\"Milestone1Creative\":6,\"Milestone1PersonalGrowth\":6,\"Milestone1Assist\":2,\"Milestone1Lead\":1,\"Milestone1Awarded\":\"2022-07-24T18:00:06.816562+10:00\",\"Milestone1Presented\":\"2022-07-23T17:37:43.630398+10:00\",\"Milestone2Community\":5,\"Milestone2Outdoors\":5,\"Milestone2Creative\":5,\"Milestone2PersonalGrowth\":5,\"Milestone2Assist\":3,\"Milestone2Lead\":2,\"Milestone2Awarded\":\"2023-05-21T19:16:38.586556+10:00\",\"Milestone2Presented\":\"2023-05-19T07:45:06.7511+10:00\",\"Milestone3Community\":4,\"Milestone3Outdoors\":4,\"Milestone3Creative\":4,\"Milestone3PersonalGrowth\":4,\"Milestone3Assist\":4,\"Milestone3Lead\":4,\"Milestone3Awarded\":\"2023-11-02T20:41:53.55126+11:00\",\"Milestone3Presented\":\"2023-11-01T07:14:28.471968+11:00\",\"OASBushcraftStage\":4,\"OASBushwalkingStage\":2,\"OASCampingStage\":4,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":2,\"OASAquaticsStage\":4,\"OASBoatingStage\":4,\"OASPaddlingStage\":2,\"NightsCamped\":22,\"NightsCampedInSection\":22,\"KMsHiked\":67,\"OASStageProgressions\":16,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":\"2023-02-15T16:24:33.223427+11:00\",\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Bethany Wong\",\"MemberPatrol\":\"Lyrebird\",\"IntroToScouting\":\"2018-03-01T00:00:00\",\"IntroToSection\":\"2020-10-02T00:00:00\",\"Milestone1Community\":6,\"Milestone1Outdoors\":6,\"Milestone1Creative\":6,\"Milestone1PersonalGrowth\":6,\"Milestone1Assist\":2,\"Milestone1Lead\":1,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":5,\"Milestone2Outdoors\":5,\"Milestone2Creative\":5,\"Milestone2PersonalGrowth\":5,\"Milestone2Assist\":1,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":4,\"Milestone3Outdoors\":4,\"Milestone3Creative\":4,\"Milestone3PersonalGrowth\":4,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":2,\"OASBushwalkingStage\":1,\"OASCampingStage\":3,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":0,\"OASAquaticsStage\":4,\"OASBoatingStage\":0,\"OASPaddlingStage\":1,\"NightsCamped\":13,\"NightsCampedInSection\":13,\"KMsHiked\":56,\"OASStageProgressions\":11,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Tynn Yam\",\"MemberPatrol\":\"Magpie\",\"IntroToScouting\":\"2016-11-07T00:00:00\",\"IntroToSection\":\"2021-06-23T19:50:15.411528+10:00\",\"Milestone1Community\":6,\"Milestone1Outdoors\":6,\"Milestone1Creative\":6,\"Milestone1PersonalGrowth\":6,\"Milestone1Assist\":2,\"Milestone1Lead\":1,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":4,\"Milestone2Outdoors\":5,\"Milestone2Creative\":5,\"Milestone2PersonalGrowth\":5,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":4,\"Milestone3Creative\":4,\"Milestone3PersonalGrowth\":4,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":1,\"OASBushwalkingStage\":2,\"OASCampingStage\":1,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":1,\"OASAquaticsStage\":2,\"OASBoatingStage\":0,\"OASPaddlingStage\":0,\"NightsCamped\":5,\"NightsCampedInSection\":5,\"KMsHiked\":48,\"OASStageProgressions\":2,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Helen Yao\",\"MemberPatrol\":\"Magpie\",\"IntroToScouting\":\"2020-03-02T00:00:00\",\"IntroToSection\":null,\"Milestone1Community\":2,\"Milestone1Outdoors\":2,\"Milestone1Creative\":0,\"Milestone1PersonalGrowth\":1,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":0,\"Milestone2Outdoors\":0,\"Milestone2Creative\":0,\"Milestone2PersonalGrowth\":0,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":4,\"OASBushwalkingStage\":3,\"OASCampingStage\":4,\"OASAlpineStage\":0,\"OASCyclingStage\":2,\"OASVerticalStage\":1,\"OASAquaticsStage\":2,\"OASBoatingStage\":3,\"OASPaddlingStage\":3,\"NightsCamped\":20,\"NightsCampedInSection\":20,\"KMsHiked\":43,\"OASStageProgressions\":0,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0},{\"MemberName\":\"Hannah Zhang\",\"MemberPatrol\":\"Magpie\",\"IntroToScouting\":\"2023-09-15T21:29:05.966579+10:00\",\"IntroToSection\":null,\"Milestone1Community\":1,\"Milestone1Outdoors\":1,\"Milestone1Creative\":1,\"Milestone1PersonalGrowth\":3,\"Milestone1Assist\":0,\"Milestone1Lead\":0,\"Milestone1Awarded\":null,\"Milestone1Presented\":null,\"Milestone2Community\":0,\"Milestone2Outdoors\":0,\"Milestone2Creative\":0,\"Milestone2PersonalGrowth\":0,\"Milestone2Assist\":0,\"Milestone2Lead\":0,\"Milestone2Awarded\":null,\"Milestone2Presented\":null,\"Milestone3Community\":0,\"Milestone3Outdoors\":0,\"Milestone3Creative\":0,\"Milestone3PersonalGrowth\":0,\"Milestone3Assist\":0,\"Milestone3Lead\":0,\"Milestone3Awarded\":null,\"Milestone3Presented\":null,\"OASBushcraftStage\":0,\"OASBushwalkingStage\":0,\"OASCampingStage\":0,\"OASAlpineStage\":0,\"OASCyclingStage\":0,\"OASVerticalStage\":0,\"OASAquaticsStage\":0,\"OASBoatingStage\":0,\"OASPaddlingStage\":0,\"NightsCamped\":0,\"NightsCampedInSection\":0,\"KMsHiked\":2,\"OASStageProgressions\":0,\"SIAAdventureSport\":0,\"SIAArtsLiterature\":0,\"SIAEnvironment\":0,\"SIAStemInnovation\":0,\"SIAGrowthDevelopment\":0,\"SIACreatingABetterWorld\":0,\"LeadershipCourse\":null,\"AdventurousJourney\":null,\"PersonalReflection\":null,\"PeakAward\":0.0}]" + }; + if (!Directory.Exists("TestResults")) + Directory.CreateDirectory("TestResults"); + } + + [TestMethod] + public void WallchartBreakByPatrolTrue_ToPDF() + { + var proxyRequest = new Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest(); + _reportGenerationRequest.BreakByPatrol = true; + proxyRequest.Body = JsonConvert.SerializeObject(_reportGenerationRequest); + var functionResult = _function.FunctionHandler(proxyRequest, null); + //Convert Base64String into PDF document + byte[] bytes = Convert.FromBase64String(functionResult); + FileStream fileStream = new FileStream(@"TestResults\Wallchart_ToPDF_BreakByPatrol_True.pdf", FileMode.Create); + BinaryWriter writer = new BinaryWriter(fileStream); + writer.Write(bytes, 0, bytes.Length); + writer.Close(); + } + + [TestMethod] + public void WallchartBreakByPatrolFalse_ToPDF() + { + var proxyRequest = new Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest(); + _reportGenerationRequest.BreakByPatrol = false; + proxyRequest.Body = JsonConvert.SerializeObject(_reportGenerationRequest); + var functionResult = _function.FunctionHandler(proxyRequest, null); + //Convert Base64String into PDF document + byte[] bytes = Convert.FromBase64String(functionResult); + FileStream fileStream = new FileStream(@"TestResults\Wallchart_ToPDF_BreakByPatrol_False.pdf", FileMode.Create); + BinaryWriter writer = new BinaryWriter(fileStream); + writer.Write(bytes, 0, bytes.Length); + writer.Close(); + } + + [TestMethod] + public void WallchartBreakByPatrolTrue_ToExcel() + { + var proxyRequest = new Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest(); + _reportGenerationRequest.BreakByPatrol = true; + _reportGenerationRequest.OutputType = OutputType.Excel; + proxyRequest.Body = JsonConvert.SerializeObject(_reportGenerationRequest); + var functionResult = _function.FunctionHandler(proxyRequest, null); + //Convert Base64String into PDF document + byte[] bytes = Convert.FromBase64String(functionResult); + FileStream fileStream = new FileStream(@"TestResults\Wallchart_ToExcel_BreakByPatrol_True.xlsx", FileMode.Create); + BinaryWriter writer = new BinaryWriter(fileStream); + writer.Write(bytes, 0, bytes.Length); + writer.Close(); + } + + [TestMethod] + public void WallchartBreakByPatrolFalse_ToExcel() + { + var proxyRequest = new Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest(); + _reportGenerationRequest.BreakByPatrol = false; + _reportGenerationRequest.OutputType = OutputType.Excel; + proxyRequest.Body = JsonConvert.SerializeObject(_reportGenerationRequest); + var functionResult = _function.FunctionHandler(proxyRequest, null); + //Convert Base64String into PDF document + byte[] bytes = Convert.FromBase64String(functionResult); + FileStream fileStream = new FileStream(@"TestResults\Wallchart_ToExcel_BreakByPatrol_False.xlsx", FileMode.Create); + BinaryWriter writer = new BinaryWriter(fileStream); + writer.Write(bytes, 0, bytes.Length); + writer.Close(); + } + } +}