Example #1
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="seqRequest"></param>
 /// <param name="destination"></param>
 /// <param name="deliveryRequest"></param>
 /// <param name="exitSession"></param>
 /// <remarks>Corresponds to SB.2.12 in the SCORM 2004 Sequencing/Navigation manual, appendix C.</remarks>
 private void ProcessSequencingRequest(SequencingRequest seqRequest, Activity destination, out Activity deliveryRequest, out bool exitSession)
 {
     switch(seqRequest)
     {
     case SequencingRequest.Choice:
         deliveryRequest = ChoiceSequencingRequest(destination);
         exitSession = false;
         return;
     case SequencingRequest.Continue:
         deliveryRequest = ContinueSequencingRequest();
         exitSession = false;
         return;
     case SequencingRequest.Exit:
         deliveryRequest = null;
         exitSession = ExitSequencingRequest();
         return;
     case SequencingRequest.Previous:
         deliveryRequest = PreviousSequencingRequest();
         exitSession = false;
         return;
     case SequencingRequest.Retry:
         deliveryRequest = RetrySequencingRequest();
         exitSession = false;
         return;
     case SequencingRequest.ResumeAll:
         deliveryRequest = ResumeAllSequencingRequest();
         exitSession = false;
         return;
     case SequencingRequest.Start:
         deliveryRequest = StartSequencingRequest();
         exitSession = false;
         return;
     }
     Utilities.Assert(false);
     deliveryRequest = null;
     exitSession = false;
     return;
 }
Example #2
0
 /// <summary>
 /// Processes post condition rules on an activity, and returns a sequencing request and/or a termination request.
 /// </summary>
 /// <param name="activity">Activity to perform post condition rules on.</param>
 /// <param name="seqRequest">Sequencing request to perform based on the post condition rules, or null if none.</param>
 /// <param name="termRequest">Termination request to perform based on the post condition rules, or null if none.</param>
 /// <remarks>Corresponds to TB.2.2 in the SCORM 2004 Sequencing/Navigation manual, appendix C.</remarks>
 private void SequencingPostConditionRules(Activity activity, out SequencingRequest? seqRequest, out TerminationRequest? termRequest)
 {
     seqRequest = null;
     termRequest = null;
     Resources.Culture = LocalizationManager.GetCurrentCulture();
     if(activity.DataModel.ActivityIsSuspended)
     {
         return;
     }
     SequencingRuleAction? action = SequencingRulesCheck(activity, activity.Sequencing.PostConditionRules);
     switch(action)
     {
     case SequencingRuleAction.Retry:
         // Attempt to override any pending sequencing request with this one
         m_navigator.LogSequencing(SequencingEventType.IntermediateNavigation, m_command, Resources.SequencingPostConditionRuleResult, activity.Key, Resources.SequencingPostConditionRuleRequestRetry);
         seqRequest = SequencingRequest.Retry;
         return;
     case SequencingRuleAction.Continue:
         // Attempt to override any pending sequencing request with this one
         m_navigator.LogSequencing(SequencingEventType.IntermediateNavigation, m_command, Resources.SequencingPostConditionRuleResult, activity.Key, Resources.SequencingPostConditionRuleRequestContinue);
         seqRequest = SequencingRequest.Continue;
         return;
     case SequencingRuleAction.Previous:
         // Attempt to override any pending sequencing request with this one
         m_navigator.LogSequencing(SequencingEventType.IntermediateNavigation, m_command, Resources.SequencingPostConditionRuleResult, activity.Key, Resources.SequencingPostConditionRuleRequestPrevious);
         seqRequest = SequencingRequest.Previous;
         return;
     case SequencingRuleAction.ExitParent:
         // Terminate the appropriate activity(s)
         m_navigator.LogSequencing(SequencingEventType.IntermediateNavigation, m_command, Resources.SequencingPostConditionRuleResult, activity.Key, Resources.SequencingPostConditionRuleRequestExitParent);
         termRequest = TerminationRequest.ExitParent;
         return;
     case SequencingRuleAction.ExitAll:
         // Terminate the appropriate activity(s)
         m_navigator.LogSequencing(SequencingEventType.IntermediateNavigation, m_command, Resources.SequencingPostConditionRuleResult, activity.Key, Resources.SequencingPostConditionRuleRequestExitAll);
         termRequest = TerminationRequest.ExitAll;
         return;
     case SequencingRuleAction.RetryAll:
         // Terminate all active activities and move the current activity to the root of the activity tree; then perform an 'in-process' start
         m_navigator.LogSequencing(SequencingEventType.IntermediateNavigation, m_command, Resources.SequencingPostConditionRuleResult, activity.Key, Resources.SequencingPostConditionRuleRequestRetryAll);
         seqRequest = SequencingRequest.Retry;
         termRequest = TerminationRequest.ExitAll;
         return;
     }
 }
Example #3
0
            private void ProcessNavigationRequest(Activity destination, out SequencingRequest? seqRequest, 
                out TerminationRequest? termRequest)
            {
                seqRequest = null;
                termRequest = null;
                switch(m_command)
                {
                case NavigationCommand.Abandon:
                    if(m_navigator.CurrentActivity != null)
                    {
                        if(m_navigator.CurrentActivity.DataModel.ActivityIsActive)
                        {
                            termRequest = TerminationRequest.Abandon;
                            seqRequest = SequencingRequest.Exit;
                        }
                        else
                        {
                            throw new SequencingException(SequencingExceptionCode.NB_2_1__12);
                        }
                    }
                    else
                    {
                        throw new SequencingException(SequencingExceptionCode.NB_2_1__2);
                    }
                    break;
                case NavigationCommand.AbandonAll:
                    // the check for CurrentActivity != null was removed
                    // so this function should always succeed
                    termRequest = TerminationRequest.AbandonAll;
                    seqRequest = SequencingRequest.Exit;
                    break;
                case NavigationCommand.Choose:
                    if(destination == m_navigator.RootActivity || destination.Parent.Sequencing.Choice)
                    {
                        if(m_navigator.CurrentActivity == null)
                        {
                            seqRequest = SequencingRequest.Choice;
                            return;
                        }
                        // We are always allowed to choose a sibling of the current activity - INCORRECT DESPITE BEING IN THE SCORM PSEUDOCODE
                        // if(destination.Parent != m_navigator.CurrentActivity.Parent)
                        {
                            // The common ancestor will not terminate as a result of processing the choice sequencing request, 
                            // unless the common ancestor is the CurrentActivity - the current activity should always 
                            // be included in the activity path
                            Activity ancestor = FindCommonAncestor(m_navigator.CurrentActivity, destination);
                            Activity final;
                            if(ancestor == m_navigator.CurrentActivity)
                            {
                                final = ancestor.Parent;
                            }
                            else
                            {
                                final = ancestor;
                            }

                            // Make sure that 'choosing' the target will not force an active activity to terminate, 
                            // if that activity does not allow choice to terminate it
                            for(Activity a = m_navigator.CurrentActivity ; a != final ; a = a.Parent)
                            {
                                if(a.DataModel.ActivityIsActive && !a.Sequencing.ChoiceExit)
                                {
                                    throw new SequencingException(SequencingExceptionCode.NB_2_1__8);
                                }
                            }
                        }
                        if(m_navigator.CurrentActivity.DataModel.ActivityIsActive)
                        {
                            termRequest = TerminationRequest.Exit;
                        }
                        seqRequest = SequencingRequest.Choice;
                    }
                    else
                    {
                        throw new SequencingException(SequencingExceptionCode.NB_2_1__10);
                    }
                    break;
                case NavigationCommand.Continue:
                    if(m_navigator.CurrentActivity == null)
                    {
                        throw new SequencingException(SequencingExceptionCode.NB_2_1__2);
                    }
                    // Validate that a 'flow' sequencing request can be processed from the current activity
                    if(m_navigator.CurrentActivity != m_navigator.RootActivity && m_navigator.CurrentActivity.Parent.Sequencing.Flow)
                    {
                        seqRequest = SequencingRequest.Continue;

                        // If the current activity has not been terminated, terminate the current the activity
                        if(m_navigator.CurrentActivity.DataModel.ActivityIsActive)
                        {
                            termRequest = TerminationRequest.Exit;
                        }
                    }
                    else
                    {
                        // Flow is not enabled or the current activity is the root of the activity tree
                        throw new SequencingException(SequencingExceptionCode.NB_2_1__4);
                    }
                    break;
                case NavigationCommand.ExitAll:
                    if(m_navigator.CurrentActivity != null)
                    {
                        // If the sequencing session has already begun, unconditionally terminate all active activities
                        termRequest = TerminationRequest.ExitAll;
                        seqRequest = SequencingRequest.Exit;
                    }
                    else
                    {
                        throw new SequencingException(SequencingExceptionCode.NB_2_1__2);
                    }
                    break;
                case NavigationCommand.Previous:
                    if(m_navigator.CurrentActivity == null)
                    {
                        throw new SequencingException(SequencingExceptionCode.NB_2_1__2);
                    }
                    // Validate that a 'flow' sequencing request can be processed from the current activity
                    if(m_navigator.CurrentActivity != m_navigator.RootActivity)
                    {
                        if(m_navigator.CurrentActivity.Parent.Sequencing.Flow && !m_navigator.CurrentActivity.Parent.Sequencing.ForwardOnly)
                        {
                            seqRequest = SequencingRequest.Previous;

                            // If the current activity has not been terminated, terminate the current the activity
                            if(m_navigator.CurrentActivity.DataModel.ActivityIsActive)
                            {
                                termRequest = TerminationRequest.Exit;
                            }
                        }
                        else
                        {
                            // Violates control mode
                            throw new SequencingException(SequencingExceptionCode.NB_2_1__5);
                        }
                    }
                    else
                    {
                        // // Cannot move backward from the root of the activity tree
                        throw new SequencingException(SequencingExceptionCode.NB_2_1__6);
                    }
                    break;
                case NavigationCommand.ResumeAll:
                    if(m_navigator.CurrentActivity == null)
                    {
                        if(m_navigator.SuspendedActivity != null)
                        {
                            seqRequest = SequencingRequest.ResumeAll;
                        }
                        else
                        {
                            throw new SequencingException(SequencingExceptionCode.NB_2_1__3);
                        }
                    }
                    else
                    {
                        throw new SequencingException(SequencingExceptionCode.NB_2_1__1);
                    }
                    break;
                case NavigationCommand.Start:
                    if(m_navigator.CurrentActivity != null)
                    {
                        throw new SequencingException(SequencingExceptionCode.NB_2_1__1);
                    }
                    seqRequest = SequencingRequest.Start;
                    break;
                case NavigationCommand.SuspendAll:
                    if(m_navigator.CurrentActivity != null)
                    {
                        termRequest = TerminationRequest.SuspendAll;
                        seqRequest = SequencingRequest.Exit;
                    }
                    else
                    {
                        throw new SequencingException(SequencingExceptionCode.NB_2_1__2);
                    }
                    break;
                case NavigationCommand.UnqualifiedExit:
                    if(m_navigator.CurrentActivity == null)
                    {
                        throw new SequencingException(SequencingExceptionCode.NB_2_1__2);
                    }
                    if(m_navigator.CurrentActivity.DataModel.ActivityIsActive)
                    {
                        termRequest = TerminationRequest.Exit;
                        seqRequest = SequencingRequest.Exit;
                    }
                    else
                    {
                        throw new SequencingException(SequencingExceptionCode.NB_2_1__12);
                    }
                    break;
                default:
                    throw new LearningComponentsInternalException("SSN0001");
                }
            }