RQTestQuestionsViewModel.m 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. //
  2. // RQTestQuestionsViewModel.m
  3. // SDJK
  4. //
  5. // Created by 张嵘 on 2021/8/12.
  6. //
  7. #import "RQTestQuestionsViewModel.h"
  8. @interface RQTestQuestionsViewModel ()
  9. @property (nonatomic, readwrite, assign) RQExerciseOptionItemType exerciseOptionItemType;
  10. @property (nonatomic, readwrite, assign) RQAnswerResultsType answerResultsType;
  11. @property (nonatomic, readwrite, copy) NSArray *optionLeftNameArr;
  12. @property (nonatomic, readwrite, assign) RQExerciseType exerciseType;
  13. /// homePageCarType
  14. @property (nonatomic, readwrite, assign) RQHomePageCarType homePageCarType;
  15. /// homePageSubjectType
  16. @property (nonatomic, readwrite, assign) RQHomePageSubjectType homePageSubjectType;
  17. @property (nonatomic, readwrite, assign) RQExerciseDoType exerciseDoType;
  18. @end
  19. @implementation RQTestQuestionsViewModel
  20. #pragma mark - Public Method
  21. - (instancetype)initWithServices:(id<RQViewModelServices>)services params:(NSDictionary *)params {
  22. if (self = [super initWithServices:services params:params]) {
  23. self.exerciseOptionItemType = RQExerciseOptionItemType_Default;
  24. self.answerResultsType = RQAnswerResultsType_Unanswered;
  25. self.exerciseType = [params[RQExerciseTypeKey] integerValue];
  26. self.exerciseModel = (RQExerciseModel *)params[RQViewModelUtilKey];
  27. self.homePageCarType = [params[RQHomePageCarTypeKey] integerValue];
  28. self.homePageSubjectType = [params[RQHomePageSubjectTypeKey] integerValue];
  29. self.exerciseDoType = RQExerciseDoType_Default;
  30. }
  31. return self;
  32. }
  33. - (void)initialize {
  34. [super initialize];
  35. self.title = @"";
  36. /// 隐藏导航栏的细线
  37. self.prefersNavigationBarBottomLineHidden = YES;
  38. ///配置数据
  39. // [self rq_configureData];
  40. }
  41. - (void)setExerciseModel:(RQExerciseModel *)exerciseModel {
  42. _exerciseModel = exerciseModel;
  43. [self rq_configureData];
  44. }
  45. #pragma mark - PrivateMethod
  46. - (void)rq_configureData {
  47. /// 第零组
  48. RQCommonGroupViewModel *group0 = [RQCommonGroupViewModel groupViewModel];
  49. group0.headerHeight = CGFLOAT_MIN;
  50. group0.footerHeight = CGFLOAT_MIN;
  51. RQExerciseQuestionItemViewModel *exerciseQuestionItemViewModel = [[RQExerciseQuestionItemViewModel alloc] initWithRQExerciseModel:self.exerciseModel];
  52. group0.itemViewModels = @[exerciseQuestionItemViewModel];
  53. /// 第二组
  54. RQCommonGroupViewModel *group2 = [RQCommonGroupViewModel groupViewModel];
  55. group2.headerHeight = CGFLOAT_MIN;
  56. group2.footerHeight = CGFLOAT_MIN;
  57. RQExerciseAnswerItemViewModel *exerciseAnswerItemViewModel = [[RQExerciseAnswerItemViewModel alloc] initWithRQExerciseModel:self.exerciseModel];
  58. if (RQStringIsNotEmpty(_exerciseModel.userAnswer) && ![_exerciseModel.userAnswer containsString:@"预选Option"] && _exerciseType != RQExerciseType_Test && _exerciseType != RQExerciseType_Exam) {
  59. group2.itemViewModels = @[exerciseAnswerItemViewModel];
  60. } else {
  61. group2.itemViewModels = @[];
  62. }
  63. /// 第三组
  64. RQCommonGroupViewModel *group3 = [RQCommonGroupViewModel groupViewModel];
  65. group3.headerHeight = CGFLOAT_MIN;
  66. group3.footerHeight = CGFLOAT_MIN;
  67. RQExerciseOptionSureBtnItemViewModel *exerciseOptionSureBtnItemViewModel = [[RQExerciseOptionSureBtnItemViewModel alloc] init];
  68. exerciseOptionSureBtnItemViewModel.rowHeight = 56.f;
  69. exerciseOptionSureBtnItemViewModel.operation = ^{
  70. if ([_exerciseModel.userAnswer containsString:@"预选Option-"]) {
  71. NSString *userAnswerStr = _exerciseModel.userAnswer;
  72. userAnswerStr = [userAnswerStr stringByReplacingOccurrencesOfString:@"预选Option-" withString:@""];
  73. _exerciseModel.userAnswer = userAnswerStr;
  74. [self rq_configureData];
  75. } else {
  76. }
  77. };
  78. if ([_exerciseModel.answer containsString:@"-"] && self.answerResultsType == RQAnswerResultsType_Unanswered) {
  79. group3.itemViewModels = @[exerciseOptionSureBtnItemViewModel];
  80. } else {
  81. group3.itemViewModels = @[];
  82. }
  83. /// 第四组
  84. RQCommonGroupViewModel *group4 = [RQCommonGroupViewModel groupViewModel];
  85. group4.headerHeight = CGFLOAT_MIN;
  86. group4.footerHeight = CGFLOAT_MIN;
  87. RQExerciseToolBarItemViewModel *exerciseToolBarItemViewModel = [[RQExerciseToolBarItemViewModel alloc] initWithRQExerciseModel:self.exerciseModel homePageCarType:self.homePageCarType homePageSubject:self.homePageSubjectType readingQuestionsAndAnswerCommand:[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
  88. _exerciseModel.userAnswer = _exerciseModel.answer;
  89. _exerciseModel.answerResultsType = RQAnswerResultsType_Correct;
  90. _exerciseDoType = RQExerciseDoType_ReadAndAnswer;
  91. [self rq_configureData];
  92. if (RQ_Exercise_Module.isAutoRead) RQ_Exercise_Module.isAutoRead = NO;
  93. return [self readAndAnswerWithExerciseModel:_exerciseModel];
  94. return [RACSignal empty];
  95. }] skillExplanationCommand:[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
  96. _exerciseModel.isShowSkillExplanation = YES;
  97. _exerciseDoType = RQExerciseDoType_SkillExplanation;
  98. if (RQ_Exercise_Module.isAutoRead) RQ_Exercise_Module.isAutoRead = NO;
  99. [self rq_configureData];
  100. return [RACSignal empty];
  101. }]];
  102. exerciseToolBarItemViewModel.rowHeight = 85.f;
  103. group4.itemViewModels = (self.exerciseType == RQExerciseType_Test || self.exerciseType == RQExerciseType_Exam)? @[] : @[exerciseToolBarItemViewModel];
  104. /// 第五组
  105. RQCommonGroupViewModel *group5 = [RQCommonGroupViewModel groupViewModel];
  106. group5.headerHeight = CGFLOAT_MIN;
  107. group5.footerHeight = CGFLOAT_MIN;
  108. RQExerciseExamToolBarItemViewModel *exerciseExamToolBarItemViewModel = [[RQExerciseExamToolBarItemViewModel alloc] initWithRQExerciseModel:self.exerciseModel homePageCarType:self.homePageCarType homePageSubject:self.homePageSubjectType readingQuestionsAndAnswerCommand:[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
  109. _exerciseModel.userAnswer = _exerciseModel.answer;
  110. _exerciseModel.answerResultsType = RQAnswerResultsType_Correct;
  111. _exerciseDoType = RQExerciseDoType_ReadAndAnswer;
  112. [self rq_configureData];
  113. if (RQ_Exercise_Module.isAutoRead) RQ_Exercise_Module.isAutoRead = NO;
  114. return [self readAndAnswerWithExerciseModel:_exerciseModel];
  115. return [RACSignal empty];
  116. }] skillExplanationCommand:[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
  117. _exerciseModel.isShowSkillExplanation = YES;
  118. _exerciseDoType = RQExerciseDoType_SkillExplanation;
  119. if (RQ_Exercise_Module.isAutoRead) RQ_Exercise_Module.isAutoRead = NO;
  120. [self rq_configureData];
  121. return [RACSignal empty];
  122. }] lastQuestionCommand:[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
  123. [self.lastQuestionCommand execute:nil];
  124. return [RACSignal empty];
  125. }] nextQuestionCommand:[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
  126. [self.nextQuestionCommand execute:nil];
  127. return [RACSignal empty];
  128. }] showCatalogueCommand:[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
  129. [self.showCatalogueCommand execute:nil];
  130. return [RACSignal empty];
  131. }]];
  132. exerciseExamToolBarItemViewModel.rowHeight = 160.f;
  133. group5.itemViewModels = (self.exerciseType != RQExerciseType_Test && self.exerciseType != RQExerciseType_Exam)? @[] : @[exerciseExamToolBarItemViewModel];
  134. /// 第一组
  135. RQCommonGroupViewModel *group1 = [RQCommonGroupViewModel groupViewModel];
  136. group1.headerHeight = CGFLOAT_MIN;
  137. group1.footerHeight = CGFLOAT_MIN;
  138. NSMutableArray *optionItemsArr = @[].mutableCopy;
  139. [[[self.exerciseModel.opts componentsSeparatedByString:@"-"].rac_sequence.signal deliverOnMainThread] subscribeNext:^(NSString * optionString) {
  140. if (RQStringIsEmpty(_exerciseModel.userAnswer)) {
  141. /// 未答题
  142. _exerciseOptionItemType = RQExerciseOptionItemType_Default;
  143. } else {
  144. /// 已答题
  145. if ([_exerciseModel.answer containsString:@"-"]) {
  146. /// 多选题
  147. if ([_exerciseModel.userAnswer containsString:@"预选Option"]) {
  148. /// 预选
  149. if ([_exerciseModel.userAnswer containsString:optionString]) {
  150. _exerciseOptionItemType = RQExerciseOptionItemType_Multiple_Primary;
  151. } else {
  152. _exerciseOptionItemType = RQExerciseOptionItemType_Default;
  153. }
  154. } else {
  155. /// 答题结果
  156. if ([_exerciseModel.answer isEqualToString:_exerciseModel.userAnswer]) {
  157. /// 答对了
  158. self.answerResultsType = RQAnswerResultsType_Correct;
  159. if ([_exerciseModel.answer containsString:optionString]) {
  160. /// 正确的选项
  161. _exerciseOptionItemType = RQExerciseOptionItemType_Correct_CorrectOption;
  162. } else {
  163. /// 错误的选项
  164. _exerciseOptionItemType = RQExerciseOptionItemType_Correct_ErrorOption;
  165. }
  166. } else {
  167. /// 答错了
  168. self.answerResultsType = RQAnswerResultsType_Error;
  169. if ([_exerciseModel.answer containsString:optionString]) {
  170. /// 正确的选项
  171. _exerciseOptionItemType = RQExerciseOptionItemType_Error_CorrectOption;
  172. } else {
  173. /// 错误的选项
  174. _exerciseOptionItemType = RQExerciseOptionItemType_Correct_ErrorOption;
  175. }
  176. }
  177. }
  178. } else {
  179. /// 单选题
  180. if ([_exerciseModel.answer isEqualToString:_exerciseModel.userAnswer]) {
  181. /// 答对了
  182. self.answerResultsType = RQAnswerResultsType_Correct;
  183. if ([optionString isEqualToString:_exerciseModel.answer]) {
  184. /// 正确的选项
  185. _exerciseOptionItemType = RQExerciseOptionItemType_Correct_CorrectOption;
  186. } else {
  187. /// 错误的选项
  188. _exerciseOptionItemType = RQExerciseOptionItemType_Correct_ErrorOption;
  189. }
  190. } else {
  191. /// 答错了
  192. self.answerResultsType = RQAnswerResultsType_Error;
  193. if ([optionString isEqualToString:_exerciseModel.answer]) {
  194. /// 正确的选项
  195. _exerciseOptionItemType = RQExerciseOptionItemType_Error_CorrectOption;
  196. } else {
  197. /// 错误的选项
  198. _exerciseOptionItemType = RQExerciseOptionItemType_Correct_ErrorOption;
  199. }
  200. }
  201. }
  202. }
  203. RQExerciseOptionItemViewModel *exerciseOptionItemViewModel = [[RQExerciseOptionItemViewModel alloc] initWithRQExerciseModel:self.exerciseModel opts:optionString RQExerciseOptionItemType:_exerciseOptionItemType exerciseType:self.exerciseType];
  204. exerciseOptionItemViewModel.rowHeight = 55.f;
  205. if ([_exerciseModel.answer containsString:@"-"]) {
  206. exerciseOptionItemViewModel.title = (([_exerciseModel.userAnswer containsString:optionString]) && self.answerResultsType != RQAnswerResultsType_Unanswered && self.exerciseType != RQExerciseType_Recitation)? @"" : self.optionLeftNameArr[[[self.exerciseModel.opts componentsSeparatedByString:@"-"] indexOfObject:optionString]];
  207. } else {
  208. exerciseOptionItemViewModel.title = ([optionString isEqualToString:_exerciseModel.userAnswer] && self.exerciseType != RQExerciseType_Recitation)? @"" : self.optionLeftNameArr[[[self.exerciseModel.opts componentsSeparatedByString:@"-"] indexOfObject:optionString]];
  209. }
  210. exerciseOptionItemViewModel.operation = ^{
  211. if ([_exerciseModel.answer containsString:@"-"]) {
  212. NSMutableArray *userArray = [NSMutableArray arrayWithArray:RQStringIsEmpty(_exerciseModel.userAnswer)? @[] : [_exerciseModel.userAnswer componentsSeparatedByString:@"-"]];
  213. if (userArray.count == 0) {
  214. [userArray addObject:@"预选Option"];
  215. }
  216. if ([userArray containsObject:optionString]) {
  217. [userArray removeObject:optionString];
  218. } else {
  219. [userArray addObject:optionString];
  220. }
  221. _exerciseModel.userAnswer = [userArray componentsJoinedByString:@"-"];
  222. } else {
  223. _exerciseModel.userAnswer = optionString;
  224. }
  225. [self rq_configureData];
  226. };
  227. [optionItemsArr addObject:exerciseOptionItemViewModel];
  228. } completed:^{
  229. group1.itemViewModels = optionItemsArr.copy;
  230. [self willChangeValueForKey:@"dataSource"];
  231. group3.itemViewModels = (self.answerResultsType == RQAnswerResultsType_Unanswered && [_exerciseModel.answer containsString:@"-"])? @[ exerciseOptionSureBtnItemViewModel
  232. ] : @[];
  233. self.dataSource = @[group0, group1, group2, group3, group4, group5];
  234. [self didChangeValueForKey:@"dataSource"];
  235. _exerciseModel.answerResultsType = _answerResultsType;
  236. [[NSNotificationCenter defaultCenter] postNotificationName:RQAnswerResultsNotification object:nil userInfo:@{
  237. RQAnswerResultsKey : _exerciseModel,
  238. RQHomePageCarTypeKey : @(self.homePageCarType),
  239. RQHomePageSubjectTypeKey: @(self.homePageSubjectType),
  240. RQExerciseDoTypeKey : @(self.exerciseDoType),
  241. }];
  242. }];
  243. }
  244. - (RACSignal *)readAndAnswerWithExerciseModel:(RQExerciseModel *)exerciseModel {
  245. return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  246. [RQ_MUSIC_MANAGER rq_resetStreamerWithURLString:exerciseModel.issuemp3 DOUAudioStreamerStatusBlock:^(DOUAudioStreamerStatus status) {
  247. if (status == DOUAudioStreamerFinished) {
  248. [RQ_MUSIC_MANAGER rq_resetStreamerWithURLString:exerciseModel.answermp3 DOUAudioStreamerStatusBlock:^(DOUAudioStreamerStatus status) {
  249. if (status == DOUAudioStreamerFinished) {
  250. [subscriber sendNext:@"DOUAudioStreamerFinished"];
  251. } else if (status == DOUAudioStreamerPlaying) {
  252. [subscriber sendNext:@"DOUAudioStreamerPlaying"];
  253. }
  254. }];
  255. } else if (status == DOUAudioStreamerPlaying) {
  256. [subscriber sendNext:@"DOUAudioStreamerPlaying"];
  257. }
  258. }];
  259. return [RACScopedDisposable disposableWithBlock:^{
  260. /// 取消任务
  261. }];
  262. }];
  263. }
  264. - (NSArray *)optionLeftNameArr {
  265. if (!_optionLeftNameArr) {
  266. _optionLeftNameArr = @[@"A", @"B", @"C", @"D"];
  267. }
  268. return _optionLeftNameArr;
  269. }
  270. @end