private static async Task <Transition?> ResolveTransitionAsync(this State state, StateMachineContext context, JToken data) { Debug.Assert(state != null); Debug.Assert(context != null); Debug.Assert(data != null); if (state.Transitions.Count == 0) { return(null); } Transition?transition = state.ResolveImplicitTransition(); if (transition == null) { transition = state.ResolveConditionalTransition(context, data); } if (transition == null) { transition = await state.ResolveEventTransitionAsync(context, data); } Debug.Assert(transition != null); return(transition); }
public void Previous_LastYear() { var januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight); var recurrence = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972); Transition?actual = recurrence.Previous(new Instant(NodaConstants.UnixEpoch.Ticks + (1 * TicksPerStandardYear)), Offset.Zero, Offset.Zero); Transition?expected = new Transition(NodaConstants.UnixEpoch, Offset.Zero, Offset.Zero); Assert.AreEqual(expected, actual); }
public void PreviousOrSame_LastYear() { var januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight); var recurrence = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972); Transition?actual = recurrence.PreviousOrSame(Instant.FromUtc(1971, 1, 1, 0, 0) - Duration.Epsilon, Offset.Zero, Offset.Zero); Transition?expected = new Transition(NodaConstants.UnixEpoch, Offset.Zero); Assert.AreEqual(expected, actual); }
public void PreviousOrSame_AfterLastYear() { var januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight); var recurrence = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972); Transition?actual = recurrence.PreviousOrSame(Instant.MaxValue, Offset.Zero, Offset.Zero); Transition?expected = new Transition(Instant.FromUtc(1972, 1, 1, 0, 0), Offset.Zero); Assert.AreEqual(expected, actual); }
internal Transition(TransitionRegexKind kind, int leaf = 0, S?test = default(S), SymbolicRegexNode <S>?look = null, Transition?first = null, Transition?second = null) { _kind = kind; _leaf = leaf; _test = test; _look = look; _first = first; _second = second; }
public void Previous_BeforeFirstYear_null() { var januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight); var recurrence = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972); Transition?actual = recurrence.Previous(NodaConstants.UnixEpoch - Duration.Epsilon, Offset.Zero, Offset.Zero); Transition?expected = null; Assert.AreEqual(expected, actual); }
public void Next_BeforeFirstYear() { var januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight); var recurrence = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972); Transition?actual = recurrence.Next(Instant.MinValue, Offset.Zero, Offset.Zero); Transition?expected = new Transition(NodaConstants.UnixEpoch, Offset.Zero, Offset.Zero); Assert.AreEqual(expected, actual); }
public void PreviousOrSame_OnFirstYear_null() { // Transition is on January 2nd, but we're asking for January 1st. var januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 2, 0, true, LocalTime.Midnight); var recurrence = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972); Transition?actual = recurrence.PreviousOrSame(NodaConstants.UnixEpoch, Offset.Zero, Offset.Zero); Transition?expected = null; Assert.AreEqual(expected, actual); }
public StyleValueDeclaration(IDependencyProperty property, StyleSetterType setterType, T value, Transition?transition) { _value = value; Property = property; SetterType = setterType; Transition = transition; }
public void Next_BeyondLastYear_null() { var afterRecurrenceEnd = Instant.FromUtc(1980, 1, 1, 0, 0); var januaryFirstMidnight = new ZoneYearOffset(TransitionMode.Utc, 1, 1, 0, true, LocalTime.Midnight); var recurrence = new ZoneRecurrence("bob", Offset.Zero, januaryFirstMidnight, 1970, 1972); Transition?actual = recurrence.Next(afterRecurrenceEnd, Offset.Zero, Offset.Zero); Transition?expected = null; Assert.AreEqual(expected, actual); }
/// <summary> /// Piggy-backs onto PreviousOrSame, but fails with a descriptive InvalidOperationException if there's no such transition. /// </summary> internal Transition PreviousOrSameOrFail(Instant instant, Offset standardOffset, Offset previousSavings) { Transition?previous = PreviousOrSame(instant, standardOffset, previousSavings); if (previous is null) { throw new InvalidOperationException( $"Noda Time bug or bad data: Expected a transition earlier than {instant}; standard offset = {standardOffset}; previousSavings = {previousSavings}; recurrence = {this}"); } return(previous.Value); }
/// <summary> /// Piggy-backs onto Next, but fails with an InvalidOperationException if there's no such transition. /// </summary> internal Transition NextOrFail(Instant instant, Offset standardOffset, Offset previousSavings) { Transition?next = Next(instant, standardOffset, previousSavings); if (next is null) { throw new InvalidOperationException( $"Noda Time bug or bad data: Expected a transition later than {instant}; standard offset = {standardOffset}; previousSavings = {previousSavings}; recurrence = {this}"); } return(next.Value); }
/// <summary> /// Piggy-backs onto Previous, but fails with a descriptive InvalidOperationException if there's no such transition. /// </summary> internal Transition PreviousOrFail(Instant instant, Offset standardOffset, Offset previousSavings) { Transition?previous = Previous(instant, standardOffset, previousSavings); if (previous == null) { throw new InvalidOperationException( string.Format("Noda Time bug or bad data: Expected a transition earlier than {0}; standard offset = {1}; previousSavings = {2}; recurrence = {3}", instant, standardOffset, previousSavings, this)); } return(previous.Value); }
private ZoneTransition GetNext(Instant nextInstant) { // Find next matching rule. ZoneRecurrence nextRule = null; Instant nextTicks = Instant.MaxValue; for (int i = 0; i < rules.Count; i++) { ZoneRecurrence rule = rules[i]; Transition? nextTransition = rule.Next(nextInstant, ruleSet.StandardOffset, savings); Instant? next = nextTransition == null ? (Instant?)null : nextTransition.Value.Instant; if (!next.HasValue || next.Value <= nextInstant) { rules.RemoveAt(i); i--; continue; } // Even if next is same as previous next, choose the rule in order for more // recently added rules to override. if (next.Value <= nextTicks) { // Found a better match. nextRule = rule; nextTicks = next.Value; } } if (nextRule == null) { return(null); } // Stop precalculating if year reaches some arbitrary limit. We can cheat in the // conversion because it is an approximation anyway. if (calendar.GetYear(nextTicks.Plus(Offset.Zero)) >= YearLimit) { return(null); } // Check if upper limit reached or passed. if (ruleSet.upperYear < Int32.MaxValue) { Instant upperTicks = ruleSet.upperYearOffset.MakeInstant(ruleSet.upperYear, ruleSet.StandardOffset, savings); if (nextTicks >= upperTicks) { // At or after upper limit. return(null); } } return(new ZoneTransition(nextTicks, nextRule.Name, ruleSet.StandardOffset, nextRule.Savings)); }
public bool MoveNext(TInput input) { if (!_currentState.HasValue) { throw new InvalidOperationException("State machine has no current state!"); } var currentState = _currentState.Value.StateValue; if (!IsFinished) { Transition?availableTransition = null; Transition?conditionlessTransition = null; foreach (var trans in _transitions[currentState]) { if (!conditionlessTransition.HasValue && trans.Condition == null) { conditionlessTransition = trans; } else if (trans.CheckCondition(input)) { availableTransition = trans; break; } } var transition = availableTransition ?? conditionlessTransition; if (transition is Transition selectedTran) { var newStateValue = selectedTran.ToState; var newState = _states[newStateValue]; _currentState.Value.OnLeave?.Invoke(currentState, input); newState.OnEnter?.Invoke(newStateValue, input); _currentState = newState; if (_transitions[newStateValue].Count == 0) { IsFinished = true; } return(true); } } _currentState?.OnTransitionError?.Invoke(currentState, input); return(false); }
///// <summary> ///// Set state on a single light ///// </summary> ///// <param name="light"></param> ///// <param name="xy"></param> ///// <param name="gamut"></param> ///// <param name="brightness"></param> ///// <param name="timeSpan"></param> ///// <param name="cancellationToken"></param> ///// <returns></returns> //public static void SetState(this EntertainmentLight light, CancellationToken cancellationToken, CIE1931Point xy, CIE1931Gamut gamut, double? brightness = null, TimeSpan timeSpan = default) //{ // var rgb = HueColorConverter.XYToRgb(xy, gamut); // //Create a new transition for this light // Transition transition = new Transition(rgb, brightness, timeSpan); // light.Transition = transition; // //Start the transition // transition.Start(light.State.RGBColor, light.State.Brightness, cancellationToken); //} //Source: https://github.com/Q42/Q42.HueApi/pull/174 public static void SetState(this EntertainmentLight light, CancellationToken cancellationToken, RGBColor?rgb = null, TimeSpan rgbTimeSpan = default, double?brightness = null, TimeSpan briTimeSpan = default, bool overwriteExistingTransition = true) { if (light == null) { throw new ArgumentNullException(nameof(light)); } // No change in state required. if (!rgb.HasValue && !brightness.HasValue) { return; } var currentTransition = light.Transition; bool hasExistingTransition = currentTransition != null && !currentTransition.IsFinished; bool canCombineTransitions = hasExistingTransition && (!rgb.HasValue || !brightness.HasValue) && (!rgb.HasValue || !currentTransition !.IsBrightnessFinished) && (!brightness.HasValue || !currentTransition !.IsRgbFinished); Transition?transition = null; // If we can't combine the existing transition (if there is one) with the new transition, start a fresh transition. if (!canCombineTransitions || overwriteExistingTransition) { if (rgb.HasValue && brightness.HasValue) { transition = new Transition(rgb.Value, brightness.Value, rgbTimeSpan, briTimeSpan); } else if (rgb.HasValue) { transition = new Transition(rgb.Value, rgbTimeSpan); } else if (brightness.HasValue) { transition = new Transition(brightness.Value, briTimeSpan); } } else { // A transition is currently in progress, which we need to combine with the colour or brightness that was specified. if (rgb.HasValue && currentTransition !.TargetBri.HasValue) { // Combine new colour transition with existing brightness transition. transition = new Transition(rgb.Value, currentTransition !.TargetBri.Value, rgbTimeSpan, currentTransition.BrightnessRemainingTime); }
/// <summary> /// Changes the state based on one or more transition /// </summary> internal void ProcessTransitions() { lock (transitionLock) { if (Transition == null) { return; } this.State.SetBrightness(Transition.TransitionState.Brightness); this.State.SetRGBColor(Transition.TransitionState.RGBColor); if (Transition.IsFinished) { Transition = null; } } }
public virtual void ChangeAppearance(string appearance, float duration = 0, EasingType easingType = default, Transition?transition = default) { if (!string.IsNullOrEmpty(appearance)) { onAppearanceChanged?.Invoke(appearance); } }
internal NullableTransitionWrapper(Transition?transition) { this.transition = transition; }
/// <summary> /// Recursively builds a complete list of generalized sequences accepted by the simplifiable part of the automaton. /// </summary> /// <param name="stateIndex">The currently traversed state.</param> /// <param name="generalizedTreeNodes">The state labels obtained from <see cref="FindGeneralizedTrees"/>.</param> /// <param name="weightedSequences">The sequence list being built.</param> /// <param name="currentSequenceElements">The list of elements of the sequence currently being built.</param> /// <param name="currentWeight">The weight of the sequence currently being built.</param> private void DoBuildAcceptedSequenceList( int stateIndex, bool[] generalizedTreeNodes, List <WeightedSequence> weightedSequences, List <GeneralizedElement> currentSequenceElements, Weight currentWeight) { var stack = new Stack <StackItem>(); stack.Push(new StateWeight(stateIndex, currentWeight)); while (stack.Count > 0) { var stackItem = stack.Pop(); if (stackItem is ElementItem elementItem) { if (elementItem.Element != null) { currentSequenceElements.Add(elementItem.Element.Value); } else { currentSequenceElements.RemoveAt(currentSequenceElements.Count - 1); } continue; } var stateAndWeight = stackItem as StateWeight; stateIndex = stateAndWeight.StateIndex; var state = this.builder[stateIndex]; currentWeight = stateAndWeight.Weight; // Find a non-epsilon self-loop if there is one Transition?selfLoop = null; for (var iterator = state.TransitionIterator; iterator.Ok; iterator.Next()) { var transition = iterator.Value; if (transition.DestinationStateIndex == stateIndex) { Debug.Assert( selfLoop == null, "Multiple self-loops should have been merged by MergeParallelTransitions()"); selfLoop = transition; } } // Push the found self-loop to the end of the current sequence if (selfLoop != null) { currentSequenceElements.Add(new GeneralizedElement( selfLoop.Value.ElementDistribution, selfLoop.Value.Group, selfLoop.Value.Weight)); stack.Push(new ElementItem(null)); } // Can this state produce a sequence? if (state.CanEnd && generalizedTreeNodes[stateIndex]) { var sequence = new GeneralizedSequence(currentSequenceElements); // TODO: use immutable data structure instead of copying sequences weightedSequences.Add(new WeightedSequence(sequence, Weight.Product(currentWeight, state.EndWeight))); } // Traverse the outgoing transitions for (var iterator = state.TransitionIterator; iterator.Ok; iterator.Next()) { var transition = iterator.Value; // Skip self-loops & disallowed states if (transition.DestinationStateIndex == stateIndex || !generalizedTreeNodes[transition.DestinationStateIndex]) { continue; } if (!transition.IsEpsilon) { // Non-epsilon transitions contribute to the sequence stack.Push(new ElementItem(null)); } stack.Push( new StateWeight( transition.DestinationStateIndex, Weight.Product(currentWeight, transition.Weight))); if (!transition.IsEpsilon) { stack.Push( new ElementItem( new GeneralizedElement(transition.ElementDistribution, transition.Group, null))); } } } }
public UniTask ChangeAppearanceAsync(string appearance, float duration, EasingType easingType = default, Transition?transition = default, CancellationToken cancellationToken = default) => UniTask.CompletedTask;