RQTestQuestionsViewModel.m 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  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. @property (nonatomic, readwrite, strong) RQCommonGroupViewModel *explainGroup;
  19. @property (nonatomic, readwrite, strong) RQExercisExplainItemViewModel *exercisExplainItemViewModel;
  20. @end
  21. @implementation RQTestQuestionsViewModel
  22. #pragma mark - Public Method
  23. - (instancetype)initWithServices:(id<RQViewModelServices>)services params:(NSDictionary *)params {
  24. if (self = [super initWithServices:services params:params]) {
  25. self.exerciseOptionItemType = RQExerciseOptionItemType_Default;
  26. self.answerResultsType = RQAnswerResultsType_Unanswered;
  27. self.exerciseType = [params[RQExerciseTypeKey] integerValue];
  28. self.exerciseModel = (RQExerciseModel *)params[RQViewModelUtilKey];
  29. self.homePageCarType = [params[RQHomePageCarTypeKey] integerValue];
  30. self.homePageSubjectType = [params[RQHomePageSubjectTypeKey] integerValue];
  31. self.exerciseDoType = RQExerciseDoType_Default;
  32. }
  33. return self;
  34. }
  35. - (void)initialize {
  36. [super initialize];
  37. self.title = @"";
  38. /// 隐藏导航栏的细线
  39. self.prefersNavigationBarBottomLineHidden = YES;
  40. ///配置数据
  41. // [self rq_configureData];
  42. }
  43. - (void)setExerciseModel:(RQExerciseModel *)exerciseModel {
  44. _exerciseModel = exerciseModel;
  45. [self rq_configureData];
  46. }
  47. #pragma mark - PrivateMethod
  48. - (void)rq_configureData {
  49. @weakify(self)
  50. /// 第零组:题目
  51. RQCommonGroupViewModel *group0 = [RQCommonGroupViewModel groupViewModel];
  52. group0.headerHeight = CGFLOAT_MIN;
  53. group0.footerHeight = CGFLOAT_MIN;
  54. RQExerciseQuestionItemViewModel *exerciseQuestionItemViewModel = [[RQExerciseQuestionItemViewModel alloc] initWithRQExerciseModel:self.exerciseModel];
  55. group0.itemViewModels = @[exerciseQuestionItemViewModel];
  56. /// 第二组:答案
  57. RQCommonGroupViewModel *group2 = [RQCommonGroupViewModel groupViewModel];
  58. group2.headerHeight = CGFLOAT_MIN;
  59. group2.footerHeight = CGFLOAT_MIN;
  60. RQExerciseAnswerItemViewModel *exerciseAnswerItemViewModel = [[RQExerciseAnswerItemViewModel alloc] initWithRQExerciseModel:self.exerciseModel];
  61. if (RQStringIsNotEmpty(_exerciseModel.userAnswer) && ![_exerciseModel.userAnswer containsString:@"预选Option"] && _exerciseType != RQExerciseType_Test && _exerciseType != RQExerciseType_Exam) {
  62. group2.itemViewModels = @[exerciseAnswerItemViewModel];
  63. } else {
  64. group2.itemViewModels = @[];
  65. }
  66. /// 第三组:多选题确定按钮
  67. RQCommonGroupViewModel *group3 = [RQCommonGroupViewModel groupViewModel];
  68. group3.headerHeight = CGFLOAT_MIN;
  69. group3.footerHeight = CGFLOAT_MIN;
  70. RQExerciseOptionSureBtnItemViewModel *exerciseOptionSureBtnItemViewModel = [[RQExerciseOptionSureBtnItemViewModel alloc] init];
  71. exerciseOptionSureBtnItemViewModel.rowHeight = RQ_FIT_HORIZONTAL(56.f);
  72. exerciseOptionSureBtnItemViewModel.operation = ^{
  73. @strongify(self)
  74. if ([_exerciseModel.userAnswer containsString:@"预选Option-"]) {
  75. NSString *userAnswerStr = _exerciseModel.userAnswer;
  76. userAnswerStr = [userAnswerStr stringByReplacingOccurrencesOfString:@"预选Option-" withString:@""];
  77. _exerciseModel.userAnswer = userAnswerStr;
  78. [self rq_configureData];
  79. } else {
  80. }
  81. };
  82. if ([_exerciseModel.answer containsString:@"-"] && self.answerResultsType == RQAnswerResultsType_Unanswered) {
  83. group3.itemViewModels = @[exerciseOptionSureBtnItemViewModel];
  84. } else {
  85. group3.itemViewModels = @[];
  86. }
  87. /// 第四组:练习模式的《收藏、读题+答案、读题、技巧讲解》工具栏
  88. RQCommonGroupViewModel *group4 = [RQCommonGroupViewModel groupViewModel];
  89. group4.headerHeight = CGFLOAT_MIN;
  90. group4.footerHeight = CGFLOAT_MIN;
  91. RQExerciseToolBarItemViewModel *exerciseToolBarItemViewModel = [[RQExerciseToolBarItemViewModel alloc] initWithRQExerciseModel:self.exerciseModel homePageCarType:self.homePageCarType homePageSubject:self.homePageSubjectType readingQuestionsAndAnswerCommand:[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
  92. @strongify(self)
  93. _exerciseModel.userAnswer = _exerciseModel.answer;
  94. _exerciseModel.answerResultsType = RQAnswerResultsType_Correct;
  95. _exerciseDoType = RQExerciseDoType_ReadAndAnswer;
  96. // self.explainGroup.itemViewModels = RQObjectIsNil(self.exercisExplainItemViewModel.explainModel)? @[] : @[self.exercisExplainItemViewModel];
  97. [self rq_configureData];
  98. if (RQ_Exercise_Module.isAutoRead) RQ_Exercise_Module.isAutoRead = NO;
  99. // return [self readAndAnswerWithExerciseModel:_exerciseModel];
  100. return [RACSignal empty];
  101. }] skillExplanationCommand:[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
  102. @strongify(self)
  103. _exerciseModel.isShowSkillExplanation = YES;
  104. _exerciseDoType = RQExerciseDoType_SkillExplanation;
  105. if (RQ_Exercise_Module.isAutoRead) RQ_Exercise_Module.isAutoRead = NO;
  106. [self rq_configureData];
  107. return [RACSignal empty];
  108. }]];
  109. exerciseToolBarItemViewModel.rowHeight = RQ_FIT_HORIZONTAL(85.f);
  110. group4.itemViewModels = (self.exerciseType == RQExerciseType_Test || self.exerciseType == RQExerciseType_Exam)? @[] : @[exerciseToolBarItemViewModel];
  111. /// 第五组:底部工具栏
  112. RQCommonGroupViewModel *group5 = [RQCommonGroupViewModel groupViewModel];
  113. group5.headerHeight = CGFLOAT_MIN;
  114. group5.footerHeight = CGFLOAT_MIN;
  115. RQExerciseExamToolBarItemViewModel *exerciseExamToolBarItemViewModel = [[RQExerciseExamToolBarItemViewModel alloc] initWithRQExerciseModel:self.exerciseModel homePageCarType:self.homePageCarType homePageSubject:self.homePageSubjectType readingQuestionsAndAnswerCommand:[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
  116. @strongify(self)
  117. _exerciseModel.userAnswer = _exerciseModel.answer;
  118. _exerciseModel.answerResultsType = RQAnswerResultsType_Correct;
  119. _exerciseDoType = RQExerciseDoType_ReadAndAnswer;
  120. [self rq_configureData];
  121. if (RQ_Exercise_Module.isAutoRead) RQ_Exercise_Module.isAutoRead = NO;
  122. // return [self readAndAnswerWithExerciseModel:_exerciseModel];
  123. return [RACSignal empty];
  124. }] skillExplanationCommand:[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
  125. @strongify(self)
  126. _exerciseModel.isShowSkillExplanation = YES;
  127. _exerciseDoType = RQExerciseDoType_SkillExplanation;
  128. if (RQ_Exercise_Module.isAutoRead) RQ_Exercise_Module.isAutoRead = NO;
  129. [self rq_configureData];
  130. return [RACSignal empty];
  131. }] lastQuestionCommand:[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
  132. @strongify(self)
  133. [self.lastQuestionCommand execute:nil];
  134. return [RACSignal empty];
  135. }] nextQuestionCommand:[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
  136. @strongify(self)
  137. [self.nextQuestionCommand execute:nil];
  138. return [RACSignal empty];
  139. }] showCatalogueCommand:[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
  140. @strongify(self)
  141. [self.showCatalogueCommand execute:nil];
  142. return [RACSignal empty];
  143. }]];
  144. exerciseExamToolBarItemViewModel.rowHeight = RQ_FIT_HORIZONTAL(80.f);
  145. group5.itemViewModels = (self.exerciseType != RQExerciseType_Test && self.exerciseType != RQExerciseType_Exam)? @[] : @[exerciseExamToolBarItemViewModel];
  146. /// 第一组:选项
  147. RQCommonGroupViewModel *group1 = [RQCommonGroupViewModel groupViewModel];
  148. group1.headerHeight = CGFLOAT_MIN;
  149. group1.footerHeight = CGFLOAT_MIN;
  150. NSMutableArray *optionItemsArr = @[].mutableCopy;
  151. [[[self.exerciseModel.opts componentsSeparatedByString:@"-"].rac_sequence.signal deliverOnMainThread] subscribeNext:^(NSString * optionString) {
  152. @strongify(self)
  153. if (RQStringIsEmpty(_exerciseModel.userAnswer)) {
  154. /// 未答题
  155. _exerciseOptionItemType = RQExerciseOptionItemType_Default;
  156. } else {
  157. /// 已答题
  158. if ([_exerciseModel.answer containsString:@"-"]) {
  159. /// 多选题
  160. if ([_exerciseModel.userAnswer containsString:@"预选Option"]) {
  161. /// 预选
  162. if ([_exerciseModel.userAnswer containsString:optionString]) {
  163. _exerciseOptionItemType = RQExerciseOptionItemType_Multiple_Primary;
  164. } else {
  165. _exerciseOptionItemType = RQExerciseOptionItemType_Default;
  166. }
  167. } else {
  168. /// 答题结果
  169. NSArray * arr1 = [_exerciseModel.answer componentsSeparatedByString:@"-"];
  170. NSArray * arr2 = [_exerciseModel.userAnswer componentsSeparatedByString:@"-"];
  171. NSPredicate * filterPredicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)",arr1];
  172. NSArray * filter = [arr2 filteredArrayUsingPredicate:filterPredicate];
  173. if (filter.count == 0) {
  174. /// 答对了
  175. self.answerResultsType = RQAnswerResultsType_Correct;
  176. if ([_exerciseModel.answer containsString:optionString]) {
  177. /// 正确的选项
  178. _exerciseOptionItemType = RQExerciseOptionItemType_Correct_CorrectOption;
  179. } else {
  180. /// 错误的选项
  181. _exerciseOptionItemType = RQExerciseOptionItemType_Correct_ErrorOption;
  182. }
  183. } else {
  184. /// 答错了
  185. self.answerResultsType = RQAnswerResultsType_Error;
  186. if ([_exerciseModel.answer containsString:optionString]) {
  187. /// 正确的选项
  188. _exerciseOptionItemType = RQExerciseOptionItemType_Error_CorrectOption;
  189. } else {
  190. /// 错误的选项
  191. _exerciseOptionItemType = RQExerciseOptionItemType_Correct_ErrorOption;
  192. }
  193. }
  194. // if ([_exerciseModel.answer isEqualToString:_exerciseModel.userAnswer]) {
  195. // /// 答对了
  196. // self.answerResultsType = RQAnswerResultsType_Correct;
  197. // if ([_exerciseModel.answer containsString:optionString]) {
  198. // /// 正确的选项
  199. // _exerciseOptionItemType = RQExerciseOptionItemType_Correct_CorrectOption;
  200. // } else {
  201. // /// 错误的选项
  202. // _exerciseOptionItemType = RQExerciseOptionItemType_Correct_ErrorOption;
  203. // }
  204. // } else {
  205. // /// 答错了
  206. // self.answerResultsType = RQAnswerResultsType_Error;
  207. // if ([_exerciseModel.answer containsString:optionString]) {
  208. // /// 正确的选项
  209. // _exerciseOptionItemType = RQExerciseOptionItemType_Error_CorrectOption;
  210. // } else {
  211. // /// 错误的选项
  212. // _exerciseOptionItemType = RQExerciseOptionItemType_Correct_ErrorOption;
  213. // }
  214. // }
  215. }
  216. } else {
  217. /// 单选题
  218. if ([_exerciseModel.answer isEqualToString:_exerciseModel.userAnswer]) {
  219. /// 答对了
  220. self.answerResultsType = RQAnswerResultsType_Correct;
  221. if ([optionString isEqualToString:_exerciseModel.answer]) {
  222. /// 正确的选项
  223. _exerciseOptionItemType = RQExerciseOptionItemType_Correct_CorrectOption;
  224. } else {
  225. /// 错误的选项
  226. _exerciseOptionItemType = RQExerciseOptionItemType_Correct_ErrorOption;
  227. }
  228. } else {
  229. /// 答错了
  230. self.answerResultsType = RQAnswerResultsType_Error;
  231. if ([optionString isEqualToString:_exerciseModel.answer]) {
  232. /// 正确的选项
  233. _exerciseOptionItemType = RQExerciseOptionItemType_Error_CorrectOption;
  234. } else {
  235. /// 错误的选项
  236. _exerciseOptionItemType = RQExerciseOptionItemType_Correct_ErrorOption;
  237. }
  238. }
  239. }
  240. }
  241. RQExerciseOptionItemViewModel *exerciseOptionItemViewModel = [[RQExerciseOptionItemViewModel alloc] initWithRQExerciseModel:self.exerciseModel opts:optionString RQExerciseOptionItemType:_exerciseOptionItemType exerciseType:self.exerciseType];
  242. exerciseOptionItemViewModel.rowHeight = RQ_FIT_HORIZONTAL(55.f);
  243. if ([_exerciseModel.answer containsString:@"-"]) {
  244. exerciseOptionItemViewModel.title = (([_exerciseModel.userAnswer containsString:optionString]) && self.answerResultsType != RQAnswerResultsType_Unanswered && self.exerciseType != RQExerciseType_Recitation)? @"" : self.optionLeftNameArr[[[self.exerciseModel.opts componentsSeparatedByString:@"-"] indexOfObject:optionString]];
  245. } else {
  246. exerciseOptionItemViewModel.title = ([optionString isEqualToString:_exerciseModel.userAnswer] && self.exerciseType != RQExerciseType_Recitation)? @"" : self.optionLeftNameArr[[[self.exerciseModel.opts componentsSeparatedByString:@"-"] indexOfObject:optionString]];
  247. }
  248. exerciseOptionItemViewModel.operation = ^{
  249. @strongify(self)
  250. if ([_exerciseModel.answer containsString:@"-"]) {
  251. NSMutableArray *userArray = [NSMutableArray arrayWithArray:RQStringIsEmpty(_exerciseModel.userAnswer)? @[] : [_exerciseModel.userAnswer componentsSeparatedByString:@"-"]];
  252. if (userArray.count == 0) {
  253. [userArray addObject:@"预选Option"];
  254. }
  255. if ([userArray containsObject:optionString]) {
  256. [userArray removeObject:optionString];
  257. } else {
  258. [userArray addObject:optionString];
  259. }
  260. NSString *myAnswer = [userArray componentsJoinedByString:@"-"];
  261. _exerciseModel.userAnswer = myAnswer;
  262. } else {
  263. _exerciseModel.userAnswer = optionString;
  264. }
  265. [self rq_configureData];
  266. };
  267. [optionItemsArr addObject:exerciseOptionItemViewModel];
  268. } completed:^{
  269. @strongify(self)
  270. group1.itemViewModels = optionItemsArr.copy;
  271. [self willChangeValueForKey:@"dataSource"];
  272. group3.itemViewModels = (self.answerResultsType == RQAnswerResultsType_Unanswered && [_exerciseModel.answer containsString:@"-"])? @[ exerciseOptionSureBtnItemViewModel
  273. ] : @[];
  274. if (_answerResultsType != RQAnswerResultsType_Unanswered) {
  275. self.explainGroup.itemViewModels = RQObjectIsNil(self.exercisExplainItemViewModel.explainModel)? @[] : @[self.exercisExplainItemViewModel];
  276. }
  277. self.dataSource = (self.exerciseType != RQExerciseType_Test && self.exerciseType != RQExerciseType_Exam)? @[group0, group1, group2, group3, group4, self.explainGroup, group5] : @[group0, group1, group2, group3, group4, group5, self.explainGroup];
  278. [self didChangeValueForKey:@"dataSource"];
  279. _exerciseModel.answerResultsType = _answerResultsType;
  280. [[NSNotificationCenter defaultCenter] postNotificationName:RQAnswerResultsNotification object:nil userInfo:@{
  281. RQAnswerResultsKey : _exerciseModel,
  282. RQHomePageCarTypeKey : @(self.homePageCarType),
  283. RQHomePageSubjectTypeKey: @(self.homePageSubjectType),
  284. RQExerciseDoTypeKey : @(self.exerciseDoType),
  285. }];
  286. }];
  287. }
  288. - (RACSignal *)readAndAnswerWithExerciseModel:(RQExerciseModel *)exerciseModel {
  289. return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  290. [RQ_MUSIC_MANAGER rq_resetStreamerWithURLString:exerciseModel.issuemp3 DOUAudioStreamerStatusBlock:^(DOUAudioStreamerStatus status) {
  291. if (status == DOUAudioStreamerFinished) {
  292. [RQ_MUSIC_MANAGER rq_resetStreamerWithURLString:exerciseModel.answermp3 DOUAudioStreamerStatusBlock:^(DOUAudioStreamerStatus status) {
  293. if (status == DOUAudioStreamerFinished) {
  294. [subscriber sendNext:@"DOUAudioStreamerFinished"];
  295. } else if (status == DOUAudioStreamerPlaying) {
  296. [subscriber sendNext:@"DOUAudioStreamerPlaying"];
  297. }
  298. }];
  299. } else if (status == DOUAudioStreamerPlaying) {
  300. [subscriber sendNext:@"DOUAudioStreamerPlaying"];
  301. }
  302. }];
  303. return [RACScopedDisposable disposableWithBlock:^{
  304. /// 取消任务
  305. }];
  306. }];
  307. }
  308. - (NSArray *)optionLeftNameArr {
  309. if (!_optionLeftNameArr) {
  310. _optionLeftNameArr = @[@"A", @"B", @"C", @"D"];
  311. }
  312. return _optionLeftNameArr;
  313. }
  314. - (RQCommonGroupViewModel *)explainGroup {
  315. if (!_explainGroup) {
  316. _explainGroup = [RQCommonGroupViewModel groupViewModel];
  317. }
  318. return _explainGroup;
  319. }
  320. - (RQExercisExplainItemViewModel *)exercisExplainItemViewModel {
  321. if (!_exercisExplainItemViewModel) {
  322. _exercisExplainItemViewModel = [[RQExercisExplainItemViewModel alloc] initWithRQExerciseModel:self.exerciseModel];
  323. }
  324. return _exercisExplainItemViewModel;
  325. }
  326. @end