예제 #1
0
        /// <summary>
        /// Adds the subfields of a score to the datamodel values to send to the client.
        /// </summary>
        private static void addDataModelScore(AddDataModelValue addDataModelValue, StringBuilder dataModelValuesBuffer, string cmiName, Score score)
        {
            string rteValue;
            float? tmpFloat;

            tmpFloat = score.Raw;
            rteValue = (tmpFloat == null) ? "" : RteDataModelConverter.RteFloatValue((float)tmpFloat);
            addDataModelValue(dataModelValuesBuffer, ResHelper.FormatInvariant("{0}.raw", cmiName), rteValue);

            tmpFloat = score.Minimum;
            rteValue = (tmpFloat == null) ? "" : RteDataModelConverter.RteFloatValue((float)tmpFloat);
            addDataModelValue(dataModelValuesBuffer, ResHelper.FormatInvariant("{0}.min", cmiName), rteValue);

            tmpFloat = score.Maximum;
            rteValue = (tmpFloat == null) ? "" : RteDataModelConverter.RteFloatValue((float)tmpFloat);
            addDataModelValue(dataModelValuesBuffer, ResHelper.FormatInvariant("{0}.max", cmiName), rteValue);
        }
예제 #2
0
        private static void AddDataModelScore(
            AddDataModelValue addDataModelValue, StringBuilder dataModelValuesBuffer, string cmiName, Score score)
        {
            float? tmpFloat = score.Raw;
            if (tmpFloat != null)
            {
                addDataModelValue(
                    dataModelValuesBuffer,
                    ResHelper.FormatInvariant("{0}.raw", cmiName),
                    RteDataModelConverter.RteFloatValue((float)tmpFloat));
            }

            tmpFloat = score.Scaled;
            if (tmpFloat != null)
            {
                addDataModelValue(
                    dataModelValuesBuffer,
                    ResHelper.FormatInvariant("{0}.scaled", cmiName),
                    RteDataModelConverter.RteFloatValue((float)tmpFloat));
            }

            tmpFloat = score.Minimum;
            if (tmpFloat != null)
            {
                addDataModelValue(
                    dataModelValuesBuffer,
                    ResHelper.FormatInvariant("{0}.min", cmiName),
                    RteDataModelConverter.RteFloatValue((float)tmpFloat));
            }

            tmpFloat = score.Maximum;
            if (tmpFloat != null)
            {
                addDataModelValue(
                    dataModelValuesBuffer,
                    ResHelper.FormatInvariant("{0}.max", cmiName),
                    RteDataModelConverter.RteFloatValue((float)tmpFloat));
            }
        }
예제 #3
0
        public override DataModelValues GetDataModelValues(AddDataModelValue addDataModelValue)
        {
            StringBuilder dataModelValuesBuffer = new StringBuilder(4096); // data model values
            StringBuilder objectiveIdMapBuffer = new StringBuilder(1000);
            string dataModelValue;
            float? tmpFloat;
            string n;

            LearningDataModel dm = this.DataModel;

            int numComments = dm.CommentsFromLearner.Count;
            addDataModelValue(
                dataModelValuesBuffer,
                "cmi.comments_from_learner._count",
                numComments.ToString(NumberFormatInfo.InvariantInfo));
            for (int i = 0; i < numComments; i++)
            {
                Comment comment = dm.CommentsFromLearner[i];
                n = XmlConvert.ToString(i);

                if (comment.CommentText != null)
                {
                    addDataModelValue(
                        dataModelValuesBuffer,
                        ResHelper.FormatInvariant("cmi.comments_from_learner.{0}.comment", n),
                        comment.CommentText);
                }

                if (comment.Location != null)
                {
                    addDataModelValue(
                        dataModelValuesBuffer,
                        ResHelper.FormatInvariant("cmi.comments_from_learner.{0}.location", n),
                        comment.Location);
                }

                if (comment.Timestamp != null)
                {
                    addDataModelValue(
                        dataModelValuesBuffer,
                        ResHelper.FormatInvariant("cmi.comments_from_learner.{0}.timestamp", n),
                        comment.Timestamp);
                }
            }
            numComments = dm.CommentsFromLms.Count;
            addDataModelValue(
                dataModelValuesBuffer,
                "cmi.comments_from_lms._count",
                numComments.ToString(NumberFormatInfo.InvariantInfo));
            for (int i = 0; i < numComments; i++)
            {
                CommentFromLms comment = dm.CommentsFromLms[i];
                n = XmlConvert.ToString(i);
                if (comment.CommentText != null)
                {
                    addDataModelValue(
                        dataModelValuesBuffer,
                        ResHelper.FormatInvariant("cmi.comments_from_lms.{0}.comment", n),
                        comment.CommentText);
                }

                if (comment.Location != null)
                {
                    addDataModelValue(
                        dataModelValuesBuffer,
                        ResHelper.FormatInvariant("cmi.comments_from_lms.{0}.location", n),
                        comment.Location);
                }

                if (comment.Timestamp != null)
                {
                    addDataModelValue(
                        dataModelValuesBuffer,
                        ResHelper.FormatInvariant("cmi.comments_from_lms.{0}.timestamp", n),
                        comment.Timestamp);
                }
            }
            addDataModelValue(
                dataModelValuesBuffer, "cmi.completion_status", GetRteCompletionStatus(dm.CompletionStatus));
            if (dm.CompletionThreshold != null)
            {
                addDataModelValue(
                    dataModelValuesBuffer,
                    "cmi.completion_threshold",
                    RteDataModelConverter.RteFloatValue((float)dm.CompletionThreshold));
            }
            addDataModelValue(
                dataModelValuesBuffer, "cmi.credit", RteDataModelConverter.GetRteCredit(dm.Credit, this.View));
            addDataModelValue(dataModelValuesBuffer, "cmi.entry", RteDataModelConverter.GetRteEntry(dm.Entry));

            if (dm.ScaledPassingScore != null)
            {
                addDataModelValue(
                    dataModelValuesBuffer,
                    "cmi.scaled_passing_score",
                    RteDataModelConverter.RteFloatValue((float)dm.ScaledPassingScore));
            }

            int numInterations = dm.Interactions.Count;
            addDataModelValue(
                dataModelValuesBuffer,
                "cmi.interactions._count",
                numInterations.ToString(NumberFormatInfo.InvariantInfo));

            int count = 0;
            foreach (Interaction interaction in dm.Interactions)
            {
                n = XmlConvert.ToString(count);

                addDataModelValue(
                    dataModelValuesBuffer, ResHelper.FormatInvariant("cmi.interactions.{0}.id", n), interaction.Id);

                if (interaction.InteractionType != null)
                {
                    addDataModelValue(
                        dataModelValuesBuffer,
                        ResHelper.FormatInvariant("cmi.interactions.{0}.type", n),
                        RteDataModelConverter.GetRteInteractionType(interaction.InteractionType));
                }

                if (interaction.Timestamp != null)
                {
                    addDataModelValue(
                        dataModelValuesBuffer,
                        ResHelper.FormatInvariant("cmi.interactions.{0}.timestamp", n),
                        interaction.Timestamp);
                }

                int numObjectivesOrig = interaction.Objectives.Count;
                int numObjectivesToClient = 0;
                for (int j = 0; j < numObjectivesOrig; j++)
                {
                    InteractionObjective obj = interaction.Objectives[j];

                    // If there is no objective id, skip it
                    if (string.IsNullOrEmpty(obj.Id))
                    {
                        continue;
                    }

                    addDataModelValue(
                        dataModelValuesBuffer,
                        ResHelper.FormatInvariant("cmi.interactions.{0}.objectives.{1}.id", n, XmlConvert.ToString(numObjectivesToClient)),
                        obj.Id);

                    numObjectivesToClient++;
                }
                addDataModelValue(
                    dataModelValuesBuffer,
                    ResHelper.FormatInvariant("cmi.interactions.{0}.objectives._count", n),
                    numObjectivesToClient.ToString(NumberFormatInfo.InvariantInfo));

                int numResponses = interaction.CorrectResponses.Count;
                addDataModelValue(
                    dataModelValuesBuffer,
                    ResHelper.FormatInvariant("cmi.interactions.{0}.correct_responses._count", n),
                    numResponses.ToString(NumberFormatInfo.InvariantInfo));
                for (int resI = 0; resI < numResponses; resI++)
                {
                    CorrectResponse response = interaction.CorrectResponses[resI];
                    if (response.Pattern != null)
                    {
                        addDataModelValue(
                            dataModelValuesBuffer,
                            ResHelper.FormatInvariant("cmi.interactions.{0}.correct_responses.{1}.pattern", n, XmlConvert.ToString(resI)),
                            response.Pattern);
                    }
                }

                if (interaction.Weighting != null)
                {
                    addDataModelValue(
                        dataModelValuesBuffer,
                        ResHelper.FormatInvariant("cmi.interactions.{0}.weighting", n),
                        RteDataModelConverter.RteFloatValue((float)interaction.Weighting));
                }

                if (interaction.LearnerResponse != null)
                {
                    addDataModelValue(
                        dataModelValuesBuffer,
                        ResHelper.FormatInvariant("cmi.interactions.{0}.learner_response", n),
                        RteDataModelConverter.GetRteLearnerResponse(interaction.LearnerResponse));
                }

                dataModelValue = this.GetRteResult(interaction.Result);
                if (dataModelValue != null)
                {
                    addDataModelValue(
                        dataModelValuesBuffer, ResHelper.FormatInvariant("cmi.interactions.{0}.result", n), dataModelValue);
                }

                if (interaction.Latency != null)
                {
                    addDataModelValue(
                        dataModelValuesBuffer,
                        ResHelper.FormatInvariant("cmi.interactions.{0}.latency", n),
                        this.GetRteTimeSpan(interaction.Latency));
                }

                if (interaction.Description != null)
                {
                    addDataModelValue(
                        dataModelValuesBuffer,
                        ResHelper.FormatInvariant("cmi.interactions.{0}.description", n),
                        interaction.Description);
                }

                count++;
            } // end interactions

            if (dm.LaunchData != null)
            {
                addDataModelValue(dataModelValuesBuffer, "cmi.launch_data", dm.LaunchData);
            }

            Learner learner = dm.Learner;
            addDataModelValue(dataModelValuesBuffer, "cmi.learner_id", learner.Id);
            addDataModelValue(dataModelValuesBuffer, "cmi.learner_name", learner.Name);
            addDataModelValue(
                dataModelValuesBuffer,
                "cmi.learner_preference.audio_level",
                learner.AudioLevel.ToString(DateTimeFormatInfo.InvariantInfo));
            addDataModelValue(
                dataModelValuesBuffer,
                "cmi.learner_preference.delivery_speed",
                learner.DeliverySpeed.ToString(NumberFormatInfo.InvariantInfo));
            addDataModelValue(dataModelValuesBuffer, "cmi.learner_preference.language", learner.Language);
            addDataModelValue(
                dataModelValuesBuffer,
                "cmi.learner_preference.audio_captioning",
                RteDataModelConverter.GetRteAudioCaptioning(learner.AudioCaptioning));

            dataModelValue = dm.Location;
            if (!string.IsNullOrEmpty(dataModelValue))
            {
                addDataModelValue(dataModelValuesBuffer, "cmi.location", dataModelValue);
            }

            if (dm.MaxTimeAllowed != null)
            {
                addDataModelValue(
                    dataModelValuesBuffer, "cmi.max_time_allowed", this.GetRteTimeSpan((TimeSpan)dm.MaxTimeAllowed));
            }

            addDataModelValue(dataModelValuesBuffer, "cmi.mode", RteDataModelConverter.GetRteMode(this.View));
            tmpFloat = dm.ProgressMeasure;
            if (tmpFloat != null)
            {
                addDataModelValue(
                    dataModelValuesBuffer, "cmi.progress_measure", RteDataModelConverter.RteFloatValue((float)tmpFloat));
            }

            int objCountOrig = dm.Objectives.Count; // num objectives in data model
            int objCountToClient = 0; // num objectives sent to client
            for (int i = 0; i < objCountOrig; i++)
            {
                Objective objective = dm.Objectives[i];

                // If the objective does not have an id, don't send it to client.
                if (string.IsNullOrEmpty(objective.Id))
                {
                    continue;
                }

                n = XmlConvert.ToString(objCountToClient);
                addDataModelValue(
                    dataModelValuesBuffer, ResHelper.FormatInvariant("cmi.objectives.{0}.id", n), objective.Id);
                addDataModelValue(objectiveIdMapBuffer, n, objective.Id);

                AddDataModelScore(
                    addDataModelValue,
                    dataModelValuesBuffer,
                    ResHelper.FormatInvariant("cmi.objectives.{0}.score", n),
                    objective.Score);
                if (objective.Description != null)
                {
                    addDataModelValue(
                        dataModelValuesBuffer,
                        ResHelper.FormatInvariant("cmi.objectives.{0}.description", n),
                        objective.Description);
                }

                addDataModelValue(
                    dataModelValuesBuffer,
                    ResHelper.FormatInvariant("cmi.objectives.{0}.completion_status", n),
                    GetRteCompletionStatus(objective.CompletionStatus));
                addDataModelValue(
                    dataModelValuesBuffer,
                    ResHelper.FormatInvariant("cmi.objectives.{0}.success_status", n),
                    GetRteSuccessStatus(objective.SuccessStatus));
                tmpFloat = objective.ProgressMeasure;
                if (tmpFloat != null)
                {
                    addDataModelValue(
                        dataModelValuesBuffer,
                        ResHelper.FormatInvariant("cmi.objectives.{0}.progress_measure", n),
                        RteDataModelConverter.RteFloatValue((float)tmpFloat));
                }

                objCountToClient++;
            }
            addDataModelValue(
                dataModelValuesBuffer,
                "cmi.objectives._count",
                objCountToClient.ToString(NumberFormatInfo.InvariantInfo));

            // Add all the cmi.score values
            AddDataModelScore(addDataModelValue, dataModelValuesBuffer, "cmi.score", dm.Score);

            if (dm.SuspendData != null)
            {
                addDataModelValue(dataModelValuesBuffer, "cmi.suspend_data", dm.SuspendData);
            }

            addDataModelValue(dataModelValuesBuffer, "cmi.success_status", GetRteSuccessStatus(dm.SuccessStatus));

            addDataModelValue(dataModelValuesBuffer, "cmi.time_limit_action", GetTimeLimitAction(dm.TimeLimitAction));

            addDataModelValue(dataModelValuesBuffer, "cmi.total_time", this.GetRteTimeSpan(dm.TotalTime));

            foreach (KeyValuePair<string, object> kvPair in dm.ExtensionData)
            {
                string name = kvPair.Key;
                string value;
                object keyValue = kvPair.Value;
                Type type = keyValue.GetType();
                if (type == typeof(double))
                {
                    var doubleValue = (double)keyValue;
                    value = doubleValue.ToString(NumberFormatInfo.InvariantInfo);
                }
                else if (type == typeof(DateTime))
                {
                    var date = (DateTime)keyValue;
                    value = RteDataModelConverter.RteDateTimeValue(date);
                }
                else
                {
                    value = keyValue.ToString();
                }
                addDataModelValue(dataModelValuesBuffer, name, value);
            }

            return new DataModelValues(
                new PlainTextString(dataModelValuesBuffer.ToString()),
                new PlainTextString(objectiveIdMapBuffer.ToString()));
        }
예제 #4
0
 /// <summary>
 /// Return the encoded string of all current data model values to pass to the client. 
 /// </summary>
 public abstract DataModelValues GetDataModelValues(AddDataModelValue addDataModelValue);
예제 #5
0
 /// <summary>
 /// Return the encoded string of all current data model values to pass to the client.
 /// </summary>
 public abstract DataModelValues GetDataModelValues(AddDataModelValue addDataModelValue);
예제 #6
0
        /// <summary>
        /// Adds the subfields of a score to the datamodel values to send to the client.
        /// </summary>
        private static void addDataModelScore(AddDataModelValue addDataModelValue, StringBuilder dataModelValuesBuffer, string cmiName, Score score)
        {
            string rteValue;
            float? tmpFloat;

            tmpFloat = score.Raw;
            rteValue = (tmpFloat == null) ? "" : RteDataModelConverter.RteFloatValue((float)tmpFloat);
            addDataModelValue(dataModelValuesBuffer, ResHelper.FormatInvariant("{0}.raw", cmiName), rteValue);

            tmpFloat = score.Minimum;
            rteValue = (tmpFloat == null) ? "" : RteDataModelConverter.RteFloatValue((float)tmpFloat);
            addDataModelValue(dataModelValuesBuffer, ResHelper.FormatInvariant("{0}.min", cmiName), rteValue);

            tmpFloat = score.Maximum;
            rteValue = (tmpFloat == null) ? "" : RteDataModelConverter.RteFloatValue((float)tmpFloat);
            addDataModelValue(dataModelValuesBuffer, ResHelper.FormatInvariant("{0}.max", cmiName), rteValue);
        }
예제 #7
0
        /// <summary>
        /// Return the encoded string of all current data model values to pass to the client. This method
        /// reinitializes the ObjectiveIndexer and InteractionIndexer values. 
        /// </summary>
        public override DataModelValues GetDataModelValues(AddDataModelValue addDataModelValue)
        {
            StringBuilder dataModelValuesBuffer = new StringBuilder(4096);  // data model values
            string n;

            LearningDataModel dm = this.DataModel;

            Learner learner = dm.Learner;
            addDataModelValue(dataModelValuesBuffer, "cmi.core.student_id", learner.Id);
            addDataModelValue(dataModelValuesBuffer, "cmi.core.student_name", learner.Name);

            // cmi.core values
            addDataModelValue(dataModelValuesBuffer, "cmi.core.lesson_location", dm.Location);
            addDataModelValue(dataModelValuesBuffer, "cmi.core.credit", GetRteCredit(dm.Credit, View));
            addDataModelValue(dataModelValuesBuffer, "cmi.core.lesson_status", GetRteLessonStatus(dm.LessonStatus));
            addDataModelValue(dataModelValuesBuffer, "cmi.core.entry", GetRteEntry(dm.Entry));

            addDataModelScore(addDataModelValue, dataModelValuesBuffer, "cmi.core.score", dm.Score);

            addDataModelValue(dataModelValuesBuffer, "cmi.core.total_time", GetRteTimeSpan(dm.TotalTime));
            addDataModelValue(dataModelValuesBuffer, "cmi.core.lesson_mode", GetRteMode(View));

            addDataModelValue(dataModelValuesBuffer, "cmi.suspend_data", dm.SuspendData);
            addDataModelValue(dataModelValuesBuffer, "cmi.launch_data", dm.LaunchData);
            addDataModelValue(dataModelValuesBuffer, "cmi.comments", GetRteComment(dm.CommentsFromLearner));
            addDataModelValue(dataModelValuesBuffer, "cmi.comments_from_lms", GetRteCommentFromLms(dm.CommentsFromLms));

            int objCountOrig = dm.Objectives.Count; // num objectives in data model
            int objCountToClient = 0;   // num objectives sent to client
            for (int i = 0; i < objCountOrig; i++)
            {
                Objective objective = dm.Objectives[i];

                n = XmlConvert.ToString(objCountToClient);
                addDataModelValue(dataModelValuesBuffer, ResHelper.FormatInvariant("cmi.objectives.{0}.id", n), objective.Id);

                addDataModelScore(addDataModelValue, dataModelValuesBuffer, ResHelper.FormatInvariant("cmi.objectives.{0}.score", n), objective.Score);

                if (objective.Status != null)
                    addDataModelValue(dataModelValuesBuffer, ResHelper.FormatInvariant("cmi.objectives.{0}.status", n), GetRteLessonStatus(objective.Status.Value));

                objCountToClient++;
            }
            addDataModelValue(dataModelValuesBuffer, "cmi.objectives._count", RteIntValue(objCountToClient));

            // cmi.student_data
            addDataModelValue(dataModelValuesBuffer, "cmi.student_data.mastery_score", GetRteFloat(dm.MasteryScore));
            addDataModelValue(dataModelValuesBuffer, "cmi.student_data.max_time_allowed", GetRteTimeSpan(dm.MaxTimeAllowed));
            addDataModelValue(dataModelValuesBuffer, "cmi.student_data.time_limit_action", GetTimeLimitAction(dm.TimeLimitAction));

            // cmi.student_preference
            addDataModelValue(dataModelValuesBuffer, "cmi.student_preference.audio", GetRteFloat(learner.AudioLevel));
            addDataModelValue(dataModelValuesBuffer, "cmi.student_preference.language", learner.Language);
            addDataModelValue(dataModelValuesBuffer, "cmi.student_preference.speed", GetRteFloat(learner.DeliverySpeed));
            addDataModelValue(dataModelValuesBuffer, "cmi.student_preference.text", GetRteAudioCaptioning(learner.AudioCaptioning));

            // Interactions
            int numInterations = dm.Interactions.Count;
            addDataModelValue(dataModelValuesBuffer, "cmi.interactions._count", numInterations.ToString(NumberFormatInfo.InvariantInfo));

            int count = 0;
            foreach (Interaction interaction in dm.Interactions)
            {
                n = XmlConvert.ToString(count);

                // Not intuitive: interaction.n.id, time, weighting, student_response and type are write only in Scorm 1.2, so don't add them here.

                int numObjectives = interaction.Objectives.Count;
                for (int j = 0; j < numObjectives; j++)
                {
                    InteractionObjective obj = interaction.Objectives[j];
                    addDataModelValue(dataModelValuesBuffer, ResHelper.FormatInvariant("cmi.interactions.{0}.objectives.{1}.id", n, RteIntValue(j)), obj.Id);
                }
                addDataModelValue(dataModelValuesBuffer, ResHelper.FormatInvariant("cmi.interactions.{0}.objectives._count", n), RteIntValue(numObjectives));

                int numResponses = interaction.CorrectResponses.Count;
                addDataModelValue(dataModelValuesBuffer, ResHelper.FormatInvariant("cmi.interactions.{0}.correct_responses._count", n), RteIntValue(numResponses));
                for (int resI = 0; resI < numResponses; resI++)
                {
                    CorrectResponse response = interaction.CorrectResponses[resI];
                    if (response.Pattern != null)
                        addDataModelValue(dataModelValuesBuffer, ResHelper.FormatInvariant("cmi.interactions.{0}.correct_responses.{1}.pattern", n, RteIntValue(resI)), response.Pattern);
                }

                count++;
            }   // end interactions

            return new DataModelValues(new PlainTextString(dataModelValuesBuffer.ToString()));
        }
예제 #8
0
        /// <summary>
        /// Return the encoded string of all current data model values to pass to the client. This method
        /// reinitializes the ObjectiveIndexer and InteractionIndexer values.
        /// </summary>
        public override DataModelValues GetDataModelValues(AddDataModelValue addDataModelValue)
        {
            StringBuilder dataModelValuesBuffer = new StringBuilder(4096); // data model values
            string        n;

            LearningDataModel dm = this.DataModel;

            Learner learner = dm.Learner;

            addDataModelValue(dataModelValuesBuffer, "cmi.core.student_id", learner.Id);
            addDataModelValue(dataModelValuesBuffer, "cmi.core.student_name", learner.Name);

            // cmi.core values
            addDataModelValue(dataModelValuesBuffer, "cmi.core.lesson_location", dm.Location);
            addDataModelValue(dataModelValuesBuffer, "cmi.core.credit", GetRteCredit(dm.Credit, this.View));
            addDataModelValue(dataModelValuesBuffer, "cmi.core.lesson_status", GetRteLessonStatus(dm.LessonStatus));
            addDataModelValue(dataModelValuesBuffer, "cmi.core.entry", GetRteEntry(dm.Entry));

            AddDataModelScore(addDataModelValue, dataModelValuesBuffer, "cmi.core.score", dm.Score);

            addDataModelValue(dataModelValuesBuffer, "cmi.core.total_time", GetRteTimeSpan(dm.TotalTime));
            addDataModelValue(dataModelValuesBuffer, "cmi.core.lesson_mode", GetRteMode(this.View));

            addDataModelValue(dataModelValuesBuffer, "cmi.suspend_data", dm.SuspendData);
            addDataModelValue(dataModelValuesBuffer, "cmi.launch_data", dm.LaunchData);
            addDataModelValue(dataModelValuesBuffer, "cmi.comments", GetRteComment(dm.CommentsFromLearner));
            addDataModelValue(dataModelValuesBuffer, "cmi.comments_from_lms", GetRteCommentFromLms(dm.CommentsFromLms));

            int objCountOrig     = dm.Objectives.Count; // num objectives in data model
            int objCountToClient = 0;                   // num objectives sent to client

            for (int i = 0; i < objCountOrig; i++)
            {
                Objective objective = dm.Objectives[i];

                n = XmlConvert.ToString(objCountToClient);
                addDataModelValue(
                    dataModelValuesBuffer, ResHelper.FormatInvariant("cmi.objectives.{0}.id", n), objective.Id);

                AddDataModelScore(
                    addDataModelValue,
                    dataModelValuesBuffer,
                    ResHelper.FormatInvariant("cmi.objectives.{0}.score", n),
                    objective.Score);

                if (objective.Status != null)
                {
                    addDataModelValue(
                        dataModelValuesBuffer,
                        ResHelper.FormatInvariant("cmi.objectives.{0}.status", n),
                        GetRteLessonStatus(objective.Status.Value));
                }

                objCountToClient++;
            }
            addDataModelValue(dataModelValuesBuffer, "cmi.objectives._count", RteIntValue(objCountToClient));

            // cmi.student_data
            addDataModelValue(dataModelValuesBuffer, "cmi.student_data.mastery_score", GetRteFloat(dm.MasteryScore));
            addDataModelValue(
                dataModelValuesBuffer, "cmi.student_data.max_time_allowed", GetRteTimeSpan(dm.MaxTimeAllowed));
            addDataModelValue(
                dataModelValuesBuffer, "cmi.student_data.time_limit_action", GetTimeLimitAction(dm.TimeLimitAction));

            // cmi.student_preference
            addDataModelValue(dataModelValuesBuffer, "cmi.student_preference.audio", GetRteFloat(learner.AudioLevel));
            addDataModelValue(dataModelValuesBuffer, "cmi.student_preference.language", learner.Language);
            addDataModelValue(dataModelValuesBuffer, "cmi.student_preference.speed", GetRteFloat(learner.DeliverySpeed));
            addDataModelValue(
                dataModelValuesBuffer, "cmi.student_preference.text", GetRteAudioCaptioning(learner.AudioCaptioning));

            // Interactions
            int numInterations = dm.Interactions.Count;

            addDataModelValue(
                dataModelValuesBuffer,
                "cmi.interactions._count",
                numInterations.ToString(NumberFormatInfo.InvariantInfo));

            int count = 0;

            foreach (Interaction interaction in dm.Interactions)
            {
                n = XmlConvert.ToString(count);

                // Not intuitive: interaction.n.id, time, weighting, student_response and type are write only in Scorm 1.2, so don't add them here.

                int numObjectives = interaction.Objectives.Count;
                for (int j = 0; j < numObjectives; j++)
                {
                    InteractionObjective obj = interaction.Objectives[j];
                    addDataModelValue(
                        dataModelValuesBuffer,
                        ResHelper.FormatInvariant("cmi.interactions.{0}.objectives.{1}.id", n, RteIntValue(j)),
                        obj.Id);
                }
                addDataModelValue(
                    dataModelValuesBuffer,
                    ResHelper.FormatInvariant("cmi.interactions.{0}.objectives._count", n),
                    RteIntValue(numObjectives));

                int numResponses = interaction.CorrectResponses.Count;
                addDataModelValue(
                    dataModelValuesBuffer,
                    ResHelper.FormatInvariant("cmi.interactions.{0}.correct_responses._count", n),
                    RteIntValue(numResponses));
                for (int resI = 0; resI < numResponses; resI++)
                {
                    CorrectResponse response = interaction.CorrectResponses[resI];
                    if (response.Pattern != null)
                    {
                        addDataModelValue(
                            dataModelValuesBuffer,
                            ResHelper.FormatInvariant("cmi.interactions.{0}.correct_responses.{1}.pattern", n, RteIntValue(resI)),
                            response.Pattern);
                    }
                }

                count++;
            } // end interactions

            return(new DataModelValues(new PlainTextString(dataModelValuesBuffer.ToString())));
        }