public ActionResult LessonDetails(string id) { if (NeedLogin()) { return(LoginRedir()); } var lesson = LessonsCtrl.Get(id); if (lesson == null) { return(new HttpNotFoundResult()); } if (!IsAdmin()) { if (!AllowedLessons(CurrentUserEmail()).Contains(lesson.LessonID)) { return(RedirectToAction("Lessons")); } } var lessonTurns = LessonsCtrl.DBConn().FindTurns(lesson.LessonID, null); var modelObj = new ExpandoObject(); var modelDict = (IDictionary <string, object>)modelObj; modelDict["Lesson"] = lesson; modelDict["Turns"] = lessonTurns; return(View("LessonDetail", modelObj)); }
public ActionResult Lessons() { if (NeedLogin()) { return(LoginRedir()); } var lessons = new List <Lesson>(); //Only lessons we're allowed to see bool admin = IsAdmin(); HashSet <string> allowedLessons = null; if (!admin) { //Only populate allowedLessons if we're not admin allowedLessons = AllowedLessons(CurrentUserEmail()); } foreach (Lesson le in LessonsCtrl.Get()) { if (admin || allowedLessons.Contains(le.LessonID)) { lessons.Add(le); } } var modelObj = new ExpandoObject(); var modelDict = (IDictionary <string, object>)modelObj; modelDict["Lessons"] = lessons; modelDict["AnswerTots"] = LessonsCtrl.DBConn().FindLessonAnswerTots(); return(View("Lessons", modelObj)); }
public ActionResult StudentLessonDevSelect() { if (NeedLogin()) { return(LoginRedir()); } if (!IsAdmin()) { return(RedirectToAction("Lessons")); } var turns = new List <ExpandoObject>(); foreach (var turn in LessonsCtrl.DBConn().FindTurnSummary()) { turns.Add(new ExpandoObject()); var turnDict = (IDictionary <string, object>)turns.Last(); turnDict["LessonID"] = turn.Item1; turnDict["UserID"] = turn.Item2; turnDict["TurnCount"] = turn.Item3; } var modelObj = new ExpandoObject(); var modelDict = (IDictionary <string, object>)modelObj; modelDict["Turns"] = turns; return(View("StudentLessonDevSelect", modelObj)); }
public ActionResult StudentLessonDevView(string id, string id2) { if (NeedLogin()) { return(LoginRedir()); } string lessonID = Util.RenderHelp.URIDecode(id); string userID = Util.RenderHelp.URIDecode(id2); if (!IsAdmin()) { if (!AllowedLessons(CurrentUserEmail()).Contains(lessonID)) { return(RedirectToAction("StudentLessonDevSelect")); } } var lesson = LessonsCtrl.Get(lessonID); if (lesson == null) { return(RedirectToAction("StudentLessonDevSelect")); } var student = StudentsCtrl.Get(userID); if (student == null) { return(RedirectToAction("StudentLessonDevSelect")); } var turns = StudentsCtrl.DBConn().FindTurns(lessonID, userID); if (turns == null || turns.Count < 1) { return(RedirectToAction("StudentLessonDevSelect")); } var modelObj = new ExpandoObject(); var modelDict = (IDictionary <string, object>)modelObj; modelDict["ID"] = id; modelDict["ID2"] = id2; modelDict["LessonID"] = lessonID; modelDict["LessonName"] = lesson.ShortName; modelDict["UserID"] = userID; modelDict["Details"] = turns[0]; return(View("StudentLessonDevView", modelObj)); }
public ActionResult StudentLessonDrill(string id, string id2) { if (NeedLogin()) { return(LoginRedir()); } string lessonID = Util.RenderHelp.URIDecode(id); string userID = Util.RenderHelp.URIDecode(id2); if (!IsAdmin()) { if (!AllowedLessons(CurrentUserEmail()).Contains(lessonID)) { return(RedirectToAction("Lessons")); } } var lesson = LessonsCtrl.Get(lessonID); if (lesson == null) { return(RedirectToAction("Lessons")); } var student = StudentsCtrl.Get(userID); if (student == null) { return(RedirectToAction("Students")); } var turns = StudentsCtrl.DBConn().FindTurns(lessonID, userID); var detailLog = new List <ExpandoObject>(); if (turns == null || turns.Count < 1 || turns[0].Turns == null || turns[0].Turns.Count < 1) { detailLog.Add(DetailLogEntry(student, "No information")); } else { var details = turns[0]; string lastQuestion = "???"; string lastDiff = "M"; foreach (var turn in details.Turns) { if (turn.TurnID == StudentLessonActs.TURN_ID_START) { detailLog.Add(DetailLogEntry(student, "Start of Lesson Attempt", "Attempt", entry: turn)); } bool completion = false; //The ignore-case comparison we use const StringComparison CMP = StringComparison.InvariantCultureIgnoreCase; foreach (var act in turn.AllValidActions()) { if (String.Equals(act.Agent, "System", CMP)) { if (String.Equals(act.Act, "Display", CMP) && !String.IsNullOrWhiteSpace(act.Data)) { lastQuestion = act.Data; } if (String.Equals(act.Act, "End", CMP)) { completion = true; } } } string evt = null; bool correct = false; bool incorrect = false; if (turn.Input != null) { evt = turn.Input.Event; if (evt != null) { evt = evt.Trim().ToLowerInvariant(); if (evt == "correct") { correct = true; } else if (evt.StartsWith("incorrect")) { incorrect = true; } } } if (correct) { detailLog.Add(DetailLogEntry(student, "CORRECT", "Answer", lastQuestion, turn)); } else if (incorrect) { detailLog.Add(DetailLogEntry(student, "MISS", "Answer", lastQuestion, turn)); } if (turn.Transitions != null && turn.Transitions.Count > 0) { foreach (var tran in turn.Transitions) { string ruleID = tran.RuleID; if (String.IsNullOrWhiteSpace(ruleID)) { continue; } ruleID = ruleID.Trim().ToLowerInvariant(); //lastDiff string newState = null; if (ruleID.EndsWith("easy")) { newState = "E"; } else if (ruleID.EndsWith("medium")) { newState = "M"; } else if (ruleID.EndsWith("hard")) { newState = "H"; } if (newState != null && newState != lastDiff) { detailLog.Add(DetailLogEntry(student, lastDiff + " to " + newState, "PathChange", entry: turn)); lastDiff = newState; } } } if (completion) { detailLog.Add(DetailLogEntry(student, "Completed Lesson", "Completion", entry: turn)); } } } var modelObj = new ExpandoObject(); var modelDict = (IDictionary <string, object>)modelObj; modelDict["ID"] = id; modelDict["ID2"] = id2; modelDict["LessonID"] = lessonID; modelDict["LessonName"] = lesson.ShortName; modelDict["UserID"] = userID; modelDict["DetailLog"] = detailLog; modelDict["BlindTarget"] = student.FirstName; return(View("StudentLessonDrill", modelObj)); }
public ActionResult ClassDetails(string id) { if (NeedLogin()) { return(LoginRedir()); } var clazz = ClassesCtrl.Get(id); if (clazz == null) { return(new HttpNotFoundResult()); } if (!IsAdmin()) { if (!clazz.IsATeacher(CurrentUserEmail())) { //Don't have rights to this class return(RedirectToAction("Classes")); } } //Don't allow null lists if (clazz.Lessons == null) { clazz.Lessons = new List <string>(); } if (clazz.Students == null) { clazz.Students = new List <string>(); } //SPECIAL: if this is a memphis class with test in the name, we do some filtering if (clazz.Location.ToLower().Contains("memphis") && clazz.ClassID.ToLower().Contains("test")) { //No carl, test, or non-alpha students then... //Sort by len and take top 10 var nonAlpha = new System.Text.RegularExpressions.Regex("[^A-Z,a-z]+"); clazz.Students = clazz.Students .Where(s => !(s.Contains("carl") || s.Contains("test") || nonAlpha.IsMatch(s))) .OrderByDescending(s => s.Length) .Take(10) .ToList(); //only lessons that match lessonN where N is a number var lessonMatch = new System.Text.RegularExpressions.Regex("lesson[0-9]+"); clazz.Lessons = clazz.Lessons.Where(l => lessonMatch.IsMatch(l)).ToList(); } //Sort info in the class for display purposes //Students are easy to sort, but we need a special sort for lessons clazz.Lessons = clazz.Lessons.OrderBy(x => Utils.LessonIDSort(x)).ToList(); clazz.Students.Sort(); var lessons = new HashSet <String>(clazz.Lessons); var students = new HashSet <String>(clazz.Students); //Make dictionary of lesson:user var lookup = new Dictionary <Tuple <string, string>, StudentLessonActs>(); if (lessons.Count > 0 && students.Count > 0) { foreach (var turns in LessonsCtrl.DBConn().FindTurnsForStudents(students)) { if (!students.Contains(turns.UserID) || !lessons.Contains(turns.LessonID)) { continue; //Nope } var key = new Tuple <string, string>(turns.LessonID, turns.UserID); lookup[key] = turns; } } //Calculate user and lessons average: first get totals and then //calculate the averages. This seemingly strange method means we //only need to perform lesson/student nested loop once var lessonTots = new Dictionary <string, Tuple <int, int> >(); var userTots = new Dictionary <string, Tuple <int, int> >(); //Per-init student dict (since students are the inner loop) foreach (string userID in clazz.Students) { userTots[userID] = new Tuple <int, int>(0, 0); } //Find totals foreach (string lessonID in clazz.Lessons) { lessonTots[lessonID] = new Tuple <int, int>(0, 0); foreach (string userID in clazz.Students) { var key = new Tuple <string, string>(lessonID, userID); StudentLessonActs turns; if (lookup.TryGetValue(key, out turns)) { int ca = turns.CorrectAnswers; int ia = turns.IncorrectAnswers; if (ca + ia > 0) { lessonTots[lessonID] = TupleAdd(lessonTots[lessonID], ca, ia); userTots[userID] = TupleAdd(userTots[userID], ca, ia); } } } } //Set up model with all this data var modelObj = new ExpandoObject(); var modelDict = (IDictionary <string, object>)modelObj; modelDict["Class"] = clazz; modelDict["LUTurns"] = lookup; modelDict["LessonNames"] = LessonsCtrl.DBConn().FindLessonNames(); modelDict["LessonCounts"] = lessonTots; modelDict["StudentCounts"] = userTots; return(View("ClassDetail", modelObj)); }