SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")] // arguments are validated public void ProcessPageLoad(HttpResponse response, PackageStore packageStore, TryGetViewInfo TryGetViewInfo, TryGetAttemptInfo TryGetAttemptInfo, ProcessViewRequest ProcessViewRequest, RegisterError RegisterError, string submitPageLinkText) { FramesetUtil.ValidateNonNullParameter("packageStore", packageStore); FramesetUtil.ValidateNonNullParameter("TryGetViewInfo", TryGetViewInfo); FramesetUtil.ValidateNonNullParameter("TryGetAttemptInfo", TryGetAttemptInfo); FramesetUtil.ValidateNonNullParameter("RegisterError", RegisterError); m_response = response; m_submitPageLinkText = submitPageLinkText; AttemptItemIdentifier attemptId; SessionView view; if (!TryGetViewInfo(true, out view)) return; // This is an attempt-based session if (!TryGetAttemptInfo(true, out attemptId)) { return; } m_session = new StoredLearningSession(view, new AttemptItemIdentifier(attemptId), packageStore); // If user cannot access the session, then remove the reference to the session. if (!ProcessViewRequest(view, m_session)) m_session = null; }
[SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")] // parameter is validated public static RteDataModelConverter Create(LearningSession session) { FramesetUtil.ValidateNonNullParameter("session", session); switch (session.PackageFormat) { case PackageFormat.V1p2: case PackageFormat.Lrm: return new Rte1p2DataModelConverter(session.View, session.CurrentActivityDataModel); case PackageFormat.V1p3: return new Rte2004DataModelConverter(session.View, session.CurrentActivityDataModel); } return null; }
/// <summary> /// Delegate to allow BWP to take action after posted data is processed. /// </summary> /// <param name="session"></param> public void ProcessPostedDataComplete(LearningSession session) { // Do nothing }
/// <summary> /// Allow the application to modify the RenderContext before content is rendered. /// </summary> /// <param name="context">The context to render. Note: If app needs to change context.Script, /// it should do so by adding to the scriptBlock buffer. </param> /// <param name="scriptBlock">The script that will be written in the onLoad handler of LRM content. /// If this value is null, then the app /// cannot modify the onload script. (This happens when the resource being rendered is not /// the primary resource of an activity that is in LRM format.)</param> /// <param name="session">The session in which content is being rendered.</param> public void UpdateRenderContext(RenderContext context, StringBuilder scriptBlock, LearningSession session) { // Set values other than Response and RelativePath context.EmbeddedUIResourcePath = new Uri(Request.Url, "Images/"); // Set values that map to file extensions SetMappings(context.MimeTypeMapping, context.IisCompatibilityModeExtensions); if (scriptBlock == null) // This is not the primary resource, so nothing else matters { return; } // Basic Web Player never shows correct answers or reviewer info context.ShowCorrectAnswers = false; context.ShowReviewerInformation = false; }
/// <summary> /// Allow application to process posted data. /// </summary> public bool ProcessPostedData( LearningSession session, HttpRequest request, Dictionary<string, HttpPostedFile> fileCollection) { // Verify that posted files map to files that actually exist. HttpFileCollection files = request.Files; StringBuilder messageBuffer = new StringBuilder(); bool firstError = true; foreach (string fileId in files) { HttpPostedFile postedFile = files[fileId]; string filename = postedFile.FileName; // If contentLength == 0 and fileName == emptyString, then this is probably a posting after // the initial file posting. (For instance, to remove the file.) This is a valid file and is added to the // collection. // If the contentLength == 0 and fileName != emptyString, then user is trying to attach a file // that has no contents. This is not allowed. if ((string.IsNullOrEmpty(filename) && (postedFile.ContentLength == 0)) || (!string.IsNullOrEmpty(filename) && (postedFile.ContentLength > 0))) { fileCollection.Add(fileId, postedFile); } else { // This is not a valid file. if (firstError) { messageBuffer.Append( Localization.GetMessage("CON_AttachedFileDoesNotExistHtml")); messageBuffer.Append("\r\n<br><br><ul>\r\n"); firstError = false; } messageBuffer.AppendFormat("<li>{0}</li>", HttpUtility.HtmlEncode(filename)); } } if (!firstError) { messageBuffer.Append("</ul><br>"); messageBuffer.Append(Localization.GetMessage("CON_FileAttachmentErrorEndHtml")); // Add information for the 'Continue' link JScriptString js = new JScriptString( ResHelper.FormatInvariant( "API_GetFramesetManager().DoChoice(\"{0}\");", FramesetUtil.GetStringInvariant(session.CurrentActivityId))); messageBuffer.AppendFormat( CultureInfo.CurrentCulture, "<br><br><a href='{0}' >{1}</a>", js.ToJavascriptProtocol(), HttpUtility.HtmlEncode(Localization.GetMessage("HID_ReloadCurrentContent"))); this.RegisterError( Localization.GetMessage("CON_FileAttachmentErrorTitleHtml"), messageBuffer.ToString(), false); } return true; }
/// <summary> /// Create a context to send to an RloHandler when calling <c>RloHandler.Render</c>. /// </summary> /// <param name="session">The session that is being rendered.</param> /// <param name="renderContext">Information required to render the current file. /// </param> internal RloRenderContext(LearningSession session, RenderContext renderContext) : base(session) { m_context = renderContext; }
internal RloReactivateContext(LearningSession session, ReactivateSettings settings) : base(session) { m_resetPoints = ((settings & ReactivateSettings.ResetEvaluationPoints) != 0); m_resetComments = ((settings & ReactivateSettings.ResetEvaluationComments) != 0); }
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] // exceptions caught, added to event log protected void Page_Load(object sender, EventArgs e) { try { SlkUtilities.RetryOnDeadlock(delegate() { //Initialize data that may need to be reset on retry Response.Clear(); ClearError(); m_sessionEnded = false; m_hiddenHelper = new HiddenHelper(Request, Response, SlkEmbeddedUIPath); m_hiddenHelper.ProcessPageLoad(SlkStore.PackageStore, GetSessionTitle, TryGetSessionView, TryGetAttemptId, AppendContentFrameDetails, RegisterError, GetErrorInfo, ProcessSessionEnd, ProcessViewRequest, GetMessage, IsPostBack); // Send assignment information to client. If the session has ended, then force a reload of the current // assignment properties. Otherwise, the cached value will have required info so no need to re-query database. LearnerAssignmentProperties la = GetLearnerAssignment(SessionEnded); // Add assignment information to the hidden controls HiddenControlInfo hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = new PlainTextString(HiddenFieldNames.LearnerAssignmentId); hiddenCtrlInfo.Value = new PlainTextString(FramesetUtil.GetStringInvariant(la.LearnerAssignmentId.GetKey())); hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString(ResHelper.Format("slkMgr.LearnerAssignmentId = document.getElementById({0}).value;", JScriptString.QuoteString(HiddenFieldNames.LearnerAssignmentId, false))); m_hiddenHelper.HiddenControls.Add(hiddenCtrlInfo); // Learner assignment status ('not started', 'in progress', etc) hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.Id = new PlainTextString(HiddenFieldNames.LearnerAssignmentStatus); hiddenCtrlInfo.Value = new PlainTextString(SlkUtilities.GetLearnerAssignmentState(la.Status)); hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString(ResHelper.Format("slkMgr.Status = document.getElementById({0}).value;", JScriptString.QuoteString(HiddenFieldNames.LearnerAssignmentStatus, false))); m_hiddenHelper.HiddenControls.Add(hiddenCtrlInfo); hiddenCtrlInfo = new HiddenControlInfo(); if (la.FinalPoints != null) { // finalPoints is passed in invariant culture, as a float hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString(ResHelper.Format("slkMgr.FinalPoints = {0};", Convert.ToString(la.FinalPoints, CultureInfo.InvariantCulture.NumberFormat))); } else { hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString("slkMgr.FinalPoints = null;"); } m_hiddenHelper.HiddenControls.Add(hiddenCtrlInfo); // Send information about total points (ie, computed points on the client). This is called 'graded score' in // grading page. LearningSession session = m_hiddenHelper.Session; if (session != null) { hiddenCtrlInfo = new HiddenControlInfo(); if (session.TotalPoints != null) { // TotalPoints is passed in current culture, as a string JScriptString totalPointsValue = JScriptString.QuoteString(Convert.ToString(session.TotalPoints, CultureInfo.CurrentCulture.NumberFormat), false); hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString(ResHelper.Format("slkMgr.ComputedPoints = {0};", totalPointsValue)); } else { hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString("slkMgr.ComputedPoints = \"\";"); } m_hiddenHelper.HiddenControls.Add(hiddenCtrlInfo); if (session.SuccessStatus != SuccessStatus.Unknown) { hiddenCtrlInfo = new HiddenControlInfo(); hiddenCtrlInfo.FrameManagerInitializationScript = new JScriptString(ResHelper.Format("slkMgr.PassFail = {0};\r\n", JScriptString.QuoteString(((session.SuccessStatus == SuccessStatus.Passed) ? "passed" : "failed"), false))); m_hiddenHelper.HiddenControls.Add(hiddenCtrlInfo); } } }); } catch (Exception ex) { ClearError(); // Unexpected exceptions are not shown to user SlkStore.LogError(FramesetResources.FRM_UnknownExceptionMsg, ex.ToString()); RegisterError(ResHelper.GetMessage(FramesetResources.FRM_UnknownExceptionTitle), ResHelper.GetMessage(SlkFrameset.FRM_UnexpectedExceptionMsg), false); } }
SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")] // parameter is validated public void ProcessSessionEnd(LearningSession session, ref string messageTitle, ref string message) { FramesetUtil.ValidateNonNullParameter("session", session); // If we have already been here, then there is nothing more to do. if (SessionEnded) { return; } LearnerAssignmentProperties la = GetLearnerAssignment(); // Session ending results in message shown to the user. if (session.View == SessionView.Execute) { StoredLearningSession slsSession = session as StoredLearningSession; if (slsSession != null) { // The rollup and/or sequencing process may have changed the state of the attempt. If so, there are some cases // that cannot continue so show an error message. switch (slsSession.AttemptStatus) { case AttemptStatus.Abandoned: messageTitle = SlkFrameset.HID_SessionAbandonedTitle; message = SlkFrameset.HID_ExecuteViewAbandonedSessionMsg; SessionEnded = true; break; case AttemptStatus.Completed: messageTitle = SlkFrameset.HID_SessionCompletedTitle; message = SlkFrameset.HID_ExecuteViewCompletedSessionMsg; SessionEnded = true; break; case AttemptStatus.Suspended: messageTitle = SlkFrameset.HID_SessionSuspendedTitle; message = SlkFrameset.HID_ExecuteViewSuspendedSessionMsg; // Do not set SessionEnded -- the session being suspended does not warrant ending the learner assignment break; } } if (SessionEnded) { // Call FinishLearnerAssignment since the attempt has already been completed. SlkStore.FinishLearnerAssignment(LearnerAssignmentGuidId); } } else if (session.View == SessionView.RandomAccess) { messageTitle = SlkFrameset.HID_GradingFinishedTitle; message = SlkFrameset.HID_GradingFinishedMessage; StringBuilder sb = new StringBuilder(1000); sb.Append(message); sb.Append("<br><script>"); // Write the assignment status to slkFrameMgr WriteSlkMgrInit(sb); sb.AppendLine("slkMgr = Slk_GetSlkManager();"); sb.AppendFormat("slkMgr.LearnerAssignmentId = {0};\r\n", JScriptString.QuoteString(FramesetUtil.GetStringInvariant(la.LearnerAssignmentId.GetKey()), false)); sb.AppendFormat("slkMgr.Status = {0};\r\n", JScriptString.QuoteString(SlkUtilities.GetLearnerAssignmentState(la.Status), false)); if (AssignmentView == AssignmentView.Grading) { string finalPointsValue = "null"; float? finalPoints = la.FinalPoints; if (finalPoints != null) { finalPointsValue = Convert.ToString(finalPoints.Value, CultureInfo.InvariantCulture.NumberFormat); } sb.AppendFormat("slkMgr.FinalPoints = {0};\r\n", finalPointsValue); } // Send information about total points (ie, computed points on the client). if (session != null) { if (session.TotalPoints != null) { sb.AppendFormat("slkMgr.ComputedPoints = {0};\r\n", JScriptString.QuoteString(Convert.ToString(session.TotalPoints, CultureInfo.CurrentCulture.NumberFormat), false)); } else { sb.AppendFormat("slkMgr.ComputedPoints = \"\";\r\n"); } if (session.SuccessStatus != SuccessStatus.Unknown) { sb.AppendFormat("slkMgr.PassFail = {0};\r\n", JScriptString.QuoteString(((session.SuccessStatus == SuccessStatus.Passed) ? "passed" : "failed"), false)); } } } }
/// <summary> /// Allow application to process posted data. /// </summary> public bool ProcessPostedData( LearningSession session, HttpRequest request, Dictionary <string, HttpPostedFile> fileCollection) { // Verify that posted files map to files that actually exist. HttpFileCollection files = request.Files; StringBuilder messageBuffer = new StringBuilder(); bool firstError = true; foreach (string fileId in files) { HttpPostedFile postedFile = files[fileId]; string filename = postedFile.FileName; // If contentLength == 0 and fileName == emptyString, then this is probably a posting after // the initial file posting. (For instance, to remove the file.) This is a valid file and is added to the // collection. // If the contentLength == 0 and fileName != emptyString, then user is trying to attach a file // that has no contents. This is not allowed. if ((string.IsNullOrEmpty(filename) && (postedFile.ContentLength == 0)) || (!string.IsNullOrEmpty(filename) && (postedFile.ContentLength > 0))) { fileCollection.Add(fileId, postedFile); } else { // This is not a valid file. if (firstError) { messageBuffer.Append( Localization.GetMessage("CON_AttachedFileDoesNotExistHtml")); messageBuffer.Append("\r\n<br><br><ul>\r\n"); firstError = false; } messageBuffer.AppendFormat("<li>{0}</li>", HttpUtility.HtmlEncode(filename)); } } if (!firstError) { messageBuffer.Append("</ul><br>"); messageBuffer.Append(Localization.GetMessage("CON_FileAttachmentErrorEndHtml")); // Add information for the 'Continue' link JScriptString js = new JScriptString( ResHelper.FormatInvariant( "API_GetFramesetManager().DoChoice(\"{0}\");", FramesetUtil.GetStringInvariant(session.CurrentActivityId))); messageBuffer.AppendFormat( CultureInfo.CurrentCulture, "<br><br><a href='{0}' >{1}</a>", js.ToJavascriptProtocol(), HttpUtility.HtmlEncode(Localization.GetMessage("HID_ReloadCurrentContent"))); this.RegisterError( Localization.GetMessage("CON_FileAttachmentErrorTitleHtml"), messageBuffer.ToString(), false); } return(true); }
public void setSession(LearningSession session) { this.curSession = session; }
public void KristalTest() { _db = new EntityMapperDbContext(); _db = new EntityMapperDbContext(); var sources = _db.TestDatas.Where(t => t.Source.Trim() != "").Select(t => t.Source).ToList(); var destinations = _db.TestDatas.Where(t => t.Destination.Trim() != "").Select(t => t.Destination).ToList(); var _authAdapter = new IdentityAuthAdapter(); var _sourceIds = new List <int>(); var _destinationIds = new List <int>(); var domainCrud = new EfRepository <Domain>(_db, _authAdapter); var domain = domainCrud.Add(new Domain { Name = "Fruit", Active = true }); var systemCrud = new EfRepository <global::Data.Models.System>(_db, _authAdapter); var sourceSystem = systemCrud.Add(new global::Data.Models.System { Domain = domain, Name = "Functions", Active = true }); var destinationSystem = systemCrud.Add(new global::Data.Models.System { Domain = domain, Name = "Tables", Active = true }); var _sourceSystemId = sourceSystem.Id; var _destinationSystemId = destinationSystem.Id; foreach (var source in sources) { var entityCrud = new EfRepository <Entity>(_db, _authAdapter); var entity = entityCrud.Add(new Entity { SystemId = _sourceSystemId, Name = source.Trim(), Active = true }); _sourceIds.Add(entity.Id); } foreach (var destination in destinations) { var entityCrud = new EfRepository <Entity>(_db, _authAdapter); var entity = entityCrud.Add(new Entity { SystemId = _destinationSystemId, Name = destination.Trim(), Active = true }); _destinationIds.Add(entity.Id); } var _logger = new InMemoryLogger(); var _entityMappingCrud = new EfRepository <EntityMapping>(_db, _authAdapter); var _repo = new EntityMappingRepository(_entityMappingCrud, _logger, null, null); var learningSession = new LearningSession(new UntrainedData { Sources = _db.Entities.Where(t => _sourceIds.Contains(t.Id)).Select(t => t.Name).ToList(), Destinations = _db.Entities.Where(t => _destinationIds.Contains(t.Id)).Select(t => t.Name).ToList() }); var result = learningSession.StartLearning(); _repo.CreateMapping(new AutomatedMapping { LearningResult = result, SourceId = _sourceSystemId, DestinationId = _destinationSystemId }); //var learningSession = new LearningSession(new UntrainedData //{ // Sources = sources, // Destinations = destinations //}); //var result = learningSession.StartLearning().Select(t => t.Mapping).ToList(); var resultText = string.Join(@"\n", result.Select(t => t.Mapping).ToList().Select(t => t.Source + " - " + t.Destination).ToList()); Assert.NotNull(resultText); }
[SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")] // parameters are validated public void ProcessPageLoad(PackageStore packageStore, TryGetViewInfo TryGetViewInfo, TryGetAttemptInfo TryGetAttemptInfo, ProcessViewRequest ProcessViewRequest) { // These should never be a problem, however fxcop complains about them. FramesetUtil.ValidateNonNullParameter("TryGetViewInfo", TryGetViewInfo); FramesetUtil.ValidateNonNullParameter("TryGetAttemptInfo", TryGetAttemptInfo); FramesetUtil.ValidateNonNullParameter("ProcessViewRequest", ProcessViewRequest); FramesetUtil.ValidateNonNullParameter("packageStore", packageStore); // Session information that may be required SessionView view; AttemptItemIdentifier attemptId; // not required for all views // Get View information. It determines what else to look for. if (!TryGetViewInfo(true, out view)) { return; } // Based on View, request other information switch (view) { case SessionView.Execute: { // AttemptId is required if (!TryGetAttemptInfo(true, out attemptId)) { return; } // Create the session m_session = new StoredLearningSession(view, attemptId, packageStore); StoredLearningSession slsSession = m_session as StoredLearningSession; if (!ProcessViewRequest(SessionView.Execute, slsSession)) { if (slsSession.AttemptStatus == AttemptStatus.Completed) { } return; } // If the attempt id appeared valid (that is, it was numeric), but does not represent a valid // attempt, the call to access AttemptStatus on the session will trigger an InvalidOperationException // containing a message for the user that the attempt id was not valid. switch (slsSession.AttemptStatus) { case AttemptStatus.Abandoned: { // Can't do execute view on abandoned sessions. The application should have handled this // in the ProcessViewRequest. return; } case AttemptStatus.Active: { // Check if it's started. If not, try starting it and forcing selection of a current activity. if (!slsSession.HasCurrentActivity) { try { slsSession.Start(false); slsSession.CommitChanges(); } catch (SequencingException) { // Intentionally ignored. This means it was either already started or could not // select an activity. In either case, just let the content frame ask the user to // deal with selecting an activity. } } else { // If the current activity is not active, then it's possible the frameset was removed from the // user and the content suspended the current activity. In that case, we do this little trick // and try suspending all the activities and then resuming them. The resume will simply resume // all the activities between the current activity and the root. Other suspended activities // will not be affected. if (!slsSession.CurrentActivityIsActive) { slsSession.Suspend(); slsSession.Resume(); slsSession.CommitChanges(); } } } break; case AttemptStatus.Completed: { // Can't do execute view on completed sessions. The application should have handled this in the // ProcessViewRequest. return; } case AttemptStatus.Suspended: { // Resume it slsSession.Resume(); slsSession.CommitChanges(); } break; default: break; } } break; case SessionView.RandomAccess: { // AttemptId is required if (!TryGetAttemptInfo(true, out attemptId)) { return; } StoredLearningSession slsSession = new StoredLearningSession(SessionView.RandomAccess, attemptId, packageStore); m_session = slsSession; if (!ProcessViewRequest(SessionView.RandomAccess, slsSession)) { return; } // Move to the first activity with a resource. PostableFrameHelper.MoveToNextActivity(m_session); } break; case SessionView.Review: { // AttemptId is required if (!TryGetAttemptInfo(true, out attemptId)) { return; } // Create the session StoredLearningSession slsSession = new StoredLearningSession(view, attemptId, packageStore); m_session = slsSession; if (!ProcessViewRequest(SessionView.Review, m_session)) { return; } // Access a property. If the user doesn't have permission, this will throw exception if (m_session.HasCurrentActivity) { // This is good. The 'if' statement is here to make compiler happy. } } break; } }
/// <summary> /// Gets the title to display in the session. /// </summary> public PlainTextString GetSessionTitle(LearningSession session) { return new PlainTextString(session.Title); }
/// <summary> /// Gets the title to display in the session. /// </summary> public PlainTextString GetSessionTitle(LearningSession session) { return(new PlainTextString(session.Title)); }
/// <summary> /// Allows the app to take action when the session is ending. /// </summary> public void ProcessSessionEnd(LearningSession session, ref string messageTitle, ref string message) { // Session ending results in message shown to the user. if (session.View == SessionView.Execute) { var slsSession = session as StoredLearningSession; if (slsSession != null) { // The rollup and/or sequencing process may have changed the state of the attempt. If so, there are some cases // that cannot continue so show an error message. switch (slsSession.AttemptStatus) { case AttemptStatus.Abandoned: messageTitle = Localization.GetMessage("HID_SessionAbandonedTitle"); message = Localization.GetMessage("FRM_ExecuteViewAbandonedSessionMsg"); break; case AttemptStatus.Completed: AttemptResult attemptResult; try { attemptResult = ServicesProxy.Instance.TestingService.GetResult(slsSession.AttemptId.GetKey()); } catch (InvalidOperationException) { attemptResult = null; } try { ServicesProxy.Instance.LmsService.Inform(TestingNotifications.TestCompleted, attemptResult); } catch (Exception) { // NOTE: do not handle event, just ignore it. } messageTitle = Localization.GetMessage("HID_SessionCompletedTitle"); message = Localization.GetMessage("FRM_ExecuteViewCompletedSessionMsg"); break; case AttemptStatus.Suspended: messageTitle = Localization.GetMessage("HID_SessionSuspendedTitle"); message = Localization.GetMessage("FRM_ExecuteViewSuspendedSessionMsg"); break; } } } }
private LearningDataModel m_learningDataModel; // only used if m_session is null /// <summary> /// Create a context to send to an RloHandler. /// </summary> /// <param name="session">The session that is being rendered.</param> internal RloProcessFormDataContext(LearningSession session) { m_session = session; }
/// <summary> /// Allow the application to modify the RenderContext before content is rendered. /// </summary> /// <param name="context">The context to render. Note: If app needs to change context.Script, /// it should do so by adding to the scriptBlock buffer. </param> /// <param name="scriptBlock">The script that will be written in the onLoad handler of LRM content. /// If this value is null, then the app /// cannot modify the onload script. (This happens when the resource being rendered is not /// the primary resource of an activity that is in LRM format.)</param> /// <param name="session">The session in which content is being rendered.</param> public void UpdateRenderContext(RenderContext context, StringBuilder scriptBlock, LearningSession session) { // Set values other than Response and RelativePath context.EmbeddedUIResourcePath = new Uri(this.Request.Url, "Images/"); // Set values that map to file extensions this.SetMappings(context.MimeTypeMapping, context.IisCompatibilityModeExtensions); // This is not the primary resource, so nothing else matters if (scriptBlock == null) { return; } // Basic Web Player never shows correct answers or reviewer info context.ShowCorrectAnswers = false; context.ShowReviewerInformation = false; }
internal RloDataModelContext(LearningSession session) { m_session = session; }
public LearningState() { Session = new LearningSession(); TokenSource = new CancellationTokenSource(); }