/// <summary> /// Iterates through all possible encounters until a sufficient match is found /// </summary> /// <remarks> /// The iterator lazily finds matching encounters, then verifies secondary checks to weed out any non-exact matches. /// </remarks> /// <param name="pk">Source data to find a match for</param> /// <param name="info">Object to store matched encounter info</param> /// <returns> /// Information containing the matched encounter and any parsed checks. /// If no clean match is found, the last checked match is returned. /// If no match is found, an invalid encounter object is returned. /// </returns> public static void FindVerifiedEncounter(PKM pk, LegalInfo info) { var encounters = EncounterGenerator.GetEncounters(pk, info); using var encounter = new PeekEnumerator <IEncounterable>(encounters); if (!encounter.PeekIsNext()) { VerifyWithoutEncounter(pk, info); return; } var first = encounter.Current; var EncounterValidator = EncounterVerifier.GetEncounterVerifierMethod(first.Generation); while (encounter.MoveNext()) { var enc = encounter.Current; // Check for basic compatibility. var e = EncounterValidator(pk, enc); if (!e.Valid && encounter.PeekIsNext()) { continue; } // Looks like we might have a good enough match. Check if this is really a good match. info.EncounterMatch = enc; info.Parse.Add(e); if (!VerifySecondaryChecks(pk, info, encounter)) { continue; } // Sanity Check -- Some secondary checks might not be as thorough as the partial-match leak-through checks done by the encounter. if (enc is not IEncounterMatch mx) { break; } var match = mx.GetMatchRating(pk); if (match != EncounterMatchRating.PartialMatch) { break; } // Reaching here implies the encounter wasn't valid. Try stepping to the next encounter. if (encounter.PeekIsNext()) { continue; } // We ran out of possible encounters without finding a suitable match; add a message indicating that the encounter is not a complete match. info.Parse.Add(new CheckResult(Severity.Invalid, LEncInvalid, CheckIdentifier.Encounter)); break; } if (!info.FrameMatches && info.EncounterMatch is EncounterSlot { Version : not GameVersion.CXD }) // if false, all valid RNG frame matches have already been consumed
public void Parse(string fileName, IProgress <int> progress = null, CancellationToken token = default) { using (var reader = new FastBinaryReader(fileName)) { enumerator_ = new PeekEnumerator <StepToken>(StepTokenizer.Tokenize(reader)); ParseStep(); } }
public void PeekEnumerator_ShouldWorkForEmptyEnumerator() { var data = new int [0]; var enumerator = new PeekEnumerator <int>(data); Assert.IsFalse(enumerator.TryPeek(out _)); Assert.IsFalse(enumerator.MoveNext()); Assert.IsFalse(enumerator.TryPeek(out _)); }
public void PeekEnumerator_ShouldWorkForOneElement() { var data = new int[] { 1 }; var enumerator = new PeekEnumerator <int>(data); Assert.IsTrue(enumerator.TryPeek(out var first)); Assert.AreEqual(1, first); Assert.IsTrue(enumerator.MoveNext()); Assert.AreEqual(1, enumerator.Current); Assert.IsFalse(enumerator.TryPeek(out _)); Assert.IsFalse(enumerator.MoveNext()); }