3 Date Created: 08/24/2016
4 ---------------------------------------------------
8 using System.Collections.Generic;
9 using System.Configuration;
10 using System.Data.Linq;
12 using CPE.App.Notify.Extensions;
13 using CPE.App.Notify.Models;
14 using CPE.App.Notify.Models.Enums;
16 namespace CPE.App.Notify.Helpers {
17 public static class SessionHelper {
18 private static readonly CPEWebDataContext _database = CPEWebDataContext.GetContext();
21 // Get meeting session
22 public static MeetingSession getMeetingSession(int meetingSessionKey) {
23 MeetingSession meetingSession = null;
24 meetingSession = _database
25 .MeetingSessions.FirstOrDefault(x => x.MeetingSessionKey == meetingSessionKey);
26 return meetingSession.Log(key: meetingSessionKey);
29 // Get first meeting participant session
30 public static MeetingParticipantSession getMeetingParticipantSession(int meetingParticipantSessionKey) {
31 var meetingParticipantSession = _database
32 .MeetingParticipantSessions.FirstOrDefault(x => x.MeetingParticipantSessionKey == meetingParticipantSessionKey)
34 return meetingParticipantSession.Log(key: meetingParticipantSessionKey);
37 // Get first meeting participant session
38 public static MeetingParticipantSession getMeetingParticipantSession(int meetingSessionKey, long participantKey) {
39 var meetingParticipantSession = _database
40 .MeetingParticipantSessions
41 .FirstOrDefault(mps => (mps.MeetingSessionKey == meetingSessionKey) && (mps.ParticipantKey == participantKey));
42 return meetingParticipantSession.Log(key: participantKey);
45 // Get meeting participant sessions
46 public static List<MeetingParticipantSession> getMeetingParticipantSessions(int meetingSessionKey) {
47 var listOfMeetingParticipantSessions = _database
48 .MeetingParticipantSessions.Where(m => m.MeetingSessionKey == meetingSessionKey)
50 return listOfMeetingParticipantSessions.Log(key: meetingSessionKey);
53 // Get participant purchase
54 public static ParticipantPurchase getParticipantPurchase(long participantKey, long scoId) {
55 var purchase = getParticipantPurchases(participantKey, scoId)
57 return purchase.Log(key: participantKey);
60 // Get participant purchase
61 public static ParticipantPurchase getParticipantPurchase(long scoId, DispositionProcessingStates dispositionProcessingState) {
62 var purchase = _database
63 .ParticipantPurchases.FirstOrDefault(pp => (pp.MeetingSco == scoId) && (pp.DispositionProcessingState == (int) dispositionProcessingState));
64 return purchase.Log(key: scoId);
67 // Get participant purchase
68 public static List<ParticipantPurchase> getParticipantPurchases(long participantKey, long scoId) {
69 var purchases = _database
71 .Where(pp => (pp.PrincipalID == participantKey) && (pp.MeetingSco == scoId))
73 return purchases.Log(key: participantKey);
76 // Get participant tracking results
77 public static List<GetParticipantTrackingsResult> getParticipantTrackingResults(int meetingParticipantSessionKey) {
78 var participantTrackings = _database
79 .GetParticipantTrackings()
80 .Where(pt => pt.MeetingParticipantSessionKey == meetingParticipantSessionKey)
82 return participantTrackings.Log(key: meetingParticipantSessionKey);
85 // Get participant session data result
86 public static ParticipantSessionsDataResult getParticipantSessionsDataResult(int meetingSessionKey, int meetingParticipantSessionKey) {
87 var participantSessionDataResult = _database.ParticipantSessionsData(meetingSessionKey)
90 psd.MeetingParticipantSessionKey ==
91 meetingParticipantSessionKey);
92 return participantSessionDataResult.Log(key: meetingSessionKey);
95 public static IQueryable<GetRecordingCandidatesResult> getRecordingCandidates(int? meetingSessionKey = null) {
96 return _database.GetRecordingCandidates(meetingSessionKey).Log(key: meetingSessionKey);
101 /// <param name="meetingParticipantSession"></param>
102 /// <param name="toEmail"></param>
103 /// <param name="meetingSco"></param>
104 /// <param name="purchaseDate"></param>
105 /// <param name="purchaseTicket"></param>
106 /// <returns></returns>
107 private static ParticipantResults processEndOfMeetingSessionAdobeConnectResultsForParticipant(MeetingParticipantSession meetingParticipantSession, out string toEmail, out int meetingSco, out DateTime purchaseDate, out string purchaseTicket) {
108 "Begin ProcessEndOfMeetingSessionAdobeConnectResultsForParticipant...".Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
110 $"ProcessEndOfMeetingSessionAdobeConnectResultsForParticipant received the meetingParticipantSession {meetingParticipantSession}".Log(LoggingLevels.Info, key: meetingParticipantSession.MeetingParticipantSessionKey);
112 var result = ParticipantResults.Wonky;
115 purchaseDate = DateTime.MinValue;
116 purchaseTicket = null;
118 var principalid = meetingParticipantSession.ParticipantKey;
119 var meetingSessionKey = meetingParticipantSession.MeetingSessionKey;
121 var meeting = meetingParticipantSession.MeetingSession;
122 $"Meeting session was found {meeting}".Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
124 var scoId = meeting.SCO_ID;
126 var participantTrackings = getParticipantTrackingResults(meetingParticipantSession.MeetingParticipantSessionKey)
128 .Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
129 var participantSession =
130 getParticipantSessionsDataResult(meetingSessionKey, meetingParticipantSession.MeetingParticipantSessionKey)
131 .Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
133 ParticipantPurchase purchase = null;
134 if(participantSession != null) {
135 purchase = getParticipantPurchase(principalid, scoId)
136 .Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
138 if(purchase == null) {
139 result = ParticipantResults.Ineligible;
141 purchase.DispositionProcessingState = (int) DispositionProcessingStates.InProgress;
142 _database.SubmitChanges(ConflictMode.ContinueOnConflict);
144 toEmail = purchase.Email;
145 meetingSco = purchase.MeetingSco;
146 purchaseDate = purchase.PurchaseDate;
147 purchaseTicket = purchase.Ticket;
149 var minutesInSessionHour = 50;
152 _database.MeetingSessionsData()
153 .FirstOrDefault(m => m.MeetingSessionKey == meetingSessionKey)
154 .Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
155 if(meetingSession != null) {
156 double maxSessionTimePossibleRoundedDown = -1;
157 if(meetingSession.ActualSessionTime != null) {
158 // one of these integers needs to be cast to a double to get a double as an answer, that's how .NET math works.
159 var maxSessionTimePossible = ((double) meetingSession.ActualSessionTime/minutesInSessionHour).Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
160 maxSessionTimePossibleRoundedDown = (Math.Floor(maxSessionTimePossible/.5)*.5).Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
163 double sessionCreditRoundedDown = 0;
164 if(participantSession.SessionCredit.HasValue) {
165 var dbSessionCredit = Convert.ToDouble(participantSession.SessionCredit)
166 .Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
168 sessionCreditRoundedDown = (Math.Floor(dbSessionCredit/.5)*.5).Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
171 var validCourseCreditsValues =
172 ConfigurationManager.AppSettings["MaxCourseCreditList"].Split(';')
173 .Select(double.Parse)
175 .Log(key: meetingParticipantSession.MeetingParticipantSessionKey); //max credits cut list
177 var mx = validCourseCreditsValues.BinarySearch(maxSessionTimePossibleRoundedDown);
178 //find appropriate valid value for this course
179 //user awarded no more than max possible credits for the course
180 var arrayPosition = mx >= 0 ? mx : ~mx - 1; //...by rounding down
181 var maxValidCourseCredit = validCourseCreditsValues[arrayPosition];
183 if(sessionCreditRoundedDown < 1) {
184 purchase.Credits = 0;
186 if(sessionCreditRoundedDown > maxSessionTimePossibleRoundedDown) {
187 purchase.Credits = maxSessionTimePossibleRoundedDown;
188 } else if(sessionCreditRoundedDown > maxValidCourseCredit) {
189 purchase.Credits = maxValidCourseCredit;
191 purchase.Credits = sessionCreditRoundedDown;
196 _database.MeetingDetails.FirstOrDefault(m => m.MeetingKey == purchase.MeetingSco)
197 .Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
199 purchase.Presenter = meetingDetail == null ? "" : meetingDetail.Instructor;
201 // 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.
202 purchase.MeetingDate = DateTime.Now.Date;
205 double sessionHeartbeatCountAsDouble = participantSession.SessionHeartbeatCount.GetValueOrDefault()
206 .Log(message: "sessionHeartbeatCountAsDouble", key: meetingParticipantSession.MeetingParticipantSessionKey);
207 double sessionEngagementCountAsDouble = participantSession.SessionEngagementCount.GetValueOrDefault()
208 .Log(message: "sessionEngagementCountAsDouble", key: meetingParticipantSession.MeetingParticipantSessionKey);
210 var percentComplete = (Math.Abs(Math.Abs(sessionHeartbeatCountAsDouble)) < 1 ? 1 : sessionEngagementCountAsDouble/sessionHeartbeatCountAsDouble).Log(message: "percentComplete", key: meetingParticipantSession.MeetingParticipantSessionKey);
212 if((purchase.Credits >= 1.0) && (percentComplete >= .75)) //threshold for earning a certificate is 75% response rate
214 purchase.EarnedCertificate = true;
215 result = ParticipantResults.Pass;
217 result = ParticipantResults.Fail;
221 purchase.DispositionProcessingState = (int) DispositionProcessingStates.Finished;
223 _database.SubmitChanges(ConflictMode.ContinueOnConflict);
227 if(purchase == null) {
228 result = ParticipantResults.Ineligible;
231 $"Participant result returned {result}".Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
233 "End ProcessEndOfMeetingSessionAdobeConnectResultsForParticipant...".Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
239 /// <param name="meetingSessionKey"></param>
240 /// <param name="isUnitTest">Bypasses sending an email for testing purposes</param>
241 public static bool StopSession(int meetingSessionKey, bool isUnitTest = false) {
242 "Begin StopSession...".Log(key:meetingSessionKey);
244 $"StopSession received the meetingSessionKey {meetingSessionKey}".Log(LoggingLevels.Info, key: meetingSessionKey);
246 var boolResult = false;
248 var meetingSession = getMeetingSession(meetingSessionKey)
249 .Log(key: meetingSessionKey);
251 if(meetingSession == null) {
252 $"Meeting session was not found for key - {meetingSessionKey}".Log(LoggingLevels.Error, key: meetingSessionKey);
255 // Is there a need to write a test for this?
256 var adobeHelper = new AdobeHelper();
257 if(adobeHelper.GetAdobeTransactions(meetingSession, _database)) {
258 "Adobe transactions were found and processed".Log(key: meetingSessionKey);
259 _database.SubmitChanges(ConflictMode.ContinueOnConflict);
261 "No Adobe transactions were found".Log(LoggingLevels.Warn, key: meetingSessionKey);
265 var listOfMeetingParticipantSessions = getMeetingParticipantSessions(meetingSession.MeetingSessionKey)
266 .Log(key: meetingSessionKey);
267 foreach (var meetingParticipantSession in listOfMeetingParticipantSessions) {
268 var purchase = getParticipantPurchase(meetingParticipantSession.ParticipantKey, meetingSession.SCO_ID)
269 .Log(key: meetingSessionKey);
270 if(purchase != null) {
271 "A purchase was found and will be processed for a certificate".Log(key: meetingSessionKey);
272 string toEmail = null;
274 DateTime purchaseDate;
275 string purchaseTicket = null;
276 "Begin ProcessEndOfMeetingSessionAdobeConnectResultsForParticipant...".Log(key: meetingSessionKey);
277 var passFailResult = processEndOfMeetingSessionAdobeConnectResultsForParticipant(meetingParticipantSession, out toEmail, out meetingSco, out purchaseDate, out purchaseTicket);
278 $"ProcessEndOfMeetingSessionAdobeConnectResultsForParticipant returned a result of {passFailResult}".Log(key: meetingSessionKey);
279 switch (passFailResult) {
280 case ParticipantResults.Ineligible:
282 case ParticipantResults.Fail:
283 "Begin SendFailNotice...".Log(key: meetingSessionKey);
285 toEmail.Log(key: meetingSessionKey);
286 EmailCertificateHelper.SendFailNotice(toEmail);
288 "End SendFailNotice...".Log(key: meetingSessionKey);
290 case ParticipantResults.Pass:
291 "Begin SendWebcastCert...".Log(key: meetingSessionKey);
293 toEmail.Log(key: meetingSessionKey);
294 EmailCertificateHelper.SendWebcastCert(toEmail, meetingSco, purchaseDate, purchaseTicket);
296 "End SendWebcastCert...".Log(key: meetingSessionKey);
298 case ParticipantResults.Wonky:
303 } catch (Exception exception) {
304 exception.Log(LoggingLevels.Fatal, key: meetingSessionKey);
308 } catch (Exception exception) {
309 exception.Log(LoggingLevels.Fatal, key: meetingSessionKey);
312 "End StopSession...".Log(key: meetingSessionKey);
314 return boolResult.Log(key: meetingSessionKey);
319 /// <param name="meetingParticipantSessionKey"></param>
320 /// <param name="isUnitTest">Bypasses sending an email for testing purposes</param>
321 public static bool ArchiveSession(int meetingParticipantSessionKey, bool isUnitTest = false) {
322 "Begin ArchiveSession...".Log(key: meetingParticipantSessionKey);
324 var boolResult = false;
326 var meetingParticipantSession = getMeetingParticipantSession(meetingParticipantSessionKey)
327 .Log(key: meetingParticipantSessionKey);
329 var meetingSession = getMeetingSession(meetingParticipantSession.MeetingSessionKey)
330 .Log(key: meetingParticipantSessionKey);
332 var purchase = getParticipantPurchase(meetingParticipantSession.ParticipantKey, meetingSession.SCO_ID)
333 .Log(key: meetingParticipantSessionKey);
334 if(purchase != null) {
335 // Is there a need to write a test for this?
336 var adobeHelper = new AdobeHelper();
337 if(adobeHelper.GetAdobeTransactions(meetingSession, _database)) {
338 "Adobe transactions were found and processed".Log(key: meetingParticipantSessionKey);
339 _database.SubmitChanges(ConflictMode.ContinueOnConflict);
341 "No Adobe transactions were found".Log(LoggingLevels.Warn, key: meetingParticipantSessionKey);
344 string toEmail = null;
346 var purchaseDate = DateTime.MinValue;
347 string purchaseTicket = null;
348 var passFailResult = processEndOfMeetingSessionAdobeConnectResultsForParticipant(meetingParticipantSession, out toEmail, out meetingSco, out purchaseDate, out purchaseTicket)
349 .Log(key: meetingParticipantSessionKey);
350 switch (passFailResult) {
351 case ParticipantResults.Ineligible:
353 case ParticipantResults.Fail:
354 "Begin SendFailNotice...".Log(key: meetingParticipantSessionKey);
357 EmailCertificateHelper.SendFailNotice(toEmail)
358 .Log(key: meetingParticipantSessionKey);
360 "End SendFailNotice...".Log(key: meetingParticipantSessionKey);
362 case ParticipantResults.Pass:
363 "Begin SendWebcastCert...".Log(key: meetingParticipantSessionKey);
366 EmailCertificateHelper.SendWebcastCert(toEmail, meetingSco, purchaseDate, purchaseTicket)
367 .Log(key: meetingParticipantSessionKey);
369 "End SendWebcastCert...".Log(key: meetingParticipantSessionKey);
371 case ParticipantResults.Wonky:
376 } catch (Exception exception) {
377 exception.Log(LoggingLevels.Fatal, key: meetingParticipantSessionKey);
379 "End ArchiveSession...".Log(key: meetingParticipantSessionKey);
384 /// Pass a meeting session to process all recordings.
386 /// <param name="meetingSessionKey"></param>
387 /// <param name="isUnitTest"></param>
388 /// <returns></returns>
389 public static bool ArchiveSessionByMeetingSession(int meetingSessionKey, bool isUnitTest = false) {
390 var returnResult = true;
391 var sessions = getRecordingCandidates(meetingSessionKey);
393 foreach (var session in sessions) {
394 if(!ArchiveSession(session.MeetingParticipantSessionKey, isUnitTest)) {
395 returnResult = false;