// // RQExerciseModule.m // JSJP // // Created by 张嵘 on 2021/8/12. // #import "RQExerciseModule.h" /// 刷新TableView NSString * const RQRefreshExerciseTableViewNotification = @"RQRefreshExerciseTableViewNotification"; /// 答题结果 NSString * const RQAnswerResultsNotification = @"RQAnswerResultsNotification"; /// 答题结果 key NSString * const RQAnswerResultsKey = @"RQAnswerResultsKey"; /// 练习模式Key NSString * const RQExerciseTypeKey = @"RQExerciseTypeKey"; /// 考试页面弹窗弹出类型Key NSString * const RQExerciseAlertTypeKey = @"RQExerciseAlertTypeKey"; /// 取消收藏成功通知 NSString * const RQCancelCollectNotification = @"RQCancelCollectNotification"; /// 取消收藏题目Key NSString * const RQCancelCollectExerciseModelKey = @"RQCancelCollectExerciseModelKey"; /// 取消错题成功通知 NSString * const RQCancelWrongNotification = @"RQCancelWrongNotification"; /// 取消错题题目Key NSString * const RQCancelWrongExerciseModelKey = @"RQCancelWrongExerciseModelKey"; /// 跳转到下一题通知 NSString * const RQAutoJumpNextNotification = @"RQAutoJumpNextNotification"; @interface RQExerciseModule () @property (nonatomic, readwrite, strong) SCLAlertView *alert; @property (nonatomic, readwrite, strong) UITextView *messageTextView; @property (nonatomic, readwrite, strong) SCLButton *rePlayButton; @property (nonatomic, readwrite, strong) SCLButton *closeButton; /// 考试交卷 @property (nonatomic, readwrite, assign) BOOL handUpIsShow; /// 考试暂停 @property (nonatomic, readwrite, assign) BOOL suspendIsShow; /// 考试恢复 @property (nonatomic, readwrite, assign) BOOL resumeIsShow; @property (nonatomic, readwrite, assign) BOOL isShow; @end @implementation RQExerciseModule static id rq_RQExerciseModule = nil; #pragma mark - init + (instancetype)sharedInstance { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ rq_RQExerciseModule = [[self alloc] init]; }); return rq_RQExerciseModule; } - (instancetype)init { if (self = [super init]) { [[RQNotificationCenter rac_addObserverForName:UIApplicationDidBecomeActiveNotification object:nil] subscribeNext:^(id x) { }]; [[RQNotificationCenter rac_addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil] subscribeNext:^(id x) { if (RQ_Exercise_Module.timer) { [RQ_Exercise_Module.timer setFireDate:[NSDate distantFuture]]; NSDictionary *dic = @{ @"questionArr" : RQ_Exercise_Module.questionArr, }; [RQ_Exercise_Module showAlertWithRQExerciseAlertType:RQExerciseAlertType_Exam_Resume valueDic:dic confirmAction:^(__kindof QMUIDialogViewController *dialogViewController) { if (RQ_Exercise_Module.timer) { [RQ_Exercise_Module.timer setFireDate:[NSDate distantPast]]; } } cancelAction:nil]; } }]; } return self; } #pragma mark - PublicMethods /** 弹出alertController,并且有多action按钮,分别有处理事件 @param alertType 弹窗类型 @param dic 参数 @param confirmTitle 左边按钮的title @param cancelTitle 右边按钮的title @param confirmAction 左边按钮的点击事件 @param cancelAction 右按钮的点击事件 */ - (void)showAlertWithRQExerciseAlertType:(RQExerciseAlertType)alertType valueDic:(NSDictionary * _Nullable )dic confirmAction:(void (^__nullable)(__kindof QMUIDialogViewController * _Nonnull dialogViewController))confirmAction cancelAction:(void (^__nullable)(__kindof QMUIDialogViewController * _Nonnull dialogViewController))cancelAction { @weakify(self) if (alertType == RQExerciseAlertType_Exam_Resume) { if (self.handUpIsShow || self.suspendIsShow) { return; } } QMUIDialogViewController *dialogViewController = [[QMUIDialogViewController alloc] init]; dialogViewController.headerSeparatorColor = nil; dialogViewController.headerViewBackgroundColor = UIColor.whiteColor; dialogViewController.headerViewHeight = (alertType != RQExerciseAlertType_Exam_Suspend)? RQ_FIT_HORIZONTAL(30.f) + 24.f : 0.f; NSArray *questionArr = @[]; if ([dic.allKeys containsObject:@"questionArr"]) { if (!RQObjectIsNil(dic[@"questionArr"])) { questionArr = dic[@"questionArr"]; } } NSInteger totalNum = questionArr.count; NSInteger errorNum = RQ_Exercise_Module.errorArr.count; NSInteger rightNum = RQ_Exercise_Module.correctArr.count; NSInteger hasdoNum = errorNum + rightNum; NSInteger undoNum = totalNum - hasdoNum; NSInteger perScore = 100 / totalNum; NSInteger score = rightNum * perScore; CGFloat progress = (hasdoNum * 1.00) / (totalNum * 1.00); BOOL isSuccess = (score >= 90); NSUInteger sec = RQ_Exercise_Module.count%60; NSUInteger min = RQ_Exercise_Module.count/60; NSString* sec0,*min0; sec0 = sec<10 ? @"0" : @""; min0 = min<10 ? @"0" : @""; /// 头部区域 QMUILabel *titleLabel = [[QMUILabel alloc] qmui_initWithFont:RQSemiboldFont(21) textColor:RQ_MAIN_TEXT_COLOR_1]; if (alertType == RQExerciseAlertType_Exam_HandUp) { titleLabel.textColor = RQ_MAIN_TEXT_COLOR_GREEN; titleLabel.text = @"考试合格"; titleLabel.textColor = RQ_MAIN_TEXT_COLOR_RED; titleLabel.text = @"考试不合格"; } else if (alertType == RQExerciseAlertType_Exam_Resume) { titleLabel.textColor = RQ_MAIN_TEXT_COLOR_1; titleLabel.text = @"为您恢复计时"; } else if (alertType == RQExerciseAlertType_Exam_Konw) { titleLabel.textColor = RQ_MAIN_TEXT_COLOR_1; titleLabel.text = @"模考须知"; } else { titleLabel.textColor = RQ_MAIN_TEXT_COLOR_1; titleLabel.text = @""; } titleLabel.textAlignment = NSTextAlignmentCenter; if (alertType != RQExerciseAlertType_Exam_Suspend) { [dialogViewController.headerView addSubview:titleLabel]; [titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.top.mas_offset(24.f); make.centerX.mas_offset(0); make.size.mas_equalTo(CGSizeMake(RQ_SCREEN_WIDTH - 80.f, RQ_FIT_HORIZONTAL(30.f))); }]; } /// 内容区域 // UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, RQ_SCREEN_WIDTH - 80.f, 36)]; // contentView.backgroundColor = UIColorWhite; // dialogViewController.contentView = contentView; if (alertType == RQExerciseAlertType_Exam_HandUp) { RQExerciseExamAlertView *exerciseExamAlertView = [RQExerciseExamAlertView exerciseExamAlertView]; exerciseExamAlertView.myImageView.image = isSuccess? RQImageNamed(@"及格") : RQImageNamed(@"不及格图"); CGFloat imageHeight = ((RQ_SCREEN_WIDTH - 80.f) * (147.f / 290.f)) * (133.51f / 147.f); exerciseExamAlertView.frame = CGRectMake(0, 0, RQ_SCREEN_WIDTH - 80.f, 4.f + imageHeight + 16.f + RQ_FIT_HORIZONTAL(60.f) + 24.f); dialogViewController.contentView = exerciseExamAlertView; exerciseExamAlertView.myTimeLabel.text = [NSString stringWithFormat:@"剩余时间:%@%lu:%@%lu",min0,(unsigned long)min,sec0,(unsigned long)sec]; exerciseExamAlertView.errorLabel.text = [NSString qmui_stringWithNSInteger:errorNum]; exerciseExamAlertView.unDoLabel.text = [NSString qmui_stringWithNSInteger:undoNum]; exerciseExamAlertView.scoreLabel.text = [NSString qmui_stringWithNSInteger:score]; } else if (alertType == RQExerciseAlertType_Exam_Suspend) { RQExerciseExamAlertHudView *exerciseExamAlertHudView = [RQExerciseExamAlertHudView exerciseExamAlertHudView]; CGFloat progressWidth = (RQ_SCREEN_WIDTH - 80.f) * (132.f / 290.f); exerciseExamAlertHudView.frame = CGRectMake(0, 0, RQ_SCREEN_WIDTH - 80.f, 24.f + progressWidth + 16.f + RQ_FIT_HORIZONTAL(24.f) + 24.f); dialogViewController.contentView = exerciseExamAlertHudView; [exerciseExamAlertHudView.myProgressView setProgress:progress]; exerciseExamAlertHudView.questionNumLabel.text = [NSString stringWithFormat:@"%ld/%ld题",hasdoNum,totalNum]; exerciseExamAlertHudView.myTimeLabel.text = [NSString stringWithFormat:@"剩余时间:%@%lu:%@%lu",min0,(unsigned long)min,sec0,(unsigned long)sec]; } else if (alertType == RQExerciseAlertType_Exam_Resume) { RQExerciseExamAlertHudView *exerciseExamAlertHudView = [RQExerciseExamAlertHudView exerciseExamAlertHudView]; CGFloat progressWidth = (RQ_SCREEN_WIDTH - 80.f) * (132.f / 290.f); exerciseExamAlertHudView.frame = CGRectMake(0, 0, RQ_SCREEN_WIDTH - 80.f, 24.f + progressWidth + 16.f + RQ_FIT_HORIZONTAL(24.f) + 24.f); dialogViewController.contentView = exerciseExamAlertHudView; [exerciseExamAlertHudView.myProgressView setProgress:progress]; exerciseExamAlertHudView.questionNumLabel.text = [NSString stringWithFormat:@"%ld/%ld题",hasdoNum,totalNum]; exerciseExamAlertHudView.myTimeLabel.text = [NSString stringWithFormat:@"剩余时间:%@%lu:%@%lu",min0,(unsigned long)min,sec0,(unsigned long)sec]; } else if (alertType == RQExerciseAlertType_Exam_Konw) { CGFloat textHeight = [@"温馨提示:模拟考试不能修改答案,每错1题扣1分,错题累计超过10道,考试不通过,系统自动提醒交卷。" heightForFont:[UIFont systemFontOfSize:13] width:RQ_SCREEN_WIDTH - 80.f - 24.f - 32.f] + 16.f; if ([dic.allKeys containsObject:@"questionArr"]) { if (!RQObjectIsNil(dic[@"questionArr"])) { questionArr = dic[@"questionArr"]; } } RQExerciseExamKnowAlertView *exerciseExamKnowAlertView = [RQExerciseExamKnowAlertView exerciseExamKnowAlertView]; exerciseExamKnowAlertView.frame = CGRectMake(0, 0, RQ_SCREEN_WIDTH - 80.f, 24.f + 104.f + 16.f + textHeight + 24.f); exerciseExamKnowAlertView.examCarTypeLabel.text = [RQ_YDTQuestion_Module getCarTypeExamNameWithCarType:RQ_YDTQuestion_Module.carType]; switch (RQ_YDTQuestion_Module.carType) { case RQHomePageCarType_Car: case RQHomePageCarType_Bus: case RQHomePageCarType_Truck: case RQHomePageCarType_Motorcycle: exerciseExamKnowAlertView.examStandardLabel.text = [NSString stringWithFormat:@"%ld题,45分钟",questionArr.count]; exerciseExamKnowAlertView.examSuccessStandardLabel.text = [NSString stringWithFormat:@"90分及格(满分100)"]; break; case RQHomePageCarType_ZGZ_JLY: case RQHomePageCarType_ZGZ_KY: case RQHomePageCarType_ZGZ_HY: exerciseExamKnowAlertView.examStandardLabel.text = [NSString stringWithFormat:@"%ld题,60分钟",questionArr.count]; exerciseExamKnowAlertView.examSuccessStandardLabel.text = [NSString stringWithFormat:@"80分及格(满分100)"]; break; case RQHomePageCarType_ZGZ_WXP: exerciseExamKnowAlertView.examStandardLabel.text = [NSString stringWithFormat:@"%ld题,60分钟",questionArr.count]; exerciseExamKnowAlertView.examSuccessStandardLabel.text = [NSString stringWithFormat:@"90分及格(满分100)"]; break; case RQHomePageCarType_ZGZ_CZC: case RQHomePageCarType_ZGZ_WYC: exerciseExamKnowAlertView.examStandardLabel.text = [NSString stringWithFormat:@"%ld题,50分钟",questionArr.count]; exerciseExamKnowAlertView.examSuccessStandardLabel.text = [NSString stringWithFormat:@"40分及格(满分50)"]; break; default: break; } dialogViewController.contentView = exerciseExamKnowAlertView; } /// 尾部区域 dialogViewController.footerSeparatorColor = nil; dialogViewController.footerViewBackgroundColor = UIColor.whiteColor; dialogViewController.footerViewHeight = RQ_FIT_HORIZONTAL(40.f) + 30.f; dialogViewController.footerView.hidden = NO; CGFloat btnWidth = (RQ_SCREEN_WIDTH - 80.f - (16 * 2) - 16) / 2.f; NSString *confirmTitle = @"确定"; NSString *cancelTitle = @"取消"; if (alertType == RQExerciseAlertType_Exam_HandUp) { confirmTitle = @"现在交卷"; cancelTitle = @"继续答题"; } else if (alertType == RQExerciseAlertType_Exam_Resume) { confirmTitle = @"继续答题"; cancelTitle = @""; } else if (alertType == RQExerciseAlertType_Exam_Suspend) { confirmTitle = @"继续考试"; cancelTitle = @"重新考试"; } else if (alertType == RQExerciseAlertType_Exam_Konw) { confirmTitle = @"知道了"; cancelTitle = @""; } else { confirmTitle = @"现在交卷"; cancelTitle = @"继续答题"; } QMUIButton *confirmBtn = [QMUIButton buttonWithType:UIButtonTypeCustom]; [confirmBtn setTitle:confirmTitle textColor:UIColor.whiteColor Font:15 fotState:UIControlStateNormal]; [confirmBtn setBackgroundColor:RQ_MAIN_COLOR]; [confirmBtn setBlockForControlEvents:UIControlEventTouchUpInside block:^(id _Nonnull sender) { [dialogViewController hide]; @strongify(self) switch (alertType) { case RQExerciseAlertType_Exam_HandUp: self.handUpIsShow = NO; break; case RQExerciseAlertType_Exam_Suspend: self.suspendIsShow = NO; break; case RQExerciseAlertType_Exam_Resume: self.resumeIsShow = NO; break; default: break; } if (confirmAction) { confirmAction(dialogViewController); } }]; [dialogViewController.footerView addSubview:confirmBtn]; [confirmBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.top.mas_offset(0); if (RQStringIsNotEmpty(cancelTitle)){make.right.mas_offset(-16);} else {make.centerX.mas_offset(0);} make.size.mas_equalTo(CGSizeMake(btnWidth, RQ_FIT_HORIZONTAL(40.f))); confirmBtn.layer.cornerRadius = RQ_FIT_HORIZONTAL(40.f) / 2.f; confirmBtn.layer.masksToBounds = YES; }]; QMUIButton *cancleBtn = [QMUIButton buttonWithType:UIButtonTypeCustom]; [cancleBtn setTitle:cancelTitle textColor:[UIColor qmui_colorWithHexString:@"#5C6066"] Font:15 fotState:UIControlStateNormal]; cancleBtn.layer.borderColor = [UIColor qmui_colorWithHexString:@"#707070"].CGColor; cancleBtn.layer.borderWidth = 1; cancleBtn.layer.cornerRadius = RQ_FIT_HORIZONTAL(40.f) / 2.f; cancleBtn.layer.masksToBounds = YES; [cancleBtn setBlockForControlEvents:UIControlEventTouchUpInside block:^(id _Nonnull sender) { [dialogViewController hide]; @strongify(self) switch (alertType) { case RQExerciseAlertType_Exam_HandUp: self.handUpIsShow = NO; break; case RQExerciseAlertType_Exam_Suspend: self.suspendIsShow = NO; break; case RQExerciseAlertType_Exam_Resume: self.resumeIsShow = NO; break; default: break; } if (cancelAction) { cancelAction(dialogViewController); } }]; if (RQStringIsNotEmpty(cancelTitle)) { [dialogViewController.footerView addSubview:cancleBtn]; [cancleBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.top.mas_offset(0); make.left.mas_offset(16); make.size.mas_equalTo(CGSizeMake(btnWidth, RQ_FIT_HORIZONTAL(40.f))); }]; } switch (alertType) { case RQExerciseAlertType_Exam_HandUp: self.handUpIsShow = YES; break; case RQExerciseAlertType_Exam_Suspend: self.suspendIsShow = YES; break; case RQExerciseAlertType_Exam_Resume: self.resumeIsShow = YES; break; default: break; } [dialogViewController show]; } - (void)startTimer { [self.timer invalidate]; self.timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(_timerValueChanged:) userInfo:nil repeats:YES]; [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes]; RQ_Exercise_Module.beginDate = [NSDate date]; } #pragma mark - PrivateMethods - (void)_timerValueChanged:(NSTimer *)timer { RQ_Exercise_Module.count --; if (RQ_Exercise_Module.count == 0) { [RQ_Exercise_Module.timer invalidate]; RQ_Exercise_Module.timer = nil; return; } } - (NSInteger)exerciseFontSize { id object = [RQ_COMMON_MANAGER getObjectWithKey:@"ExerciseFontSize"]; if (RQObjectIsNil(object)) { return 17; } else { NSInteger myExerciseFontSize = [object integerValue]; return myExerciseFontSize; } } - (void)setExerciseFontSize:(NSInteger)exerciseFontSize { [RQ_COMMON_MANAGER saveObjectWithObject:[NSNumber numberWithInteger:exerciseFontSize] ForKey:@"ExerciseFontSize"]; } - (BOOL)isRightAutoJumpToNext { id object = [RQ_COMMON_MANAGER getObjectWithKey:@"isRightAutoJumpToNext"]; if (RQObjectIsNil(object)) { return NO; } else { BOOL myIsRightAutoJumpToNext = [object boolValue]; return myIsRightAutoJumpToNext; } } - (void)setIsRightAutoJumpToNext:(BOOL)isRightAutoJumpToNext { [RQ_COMMON_MANAGER saveObjectWithObject:[NSNumber numberWithBool:isRightAutoJumpToNext] ForKey:@"isRightAutoJumpToNext"]; } - (BOOL)isRightAutoRemoveError { id object = [RQ_COMMON_MANAGER getObjectWithKey:@"isRightAutoRemoveError"]; if (RQObjectIsNil(object)) { return NO; } else { BOOL myIsRightAutoRemoveError = [object boolValue]; return myIsRightAutoRemoveError; } } - (void)setIsRightAutoRemoveError:(BOOL)isRightAutoRemoveError { [RQ_COMMON_MANAGER saveObjectWithObject:[NSNumber numberWithBool:isRightAutoRemoveError] ForKey:@"isRightAutoRemoveError"]; } - (BOOL)isExerciseSound { id object = [RQ_COMMON_MANAGER getObjectWithKey:@"isExerciseSound"]; if (RQObjectIsNil(object)) { return NO; } else { BOOL myIsExerciseSound = [object boolValue]; return myIsExerciseSound; } } - (void)setIsExerciseSound:(BOOL)isExerciseSound { [RQ_COMMON_MANAGER saveObjectWithObject:[NSNumber numberWithBool:isExerciseSound] ForKey:@"isExerciseSound"]; } - (NSArray *)questionArr { if (!_questionArr) { _questionArr = @[]; } return _questionArr; } - (NSArray *)correctArr { if (!_correctArr) { _correctArr = @[]; } return _correctArr; } - (NSArray *)errorArr { if (!_errorArr) { _errorArr = @[]; } return _errorArr; } @end