public ActionResult Grade(int assignmentID, int authorTeamID, bool resubmission = false) { WebClient client = new WebClient(); Assignment assignment = db.Assignments.Find(assignmentID); AssignmentTeam at = GetAssignmentTeam(assignment, ActiveCourseUser); ReviewTeam reviewTeam = null; if (at != null) { reviewTeam = (from rt in assignment.ReviewTeams where rt.ReviewTeamID == at.TeamID && rt.AuthorTeamID == authorTeamID select rt).FirstOrDefault(); } //Send off to Annotate if we have exactly one deliverable and that deliverable is a PDF document if (assignment.Deliverables.Count == 1 && assignment.Deliverables[0].DeliverableType == DeliverableType.PDF) { AnnotateApi api = new AnnotateApi(ConfigurationManager.AppSettings["AnnotateUserName"], ConfigurationManager.AppSettings["AnnotateApiKey"]); AnnotateResult uploadResult = api.UploadDocument((int)assignment.ID, authorTeamID, resubmission); if (uploadResult.Result == ResultCode.OK) { AnnotateResult createResult = api.CreateAccount(CurrentUser); if (createResult.Result == ResultCode.OK) { //instructors get to see everyone, regardless of CR settings CriticalReviewSettings settings = new CriticalReviewSettings(); settings.AnonymizeComments = false; api.SetDocumentAnonymity(CurrentUser, uploadResult.DocumentCode, uploadResult.DocumentDate, settings); api.GiveAccessToDocument(CurrentUser, uploadResult.DocumentCode, uploadResult.DocumentDate); //log the user in to annotate string loginString = api.GetAnnotateLoginUrl(CurrentUser, uploadResult.DocumentCode, uploadResult.DocumentDate); //load the annotate url for the view ViewBag.AnnotateUrl = loginString; } } } else { return(RedirectToRoute(new { controller = "Home", action = "Index", area = "" })); } return(View("Review")); }
public ActionResult Index(CriticalReviewSettings model) { Assignment = db.Assignments.Find(model.AssignmentID); //delete preexisting settings to prevent an FK relation issue CriticalReviewSettings setting = db.CriticalReviewSettings.Find(model.AssignmentID); if (setting != null) { db.CriticalReviewSettings.Remove(setting); } db.SaveChanges(); //...and then re-add it. Assignment.CriticalReviewSettings = model; db.SaveChanges(); //Blow out all previous review teams and readd the ones we get from the view. //AC Note: This may have to be changed depending on how we implement the new //HTML-based review interface. List <ReviewTeam> oldTeams = db.ReviewTeams.Where(rt => rt.AssignmentID == Assignment.ID).ToList(); foreach (ReviewTeam oldTeam in oldTeams) { db.ReviewTeams.Remove(oldTeam); } db.SaveChanges(); //add new values back in, save again. Assignment.ReviewTeams = ParseReviewTeams(); db.SaveChanges(); WasUpdateSuccessful = true; //This could have been an edit of the CR, and as a reuslt any CRDs associated with the assignment should be updated. UpdateCriticalReviewDiscussions(); SetUpViewBag(); return(base.PostBack(Assignment)); }
/// <summary> /// Returns true if the user should be anonymized for a critical review discussion /// </summary> /// <param name="currentUser">Current users</param> /// <param name="poster">Poster's courseuser</param> /// <param name="assignment">The Critical Review Discussion assignment</param> /// <param name="isAuthor">This value should be true if the poster if an author of the reviewed document</param> /// <param name="isReviewer">This value should be true if the poster if a reviewer of the document.</param> /// <returns></returns> public static bool AnonymizeNameForCriticalReviewDiscussion(CourseUser poster, CourseUser currentUser, Assignment assignment, bool posterIsAuthor, bool posterIsReviewer, bool currentUserIsAuthor, bool currentUserIsReviewer) { bool Anonymous = false; //Only attempt to anomize if current user is NOT an instructor or TA if (currentUser.AbstractRoleID != (int)CourseRole.CourseRoles.Instructor && currentUser.AbstractRoleID != (int)CourseRole.CourseRoles.TA) { CriticalReviewSettings criticalReviewSettings = assignment.PreceedingAssignment.CriticalReviewSettings; if (criticalReviewSettings.AnonymizeAuthor && currentUserIsReviewer && posterIsAuthor) { Anonymous = true; } else if (criticalReviewSettings.AnonymizeComments) { Anonymous = true; } } //For critical review discussions, we not only want to check the Assignment.PreceedingAssignment.CriticalReviewSettings //but additionally, apply any anonmization based off of Assignment.DiscussionSettings return(Anonymous || AnonymizeNameForDiscussion(poster, currentUser, assignment.DiscussionSettings)); }
/// <summary> /// Loads a PDF for critical review /// </summary> /// <param name="assignmentID"></param> /// <param name="authorTeamID"></param> /// <returns></returns> public ActionResult Review(int assignmentID, int authorTeamID) { WebClient client = new WebClient(); Assignment CRassignment = db.Assignments.Find(assignmentID); AssignmentTeam at = GetAssignmentTeam(CRassignment, ActiveCourseUser); ReviewTeam reviewTeam = null; if (at != null) { reviewTeam = (from rt in CRassignment.ReviewTeams where rt.ReviewTeamID == at.TeamID && rt.AuthorTeamID == authorTeamID select rt).FirstOrDefault(); } bool canAccessReview = false; //Determine whether or not the current user can access the document if (CRassignment.Type == AssignmentTypes.CriticalReview) { //is the user a reviewer? if (reviewTeam != null) { canAccessReview = true; } //or, is the user an instructor? else if (ActiveCourseUser.AbstractRole.CanGrade) { canAccessReview = true; } //or, has the review been published and the current user is the author of the docment? else if (CRassignment.IsCriticalReviewPublished == true) { reviewTeam = (from rt in CRassignment.ReviewTeams where rt.AuthorTeamID == authorTeamID select rt ).FirstOrDefault(); if (reviewTeam != null) { TeamMember tm = reviewTeam.AuthorTeam.TeamMembers.Where(t => t.CourseUserID == ActiveCourseUser.ID).FirstOrDefault(); if (tm != null) { canAccessReview = true; } } } } if (canAccessReview) { //Send off to Annotate if we have exactly one deliverable and that deliverable is a PDF document if (CRassignment.PreceedingAssignment.Deliverables.Count == 1 && CRassignment.PreceedingAssignment.Deliverables[0].DeliverableType == DeliverableType.PDF) { AnnotateApi api = new AnnotateApi(ConfigurationManager.AppSettings["AnnotateUserName"], ConfigurationManager.AppSettings["AnnotateApiKey"]); AnnotateResult uploadResult = api.UploadDocument((int)CRassignment.PrecededingAssignmentID, authorTeamID); if (uploadResult.Result == ResultCode.OK) { AnnotateResult createResult = api.CreateAccount(CurrentUser); if (createResult.Result == ResultCode.OK) { //instructors get to see everyone, regardless of CR settings CriticalReviewSettings settings = CRassignment.CriticalReviewSettings; if (ActiveCourseUser.AbstractRoleID == (int)CourseRole.CourseRoles.Instructor) { settings.AnonymizeComments = false; } api.SetDocumentAnonymity(CurrentUser, uploadResult.DocumentCode, uploadResult.DocumentDate, settings); api.GiveAccessToDocument(CurrentUser, uploadResult.DocumentCode, uploadResult.DocumentDate); //log the user in to annotate string loginString = api.GetAnnotateLoginUrl(CurrentUser, uploadResult.DocumentCode, uploadResult.DocumentDate); //load the annotate url for the view ViewBag.AnnotateUrl = loginString; } } } else { return(RedirectToRoute(new { controller = "Home", action = "Index", area = "" })); } } return(View()); }
/// <summary> /// Loads a PDF for critical review /// </summary> /// <param name="assignmentID"></param> /// <param name="authorTeamID"></param> /// <returns></returns> public ActionResult ReviewGradedDocument(int assignmentID, int authorTeamID, int anonReview = 0) { WebClient client = new WebClient(); Assignment CRassignment = db.Assignments.Find(assignmentID); AssignmentTeam at = GetAssignmentTeam(CRassignment, ActiveCourseUser); bool canAccessReview = false; //Determine whether or not the current user can access the document //is the author of the docment? TeamMember tm = at.Team.TeamMembers.Where(tms => tms.CourseUserID == ActiveCourseUser.ID).FirstOrDefault(); if (tm != null) { canAccessReview = true; } if (canAccessReview) { //Send off to Annotate if we have exactly one deliverable and that deliverable is a PDF document if (true) { AnnotateApi api = new AnnotateApi(ConfigurationManager.AppSettings["AnnotateUserName"], ConfigurationManager.AppSettings["AnnotateApiKey"]); AnnotateResult uploadResult = api.UploadDocument((int)assignmentID, authorTeamID); if (uploadResult.Result == ResultCode.OK) { AnnotateResult createResult = api.CreateAccount(CurrentUser); if (createResult.Result == ResultCode.OK) { //instructors get to see everyone, regardless of CR settings CriticalReviewSettings settings = CRassignment.CriticalReviewSettings; if (ActiveCourseUser.AbstractRoleID == (int)CourseRole.CourseRoles.Instructor) { settings.AnonymizeComments = false; } if (settings == null) { settings = new CriticalReviewSettings(); settings.Assignment = CRassignment; } if (anonReview == 1) { settings.AnonymizeComments = true; } api.SetDocumentAnonymity(CurrentUser, uploadResult.DocumentCode, uploadResult.DocumentDate, settings); api.GiveAccessToDocument(CurrentUser, uploadResult.DocumentCode, uploadResult.DocumentDate); //log the user in to annotate string loginString = api.GetAnnotateLoginUrl(CurrentUser, uploadResult.DocumentCode, uploadResult.DocumentDate); //load the annotate url for the view ViewBag.AnnotateUrl = loginString; } } } else { return(RedirectToRoute(new { controller = "Home", action = "Index", area = "" })); } } return(View("Review")); }
/// <summary> /// Sets the anonymity settings for the given document. /// </summary> /// <param name="user"></param> /// <param name="docCode"></param> /// <param name="docDate"></param> /// <param name="isAnonymous"></param> /// <param name="anonName"></param> /// <returns></returns> public AnnotateResult SetDocumentAnonymity(UserProfile user, string docCode, string docDate, CriticalReviewSettings settings, string anonName = "anonymous") { AnnotateResult result = new AnnotateResult(); result.Result = ResultCode.ERROR; WebClient client = new WebClient(); string webResult = ""; long epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds; //apiAddUserMapping.php does not exist! it appears to be a custom file... //TODO: re-create... string apiKey = GenerateAnnotateKey("apiAddUserMapping.php", user.UserName, epoch); Dictionary <string, string> mapping = new Dictionary <string, string>(); mapping["other"] = "anonymous"; mapping[user.UserName] = anonName; string jsonMapping = (new JavaScriptSerializer()).Serialize(mapping); int enable = 1; if (settings.AnonymizeComments == false) { enable = 0; } //TODO: this was changed when helplab went down. //string anonString = "http://helplab.org/annotate/php/apiAddUserMapping.php?" + string anonString = AnnotateURL + "/annotate/php/apiAddUserMapping.php?" + "api-user={0}" + //Annotate admin user name (see web config) "&api-auth={1}" + //Annotate admin auth key "&api-requesttime={2}" + //UNIX timestamp "&api-annotateuser={3}" + //current user (not used?) "&date={4}" + //date for document "&code={5}" + //code for document "&mapping={6}" + //anonymous mapping "&enable={7}"; //enable or disable mapping //"&rm={8}"; //add or remove mapping anonString = string.Format(anonString, ApiUser, apiKey, epoch, user.UserName, docDate, docCode, jsonMapping, enable //"" ); try { webResult = client.DownloadString(anonString); //WriteLog("SetDocumentAnnonymity: " + webResult); result.RawMessage = webResult; } catch (Exception) { throw; } if (webResult.Substring(0, 2) == "OK") { result.Result = ResultCode.OK; } return(result); }
/// <summary> /// yc: with a given list of assignments, copy them from one course to another. /// </summary> /// <param name="courseDestination"></param> /// <param name="courseSource"></param> /// <param name="previousAssignments"></param> /// <returns></returns> public bool CopyAssignments(Course courseDestination, Course courseSource, List <Assignment> previousAssignments) { try { //calculate # of weeks since start date double difference = courseDestination.StartDate.Subtract(courseSource.StartDate).TotalDays; //for linking purposes, key == previous id, value == the clone course that is teh same Dictionary <int, int> linkHolder = new Dictionary <int, int>(); foreach (Assignment p in previousAssignments) { //disabling assignments that are not finished being handled yet if (p.Type == AssignmentTypes.AnchoredDiscussion || p.Type == AssignmentTypes.CommitteeDiscussion || p.Type == AssignmentTypes.ReviewOfStudentWork) { continue; } int prid = -1, paid = p.ID; //for insert sake of cloned assigntment we must temprarly hold the list of assignments //whos id links to this assignment for temporary holding List <Assignment> previouslyLinked = (from pl in db.Assignments where pl.PrecededingAssignmentID == paid select pl).ToList(); //remove the links for now foreach (Assignment link in previouslyLinked) { link.PrecededingAssignmentID = null; db.Entry(link).State = EntityState.Modified; db.SaveChanges(); } //tmp holders if (p.RubricID != null) { prid = (int)p.RubricID; } //we are now ready for copying Assignment na = new Assignment(p); //na = p; na.CourseID = courseDestination.ID; //rewrite course id na.IsDraft = true; na.AssociatedEvent = null; na.AssociatedEventID = null; na.PrecededingAssignmentID = null; na.AssignmentTeams = new List <AssignmentTeam>(); na.DiscussionTeams = new List <DiscussionTeam>(); na.ReviewTeams = new List <ReviewTeam>(); na.Deliverables = new List <Deliverable>(); SetUpClonedAssignmentTeams(p, na); //recalcualte new offsets for due dates on assignment if (p.CriticalReviewPublishDate != null) { na.CriticalReviewPublishDate = ((DateTime)(p.CriticalReviewPublishDate)).Add(new TimeSpan(Convert.ToInt32(difference), 0, 0, 0)); } //CourseController cc = new CourseController(); // to retain the time incase of in differt daylightsavings .. shifts //DateTime dd = cc.convertFromUtc(courseSource.TimeZoneOffset, na.DueDate); //DateTime dt = cc.convertFromUtc(courseSource.TimeZoneOffset, na.DueTime); //DateTime rd = cc.convertFromUtc(courseSource.TimeZoneOffset, na.ReleaseDate); //DateTime rt = cc.convertFromUtc(courseSource.TimeZoneOffset, na.ReleaseTime); DateTime dd = na.DueDate.UTCToCourse(courseSource.ID); DateTime dt = na.DueTime.UTCToCourse(courseSource.ID); DateTime rd = na.ReleaseDate.UTCToCourse(courseSource.ID); DateTime rt = na.ReleaseTime.UTCToCourse(courseSource.ID); dd = dd.Add(new TimeSpan(Convert.ToInt32(difference), 0, 0, 0)); dt = dt.Add(new TimeSpan(Convert.ToInt32(difference), 0, 0, 0)); rd = rd.Add(new TimeSpan(Convert.ToInt32(difference), 0, 0, 0)); rt = rt.Add(new TimeSpan(Convert.ToInt32(difference), 0, 0, 0)); //convert back to utc //na.DueDate = cc.convertToUtc(courseDestination.TimeZoneOffset, dd); //na.DueTime = cc.convertToUtc(courseDestination.TimeZoneOffset, dt); //na.ReleaseDate = cc.convertToUtc(courseDestination.TimeZoneOffset, rd); //na.ReleaseTime = cc.convertToUtc(courseDestination.TimeZoneOffset, rt); na.DueDate = dd.CourseToUTC(courseDestination.ID); na.DueTime = dt.CourseToUTC(courseDestination.ID); na.ReleaseDate = rd.CourseToUTC(courseDestination.ID); na.ReleaseTime = rt.CourseToUTC(courseDestination.ID); //we now have a base to save db.Assignments.Add(na); db.SaveChanges(); //fix the link now foreach (Assignment link in previouslyLinked) { link.PrecededingAssignmentID = paid; db.Entry(link).State = EntityState.Modified; db.SaveChanges(); } linkHolder.Add(paid, na.ID); //for future assignment links if (p.PrecededingAssignmentID != null) { na.PrecededingAssignmentID = linkHolder[(int)p.PrecededingAssignmentID]; na.PreceedingAssignment = db.Assignments.Find(linkHolder[(int)p.PrecededingAssignmentID]); db.Entry(na).State = EntityState.Modified; db.SaveChanges(); } //copy assignmenttypes if (p.Type == AssignmentTypes.DiscussionAssignment || p.Type == AssignmentTypes.CriticalReviewDiscussion) { DiscussionSetting pds = (from ds in db.DiscussionSettings where ds.AssignmentID == paid select ds).FirstOrDefault(); DiscussionSetting nds = new DiscussionSetting(); nds.InitialPostDueDate = pds.InitialPostDueDate.Add(new TimeSpan(Convert.ToInt32(difference), 0, 0, 0)); nds.InitialPostDueDueTime = pds.InitialPostDueDueTime.Add(new TimeSpan(Convert.ToInt32(difference), 0, 0, 0)); nds.AssociatedEventID = null; nds.MaximumFirstPostLength = pds.MaximumFirstPostLength; nds.MinimumFirstPostLength = pds.MinimumFirstPostLength; nds.AnonymitySettings = pds.AnonymitySettings; na.DiscussionSettings = nds; db.Entry(na).State = EntityState.Modified; db.SaveChanges(); } //copy critical review settings if (p.Type == AssignmentTypes.CriticalReview) { CriticalReviewSettings pcs = (from ds in db.CriticalReviewSettings where ds.AssignmentID == paid select ds).FirstOrDefault(); if (pcs != null) { CriticalReviewSettings ncs = new CriticalReviewSettings(); ncs.ReviewSettings = pcs.ReviewSettings; na.CriticalReviewSettings = ncs; db.Entry(na).State = EntityState.Modified; db.SaveChanges(); } } //team eval if (p.Type == AssignmentTypes.TeamEvaluation) { TeamEvaluationSettings ptes = (from tes in db.TeamEvaluationSettings where tes.AssignmentID == paid select tes).FirstOrDefault(); if (ptes != null) { TeamEvaluationSettings ntes = new TeamEvaluationSettings(); ntes.DiscrepancyCheckSize = ptes.DiscrepancyCheckSize; ntes.RequiredCommentLength = ptes.RequiredCommentLength; ntes.MaximumMultiplier = ptes.MaximumMultiplier; ntes.AssignmentID = na.ID; na.TeamEvaluationSettings = ntes; db.Entry(na).State = EntityState.Modified; db.SaveChanges(); } } //components //rubrics if (p.RubricID != null) { CopyRubric(p, na); } ///deliverables List <Deliverable> pads = (from d in db.Deliverables where d.AssignmentID == paid select d).ToList(); foreach (Deliverable pad in pads) { Deliverable nad = new Deliverable(); nad.AssignmentID = na.ID; nad.DeliverableType = pad.DeliverableType; nad.Assignment = na; nad.Name = pad.Name; db.Deliverables.Add(nad); db.SaveChanges(); na.Deliverables.Add(nad); db.Entry(na).State = EntityState.Modified; db.SaveChanges(); } //abet stuff should prolly go here } return(true); } catch (Exception ex) { return(false); } }