using CPE.App.Api.Models; using CPE.App.Web.Code; using System; using System.Collections.Generic; using System.Linq; using System.Web; using Newtonsoft.Json; namespace CPE.App.Api.Helpers { public class TinCanHelper { public static bool HandleStatement(TinCanStatementModel statement) { // statement.Verb.Id=http://adlnet.gov/expapi/verbs/answered // statement.Verb.Id=http://adlnet.gov/expapi/verbs/experienced var dtNow = DateTime.UtcNow.ToString("yyyyMMdd_HHmmss"); if (statement.Verb.Id.IndexOf("passed")>-1) { Utilities.LogWrapper.Info("[TinCanHelper][HandleStatement] {0} statement.Verb.Id={1}. statement={2}", dtNow, statement.Verb.Id, JsonConvert.SerializeObject(statement)); //parse statement to db variables var email = statement.Actor.Mbox.Substring(7); var fname = statement.Actor.Name.Substring(0, statement.Actor.Name.IndexOf(" ") + 1); var lname = statement.Actor.Name.Substring(statement.Actor.Name.LastIndexOf(" ") + 1); var courseUrl = statement.Object.Id.Substring(statement.Object.Id.LastIndexOf("/") + 1); var courseName = statement.Object.Definition.Name.EnUs; bool done; //cpe has test data with multiple, currently valid purchases of the same course for one user, which causes problems but is not a real-world problem. //elucidat tracks all users globally by email address so a tincan statement won't identify a specific purchase here //unless we create unique email addy (e.g. email+ticket@mail.com) when originally logging them in to content var course = BaseController.Database.PurchasedCourses.FirstOrDefault(c => c.Email == email && c.ContentUrl == courseUrl && c.CertificateDate == null); if (course == null) { Utilities.LogWrapper.Info("[TinCanHelper][HandleStatement] {0} no action 1, cert already earned email={1} courseName={2}", dtNow, email, courseName); //no action, cert already earned //try //{ // course = BaseController.Database.PurchasedCourses.FirstOrDefault(c => c.Email == email && c.ContentUrl == courseUrl && c.CertificateDate!=null); // if (course == null) // { // Utilities.LogWrapper.Info("[TinCanHelper][HandleStatement] {0} no action, course == null, select courseName={1} from db with CertificateDate.", dtNow, courseName); // } // Utilities.LogWrapper.Info("[TinCanHelper][HandleStatement] {0} no action, select courseName={1} from db with CertificateDate. course={2}", dtNow, courseName, JsonConvert.SerializeObject(course)); // done = SendEmailHelper.SendCertificateEmail(course); // Utilities.LogWrapper.Info("[TinCanHelper][HandleStatement] {0} no action, send courseName={1} from db to email={2} successfully", dtNow, courseName, email); //} //catch (Exception exception) //{ // var innerException = ""; // if (exception.InnerException != null) innerException = exception.InnerException.ToString(); // Utilities.LogWrapper.Info("[TinCanHelper][HandleStatement] {0} email={1} courseName={2} exception={3}", dtNow, email, courseName, exception.ToString()+ innerException); //} //Utilities.LogWrapper.Info("[TinCanHelper][HandleStatement] {0} cert sent email={1} courseName={2}", dtNow, email, courseName); return true; } course.CertificateDate = Convert.ToDateTime(statement.Timestamp); try { BaseController.Database.SubmitChanges(); } catch (Exception exception) { Utilities.LogWrapper.Error("[TinCanHelper][HandleStatement] {0} email={1} courseName={2} exception={3}", dtNow, email, courseName, exception.ToString()); } done = SendEmailHelper.SendCertificateEmail(course); Utilities.LogWrapper.Info("[TinCanHelper][HandleStatement] {0} cert sent email={1} courseName={2}", dtNow, email, courseName); //umm why am i not returning done here? return true; } if (statement.Verb.Id.IndexOf("failed") > -1) { Utilities.LogWrapper.Info("[TinCanHelper][HandleStatement] {0} statement.Verb.Id={1}. statement={2}", dtNow, statement.Verb.Id, JsonConvert.SerializeObject(statement)); //parse statement to db variables var email = statement.Actor.Mbox.Substring(7); var fname = statement.Actor.Name.Substring(0, statement.Actor.Name.IndexOf(" ") + 1); var lname = statement.Actor.Name.Substring(statement.Actor.Name.LastIndexOf(" ") + 1); var courseUrl = statement.Object.Id.Substring(statement.Object.Id.LastIndexOf("/") + 1); var courseName = statement.Object.Definition.Name.EnUs; //only logging failed attempts prior to earning a cert //selecting first record for a user for a course that is not expired. To allow for if a user fails to earn a cert within a year and re-purchases course var course = BaseController.Database.PurchasedCourses.FirstOrDefault(c => c.Email == email && c.ContentUrl == courseUrl && c.CertificateDate == null && ((c.PurchaseDate).AddYears(1)) > DateTime.UtcNow); if (course == null) { //no action, cert already earned return true; } Utilities.LogWrapper.Info("[TinCanHelper][HandleStatement] {0} course.Ticket={1}", dtNow, course.Ticket); if (!course.FailedAttempts.HasValue) { course.FailedAttempts = 0; } course.FailedAttempts++; try { BaseController.Database.SubmitChanges(); } catch (Exception exception) { Utilities.LogWrapper.Error("[TinCanHelper][HandleStatement] {0} email={1} courseName={2} exception={3}", dtNow, email, courseName, exception.ToString()); } Utilities.LogWrapper.Info("[TinCanHelper][HandleStatement] {0} failure recorded email={1} courseName={2}", dtNow, email, courseName); return true; } return true; } } }