diff --git a/Stepic/Legacy/Analytics/Events/AmplitudeAnalyticsEvents.swift b/Stepic/Legacy/Analytics/Events/AmplitudeAnalyticsEvents.swift index aa92ade5c6..b4b342ad8f 100644 --- a/Stepic/Legacy/Analytics/Events/AmplitudeAnalyticsEvents.swift +++ b/Stepic/Legacy/Analytics/Events/AmplitudeAnalyticsEvents.swift @@ -979,6 +979,74 @@ extension AnalyticsEvent { static let wishlistScreenOpened = AmplitudeAnalyticsEvent(name: "Wishlist screen opened") + // MARK: - Finished Steps - + + static func finishedStepsScreenOpened(course: Course) -> AmplitudeAnalyticsEvent { + AmplitudeAnalyticsEvent( + name: "Finished steps screen opened", + parameters: [ + "course": course.id, + "title": course.title, + "complete_rate": course.progress?.completeRate ?? 0 + ] + ) + } + + static func finishedStepsSharePressed(course: Course) -> AmplitudeAnalyticsEvent { + AmplitudeAnalyticsEvent( + name: "Finished steps share pressed", + parameters: [ + "course": course.id, + "title": course.title, + "complete_rate": course.progress?.completeRate ?? 0 + ] + ) + } + + static func finishedStepsViewCertificatePressed(course: Course) -> AmplitudeAnalyticsEvent { + AmplitudeAnalyticsEvent( + name: "Finished steps view certificate pressed", + parameters: [ + "course": course.id, + "title": course.title, + "complete_rate": course.progress?.completeRate ?? 0 + ] + ) + } + + static func finishedStepsBackToAssignmentsPressed(course: Course) -> AmplitudeAnalyticsEvent { + AmplitudeAnalyticsEvent( + name: "Finished steps back to assignments pressed", + parameters: [ + "course": course.id, + "title": course.title, + "complete_rate": course.progress?.completeRate ?? 0 + ] + ) + } + + static func finishedStepsFindNewCoursePressed(course: Course) -> AmplitudeAnalyticsEvent { + AmplitudeAnalyticsEvent( + name: "Finished steps find new course pressed", + parameters: [ + "course": course.id, + "title": course.title, + "complete_rate": course.progress?.completeRate ?? 0 + ] + ) + } + + static func finishedStepsLeaveReviewPressed(course: Course) -> AmplitudeAnalyticsEvent { + AmplitudeAnalyticsEvent( + name: "Finished steps leave review pressed", + parameters: [ + "course": course.id, + "title": course.title, + "complete_rate": course.progress?.completeRate ?? 0 + ] + ) + } + // MARK: - UserCourse - static func userCourseActionMade( diff --git a/Stepic/Legacy/Model/Entities/Progress/Progress.swift b/Stepic/Legacy/Model/Entities/Progress/Progress.swift index 932263ef7a..863f469fec 100644 --- a/Stepic/Legacy/Model/Entities/Progress/Progress.swift +++ b/Stepic/Legacy/Model/Entities/Progress/Progress.swift @@ -63,10 +63,14 @@ final class Progress: NSManagedObject, JSONSerializable, IDFetchable { return true } - var percentPassed: Float { + var completeRate: Float { self.numberOfSteps != 0 - ? Float(self.numberOfStepsPassed) / Float(self.numberOfSteps) * 100 - : 100.0 + ? Float(self.numberOfStepsPassed) / Float(self.numberOfSteps) + : 1 + } + + var percentPassed: Float { + self.completeRate * 100 } enum JSONKey: String { diff --git a/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalAssembly.swift b/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalAssembly.swift index a63d2667e5..3bbec94973 100644 --- a/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalAssembly.swift +++ b/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalAssembly.swift @@ -30,7 +30,8 @@ final class LessonFinishedStepsPanModalAssembly: Assembly { let interactor = LessonFinishedStepsPanModalInteractor( courseID: self.courseID, presenter: presenter, - provider: provider + provider: provider, + analytics: StepikAnalytics.shared ) let viewController = LessonFinishedStepsPanModalViewController(interactor: interactor) diff --git a/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalDataFlow.swift b/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalDataFlow.swift index 0c8b9c1609..5df1bc012e 100644 --- a/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalDataFlow.swift +++ b/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalDataFlow.swift @@ -14,9 +14,13 @@ enum LessonFinishedStepsPanModal { } } - enum ShareResultPresentation { - struct Request {} + enum ModalAction { + struct Request { + let actionUniqueIdentifier: UniqueIdentifierType + } + } + enum ShareResultPresentation { struct Response { let course: Course } @@ -27,8 +31,6 @@ enum LessonFinishedStepsPanModal { } enum CertificatePresentation { - struct Request {} - struct Response { let certificate: Certificate } @@ -38,12 +40,10 @@ enum LessonFinishedStepsPanModal { } } - enum LeaveReviewPresentation { - struct Request {} - } + enum BackToAssignmentsPresentation { + struct Response {} - enum FindNewCoursePresentation { - struct Request {} + struct ViewModel {} } // MARK: Enums diff --git a/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalInteractor.swift b/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalInteractor.swift index 7ae446af1c..20871f818f 100644 --- a/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalInteractor.swift +++ b/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalInteractor.swift @@ -3,10 +3,7 @@ import PromiseKit protocol LessonFinishedStepsPanModalInteractorProtocol { func doModalLoad(request: LessonFinishedStepsPanModal.ModalLoad.Request) - func doShareResultPresentation(request: LessonFinishedStepsPanModal.ShareResultPresentation.Request) - func doCertificatePresentation(request: LessonFinishedStepsPanModal.CertificatePresentation.Request) - func doLeaveReviewPresentation(request: LessonFinishedStepsPanModal.LeaveReviewPresentation.Request) - func doFindNewCoursePresentation(request: LessonFinishedStepsPanModal.FindNewCoursePresentation.Request) + func doModalAction(request: LessonFinishedStepsPanModal.ModalAction.Request) } final class LessonFinishedStepsPanModalInteractor: LessonFinishedStepsPanModalInteractorProtocol { @@ -18,14 +15,19 @@ final class LessonFinishedStepsPanModalInteractor: LessonFinishedStepsPanModalIn private let courseID: Course.IdType private var currentCourse: Course? + private let analytics: Analytics + private var shouldOpenedAnalyticsEventSend = true + init( courseID: Course.IdType, presenter: LessonFinishedStepsPanModalPresenterProtocol, - provider: LessonFinishedStepsPanModalProviderProtocol + provider: LessonFinishedStepsPanModalProviderProtocol, + analytics: Analytics ) { self.courseID = courseID self.presenter = presenter self.provider = provider + self.analytics = analytics } func doModalLoad(request: LessonFinishedStepsPanModal.ModalLoad.Request) { @@ -46,6 +48,7 @@ final class LessonFinishedStepsPanModalInteractor: LessonFinishedStepsPanModalIn CoreDataHelper.shared.save() } + self.sendOpenedAnalyticsEventIfNeeded() self.presenter.presentModal(response: .init(course: course, courseReview: courseReviewOrNil)) } .catch { error in @@ -53,23 +56,41 @@ final class LessonFinishedStepsPanModalInteractor: LessonFinishedStepsPanModalIn } } - func doShareResultPresentation(request: LessonFinishedStepsPanModal.ShareResultPresentation.Request) { - if let currentCourse = self.currentCourse { - self.presenter.presentShareResult(response: .init(course: currentCourse)) + func doModalAction(request: LessonFinishedStepsPanModal.ModalAction.Request) { + guard let targetAction = LessonFinishedStepsPanModal.ActionType(rawValue: request.actionUniqueIdentifier), + let currentCourse = self.currentCourse else { + return } - } - func doCertificatePresentation(request: LessonFinishedStepsPanModal.CertificatePresentation.Request) { - if let certificate = self.currentCourse?.certificateEntity { - self.presenter.presentCertificate(response: .init(certificate: certificate)) + switch targetAction { + case .backToAssignments: + self.analytics.send(.finishedStepsBackToAssignmentsPressed(course: currentCourse)) + self.presenter.presentBackToAssignments(response: .init()) + case .leaveReview: + self.analytics.send(.finishedStepsLeaveReviewPressed(course: currentCourse)) + self.moduleOutput?.handleLessonFinishedStepsPanModalLeaveReviewAction() + case .findNewCourse: + self.analytics.send(.finishedStepsFindNewCoursePressed(course: currentCourse)) + self.moduleOutput?.handleLessonFinishedStepsPanModalFindNewCourseAction() + case .shareResult: + self.analytics.send(.finishedStepsSharePressed(course: currentCourse)) + self.presenter.presentShareResult(response: .init(course: currentCourse)) + case .viewCertificate: + self.analytics.send(.finishedStepsViewCertificatePressed(course: currentCourse)) + + if let certificate = currentCourse.certificateEntity { + self.presenter.presentCertificate(response: .init(certificate: certificate)) + } } } - func doLeaveReviewPresentation(request: LessonFinishedStepsPanModal.LeaveReviewPresentation.Request) { - self.moduleOutput?.handleLessonFinishedStepsPanModalLeaveReviewAction() - } + private func sendOpenedAnalyticsEventIfNeeded() { + guard self.shouldOpenedAnalyticsEventSend, + let currentCourse = self.currentCourse else { + return + } - func doFindNewCoursePresentation(request: LessonFinishedStepsPanModal.FindNewCoursePresentation.Request) { - self.moduleOutput?.handleLessonFinishedStepsPanModalFindNewCourseAction() + self.shouldOpenedAnalyticsEventSend = false + self.analytics.send(.finishedStepsScreenOpened(course: currentCourse)) } } diff --git a/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalPresenter.swift b/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalPresenter.swift index ab4f934e61..5ceceb6fa0 100644 --- a/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalPresenter.swift +++ b/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalPresenter.swift @@ -5,6 +5,7 @@ protocol LessonFinishedStepsPanModalPresenterProtocol { func presentModal(response: LessonFinishedStepsPanModal.ModalLoad.Response) func presentShareResult(response: LessonFinishedStepsPanModal.ShareResultPresentation.Response) func presentCertificate(response: LessonFinishedStepsPanModal.CertificatePresentation.Response) + func presentBackToAssignments(response: LessonFinishedStepsPanModal.BackToAssignmentsPresentation.Response) } final class LessonFinishedStepsPanModalPresenter: LessonFinishedStepsPanModalPresenterProtocol { @@ -47,6 +48,10 @@ final class LessonFinishedStepsPanModalPresenter: LessonFinishedStepsPanModalPre self.viewController?.displayCertificate(viewModel: .init(certificateURL: url)) } + func presentBackToAssignments(response: LessonFinishedStepsPanModal.BackToAssignmentsPresentation.Response) { + self.viewController?.displayBackToAssignments(viewModel: .init()) + } + // MARK: Private API private func makeViewModel(course: Course, courseReview: CourseReview?) -> LessonFinishedStepsPanModalViewModel { diff --git a/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalViewController.swift b/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalViewController.swift index 901a2000de..59e5d930a8 100644 --- a/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalViewController.swift +++ b/Stepic/Sources/Modules/LessonPanModals/LessonFinishedStepsPanModal/LessonFinishedStepsPanModalViewController.swift @@ -5,6 +5,7 @@ protocol LessonFinishedStepsPanModalViewControllerProtocol: AnyObject { func displayModal(viewModel: LessonFinishedStepsPanModal.ModalLoad.ViewModel) func displayShareResult(viewModel: LessonFinishedStepsPanModal.ShareResultPresentation.ViewModel) func displayCertificate(viewModel: LessonFinishedStepsPanModal.CertificatePresentation.ViewModel) + func displayBackToAssignments(viewModel: LessonFinishedStepsPanModal.BackToAssignmentsPresentation.ViewModel) } final class LessonFinishedStepsPanModalViewController: PanModalPresentableViewController { @@ -104,6 +105,10 @@ extension LessonFinishedStepsPanModalViewController: LessonFinishedStepsPanModal backButtonStyle: .close ) } + + func displayBackToAssignments(viewModel: LessonFinishedStepsPanModal.BackToAssignmentsPresentation.ViewModel) { + self.dismiss(animated: true) + } } extension LessonFinishedStepsPanModalViewController: LessonFinishedStepsPanModalViewDelegate { @@ -116,24 +121,11 @@ extension LessonFinishedStepsPanModalViewController: LessonFinishedStepsPanModal didClickButtonWith uniqueIdentifier: UniqueIdentifierType?, sourceView: UIView ) { - guard let uniqueIdentifier = uniqueIdentifier, - let actionType = LessonFinishedStepsPanModal.ActionType(rawValue: uniqueIdentifier) else { + guard let uniqueIdentifier = uniqueIdentifier else { return } self.currentPopoverPresentationSourceView = sourceView - - switch actionType { - case .backToAssignments: - self.dismiss(animated: true) - case .leaveReview: - self.interactor.doLeaveReviewPresentation(request: .init()) - case .findNewCourse: - self.interactor.doFindNewCoursePresentation(request: .init()) - case .shareResult: - self.interactor.doShareResultPresentation(request: .init()) - case .viewCertificate: - self.interactor.doCertificatePresentation(request: .init()) - } + self.interactor.doModalAction(request: .init(actionUniqueIdentifier: uniqueIdentifier)) } }