async Task Load(int id) { // Get a test from the API ABTestData aBTestData = await TJBarnesService.GetHttpClient() .GetFromJsonAsync <ABTestData>("api/abtests/" + id.ToString()); // Use the Deserializer method of the JsonSerializer class (in the System.Text.Json namespace) to create // a BlowSetCore object for each of A and B BlowSetCore blowSetCoreA = JsonSerializer.Deserialize <BlowSetCore>(aBTestData.ABTestSpecA); BlowSetCore blowSetCoreB = JsonSerializer.Deserialize <BlowSetCore>(aBTestData.ABTestSpecB); testSpec.AHasErrors = blowSetCoreA.HasErrors; // Create a BlowSet object from the BlowSetCore object for A blowSetA = new BlowSet(blowSetCoreA.Stage, blowSetCoreA.NumRows, blowSetCoreA.TenorWeight, blowSetCoreA.ErrorType, blowSetCoreA.HasErrors); // Use an audioIdSuffix of "b" for this blowset blowSetA.LoadBlows(blowSetCoreA, "a"); blowSetA.SetUnstruck(); // Create a BlowSet object from the BlowSetCore object for B blowSetB = new BlowSet(blowSetCoreB.Stage, blowSetCoreB.NumRows, blowSetCoreB.TenorWeight, blowSetCoreB.ErrorType, blowSetCoreB.HasErrors); // Use an audioIdSuffix of "b" for this blowset blowSetB.LoadBlows(blowSetCoreB, "b"); blowSetB.SetUnstruck(); // Update drop down boxes on screen // Use BlowSetA - by definition the following properties for BlowSetA and BlowSetB will be the same testSpec.Stage = blowSetA.Stage; testSpec.TenorWeight = blowSetA.TenorWeight; testSpec.ErrorType = blowSetA.ErrorType; // Set up test spec-dependent elements of the screen object int baseGap = BaseGaps.BaseGap(testSpec.Stage, testSpec.TenorWeight, 1); testSpec.BaseGap = baseGap; // Set the timing for the animation (when not showing the bells) screenA.AnimationDuration = blowSetA.Blows.Last().GapCumulative + 1000; screenB.AnimationDuration = blowSetB.Blows.Last().GapCumulative + 1000; testSpec.ResultEntered = false; testSpec.ShowGaps = false; StateHasChanged(); }
async Task Load(int id) { // Get a test from the API GapTestData gapTestData = await TJBarnesService.GetHttpClient(). GetFromJsonAsync <GapTestData>("api/gaptests/" + id.ToString()); // Use the Deserializer method of the JsonSerializer class (in the System.Text.Json namespace) to create // a BlowSetCore object BlowSetCore blowSetCore = JsonSerializer.Deserialize <BlowSetCore>(gapTestData.GapTestSpec); // Now create a BlowSet object from the BlowSetCore object blowSet = new BlowSet(blowSetCore.Stage, blowSetCore.NumRows, blowSetCore.TenorWeight, blowSetCore.ErrorType, true); // No need for an audio suffix in a Gap test (this is used to distinguish A and B in an A/B test) blowSet.LoadBlows(blowSetCore, string.Empty); blowSet.SetUnstruck(); // Update drop down boxes on screen testSpec.Stage = blowSet.Stage; testSpec.TenorWeight = blowSet.TenorWeight; testSpec.NumRows = blowSet.NumRows; // Set up test spec-dependent elements of the screen object int baseGap = BaseGaps.BaseGap(testSpec.Stage, testSpec.TenorWeight, 1); testSpec.BaseGap = baseGap; testSpec.GapMin = 20; // If test bell is 1st's place of a handstroke row, need to adjust GapMax to have a higher value // because of the handstroke gap if (blowSet.Blows.Last().IsHandstroke == true && blowSet.Blows.Last().Place == 1) { testSpec.GapMax = Convert.ToInt32(Math.Round(((double)testSpec.BaseGap * 3) / 50)) * 50; } else { testSpec.GapMax = Convert.ToInt32(Math.Round(((double)baseGap * 2) / 50)) * 50; } testSpec.ShowGaps = false; StateHasChanged(); }
void Create() { Block testBlock = new Block(testSpec.Stage, testSpec.NumRows); testBlock.CreateRandomBlock(); // Set place to be the test place int testPlace; testPlace = testSpec.Stage + (testSpec.Stage % 2); if (testSpec.TestBellLoc != 1) { Random rand = new Random(); testPlace = rand.Next(1, testPlace + 1); } blowSet = new BlowSet(testSpec.Stage, testSpec.NumRows, testSpec.TenorWeight, testSpec.ErrorType, true); // No need for an audio suffix in a Gap test (this is used to distinguish A and B in an A/B test) blowSet.PopulateBlows(testBlock, testPlace, string.Empty); blowSet.CreateRandomSpacing(testSpec.ErrorSize, Constants.Rounding); blowSet.SetUnstruck(); // Set up test spec-dependent elements of the screen object // When practicing in a Gap Test, gaps are rounded to the nearest 10ms so that bells will align // if zero gap error is selected int baseGap = BaseGaps.BaseGap(testSpec.Stage, testSpec.TenorWeight, 10); testSpec.BaseGap = baseGap; testSpec.GapMin = 20; // If test bell is 1st's place of a handstroke row, need to adjust GapMax to have a higher value // because of the handstroke gap if (testSpec.NumRows % 2 == 1 && testPlace == 1) { testSpec.GapMax = Convert.ToInt32(Math.Round(((double)testSpec.BaseGap * 3) / 50)) * 50; } else { testSpec.GapMax = Convert.ToInt32(Math.Round(((double)baseGap * 2) / 50)) * 50; } }
async Task PlayAsync() { int initialDelay = 1000; if (screen.PlayLabel == "Play") { // Change test bell color to disabled color - can't adjust gap during play blowSet.Blows.Last().BellColor = Constants.DisabledUnstruckTestBellColor; DateTime strikeTime = DateTime.Now; foreach (Blow blow in blowSet.Blows) { // Set strike times strikeTime = strikeTime.AddMilliseconds(blow.Gap); blow.StrikeTime = strikeTime; } cancellationTokenSource = new CancellationTokenSource(); cancellationToken = cancellationTokenSource.Token; screen.PlayLabel = "Stop"; testSpec.ControlsDisabled = true; testSpec.TenorWeightDisabled = true; TimeSpan delay; int delayMs; foreach (Blow blow in blowSet.Blows) { delay = blow.StrikeTime - DateTime.Now; delayMs = Convert.ToInt32(delay.TotalMilliseconds); if (delayMs > 0) { await Task.Delay(delayMs, cancellationToken); } if (cancellationToken.IsCancellationRequested) { break; } // Change bell color if (Device.DeviceLoad == DeviceLoad.High) { blow.BellColor = Constants.StruckBellColor; // Confirmed this is needed here StateHasChanged(); } // Strike bell await JSRuntime.InvokeVoidAsync("PlayBellAudio", blow.AudioId); } } else if (screen.PlayLabel == "Stop") { cancellationTokenSource.Cancel(); initialDelay = 0; } // Initial delay if (initialDelay > 0) { await Task.Delay(initialDelay); } // Start spinner screen.PlayDisabled = true; screen.PlayLabel = "Wait"; screen.SpinnerPlaying = true; StateHasChanged(); // Wait 2.6 or 1.6 further seconds for the sound to finish, depending on whether arriving here // on stop or end of play await Task.Delay(2600 - initialDelay); // Reset play button screen.SpinnerPlaying = false; screen.PlayLabel = "Play"; screen.PlayDisabled = false; // Reset screen if (Device.DeviceLoad == DeviceLoad.High) { blowSet.SetUnstruck(); } else { blowSet.Blows.Last().BellColor = Constants.UnstruckTestBellColor; } testSpec.ControlsDisabled = false; testSpec.TenorWeightDisabled = TenorWeightSelect.TenorWeightDisabled(testSpec.Stage); StateHasChanged(); }
async Task PlayAsyncB() { int initialDelay = 1000; if (screenB.PlayLabel == "Play B") { DateTime strikeTime = DateTime.Now; foreach (Blow blow in blowSetB.Blows) { // Set strike times strikeTime = strikeTime.AddMilliseconds(blow.Gap); blow.StrikeTime = strikeTime; } cancellationTokenSource = new CancellationTokenSource(); cancellationToken = cancellationTokenSource.Token; screenB.PlayLabel = "Stop B"; testSpec.ControlsDisabled = true; testSpec.TenorWeightDisabled = true; screenA.PlayDisabled = true; // Start the animation if not showing the bells if (testSpec.ShowGaps == false) { screenB.RunAnimation = true; } TimeSpan delay; int delayMs; foreach (Blow blow in blowSetB.Blows) { delay = blow.StrikeTime - DateTime.Now; delayMs = Convert.ToInt32(delay.TotalMilliseconds); if (delayMs > 0) { await Task.Delay(delayMs, cancellationToken); } if (cancellationToken.IsCancellationRequested) { break; } // Change bell color if (Device.DeviceLoad == DeviceLoad.High && testSpec.ShowGaps == true) { blow.BellColor = Constants.StruckBellColor; // Confirmed this is needed here StateHasChanged(); } // Strike bell await JSRuntime.InvokeVoidAsync("PlayBellAudio", blow.AudioId); } } else if (screenB.PlayLabel == "Stop B") { cancellationTokenSource.Cancel(); initialDelay = 0; } // Initial delay if (initialDelay > 0) { // Test was not stopped await Task.Delay(initialDelay); } else { // Reset animation immediately when test is stopped if (testSpec.ShowGaps == false) { screenB.RunAnimation = false; } } // Start spinner screenB.PlayDisabled = true; screenB.PlayLabel = "Wait"; screenB.SpinnerPlaying = true; StateHasChanged(); // Wait 2.6 or 1.6 further seconds for the sound to finish, depending on whether arriving here // on stop or end of play await Task.Delay(2600 - initialDelay); // Reset animation, unless it was already reset earlier after a stop if (initialDelay > 0 && testSpec.ShowGaps == false) { screenB.RunAnimation = false; } // Reset play button screenB.SpinnerPlaying = false; screenB.PlayLabel = "Play B"; screenB.PlayDisabled = false; // Reset screen if (Device.DeviceLoad == DeviceLoad.High && testSpec.ShowGaps == true) { blowSetB.SetUnstruck(); } testSpec.ControlsDisabled = false; testSpec.TenorWeightDisabled = TenorWeightSelect.TenorWeightDisabled(testSpec.Stage); screenA.PlayDisabled = false; StateHasChanged(); }
void Create() { // Choose whether A or B will have the errors Random rand = new Random(); testSpec.AHasErrors = rand.Next(0, 2) == 0; // Create the test block Block testBlock = new Block(testSpec.Stage, testSpec.NumRows); testBlock.CreateRandomBlock(); blowSetA = new BlowSet(testSpec.Stage, testSpec.NumRows, testSpec.TenorWeight, testSpec.ErrorType, testSpec.AHasErrors); blowSetA.PopulateBlows(testBlock, testSpec.TestBellLoc, "a"); // No rounding in an A/B test blowSetA.CreateEvenSpacing(1); blowSetA.SetUnstruck(); blowSetB = new BlowSet(testSpec.Stage, testSpec.NumRows, testSpec.TenorWeight, testSpec.ErrorType, !testSpec.AHasErrors); blowSetB.PopulateBlows(testBlock, testSpec.TestBellLoc, "b"); // No rounding in an A/B test blowSetB.CreateEvenSpacing(1); blowSetB.SetUnstruck(); if (testSpec.AHasErrors == true) { if (testSpec.ErrorType == 1) { blowSetA.CreateStrikingError(testSpec.ErrorSize); } else { blowSetA.CreateCompassError(testSpec.ErrorSize); } } else { if (testSpec.ErrorType == 1) { blowSetB.CreateStrikingError(testSpec.ErrorSize); } else { blowSetB.CreateCompassError(testSpec.ErrorSize); } } // Set up test spec-dependent elements of the screen object int baseGap = BaseGaps.BaseGap(testSpec.Stage, testSpec.TenorWeight, 1); testSpec.BaseGap = baseGap; // Set the timing for the animation (when not showing the bells) screenA.AnimationDuration = blowSetA.Blows.Last().GapCumulative + 1000; screenB.AnimationDuration = blowSetB.Blows.Last().GapCumulative + 1000; testSpec.ResultEntered = false; testSpec.ShowGaps = false; }