SimulationWaitExamController.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. //
  2. // SimulationWaitExamController.m
  3. // MusicGradeExam
  4. //
  5. // Created by Kyle on 2020/9/21.
  6. // Copyright © 2020 DayaMusic. All rights reserved.
  7. //
  8. #import "SimulationWaitExamController.h"
  9. #import "WaitExamBodyView.h"
  10. #import "OnlineRoomManager.h"
  11. #import "ExamGuideViewController.h"
  12. #import "KSGuideMaskView.h"
  13. #import "UserInfoManager.h"
  14. #import "WaitExamBottomView.h"
  15. #import "AppDelegate.h"
  16. #define BOTTOMVIEW_HEIGHT (150)
  17. @interface SimulationWaitExamController ()<UIScrollViewDelegate>
  18. @property (nonatomic, strong) WaitExamBodyView *bodyView;
  19. @property (nonatomic, strong) OnlineRoomManager *classManager;
  20. @property (nonatomic, assign) BOOL cancleRequest;
  21. @property (nonatomic, strong) WaitExamBottomView *bottomView;
  22. @property (nonatomic, assign) BOOL hasShowTopTips;
  23. @property (nonatomic, assign) BOOL hasShowBottomTips;
  24. @property (nonatomic, strong) NSTimer *timeTimer;
  25. @end
  26. @implementation SimulationWaitExamController
  27. - (void)viewDidLoad {
  28. [super viewDidLoad];
  29. // Do any additional setup after loading the view.
  30. [self allocTitle:@"直播模拟考试"];
  31. self.view.backgroundColor = HexRGB(0xf3f4f8);
  32. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(backLoginView) name:@"backLoginView" object:nil];
  33. [self configUI];
  34. self.sourceModel.desc = [self.sourceModel.desc replaceAll:@"\\n" WithString:@"\n"];
  35. [self evaluateSource];
  36. }
  37. // 被挤掉
  38. - (void)backLoginView {
  39. _cancleRequest = YES;
  40. }
  41. - (void)viewWillDisappear:(BOOL)animated {
  42. [super viewWillDisappear:animated];
  43. [[UIApplication sharedApplication] setIdleTimerDisabled:NO];
  44. }
  45. - (void)viewWillAppear:(BOOL)animated {
  46. [super viewWillAppear:animated];
  47. [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;
  48. if(@available(iOS 13.0, *)){
  49. [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDarkContent;
  50. }
  51. if (_cancleRequest) {
  52. _cancleRequest = NO;
  53. [KSRequestManager logoutAction];
  54. return;
  55. }
  56. [[UIApplication sharedApplication] setIdleTimerDisabled:YES];
  57. }
  58. - (void)viewDidAppear:(BOOL)animated {
  59. [super viewDidAppear:animated];
  60. if (_hasShowTopTips == NO) {
  61. [self addIntroduceView];
  62. }
  63. }
  64. - (void)addIntroduceView {
  65. _hasShowTopTips = YES;
  66. CGRect rect1 = [self.bodyView convertRect:self.bodyView.signButton.frame toView:[UIApplication sharedApplication].keyWindow];
  67. rect1.origin.y += 8;
  68. rect1.origin.x += 8;
  69. rect1.size.width -= 16;
  70. rect1.size.height -= 16;
  71. UIBezierPath *pathOne = [UIBezierPath bezierPathWithOvalInRect:rect1];
  72. CGRect rect2 = [self.bodyView convertRect:self.bodyView.examMessageView.frame toView:[UIApplication sharedApplication].keyWindow];
  73. UIBezierPath *pathSecond = [UIBezierPath bezierPathWithRect:rect2];
  74. CGFloat height = CGRectGetHeight(self.bodyView.frame);
  75. NSArray *tipsArray = @[@"考场开启后,才可已进行签到,签到后排考", @"这是您的考试信息"];
  76. NSArray *bezierArray = @[pathOne,pathSecond];
  77. if (height == kScreenHeight - kTabBarHeight - iPhoneXSafeBottomMargin - BOTTOMVIEW_HEIGHT) {
  78. CGRect rect3 = [self.bodyView convertRect:self.bodyView.tipsView.frame toView:[UIApplication sharedApplication].keyWindow];
  79. UIBezierPath *pathThree = [UIBezierPath bezierPathWithRect:rect3];
  80. tipsArray = @[@"考场开启后,才可已进行签到,签到后排考", @"这是您的考试信息",@"请认真阅读考试注意事项"];
  81. bezierArray = @[pathOne,pathSecond,pathThree];
  82. }
  83. KSGuideMaskView *guideView = [[KSGuideMaskView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight)];
  84. [guideView addTips:tipsArray transparentRect:bezierArray shaperLayerIndex:0];
  85. if (tipsArray.count == 2) {
  86. [guideView completeCallback:^{
  87. [self scrollToBottom];
  88. }];
  89. }
  90. [guideView showMaskViewInView:nil];
  91. }
  92. - (void)showBottomTips {
  93. _hasShowBottomTips = YES;
  94. NSArray *tipsArray = @[@"请认真阅读考试注意事项"];
  95. CGRect rect3 = [self.bodyView convertRect:self.bodyView.tipsView.frame toView:[UIApplication sharedApplication].keyWindow];
  96. UIBezierPath *pathThree = [UIBezierPath bezierPathWithRect:rect3];
  97. NSArray *bezierArray = @[pathThree];
  98. KSGuideMaskView *guideView = [[KSGuideMaskView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight)];
  99. [guideView addTips:tipsArray transparentRect:bezierArray shaperLayerIndex:-1];
  100. [guideView showMaskViewInView:nil];
  101. }
  102. - (void)evaluateSource {
  103. [self.bodyView configMessageSource:self.sourceModel];
  104. [self.bottomView configMessageSource:self.sourceModel];
  105. [self configViewHeight];
  106. if (USER_MANAGER.needConnect == NO) {
  107. if (![NSString isEmptyString:self.sourceModel.examStartTime]) {
  108. NSString *examDay = [[self.sourceModel.examStartTime componentsSeparatedByString:@" "] firstObject];
  109. NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
  110. [formatter setDateFormat:@"yyyy-MM-dd"];
  111. formatter.timeZone = [NSTimeZone systemTimeZone];
  112. NSDate *currentDate = [NSDate date];
  113. NSString *currentDay = [formatter stringFromDate:currentDate];
  114. if ([examDay isEqualToString:currentDay]) { // 如果今天有考试,IM建立连接
  115. [self configIMConnection];
  116. }
  117. }
  118. }
  119. }
  120. - (void)configIMConnection {
  121. [USER_MANAGER connectRongCloud];
  122. USER_MANAGER.needConnect = YES;
  123. }
  124. - (void)configViewHeight {
  125. CGFloat tipsHeight = [self.bodyView configTipsHeight:self.sourceModel.desc];
  126. CGFloat viewHeight = 206 + 200 + 19 + tipsHeight + 15;
  127. viewHeight = viewHeight > kScreenHeight - kTabBarHeight - iPhoneXSafeBottomMargin ? viewHeight : kScreenHeight - kTabBarHeight - iPhoneXSafeBottomMargin;
  128. self.bodyView.frame = CGRectMake(0, 0, kScreenWidth, viewHeight);
  129. [self.scrollView setContentSize:CGSizeMake(kScreenWidth, viewHeight)];
  130. }
  131. - (void)configUI {
  132. self.scrollView.backgroundColor = HexRGB(0xf3f4f8);
  133. self.scrollView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight - kTabBarHeight - iPhoneXSafeBottomMargin - BOTTOMVIEW_HEIGHT);
  134. self.scrollView.delegate = self;
  135. self.scrollView.bounces = NO;
  136. _bodyView = [WaitExamBodyView shareInstance];
  137. CGFloat viewHeight = 206 + 200 + 19 + 204 + 15;
  138. viewHeight = viewHeight > kScreenHeight - kTabBarHeight - iPhoneXSafeBottomMargin - BOTTOMVIEW_HEIGHT ? viewHeight : kScreenHeight - kTabBarHeight - iPhoneXSafeBottomMargin - BOTTOMVIEW_HEIGHT;
  139. _bodyView.frame = CGRectMake(0, 0, kScreenWidth, viewHeight);
  140. MJWeakSelf;
  141. [_bodyView operationCallback:^(JOINROOMACTION action, TicketDetailModel * _Nullable source) {
  142. [weakSelf opreationAction:action source:source];
  143. }];
  144. [self.scrollView addSubview:_bodyView];
  145. [self.scrollView setContentSize:CGSizeMake(kScreenWidth, viewHeight)];
  146. _bottomView = [WaitExamBottomView shareInstance];
  147. _bottomView.isSimulation = YES;
  148. _bottomView.frame = CGRectMake(0, CGRectGetMaxY(self.scrollView.frame), kScreenWidth, BOTTOMVIEW_HEIGHT);
  149. [_bottomView operationCallback:^(JOINROOMACTION action, TicketDetailModel * _Nullable source) {
  150. [weakSelf opreationAction:action source:source];
  151. }];
  152. [self.view addSubview:_bottomView];
  153. }
  154. - (void)opreationAction:(JOINROOMACTION)action source:(TicketDetailModel *)source {
  155. switch (action) {
  156. case JOINROOMACTION_SIGN: // 签到
  157. {
  158. [self signAction];
  159. }
  160. break;
  161. case JOINROOMACTION_GUIDE: // 引导页
  162. {
  163. ExamGuideViewController *guideVC = [[ExamGuideViewController alloc] init];
  164. [self.navigationController pushViewController:guideVC animated:YES];
  165. }
  166. break;
  167. case JOINROOMACTION_JOIN: // 加入房间
  168. {
  169. if (self.sourceModel.classroomSwitch == 1) {
  170. NSString *roomId = [NSString stringWithFormat:@"%.0f", source.examRegistrationId];
  171. [self joinRoomAction:roomId];
  172. }
  173. }
  174. break;
  175. default:
  176. break;
  177. }
  178. }
  179. #pragma mark ----- 签到
  180. - (void)signAction {
  181. MJWeakSelf;
  182. [self KSShowMsg:@"签到成功" promptCompletion:^{
  183. weakSelf.sourceModel.finishedExam = 2;
  184. weakSelf.sourceModel.signInTime = @"2020-09-22 18:00:00";
  185. // 滑动到底部
  186. [weakSelf scrollToBottom];
  187. // 开始排队
  188. [weakSelf evaluateSource];
  189. [weakSelf countWaitList];
  190. }];
  191. }
  192. // 开启定时器
  193. - (void)countWaitList {
  194. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  195. [self.timeTimer setFireDate:[NSDate distantPast]];
  196. });
  197. }
  198. - (void)scrollToBottom {
  199. CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height);
  200. [self.scrollView setContentOffset:bottomOffset animated:YES];
  201. }
  202. #pragma mark ----- 加入房间
  203. - (void)joinRoomAction:(NSString *)roomId {
  204. [self.classManager joinRoomWithId:roomId subjectName:self.sourceModel.subjectName inViewController:self];
  205. }
  206. - (OnlineRoomManager *)classManager {
  207. if (!_classManager) {
  208. _classManager = [[OnlineRoomManager alloc] init];
  209. }
  210. return _classManager;
  211. }
  212. - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
  213. CGPoint offset = scrollView.contentOffset;
  214. CGRect bounds = scrollView.bounds;
  215. CGSize size = scrollView.contentSize;
  216. UIEdgeInsets inset = scrollView.contentInset;
  217. CGFloat currentOffset = offset.y + bounds.size.height - inset.bottom;
  218. CGFloat maximumOffset = size.height;
  219. if((maximumOffset - currentOffset) < 40.0) {
  220. if (_hasShowBottomTips == NO) {
  221. [self showBottomTips];
  222. }
  223. }
  224. }
  225. - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
  226. CGPoint offset = scrollView.contentOffset;
  227. CGRect bounds = scrollView.bounds;
  228. CGSize size = scrollView.contentSize;
  229. UIEdgeInsets inset = scrollView.contentInset;
  230. CGFloat currentOffset = offset.y + bounds.size.height - inset.bottom;
  231. CGFloat maximumOffset = size.height;
  232. if((maximumOffset - currentOffset) < 40.0) {
  233. if (_hasShowBottomTips == NO) {
  234. [self showBottomTips];
  235. }
  236. }
  237. }
  238. - (void)timeFunction:(NSTimer *)timer {
  239. if (self.sourceModel.waitNum > 0) {
  240. self.sourceModel.waitNum--;
  241. }
  242. else {
  243. [self stopTimer];
  244. self.sourceModel.classroomSwitch = 1;
  245. }
  246. [self.bottomView configMessageSource:self.sourceModel];
  247. }
  248. - (void)stopTimer {
  249. [self.timeTimer setFireDate:[NSDate distantFuture]];
  250. if (self.timeTimer.valid) {
  251. [self.timeTimer invalidate];
  252. self.timeTimer = nil;
  253. }
  254. }
  255. - (NSTimer *)timeTimer {
  256. if (_timeTimer == nil) {
  257. _timeTimer = [NSTimer scheduledTimerWithTimeInterval:5
  258. target:self
  259. selector:@selector(timeFunction:)
  260. userInfo:nil
  261. repeats:YES];
  262. [[NSRunLoop currentRunLoop] addTimer:_timeTimer forMode:NSRunLoopCommonModes];
  263. }
  264. return _timeTimer;
  265. }
  266. - (void)dealloc {
  267. [self stopTimer];
  268. [[NSNotificationCenter defaultCenter] removeObserver:self];
  269. }
  270. /*
  271. #pragma mark - Navigation
  272. // In a storyboard-based application, you will often want to do a little preparation before navigation
  273. - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
  274. // Get the new view controller using [segue destinationViewController].
  275. // Pass the selected object to the new view controller.
  276. }
  277. */
  278. @end