/* Developer: Tyler Allen Date Created: 08/24/2016 --------------------------------------------------- */ using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using CPE.App.NotifyConsole.Extensions; using CPE.App.NotifyConsole.Models; using CPE.App.NotifyConsole.Models.Enums; namespace CPE.App.NotifyConsole.Helpers { public static class SessionHelper { private static readonly CPEWebDataContext _database = CPEWebDataContext.GetContext(); // Get meeting session public static MeetingSession getMeetingSession(int meetingSessionKey) { MeetingSession meetingSession = null; meetingSession = _database .MeetingSessions.FirstOrDefault(x => x.MeetingSessionKey == meetingSessionKey); return meetingSession.Log(key: meetingSessionKey); } // Get first meeting participant session public static MeetingParticipantSession getMeetingParticipantSession(int meetingParticipantSessionKey) { var meetingParticipantSession = _database .MeetingParticipantSessions.FirstOrDefault(x => x.MeetingParticipantSessionKey == meetingParticipantSessionKey) .Log(); return meetingParticipantSession.Log(key: meetingParticipantSessionKey); } // Get first meeting participant session public static MeetingParticipantSession getMeetingParticipantSession(int meetingSessionKey, long participantKey) { var meetingParticipantSession = _database .MeetingParticipantSessions .FirstOrDefault(mps => (mps.MeetingSessionKey == meetingSessionKey) && (mps.ParticipantKey == participantKey)); return meetingParticipantSession.Log(key: participantKey); } // Get meeting participant sessions public static List getMeetingParticipantSessions(int meetingSessionKey) { var listOfMeetingParticipantSessions = _database .MeetingParticipantSessions.Where(m => m.MeetingSessionKey == meetingSessionKey) .ToList(); return listOfMeetingParticipantSessions.Log(key: meetingSessionKey); } // Get participant purchase public static ParticipantPurchase getParticipantPurchase(long participantKey, long scoId) { var purchase = getParticipantPurchases(participantKey, scoId) .FirstOrDefault(); return purchase.Log(key: participantKey); } // Get participant purchase public static ParticipantPurchase getParticipantPurchase(long scoId, DispositionProcessingStates dispositionProcessingState) { var purchase = _database .ParticipantPurchases.FirstOrDefault(pp => (pp.MeetingSco == scoId) && (pp.DispositionProcessingState == (int) dispositionProcessingState)); return purchase.Log(key: scoId); } // Get participant purchase public static List getParticipantPurchases(long participantKey, long scoId) { var purchases = _database .ParticipantPurchases .Where(pp => (pp.PrincipalID == participantKey) && (pp.MeetingSco == scoId)) .ToList(); return purchases.Log(key: participantKey); } // Get participant tracking results public static List getParticipantTrackingResults(int meetingParticipantSessionKey) { var participantTrackings = _database .GetParticipantTrackings() .Where(pt => pt.MeetingParticipantSessionKey == meetingParticipantSessionKey) .ToList(); return participantTrackings.Log(key: meetingParticipantSessionKey); } // Get participant session data result public static ParticipantSessionsDataResult getParticipantSessionsDataResult(int meetingSessionKey, int meetingParticipantSessionKey) { var participantSessionDataResult = _database.ParticipantSessionsData(meetingSessionKey) .FirstOrDefault( psd => psd.MeetingParticipantSessionKey == meetingParticipantSessionKey); return participantSessionDataResult.Log(key: meetingSessionKey); } public static IQueryable getRecordingCandidates(int meetingSessionKey) { return _database.GetRecordingCandidates(meetingSessionKey).Log(key: meetingSessionKey); } /// /// /// /// /// /// /// /// private static ParticipantResults processEndOfMeetingSessionAdobeConnectResultsForParticipant(MeetingParticipantSession meetingParticipantSession, out string toEmail, out int meetingSco, out DateTime purchaseDate, out string purchaseTicket) { "Begin ProcessEndOfMeetingSessionAdobeConnectResultsForParticipant...".Log(key: meetingParticipantSession.MeetingParticipantSessionKey); $"ProcessEndOfMeetingSessionAdobeConnectResultsForParticipant received the meetingParticipantSession {meetingParticipantSession}".Log(LoggingLevels.Info, key: meetingParticipantSession.MeetingParticipantSessionKey); var result = ParticipantResults.Wonky; toEmail = null; meetingSco = -1; purchaseDate = DateTime.MinValue; purchaseTicket = null; var principalid = meetingParticipantSession.ParticipantKey; var meetingSessionKey = meetingParticipantSession.MeetingSessionKey; var meeting = meetingParticipantSession.MeetingSession; $"Meeting session was found {meeting}".Log(key: meetingParticipantSession.MeetingParticipantSessionKey); var scoId = meeting.SCO_ID; var participantTrackings = getParticipantTrackingResults(meetingParticipantSession.MeetingParticipantSessionKey) .ToList() .Log(key: meetingParticipantSession.MeetingParticipantSessionKey); var participantSession = getParticipantSessionsDataResult(meetingSessionKey, meetingParticipantSession.MeetingParticipantSessionKey) .Log(key: meetingParticipantSession.MeetingParticipantSessionKey); ParticipantPurchase purchase = null; if(participantSession != null) { purchase = getParticipantPurchase(principalid, scoId) .Log(key: meetingParticipantSession.MeetingParticipantSessionKey); if(purchase == null) { result = ParticipantResults.Ineligible; } else { purchase.DispositionProcessingState = (int) DispositionProcessingStates.InProgress; _database.SubmitChanges(); toEmail = purchase.Email; meetingSco = purchase.MeetingSco; purchaseDate = purchase.PurchaseDate; purchaseTicket = purchase.Ticket; var minutesInSessionHour = 50; var meetingSession = _database.MeetingSessionsData() .FirstOrDefault(m => m.MeetingSessionKey == meetingSessionKey) .Log(key: meetingParticipantSession.MeetingParticipantSessionKey); if(meetingSession != null) { double maxSessionTimePossibleRoundedDown = -1; if(meetingSession.ActualSessionTime != null) { // one of these integers needs to be cast to a double to get a double as an answer, that's how .NET math works. var maxSessionTimePossible = ((double) meetingSession.ActualSessionTime/minutesInSessionHour).Log(key: meetingParticipantSession.MeetingParticipantSessionKey); maxSessionTimePossibleRoundedDown = (Math.Floor(maxSessionTimePossible/.5)*.5).Log(key: meetingParticipantSession.MeetingParticipantSessionKey); } double sessionCreditRoundedDown = 0; if(participantSession.SessionCredit.HasValue) { var dbSessionCredit = Convert.ToDouble(participantSession.SessionCredit) .Log(key: meetingParticipantSession.MeetingParticipantSessionKey); sessionCreditRoundedDown = (Math.Floor(dbSessionCredit/.5)*.5).Log(key: meetingParticipantSession.MeetingParticipantSessionKey); } var validCourseCreditsValues = ConfigurationManager.AppSettings["MaxCourseCreditList"].Split(';') .Select(double.Parse) .ToList() .Log(key: meetingParticipantSession.MeetingParticipantSessionKey); //max credits cut list var mx = validCourseCreditsValues.BinarySearch(maxSessionTimePossibleRoundedDown); //find appropriate valid value for this course //user awarded no more than max possible credits for the course var arrayPosition = mx >= 0 ? mx : ~mx - 1; //...by rounding down var maxValidCourseCredit = validCourseCreditsValues[arrayPosition]; if(sessionCreditRoundedDown < 1) { purchase.Credits = 0; } else { if(sessionCreditRoundedDown > maxSessionTimePossibleRoundedDown) { purchase.Credits = maxSessionTimePossibleRoundedDown; } else if(sessionCreditRoundedDown > maxValidCourseCredit) { purchase.Credits = maxValidCourseCredit; } else { purchase.Credits = sessionCreditRoundedDown; } } var meetingDetail = _database.MeetingDetails.FirstOrDefault(m => m.MeetingKey == purchase.MeetingSco) .Log(key: meetingParticipantSession.MeetingParticipantSessionKey); purchase.Presenter = meetingDetail == null ? "" : meetingDetail.Instructor; // This value gets set on first login, which may not be the date the cerficate was earned on (this value gets displayed on the certificate). Ideally we would use the local user's time zone to figure the date. purchase.MeetingDate = DateTime.Now.Date; double sessionHeartbeatCountAsDouble = participantSession.SessionHeartbeatCount.GetValueOrDefault() .Log(message: "sessionHeartbeatCountAsDouble", key: meetingParticipantSession.MeetingParticipantSessionKey); double sessionEngagementCountAsDouble = participantSession.SessionEngagementCount.GetValueOrDefault() .Log(message: "sessionEngagementCountAsDouble", key: meetingParticipantSession.MeetingParticipantSessionKey); var percentComplete = (Math.Abs(Math.Abs(sessionHeartbeatCountAsDouble)) < 1 ? 1 : sessionEngagementCountAsDouble/sessionHeartbeatCountAsDouble).Log(message: "percentComplete", key: meetingParticipantSession.MeetingParticipantSessionKey); if((purchase.Credits >= 1.0) && (percentComplete >= .75)) //threshold for earning a certificate is 75% response rate { purchase.EarnedCertificate = true; result = ParticipantResults.Pass; } else { result = ParticipantResults.Fail; } purchase.DispositionProcessingState = (int) DispositionProcessingStates.Finished; _database.SubmitChanges(); } } } if(purchase == null) { result = ParticipantResults.Ineligible; } $"Participant result returned {result}".Log(key: meetingParticipantSession.MeetingParticipantSessionKey); "End ProcessEndOfMeetingSessionAdobeConnectResultsForParticipant...".Log(key: meetingParticipantSession.MeetingParticipantSessionKey); return result; } /// /// /// /// Bypasses sending an email for testing purposes public static bool StopSession(int meetingSessionKey, bool isUnitTest = false) { "Begin StopSession...".Log(key:meetingSessionKey); $"StopSession received the meetingSessionKey {meetingSessionKey}".Log(LoggingLevels.Info, key: meetingSessionKey); var boolResult = false; try { var meetingSession = getMeetingSession(meetingSessionKey) .Log(key: meetingSessionKey); if(meetingSession == null) { $"Meeting session was not found for key - {meetingSessionKey}".Log(LoggingLevels.Error, key: meetingSessionKey); } else { try { // Is there a need to write a test for this? var adobeHelper = new AdobeHelper(); if(adobeHelper.GetAdobeTransactions(meetingSession, _database)) { "Adobe transactions were found and processed".Log(key: meetingSessionKey); _database.SubmitChanges(); } else { "No Adobe transactions were found".Log(LoggingLevels.Warn, key: meetingSessionKey); } var listOfMeetingParticipantSessions = getMeetingParticipantSessions(meetingSession.MeetingSessionKey) .Log(key: meetingSessionKey); foreach (var meetingParticipantSession in listOfMeetingParticipantSessions) { var purchase = getParticipantPurchase(meetingParticipantSession.ParticipantKey, meetingSession.SCO_ID) .Log(key: meetingSessionKey); if(purchase != null) { "A purchase was found and will be processed for a certificate".Log(key: meetingSessionKey); string toEmail = null; var meetingSco = -1; DateTime purchaseDate; string purchaseTicket = null; "Begin ProcessEndOfMeetingSessionAdobeConnectResultsForParticipant...".Log(key: meetingSessionKey); var passFailResult = processEndOfMeetingSessionAdobeConnectResultsForParticipant(meetingParticipantSession, out toEmail, out meetingSco, out purchaseDate, out purchaseTicket); $"ProcessEndOfMeetingSessionAdobeConnectResultsForParticipant returned a result of {passFailResult}".Log(key: meetingSessionKey); switch (passFailResult) { case ParticipantResults.Ineligible: break; case ParticipantResults.Fail: "Begin SendFailNotice...".Log(key: meetingSessionKey); if(!isUnitTest) { toEmail.Log(key: meetingSessionKey); EmailCertificateHelper.SendFailNotice(toEmail); } "End SendFailNotice...".Log(key: meetingSessionKey); break; case ParticipantResults.Pass: "Begin SendWebcastCert...".Log(key: meetingSessionKey); if(!isUnitTest) { toEmail.Log(key: meetingSessionKey); EmailCertificateHelper.SendWebcastCert(toEmail, meetingSco, purchaseDate, purchaseTicket); } "End SendWebcastCert...".Log(key: meetingSessionKey); break; case ParticipantResults.Wonky: break; } } } } catch (Exception exception) { exception.Log(LoggingLevels.Fatal, key: meetingSessionKey); } } boolResult = true; } catch (Exception exception) { exception.Log(LoggingLevels.Fatal, key: meetingSessionKey); } "End StopSession...".Log(key: meetingSessionKey); return boolResult.Log(key: meetingSessionKey); } /// /// /// /// Bypasses sending an email for testing purposes public static bool ArchiveSession(int meetingParticipantSessionKey, bool isUnitTest = false) { "Begin ArchiveSession...".Log(key: meetingParticipantSessionKey); var boolResult = false; try { var meetingParticipantSession = getMeetingParticipantSession(meetingParticipantSessionKey) .Log(key: meetingParticipantSessionKey); var meetingSession = getMeetingSession(meetingParticipantSession.MeetingSessionKey) .Log(key: meetingParticipantSessionKey); var purchase = getParticipantPurchase(meetingParticipantSession.ParticipantKey, meetingSession.SCO_ID) .Log(key: meetingParticipantSessionKey); if(purchase != null) { // Is there a need to write a test for this? var adobeHelper = new AdobeHelper(); if(adobeHelper.GetAdobeTransactions(meetingSession, _database)) { "Adobe transactions were found and processed".Log(key: meetingParticipantSessionKey); _database.SubmitChanges(); } else { "No Adobe transactions were found".Log(LoggingLevels.Warn, key: meetingParticipantSessionKey); } string toEmail = null; var meetingSco = -1; var purchaseDate = DateTime.MinValue; string purchaseTicket = null; var passFailResult = processEndOfMeetingSessionAdobeConnectResultsForParticipant(meetingParticipantSession, out toEmail, out meetingSco, out purchaseDate, out purchaseTicket) .Log(key: meetingParticipantSessionKey); switch (passFailResult) { case ParticipantResults.Ineligible: break; case ParticipantResults.Fail: "Begin SendFailNotice...".Log(key: meetingParticipantSessionKey); if(!isUnitTest) { toEmail.Log(); EmailCertificateHelper.SendFailNotice(toEmail) .Log(key: meetingParticipantSessionKey); } "End SendFailNotice...".Log(key: meetingParticipantSessionKey); break; case ParticipantResults.Pass: "Begin SendWebcastCert...".Log(key: meetingParticipantSessionKey); if(!isUnitTest) { toEmail.Log(); EmailCertificateHelper.SendWebcastCert(toEmail, meetingSco, purchaseDate, purchaseTicket) .Log(key: meetingParticipantSessionKey); } "End SendWebcastCert...".Log(key: meetingParticipantSessionKey); break; case ParticipantResults.Wonky: break; } } boolResult = true; } catch (Exception exception) { exception.Log(LoggingLevels.Fatal, key: meetingParticipantSessionKey); } "End ArchiveSession...".Log(key: meetingParticipantSessionKey); return boolResult; } /// /// Pass a meeting session to process all recordings. /// /// /// /// public static bool ArchiveSessionByMeetingSession(int meetingSessionKey, bool isUnitTest = false) { var returnResult = true; var sessions = getRecordingCandidates(meetingSessionKey); if(sessions.Any()) { foreach (var session in sessions) { if(!ArchiveSession(session.MeetingParticipantSessionKey, isUnitTest)) { returnResult = false; } } } return returnResult; } } }