コード例 #1
0
        /// <summary>
        /// Creates a new <Typ>ExecuteNavigator</Typ> object in memory and its representation in the database.
        /// </summary>
        /// <param name="store">A <Typ>LearningStore</Typ> object that references the database to use.</param>
        /// <param name="rootActivityId">The database identifier for the root activity (i.e. organization) of the activity tree to attempt.</param>
        /// <param name="learnerId">The database identifier for the learner information.</param>
        /// <param name="learnerAssignmentId">The database identifier for the learner assignment information. Only used in SLK.</param>
        /// <param name="loggingFlags">Flags specifying which actions to log.</param>
        /// <returns>A new <Typ>ExecuteNavigator</Typ> object.</returns>
        /// <exception cref="LearningStoreItemNotFoundException">Thrown if the learner ID or root activity ID is invalid, or if the package information cannot be found.</exception>
        static public ExecuteNavigator CreateExecuteNavigator(LearningStore store, long rootActivityId, long learnerId, long learnerAssignmentId, LoggingOptions loggingFlags)
        {
            ExecuteNavigator eNav = new ExecuteNavigator();

            LearningStoreJob job = store.CreateJob();

            // first add security
            Dictionary <string, object> securityParameters = new Dictionary <string, object>();

            securityParameters[Schema.CreateAttemptRight.RootActivityId] =
                new LearningStoreItemIdentifier(Schema.ActivityPackageItem.ItemTypeName, rootActivityId);
            securityParameters[Schema.CreateAttemptRight.LearnerId] =
                new LearningStoreItemIdentifier(Schema.UserItem.ItemTypeName, learnerId);
            job.DemandRight(Schema.CreateAttemptRight.RightName, securityParameters);
            job.DisableFollowingSecurityChecks();

            // first query for all information about the learner
            LearningStoreQuery query = store.CreateQuery(Schema.UserItem.ItemTypeName);

            query.AddColumn(Schema.UserItem.Id);
            query.AddColumn(Schema.UserItem.Name);
            query.AddColumn(Schema.UserItem.Language);
            query.AddColumn(Schema.UserItem.AudioCaptioning);
            query.AddColumn(Schema.UserItem.AudioLevel);
            query.AddColumn(Schema.UserItem.DeliverySpeed);
            query.AddCondition(Schema.UserItem.Id, LearningStoreConditionOperator.Equal,
                               new LearningStoreItemIdentifier(Schema.UserItem.ItemTypeName, learnerId));
            job.PerformQuery(query);

            // then query the package information
            query = store.CreateQuery(Schema.SeqNavActivityPackageView.ViewName);
            LearningStoreItemIdentifier rootId = new LearningStoreItemIdentifier(Schema.ActivityPackageItem.ItemTypeName, rootActivityId);

            query.AddColumn(Schema.SeqNavActivityPackageView.PackageId);
            query.AddColumn(Schema.SeqNavActivityPackageView.PackageFormat);
            query.AddColumn(Schema.SeqNavActivityPackageView.PackagePath);
            query.AddCondition(Schema.SeqNavActivityPackageView.Id, LearningStoreConditionOperator.Equal, rootId);
            job.PerformQuery(query);

            // then query for the activity tree
            query = store.CreateQuery(Schema.SeqNavActivityTreeView.ViewName);
            query.AddColumn(Schema.SeqNavActivityTreeView.DataModelCache);
            query.AddColumn(Schema.SeqNavActivityTreeView.ParentActivityId);
            query.AddColumn(Schema.SeqNavActivityTreeView.Id);
            query.AddColumn(Schema.SeqNavActivityTreeView.ObjectivesGlobalToSystem);
            query.AddCondition(Schema.SeqNavActivityTreeView.RootActivityId, LearningStoreConditionOperator.Equal, new LearningStoreItemIdentifier(Schema.ActivityPackageItem.ItemTypeName, rootActivityId));
            job.PerformQuery(query);

            DataTable d;  // used to store results of query
            ReadOnlyCollection <object> ids;

            // for this transaction we need to read from the activitypackageitem table and write new records to
            // the activityattemptitem and attemptitem tables
            TransactionOptions options = new TransactionOptions();

            options.IsolationLevel = System.Transactions.IsolationLevel.RepeatableRead;
            using (LearningStoreTransactionScope scope = new LearningStoreTransactionScope(options))
            {
                // execute the query
                ReadOnlyCollection <object> c = job.Execute();
                Utilities.Assert(c.Count == 3);

                if (((DataTable)c[0]).Rows.Count < 1)
                {
                    throw new LearningStoreItemNotFoundException(Resources.InvalidLearnerId);
                }
                if (((DataTable)c[1]).Rows.Count < 1)
                {
                    throw new LearningStoreItemNotFoundException(Resources.InvalidRootActivityId);
                }
                if (((DataTable)c[2]).Rows.Count < 1)
                {
                    throw new LearningStoreItemNotFoundException(Resources.InvalidRootActivityId);
                }

                d = (DataTable)c[0];  // save learner information

                string          learnerName          = (string)d.Rows[0][Schema.UserItem.Name];
                AudioCaptioning learnerCaption       = (AudioCaptioning)d.Rows[0][Schema.UserItem.AudioCaptioning];
                float           learnerAudioLevel    = (float)d.Rows[0][Schema.UserItem.AudioLevel];
                float           learnerDeliverySpeed = (float)d.Rows[0][Schema.UserItem.DeliverySpeed];
                string          learnerLanguage      = (string)d.Rows[0][Schema.UserItem.Language];

                d = (DataTable)c[1];  // save package information

                // we need to create the activity tree within the transaction because it may affect the data written
                // by means of the selection and randomization processes.

                eNav.m_packageFormat   = (PackageFormat)d.Rows[0][Schema.SeqNavActivityPackageView.PackageFormat];
                eNav.m_packageId       = ((LearningStoreItemIdentifier)d.Rows[0][Schema.SeqNavActivityPackageView.PackageId]).GetKey();
                eNav.m_packageLocation = (string)d.Rows[0][Schema.SeqNavActivityPackageView.PackagePath];
                eNav.m_store           = store;
                eNav.m_learnerId       = learnerId;
                eNav.m_loggingFlags    = loggingFlags;

                // we must set this here so that the Activity  constructor doesn't try and load missing info
                eNav.m_attemptItemInformationIsValid = true;

                d = (DataTable)c[2];  // save data to create activity tree later, when we are done with sql processing

                eNav.AddActivities(d, rootActivityId, learnerName, learnerLanguage, learnerCaption, learnerAudioLevel, learnerDeliverySpeed);

                /*
                 * // create activity objects and store them in a big dictionary
                 * foreach(DataRow row in d.Rows)
                 * {
                 *  Activity act = new Activity(eNav, ((LearningStoreItemIdentifier)row[Schema.SeqNavActivityTreeView.Id]).GetKey(),
                 *      ConvertLearningStoreXmlToXPathNavigator(row[Schema.SeqNavActivityTreeView.DataModelCache] as LearningStoreXml, true),
                 *      null, null, null, eNav.WrapAttachment, eNav.WrapAttachmentGuid, -1,
                 *      (bool)row[Schema.SeqNavActivityTreeView.ObjectivesGlobalToSystem], eNav.m_learnerId.ToString(System.Globalization.CultureInfo.InvariantCulture),
                 *      learnerName, learnerLanguage, learnerCaption, learnerAudioLevel, learnerDeliverySpeed);
                 *  eNav.m_activities[act.ActivityId] = act;
                 *  if(act.ActivityId == rootActivityId)
                 *  {
                 *      eNav.RootActivity = act;
                 *      if(!(row[Schema.SeqNavActivityTreeView.ParentActivityId] is DBNull))
                 *      {
                 *          throw new LearningStoreItemNotFoundException(Resources.InvalidRootActivityId);
                 *      }
                 *  }
                 * }
                 *
                 * // now that we have all the activities in a big dictionary, find all the parents to build the tree
                 * // in theory this could be done in the first loop if I sort the query by parentid, but that's making a lot
                 * // of assumptions about the structure of the database that I don't think are safe to make
                 * foreach(DataRow row in d.Rows)
                 * {
                 *  LearningStoreItemIdentifier parentId = row[Schema.SeqNavActivityTreeView.ParentActivityId] as LearningStoreItemIdentifier;
                 *  if (parentId != null)
                 *  {
                 *      long id = ((LearningStoreItemIdentifier)row[Schema.SeqNavActivityTreeView.Id]).GetKey();
                 *      eNav.m_activities[id].Parent = eNav.m_activities[parentId.GetKey()];
                 *      eNav.m_activities[parentId.GetKey()].AddChild(eNav.m_activities[id]);
                 *  }
                 * }
                 *
                 * // make sure children of each parent are in the right order, and set Previous and Next pointer correctly.
                 * eNav.SortActivityTree();
                 *
                 * // step through the activity tree searching for selection and randomization instructions
                 * // this must be done before the ActivityAttemptItems are saved because they may reorder
                 * // and potentially even remove children.
                 * Random rand = new Random();
                 * foreach(Activity a in eNav.Traverse)
                 * {
                 *  if(!a.IsLeaf)
                 *  {
                 *      // if there's a valid selection instruction, remove excess
                 *      // child activities randomly
                 *      if(a.Sequencing.SelectionTiming == RandomizationTiming.Once &&
                 *          a.Sequencing.RandomizationSelectCount > 0 &&
                 *          a.Sequencing.RandomizationSelectCount < a.Children.Count)
                 *      {
                 *          int selCount = a.Sequencing.RandomizationSelectCount;
                 *          for(int i = 0 ; i < a.Children.Count ; ++i)
                 *          {
                 *              if(rand.Next(a.Children.Count) < selCount)
                 *              {
                 *                  --selCount;
                 *              }
                 *              else
                 *              {
                 *                  a.RemoveChild(i);
                 *              }
                 *          }
                 *          a.SortChildren();
                 *      }
                 *
                 *      // if there's a valid randomization instruction, randomize order of the children
                 *      // of this activity
                 *      if((a.Sequencing.RandomizationTiming == RandomizationTiming.Once ||
                 *          a.Sequencing.RandomizationTiming == RandomizationTiming.OnEachNewAttempt) &&
                 *          a.Sequencing.ReorderChildren)
                 *      {
                 *          List<Activity> randlist = new List<Activity>();
                 *          while(a.Children.Count > 0)
                 *          {
                 *              int i = rand.Next(a.Children.Count);
                 *              randlist.Add((Activity)a.Children[i]);
                 *              a.RemoveChild(i);
                 *          }
                 *          for(int i = 0 ; i < randlist.Count ; ++i)
                 *          {
                 *              randlist[i].RandomPlacement = i;
                 *              a.AddChild(randlist[i]);
                 *          }
                 *          a.SortChildren();
                 *      }
                 *  }
                 * }
                 * */

                // create the attemptitem
                // fill in fields with no defaults
                job = store.CreateJob();
                job.DisableFollowingSecurityChecks();
                Dictionary <string, object> attempt = new Dictionary <string, object>();
                attempt[Schema.AttemptItem.RootActivityId] = new LearningStoreItemIdentifier(Schema.ActivityPackageItem.ItemTypeName, rootActivityId);
                attempt[Schema.AttemptItem.LearnerId]      = new LearningStoreItemIdentifier(Schema.UserItem.ItemTypeName, learnerId);
                if (learnerAssignmentId != 0)
                {
                    attempt[Schema.AttemptItem.LearnerAssignmentId] = new LearningStoreItemIdentifier("LearnerAssignmentItem", learnerAssignmentId);
                }
                attempt[Schema.AttemptItem.PackageId] = new LearningStoreItemIdentifier(Schema.PackageItem.ItemTypeName, eNav.m_packageId);
                eNav.m_attemptStartTime = DateTime.UtcNow;
                attempt[Schema.AttemptItem.StartedTimestamp]    = eNav.m_attemptStartTime;
                attempt[Schema.AttemptItem.LogDetailSequencing] = ((loggingFlags & LoggingOptions.LogDetailSequencing) == LoggingOptions.LogDetailSequencing);
                attempt[Schema.AttemptItem.LogFinalSequencing]  = ((loggingFlags & LoggingOptions.LogFinalSequencing) == LoggingOptions.LogFinalSequencing);
                attempt[Schema.AttemptItem.LogRollup]           = ((loggingFlags & LoggingOptions.LogRollup) == LoggingOptions.LogRollup);
                LearningStoreItemIdentifier attemptId = job.AddItem(Schema.AttemptItem.ItemTypeName, attempt, true);

                // create activityattemptitems for each activity in the tree
                foreach (Activity a in eNav.Traverse)
                {
                    Dictionary <string, object> activity = new Dictionary <string, object>();

                    // fill in everything that has no default
                    activity[Schema.ActivityAttemptItem.AttemptId]         = attemptId;
                    activity[Schema.ActivityAttemptItem.ActivityPackageId] = new LearningStoreItemIdentifier(Schema.ActivityPackageItem.ItemTypeName, a.ActivityId);
                    if (a.RandomPlacement >= 0)
                    {
                        activity[Schema.ActivityAttemptItem.RandomPlacement] = a.RandomPlacement;
                        // sibling activities are ordered by RandomPlacement first,
                        // then by OriginalPlacment; RandomPlacement is -1 for all siblings if not randomization occurs
                    }
                    job.AddItem(Schema.ActivityAttemptItem.ItemTypeName, activity, true);
                }
                ids = job.Execute();
                scope.Complete();
            }

            // fill in some vital data for the navigator
            eNav.m_attemptId = ((LearningStoreItemIdentifier)ids[0]).GetKey();
            int index = 1;

            foreach (Activity a in eNav.Traverse)
            {
                a.InternalActivityId = ((LearningStoreItemIdentifier)ids[index++]).GetKey();
            }

            return(eNav);
        }