3 Date Created: 08/24/2016
4 ---------------------------------------------------
8 using System.Collections.Generic;
9 using System.Configuration;
11 using CPE.App.NotifyConsole.Extensions;
12 using CPE.App.NotifyConsole.Models;
13 using CPE.App.NotifyConsole.Models.Enums;
15 namespace CPE.App.NotifyConsole.Helpers {
16 public static class SessionHelper {
17 private static readonly CPEWebDataContext _database = CPEWebDataContext.GetContext();
20 // Get meeting session
21 public static MeetingSession getMeetingSession(int meetingSessionKey) {
22 MeetingSession meetingSession = null;
23 meetingSession = _database
24 .MeetingSessions.FirstOrDefault(x => x.MeetingSessionKey == meetingSessionKey);
25 return meetingSession.Log(key: meetingSessionKey);
28 // Get first meeting participant session
29 public static MeetingParticipantSession getMeetingParticipantSession(int meetingParticipantSessionKey) {
30 var meetingParticipantSession = _database
31 .MeetingParticipantSessions.FirstOrDefault(x => x.MeetingParticipantSessionKey == meetingParticipantSessionKey)
33 return meetingParticipantSession.Log(key: meetingParticipantSessionKey);
36 // Get first meeting participant session
37 public static MeetingParticipantSession getMeetingParticipantSession(int meetingSessionKey, long participantKey) {
38 var meetingParticipantSession = _database
39 .MeetingParticipantSessions
40 .FirstOrDefault(mps => (mps.MeetingSessionKey == meetingSessionKey) && (mps.ParticipantKey == participantKey));
41 return meetingParticipantSession.Log(key: participantKey);
44 // Get meeting participant sessions
45 public static List<MeetingParticipantSession> getMeetingParticipantSessions(int meetingSessionKey) {
46 var listOfMeetingParticipantSessions = _database
47 .MeetingParticipantSessions.Where(m => m.MeetingSessionKey == meetingSessionKey)
49 return listOfMeetingParticipantSessions.Log(key: meetingSessionKey);
52 // Get participant purchase
53 public static ParticipantPurchase getParticipantPurchase(long participantKey, long scoId) {
54 var purchase = getParticipantPurchases(participantKey, scoId)
56 return purchase.Log(key: participantKey);
59 // Get participant purchase
60 public static ParticipantPurchase getParticipantPurchase(long scoId, DispositionProcessingStates dispositionProcessingState) {
61 var purchase = _database
62 .ParticipantPurchases.FirstOrDefault(pp => (pp.MeetingSco == scoId) && (pp.DispositionProcessingState == (int) dispositionProcessingState));
63 return purchase.Log(key: scoId);
66 // Get participant purchase
67 public static List<ParticipantPurchase> getParticipantPurchases(long participantKey, long scoId) {
68 var purchases = _database
70 .Where(pp => (pp.PrincipalID == participantKey) && (pp.MeetingSco == scoId))
72 return purchases.Log(key: participantKey);
75 // Get participant tracking results
76 public static List<GetParticipantTrackingsResult> getParticipantTrackingResults(int meetingParticipantSessionKey) {
77 var participantTrackings = _database
78 .GetParticipantTrackings()
79 .Where(pt => pt.MeetingParticipantSessionKey == meetingParticipantSessionKey)
81 return participantTrackings.Log(key: meetingParticipantSessionKey);
84 // Get participant session data result
85 public static ParticipantSessionsDataResult getParticipantSessionsDataResult(int meetingSessionKey, int meetingParticipantSessionKey) {
86 var participantSessionDataResult = _database.ParticipantSessionsData(meetingSessionKey)
89 psd.MeetingParticipantSessionKey ==
90 meetingParticipantSessionKey);
91 return participantSessionDataResult.Log(key: meetingSessionKey);
94 public static IQueryable<GetRecordingCandidatesResult> getRecordingCandidates(int meetingSessionKey) {
95 return _database.GetRecordingCandidates(meetingSessionKey).Log(key: meetingSessionKey);
100 /// <param name="meetingParticipantSession"></param>
101 /// <param name="toEmail"></param>
102 /// <param name="meetingSco"></param>
103 /// <param name="purchaseDate"></param>
104 /// <param name="purchaseTicket"></param>
105 /// <returns></returns>
106 private static ParticipantResults processEndOfMeetingSessionAdobeConnectResultsForParticipant(MeetingParticipantSession meetingParticipantSession, out string toEmail, out int meetingSco, out DateTime purchaseDate, out string purchaseTicket) {
107 "Begin ProcessEndOfMeetingSessionAdobeConnectResultsForParticipant...".Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
109 $"ProcessEndOfMeetingSessionAdobeConnectResultsForParticipant received the meetingParticipantSession {meetingParticipantSession}".Log(LoggingLevels.Info, key: meetingParticipantSession.MeetingParticipantSessionKey);
111 var result = ParticipantResults.Wonky;
114 purchaseDate = DateTime.MinValue;
115 purchaseTicket = null;
117 var principalid = meetingParticipantSession.ParticipantKey;
118 var meetingSessionKey = meetingParticipantSession.MeetingSessionKey;
120 var meeting = meetingParticipantSession.MeetingSession;
121 $"Meeting session was found {meeting}".Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
123 var scoId = meeting.SCO_ID;
125 var participantTrackings = getParticipantTrackingResults(meetingParticipantSession.MeetingParticipantSessionKey)
127 .Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
128 var participantSession =
129 getParticipantSessionsDataResult(meetingSessionKey, meetingParticipantSession.MeetingParticipantSessionKey)
130 .Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
132 ParticipantPurchase purchase = null;
133 if(participantSession != null) {
134 purchase = getParticipantPurchase(principalid, scoId)
135 .Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
137 if(purchase == null) {
138 result = ParticipantResults.Ineligible;
140 purchase.DispositionProcessingState = (int) DispositionProcessingStates.InProgress;
141 _database.SubmitChanges();
143 toEmail = purchase.Email;
144 meetingSco = purchase.MeetingSco;
145 purchaseDate = purchase.PurchaseDate;
146 purchaseTicket = purchase.Ticket;
148 var minutesInSessionHour = 50;
151 _database.MeetingSessionsData()
152 .FirstOrDefault(m => m.MeetingSessionKey == meetingSessionKey)
153 .Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
154 if(meetingSession != null) {
155 double maxSessionTimePossibleRoundedDown = -1;
156 if(meetingSession.ActualSessionTime != null) {
157 // one of these integers needs to be cast to a double to get a double as an answer, that's how .NET math works.
158 var maxSessionTimePossible = ((double) meetingSession.ActualSessionTime/minutesInSessionHour).Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
159 maxSessionTimePossibleRoundedDown = (Math.Floor(maxSessionTimePossible/.5)*.5).Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
162 double sessionCreditRoundedDown = 0;
163 if(participantSession.SessionCredit.HasValue) {
164 var dbSessionCredit = Convert.ToDouble(participantSession.SessionCredit)
165 .Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
167 sessionCreditRoundedDown = (Math.Floor(dbSessionCredit/.5)*.5).Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
170 var validCourseCreditsValues =
171 ConfigurationManager.AppSettings["MaxCourseCreditList"].Split(';')
172 .Select(double.Parse)
174 .Log(key: meetingParticipantSession.MeetingParticipantSessionKey); //max credits cut list
176 var mx = validCourseCreditsValues.BinarySearch(maxSessionTimePossibleRoundedDown);
177 //find appropriate valid value for this course
178 //user awarded no more than max possible credits for the course
179 var arrayPosition = mx >= 0 ? mx : ~mx - 1; //...by rounding down
180 var maxValidCourseCredit = validCourseCreditsValues[arrayPosition];
182 if(sessionCreditRoundedDown < 1) {
183 purchase.Credits = 0;
185 if(sessionCreditRoundedDown > maxSessionTimePossibleRoundedDown) {
186 purchase.Credits = maxSessionTimePossibleRoundedDown;
187 } else if(sessionCreditRoundedDown > maxValidCourseCredit) {
188 purchase.Credits = maxValidCourseCredit;
190 purchase.Credits = sessionCreditRoundedDown;
195 _database.MeetingDetails.FirstOrDefault(m => m.MeetingKey == purchase.MeetingSco)
196 .Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
198 purchase.Presenter = meetingDetail == null ? "" : meetingDetail.Instructor;
200 // 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.
201 purchase.MeetingDate = DateTime.Now.Date;
204 double sessionHeartbeatCountAsDouble = participantSession.SessionHeartbeatCount.GetValueOrDefault()
205 .Log(message: "sessionHeartbeatCountAsDouble", key: meetingParticipantSession.MeetingParticipantSessionKey);
206 double sessionEngagementCountAsDouble = participantSession.SessionEngagementCount.GetValueOrDefault()
207 .Log(message: "sessionEngagementCountAsDouble", key: meetingParticipantSession.MeetingParticipantSessionKey);
209 var percentComplete = (Math.Abs(Math.Abs(sessionHeartbeatCountAsDouble)) < 1 ? 1 : sessionEngagementCountAsDouble/sessionHeartbeatCountAsDouble).Log(message: "percentComplete", key: meetingParticipantSession.MeetingParticipantSessionKey);
211 if((purchase.Credits >= 1.0) && (percentComplete >= .75)) //threshold for earning a certificate is 75% response rate
213 purchase.EarnedCertificate = true;
214 result = ParticipantResults.Pass;
216 result = ParticipantResults.Fail;
220 purchase.DispositionProcessingState = (int) DispositionProcessingStates.Finished;
222 _database.SubmitChanges();
226 if(purchase == null) {
227 result = ParticipantResults.Ineligible;
230 $"Participant result returned {result}".Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
232 "End ProcessEndOfMeetingSessionAdobeConnectResultsForParticipant...".Log(key: meetingParticipantSession.MeetingParticipantSessionKey);
238 /// <param name="meetingSessionKey"></param>
239 /// <param name="isUnitTest">Bypasses sending an email for testing purposes</param>
240 public static bool StopSession(int meetingSessionKey, bool isUnitTest = false) {
241 "Begin StopSession...".Log(key:meetingSessionKey);
243 $"StopSession received the meetingSessionKey {meetingSessionKey}".Log(LoggingLevels.Info, key: meetingSessionKey);
245 var boolResult = false;
247 var meetingSession = getMeetingSession(meetingSessionKey)
248 .Log(key: meetingSessionKey);
250 if(meetingSession == null) {
251 $"Meeting session was not found for key - {meetingSessionKey}".Log(LoggingLevels.Error, key: meetingSessionKey);
254 // Is there a need to write a test for this?
255 var adobeHelper = new AdobeHelper();
256 if(adobeHelper.GetAdobeTransactions(meetingSession, _database)) {
257 "Adobe transactions were found and processed".Log(key: meetingSessionKey);
258 _database.SubmitChanges();
260 "No Adobe transactions were found".Log(LoggingLevels.Warn, key: meetingSessionKey);
264 var listOfMeetingParticipantSessions = getMeetingParticipantSessions(meetingSession.MeetingSessionKey)
265 .Log(key: meetingSessionKey);
266 foreach (var meetingParticipantSession in listOfMeetingParticipantSessions) {
267 var purchase = getParticipantPurchase(meetingParticipantSession.ParticipantKey, meetingSession.SCO_ID)
268 .Log(key: meetingSessionKey);
269 if(purchase != null) {
270 "A purchase was found and will be processed for a certificate".Log(key: meetingSessionKey);
271 string toEmail = null;
273 DateTime purchaseDate;
274 string purchaseTicket = null;
275 "Begin ProcessEndOfMeetingSessionAdobeConnectResultsForParticipant...".Log(key: meetingSessionKey);
276 var passFailResult = processEndOfMeetingSessionAdobeConnectResultsForParticipant(meetingParticipantSession, out toEmail, out meetingSco, out purchaseDate, out purchaseTicket);
277 $"ProcessEndOfMeetingSessionAdobeConnectResultsForParticipant returned a result of {passFailResult}".Log(key: meetingSessionKey);
278 switch (passFailResult) {
279 case ParticipantResults.Ineligible:
281 case ParticipantResults.Fail:
282 "Begin SendFailNotice...".Log(key: meetingSessionKey);
284 toEmail.Log(key: meetingSessionKey);
285 EmailCertificateHelper.SendFailNotice(toEmail);
287 "End SendFailNotice...".Log(key: meetingSessionKey);
289 case ParticipantResults.Pass:
290 "Begin SendWebcastCert...".Log(key: meetingSessionKey);
292 toEmail.Log(key: meetingSessionKey);
293 EmailCertificateHelper.SendWebcastCert(toEmail, meetingSco, purchaseDate, purchaseTicket);
295 "End SendWebcastCert...".Log(key: meetingSessionKey);
297 case ParticipantResults.Wonky:
302 } catch (Exception exception) {
303 exception.Log(LoggingLevels.Fatal, key: meetingSessionKey);
307 } catch (Exception exception) {
308 exception.Log(LoggingLevels.Fatal, key: meetingSessionKey);
311 "End StopSession...".Log(key: meetingSessionKey);
313 return boolResult.Log(key: meetingSessionKey);
318 /// <param name="meetingParticipantSessionKey"></param>
319 /// <param name="isUnitTest">Bypasses sending an email for testing purposes</param>
320 public static bool ArchiveSession(int meetingParticipantSessionKey, bool isUnitTest = false) {
321 "Begin ArchiveSession...".Log(key: meetingParticipantSessionKey);
323 var boolResult = false;
325 var meetingParticipantSession = getMeetingParticipantSession(meetingParticipantSessionKey)
326 .Log(key: meetingParticipantSessionKey);
328 var meetingSession = getMeetingSession(meetingParticipantSession.MeetingSessionKey)
329 .Log(key: meetingParticipantSessionKey);
331 var purchase = getParticipantPurchase(meetingParticipantSession.ParticipantKey, meetingSession.SCO_ID)
332 .Log(key: meetingParticipantSessionKey);
333 if(purchase != null) {
334 // Is there a need to write a test for this?
335 var adobeHelper = new AdobeHelper();
336 if(adobeHelper.GetAdobeTransactions(meetingSession, _database)) {
337 "Adobe transactions were found and processed".Log(key: meetingParticipantSessionKey);
338 _database.SubmitChanges();
340 "No Adobe transactions were found".Log(LoggingLevels.Warn, key: meetingParticipantSessionKey);
343 string toEmail = null;
345 var purchaseDate = DateTime.MinValue;
346 string purchaseTicket = null;
347 var passFailResult = processEndOfMeetingSessionAdobeConnectResultsForParticipant(meetingParticipantSession, out toEmail, out meetingSco, out purchaseDate, out purchaseTicket)
348 .Log(key: meetingParticipantSessionKey);
349 switch (passFailResult) {
350 case ParticipantResults.Ineligible:
352 case ParticipantResults.Fail:
353 "Begin SendFailNotice...".Log(key: meetingParticipantSessionKey);
356 EmailCertificateHelper.SendFailNotice(toEmail)
357 .Log(key: meetingParticipantSessionKey);
359 "End SendFailNotice...".Log(key: meetingParticipantSessionKey);
361 case ParticipantResults.Pass:
362 "Begin SendWebcastCert...".Log(key: meetingParticipantSessionKey);
365 EmailCertificateHelper.SendWebcastCert(toEmail, meetingSco, purchaseDate, purchaseTicket)
366 .Log(key: meetingParticipantSessionKey);
368 "End SendWebcastCert...".Log(key: meetingParticipantSessionKey);
370 case ParticipantResults.Wonky:
375 } catch (Exception exception) {
376 exception.Log(LoggingLevels.Fatal, key: meetingParticipantSessionKey);
378 "End ArchiveSession...".Log(key: meetingParticipantSessionKey);
383 /// Pass a meeting session to process all recordings.
385 /// <param name="meetingSessionKey"></param>
386 /// <param name="isUnitTest"></param>
387 /// <returns></returns>
388 public static bool ArchiveSessionByMeetingSession(int meetingSessionKey, bool isUnitTest = false) {
389 var returnResult = true;
390 var sessions = getRecordingCandidates(meetingSessionKey);
392 foreach (var session in sessions) {
393 if(!ArchiveSession(session.MeetingParticipantSessionKey, isUnitTest)) {
394 returnResult = false;