RQQuestionDBManager.m 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. //
  2. // RQQuestionDBManager.m
  3. // SDJK
  4. //
  5. // Created by 张嵘 on 2021/8/20.
  6. //
  7. #import "RQQuestionDBManager.h"
  8. static NSString *dbNameStr = @"question";
  9. static NSString *dbTypeStr = @"db";
  10. static NSString *questionTableNameStr = @"question_info";
  11. @interface RQQuestionDBManager ()
  12. @property (nonatomic, readwrite, strong) FMDatabaseQueue *databaseQueue;
  13. @end
  14. @implementation RQQuestionDBManager
  15. static id rq_questionDBManager = nil;
  16. #pragma mark - init
  17. + (instancetype)sharedInstance {
  18. static dispatch_once_t onceToken;
  19. dispatch_once(&onceToken, ^{
  20. rq_questionDBManager = [[self alloc] init];
  21. });
  22. return rq_questionDBManager;
  23. }
  24. - (instancetype)init {
  25. if (self = [super init]) {
  26. NSString *resourcePath = [[NSBundle mainBundle] pathForResource:@"question" ofType:@"db"];
  27. [self initDatabaseQueueWithResourcePath:resourcePath];
  28. }
  29. return self;
  30. }
  31. - (void)initDatabaseQueueWithResourcePath:(NSString *)resourcePath {
  32. NSError *error;
  33. NSString *dbPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:[NSString stringWithFormat:@"question.db"]];
  34. if ([RQFileManager isPathExist:dbPath]) {
  35. self.databaseQueue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
  36. NSLog(@"数据库path-----%@",dbPath);
  37. if ([self getQuestionVersion] >= [self getQuestionVersionWithResourcePath:resourcePath]) {
  38. } else {
  39. [[RQFileManager fileManager] removeItemAtPath:dbPath error:&error];
  40. [[RQFileManager fileManager] copyItemAtPath:resourcePath toPath:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:[NSString stringWithFormat:@"question.db"]] error:&error];
  41. self.databaseQueue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
  42. }
  43. } else {
  44. [[RQFileManager fileManager] copyItemAtPath:resourcePath toPath:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:[NSString stringWithFormat:@"question.db"]] error:&error];
  45. self.databaseQueue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
  46. NSLog(@"数据库path-----%@",dbPath);
  47. }
  48. }
  49. #pragma mark - Public Method
  50. - (NSArray *)getColumnWithCarType:(RQHomePageCarType)carType subject:(RQHomePageSubjectType)subject pageType:(RQHomeSubPageType)pageType {
  51. /// 默认为轿车 cart,bus,truck
  52. NSString *queryCarTypeStr = @"model LIKE '%cart%'";
  53. switch (carType) {
  54. case RQHomePageCarType_Car:
  55. queryCarTypeStr = @"model LIKE '%cart%'";
  56. break;
  57. case RQHomePageCarType_Bus:
  58. queryCarTypeStr = @"model LIKE '%bus%'";
  59. break;
  60. case RQHomePageCarType_Truck:
  61. queryCarTypeStr = @"model LIKE '%truck%'";
  62. break;
  63. case RQHomePageCarType_Motorcycle:
  64. queryCarTypeStr = @"model LIKE '%mtc%'";
  65. break;
  66. default:
  67. break;
  68. }
  69. /// 默认科目一
  70. NSString *querySubjectTypeStr = @"k1";
  71. switch (subject) {
  72. case RQHomePageSubjectType_SubjectOne:
  73. querySubjectTypeStr = @"k1";
  74. break;
  75. case RQHomePageSubjectType_SubjectTwo:
  76. querySubjectTypeStr = @"k2";
  77. break;
  78. case RQHomePageSubjectType_SubjectThree:
  79. querySubjectTypeStr = @"k3";
  80. break;
  81. case RQHomePageSubjectType_SubjectFour:
  82. querySubjectTypeStr = @"k4";
  83. break;
  84. default:
  85. break;
  86. }
  87. /// 默认顺序练习
  88. NSString *pageTypeStr = @"title";
  89. NSString *pageTypeByOrderStr = @"sort";
  90. switch (pageType) {
  91. case RQHomeSubPageType_SequentialPractice:/// 顺序练习
  92. pageTypeStr = @"title,column_id";
  93. pageTypeByOrderStr = @"sort";
  94. querySubjectTypeStr = [NSString stringWithFormat:@"subject = '%@'",querySubjectTypeStr];
  95. break;
  96. case RQHomeSubPageType_LocalTopics: /// 地方专题
  97. pageTypeStr = @"place_issue_name";
  98. pageTypeByOrderStr = @"place_issue";
  99. break;
  100. case RQHomeSubPageType_ClassificationExercise:/// 分类练习
  101. pageTypeStr = @"title,column_id";
  102. pageTypeByOrderStr = @"sort";
  103. querySubjectTypeStr = [NSString stringWithFormat:@"%@_3",querySubjectTypeStr];
  104. querySubjectTypeStr = [NSString stringWithFormat:@"subject = '%@'",querySubjectTypeStr];
  105. break;
  106. case RQHomeSubPageType_SelectedTestQuestions: //精选考题
  107. pageTypeStr = @"title,column_id";
  108. pageTypeByOrderStr = @"sort";
  109. querySubjectTypeStr = [NSString stringWithFormat:@"%@_2",querySubjectTypeStr];
  110. querySubjectTypeStr = [NSString stringWithFormat:@"subject = '%@'",querySubjectTypeStr];
  111. break;
  112. default:
  113. break;
  114. }
  115. //v1.1.2 旧逻辑
  116. // NSString *queryStr = [NSString stringWithFormat:@"select distinct %@ from question_info where %@ and %@ %@ order by %@ + 0 ASC", pageTypeStr, queryCarTypeStr, querySubjectTypeStr, (pageType == RQHomeSubPageType_LocalTopics)? @"and place_issue IS NOT NULL" : @"", pageTypeByOrderStr];
  117. //v1.1.3
  118. NSString *queryStr = [NSString stringWithFormat:@"select distinct %@ from question_column where %@ and %@ order by %@ + 0 ASC", pageTypeStr, queryCarTypeStr, querySubjectTypeStr, pageTypeByOrderStr];
  119. // select distinct * from WHERE subject = 'k1_2' AND model LIKE '%cart%' order by sort ASC
  120. NSMutableArray *arr = @[].mutableCopy;
  121. @weakify(arr)
  122. [_databaseQueue inTransaction:^(FMDatabase * _Nonnull db, BOOL * _Nonnull rollback) {
  123. @try {
  124. @strongify(arr)
  125. FMResultSet *resultSet = [db executeQuery:queryStr];
  126. while ([resultSet next]) {
  127. if([pageTypeStr containsString:@","]){
  128. NSString *str = [resultSet stringForColumn:@"title"];
  129. NSString *strCol = [resultSet stringForColumn:@"column_id"];
  130. NSString *str_title = [NSString stringWithFormat:@"%@,%@",str,strCol];
  131. // 对应字段来取数据
  132. [arr addObject:str_title? : @"地方题"];
  133. }else{
  134. NSString *str = [resultSet stringForColumn:pageTypeStr];
  135. // 对应字段来取数据
  136. [arr addObject:str? : @"地方题"];
  137. }
  138. }
  139. if ([arr containsObject:@"地方题"] && [arr indexOfObject:@"地方题"] == 0) {
  140. NSString *saveStr = arr.firstObject;
  141. [arr removeFirstObject];
  142. [arr addObject:saveStr];
  143. }
  144. } @catch (NSException *exception) {
  145. *rollback = YES;
  146. } @finally {
  147. *rollback = NO;
  148. }
  149. }];
  150. return arr.copy;
  151. }
  152. - (NSArray *)getQuestionWithCarType:(RQHomePageCarType)carType subject:(RQHomePageSubjectType)subject pageType:(RQHomeSubPageType)pageType name:(NSString *)name exerciseType:(RQExerciseType)exerciseType {
  153. NSMutableArray *arr = @[].mutableCopy;
  154. /// 默认为轿车 cart,bus,truck
  155. NSString *queryCarTypeStr = @"model LIKE '%cart%'";
  156. NSString *carTypeStr = @"cart";
  157. switch (carType) {
  158. case RQHomePageCarType_Car:
  159. queryCarTypeStr = @"model LIKE '%cart%'";
  160. carTypeStr = @"cart";
  161. break;
  162. case RQHomePageCarType_Bus:
  163. queryCarTypeStr = @"model LIKE '%bus%'";
  164. carTypeStr = @"bus";
  165. break;
  166. case RQHomePageCarType_Truck:
  167. queryCarTypeStr = @"model LIKE '%truck%'";
  168. carTypeStr = @"truck";
  169. break;
  170. case RQHomePageCarType_Motorcycle:
  171. queryCarTypeStr = @"model LIKE '%mtc%'";
  172. break;
  173. default:
  174. break;
  175. }
  176. /// 默认科目一
  177. NSString *querySubjectTypeStr = @"subject = 1";
  178. NSString *subjectTypeStr = @"1";
  179. switch (subject) {
  180. case RQHomePageSubjectType_SubjectOne:
  181. querySubjectTypeStr = @"subject = 1";
  182. subjectTypeStr = @"1";
  183. break;
  184. case RQHomePageSubjectType_SubjectTwo:
  185. querySubjectTypeStr = @"subject = 2";
  186. subjectTypeStr = @"2";
  187. break;
  188. case RQHomePageSubjectType_SubjectThree:
  189. querySubjectTypeStr = @"subject = 3";
  190. subjectTypeStr = @"3";
  191. break;
  192. case RQHomePageSubjectType_SubjectFour:
  193. querySubjectTypeStr = @"subject = 4";
  194. subjectTypeStr = @"4";
  195. break;
  196. default:
  197. break;
  198. }
  199. /// 默认顺序练习
  200. // NSString *pageTypeStr = @"seque_issue_name";
  201. // NSString *pageTypeByOrderStr = @"seque_issue";
  202. NSString *nameStr = @"";
  203. NSString *orderStr = @"";
  204. NSString *colidStr = @"";
  205. if([name containsString:@","]){
  206. colidStr = [[name componentsSeparatedByString:@","] lastObject];
  207. }
  208. switch (pageType) {
  209. //// pageTypeStr = @"place_issue_name";
  210. //// pageTypeByOrderStr = @"place_issue";
  211. // nameStr = [NSString stringWithFormat:@"and place_issue_name = '%@'",name];
  212. // orderStr = @"number";
  213. // break;
  214. case RQHomeSubPageType_LocalTopics:
  215. case RQHomeSubPageType_ClassificationExercise:
  216. case RQHomeSubPageType_SequentialPractice:
  217. case RQHomeSubPageType_SelectedTestQuestions:
  218. // pageTypeStr = @"excell_issue_name";
  219. // pageTypeByOrderStr = @"excell_issue";
  220. nameStr = [NSString stringWithFormat:@"(INSTR ( column_all, ',' || '%@' || ',' ) > 0 OR INSTR ( column_all, '%@' || ',' ) = 1 OR INSTR ( column_all, ',' || '%@' ) = ( length( column_all ) - length( ',' || '%@' ) ) + 1 OR column_all = '%@')",colidStr,colidStr,colidStr,colidStr,colidStr];
  221. orderStr = @"number";
  222. break;
  223. default:
  224. break;
  225. }
  226. if (RQStringIsEmpty(name)) {
  227. nameStr = @"";
  228. }
  229. /// excell_sort
  230. /// 默认按_id排序
  231. NSString *exerciseTypeStr = [NSString stringWithFormat:@"%@ + 0 ASC", orderStr];
  232. switch (exerciseType) {
  233. case RQExerciseType_Sequential:
  234. // exerciseTypeStr = [NSString stringWithFormat:@"%@ + 0 ASC", orderStr];
  235. break;
  236. case RQExerciseType_Random:
  237. // exerciseTypeStr = @"random()";
  238. break;
  239. case RQExerciseType_Recitation:
  240. // exerciseTypeStr = [NSString stringWithFormat:@"%@ + 0 ASC", orderStr];
  241. break;
  242. case RQExerciseType_Test:
  243. // exerciseTypeStr = @"random() limit 50";
  244. break;
  245. case RQExerciseType_Exam:
  246. // exerciseTypeStr = @"random() limit 5";
  247. break;
  248. default:
  249. break;
  250. }
  251. // resultSet = [_db executeQuery:@"select * from question_info where answer like '%-%'"];
  252. NSString *queryStr = [NSString stringWithFormat:@"select * from question_info where %@ and %@ order by %@", queryCarTypeStr, nameStr, exerciseTypeStr];
  253. @weakify(queryStr)
  254. if (pageType == RQHomeSubPageType_MockExamination && exerciseType == RQExerciseType_Test) {
  255. NSString *excellIssueNameStr = (carType == RQHomePageCarType_Motorcycle)? @"" : @"AND excell_issue_name LIKE '%%必%%'";
  256. NSString *newExcellIssueNameStr = (carType == RQHomePageCarType_Motorcycle)? @"" : @"AND excell_issue_name LIKE '%%新%%'";
  257. RACSignal *signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  258. @strongify(queryStr)
  259. queryStr = [NSString stringWithFormat:@"select * from question_info where %@ and %@ %@ and question_type = 1 and place_issue IS NULL %@ order by %@", queryCarTypeStr, querySubjectTypeStr, nameStr, excellIssueNameStr, [self getQuestionNumQueryStrWithCarType:carType subject:subject questionType:RQQuestionType_Judgment isNew:NO]];
  260. [subscriber sendNext:[self queryQuestionWithQueryStr:queryStr exerciseType:exerciseType]];
  261. [subscriber sendCompleted];
  262. return [RACDisposable disposableWithBlock:^{
  263. }];
  264. }];
  265. RACSignal *signal2 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  266. @strongify(queryStr)
  267. queryStr = [NSString stringWithFormat:@"select * from question_info where %@ and %@ %@ and question_type = 1 and place_issue IS NULL %@ order by %@", queryCarTypeStr, querySubjectTypeStr, nameStr, newExcellIssueNameStr, [self getQuestionNumQueryStrWithCarType:carType subject:subject questionType:RQQuestionType_Judgment isNew:YES]];
  268. [subscriber sendNext:[self queryQuestionWithQueryStr:queryStr exerciseType:exerciseType]];
  269. [subscriber sendCompleted];
  270. return [RACDisposable disposableWithBlock:^{
  271. }];
  272. }];
  273. RACSignal *signal3 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  274. @strongify(queryStr)
  275. queryStr = [NSString stringWithFormat:@"select * from question_info where %@ and %@ %@ and question_type = 2 and place_issue IS NULL %@ order by %@", queryCarTypeStr, querySubjectTypeStr, nameStr, excellIssueNameStr, [self getQuestionNumQueryStrWithCarType:carType subject:subject questionType:RQQuestionType_SingleChoice isNew:NO]];
  276. [subscriber sendNext:[self queryQuestionWithQueryStr:queryStr exerciseType:exerciseType]];
  277. [subscriber sendCompleted];
  278. return [RACDisposable disposableWithBlock:^{
  279. }];
  280. }];
  281. RACSignal *signal4 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  282. @strongify(queryStr)
  283. queryStr = [NSString stringWithFormat:@"select * from question_info where %@ and %@ %@ and question_type = 2 and place_issue IS NULL %@ order by %@", queryCarTypeStr, querySubjectTypeStr, nameStr, newExcellIssueNameStr, [self getQuestionNumQueryStrWithCarType:carType subject:subject questionType:RQQuestionType_SingleChoice isNew:YES]];
  284. [subscriber sendNext:[self queryQuestionWithQueryStr:queryStr exerciseType:exerciseType]];
  285. [subscriber sendCompleted];
  286. return [RACDisposable disposableWithBlock:^{
  287. }];
  288. }];
  289. RACSignal *signal5 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  290. @strongify(queryStr)
  291. queryStr = [NSString stringWithFormat:@"select * from question_info where %@ and %@ %@ and question_type = 3 and place_issue IS NULL %@ order by %@", queryCarTypeStr, querySubjectTypeStr, nameStr, excellIssueNameStr, [self getQuestionNumQueryStrWithCarType:carType subject:subject questionType:RQQuestionType_MultipleChoice isNew:NO]];
  292. [subscriber sendNext:[self queryQuestionWithQueryStr:queryStr exerciseType:exerciseType]];
  293. [subscriber sendCompleted];
  294. return [RACDisposable disposableWithBlock:^{
  295. }];
  296. }];
  297. RACSignal *signal6 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  298. @strongify(queryStr)
  299. queryStr = [NSString stringWithFormat:@"select * from question_info where %@ and %@ %@ and question_type = 3 and place_issue IS NULL %@ order by %@", queryCarTypeStr, querySubjectTypeStr, nameStr, newExcellIssueNameStr, [self getQuestionNumQueryStrWithCarType:carType subject:subject questionType:RQQuestionType_MultipleChoice isNew:YES]];
  300. [subscriber sendNext:[self queryQuestionWithQueryStr:queryStr exerciseType:exerciseType]];
  301. [subscriber sendCompleted];
  302. return [RACDisposable disposableWithBlock:^{
  303. }];
  304. }];
  305. RACSignal *signal = [RACSignal combineLatest:@[signal1, signal2, signal3, signal4, signal5, signal6] reduce:^id (NSArray *arr1, NSArray *arr2, NSArray *arr3, NSArray *arr4, NSArray *arr5, NSArray *arr6) {
  306. NSMutableArray *judgmentArr = @[].mutableCopy;
  307. [judgmentArr addObjectsFromArray:arr1];
  308. [judgmentArr addObjectsFromArray:arr2];
  309. judgmentArr = [judgmentArr rq_randomArray].mutableCopy;
  310. NSMutableArray *singleChoiceArr = @[].mutableCopy;
  311. [singleChoiceArr addObjectsFromArray:arr3];
  312. [singleChoiceArr addObjectsFromArray:arr4];
  313. singleChoiceArr = [singleChoiceArr rq_randomArray].mutableCopy;
  314. NSMutableArray *multipleChoiceArr = @[].mutableCopy;
  315. [multipleChoiceArr addObjectsFromArray:arr5];
  316. [multipleChoiceArr addObjectsFromArray:arr6];
  317. multipleChoiceArr = [multipleChoiceArr rq_randomArray].mutableCopy;
  318. [arr addObjectsFromArray:judgmentArr];
  319. [arr addObjectsFromArray:singleChoiceArr];
  320. [arr addObjectsFromArray:multipleChoiceArr];
  321. return arr.copy;
  322. }];
  323. [signal subscribeNext:^(NSArray *allArr) {
  324. }];
  325. return arr.copy;
  326. } else if (pageType == RQHomeSubPageType_MockExamination && exerciseType == RQExerciseType_Exam) {
  327. @weakify(self)
  328. RACSignal *signal0 = [RQ_HTTP_Service getSelectTestK14QuestionInfoList:carTypeStr subject:subjectTypeStr];
  329. [[signal0 takeUntil:self.rac_willDeallocSignal] subscribeNext:^(NSArray *array) {
  330. NSLog(@"%@",array);
  331. } error:^(NSError * _Nullable error) {
  332. }];
  333. RACSignal *signal = [RACSignal combineLatest:@[signal0] reduce:^id (NSArray *arr1) {
  334. NSLog(@"signal0=========%@",arr1);
  335. [arr addObjectsFromArray:arr1];
  336. return arr.copy;
  337. }];
  338. [signal subscribeNext:^(NSArray *allArr) {
  339. }];
  340. return arr.copy;
  341. // RACSignal *signal0 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  342. // @strongify(self)
  343. // NSMutableArray *difficultArr = @[].mutableCopy;
  344. //
  345. //// [[[self getExamRuleWithCarType:carType subject:subject].rac_sequence.signal map:^id _Nullable(RQExamRuleModel *examRuleModel) {
  346. //// NSString *chapterIdStr = [NSString stringWithFormat:@"chapter_id = %ld",(long)examRuleModel.chapter_id];
  347. //// NSString *typeStr = [NSString stringWithFormat:@"question_type IN %@",(subject == RQHomePageSubjectType_SubjectOne)? @"(1, 2)" : @"(1, 2, 3)"];
  348. //// NSString *randomStr = [NSString stringWithFormat:@"RANDOM() LIMIT %@",[NSString qmui_stringWithNSInteger:examRuleModel.difficult_count]];
  349. //// NSString *difficultQueryStr = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@ AND %@ AND diff_degree IN (4, 5) AND place_issue IS NULL AND %@ AND %@ ORDER BY %@",questionTableNameStr , queryCarTypeStr, querySubjectTypeStr, chapterIdStr, typeStr, randomStr];
  350. //// return difficultQueryStr;
  351. //// }].toArray.rac_sequence.signal subscribeNext:^(NSString *difficultQueryStr) {
  352. //// @strongify(self)
  353. //// [difficultArr addObjectsFromArray:[self queryQuestionWithQueryStr:difficultQueryStr]];
  354. //// } completed:^{
  355. //// [subscriber sendNext:difficultArr.copy];
  356. //// [subscriber sendCompleted];
  357. //// }];
  358. // return [RACDisposable disposableWithBlock:^{}];
  359. // }];
  360. // RACSignal *signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  361. // NSMutableArray *judgeArr = @[].mutableCopy;
  362. // [[[self getExamRuleWithCarType:carType subject:subject].rac_sequence.signal map:^id _Nullable(RQExamRuleModel *examRuleModel) {
  363. // NSString *chapterIdStr = [NSString stringWithFormat:@"AND chapter_id = %ld",(long)examRuleModel.chapter_id];
  364. // NSString *judgeCountStr = [NSString stringWithFormat:@"RANDOM() LIMIT %ld",(long)examRuleModel.judge_count];
  365. // NSString *judgeQueryStr = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@ AND %@ AND question_type = 1 AND diff_degree IN (0,1,2,3) AND place_issue IS NULL %@ ORDER BY %@",questionTableNameStr , queryCarTypeStr, querySubjectTypeStr, chapterIdStr, judgeCountStr];
  366. // NSMutableArray *judgeChapterArr = [self queryQuestionWithQueryStr:judgeQueryStr].mutableCopy;
  367. // if (judgeChapterArr.count < examRuleModel.judge_count) {
  368. // NSString *judgeQueryAddStr = [NSString stringWithFormat:@"SELECT DISTINCT * FROM %@ WHERE %@ AND %@ AND question_type = 1 AND diff_degree IN (4,5) AND place_issue IS NULL %@ ORDER BY RANDOM() LIMIT %@",questionTableNameStr , queryCarTypeStr, querySubjectTypeStr, chapterIdStr, [NSString stringWithFormat:@"%ld",(long)(examRuleModel.judge_count - judgeChapterArr.count)]];
  369. // NSArray *judgeChapterAddArr = [self queryQuestionWithQueryStr:judgeQueryAddStr];
  370. // [judgeChapterArr addObjectsFromArray:judgeChapterAddArr];
  371. // return judgeChapterArr.copy;
  372. // } else {
  373. // return judgeChapterArr.copy;
  374. // }
  375. // }].toArray.rac_sequence.signal subscribeNext:^(NSArray *judgeChapterArr) {
  376. // [judgeArr addObjectsFromArray:judgeChapterArr];
  377. // } completed:^{
  378. // [subscriber sendNext:judgeArr.copy];
  379. // [subscriber sendCompleted];
  380. // }];
  381. // return [RACDisposable disposableWithBlock:^{}];
  382. // }];
  383. //
  384. // RACSignal *signal2 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  385. // NSMutableArray *choiceArr = @[].mutableCopy;
  386. // [[[self getExamRuleWithCarType:carType subject:subject].rac_sequence.signal map:^id _Nullable(RQExamRuleModel *examRuleModel) {
  387. // NSString *chapterIdStr = [NSString stringWithFormat:@"AND chapter_id = %ld",(long)examRuleModel.chapter_id];
  388. // NSString *choiceCountStr = [NSString stringWithFormat:@"RANDOM() LIMIT %ld",(long)examRuleModel.choice_count];
  389. // NSString *choiceQueryStr = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@ AND %@ AND question_type = 2 AND diff_degree IN (0,1,2,3) AND place_issue IS NULL %@ ORDER BY %@",questionTableNameStr , queryCarTypeStr, querySubjectTypeStr, chapterIdStr, choiceCountStr];
  390. // NSMutableArray *choiceChapterArr = [self queryQuestionWithQueryStr:choiceQueryStr].mutableCopy;
  391. // if (choiceChapterArr.count < examRuleModel.choice_count) {
  392. // NSString *choiceQueryAddStr = [NSString stringWithFormat:@"SELECT DISTINCT * FROM %@ WHERE %@ AND %@ AND question_type = 2 AND diff_degree IN (4,5) AND place_issue IS NULL %@ ORDER BY RANDOM() LIMIT %@",questionTableNameStr , queryCarTypeStr, querySubjectTypeStr, chapterIdStr, [NSString stringWithFormat:@"%ld",(long)(examRuleModel.choice_count - choiceChapterArr.count)]];
  393. // NSArray *choiceChapterAddArr = [self queryQuestionWithQueryStr:choiceQueryAddStr];
  394. // [choiceChapterArr addObjectsFromArray:choiceChapterAddArr];
  395. // return choiceChapterArr.copy;
  396. // } else {
  397. // return choiceChapterArr.copy;
  398. // }
  399. // }].toArray.rac_sequence.signal subscribeNext:^(NSArray *choiceChapterArr) {
  400. // [choiceArr addObjectsFromArray:choiceChapterArr];
  401. // } completed:^{
  402. // [subscriber sendNext:choiceArr.copy];
  403. // [subscriber sendCompleted];
  404. // }];
  405. // return [RACDisposable disposableWithBlock:^{}];
  406. // }];
  407. // RACSignal *signal3 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
  408. // NSMutableArray *multipleChoiceArr = @[].mutableCopy;
  409. // [[[self getExamRuleWithCarType:carType subject:subject].rac_sequence.signal map:^id _Nullable(RQExamRuleModel *examRuleModel) {
  410. // NSString *chapterIdStr = [NSString stringWithFormat:@"AND chapter_id = %ld",(long)examRuleModel.chapter_id];
  411. // NSString *multipleChoiceCountStr = [NSString stringWithFormat:@"RANDOM() LIMIT %ld",(long)examRuleModel.multiple_choice_count];
  412. // NSString *multipleChoiceQueryStr = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@ AND %@ AND question_type = 3 AND diff_degree IN (0,1,2,3) AND place_issue IS NULL %@ ORDER BY %@",questionTableNameStr , queryCarTypeStr, querySubjectTypeStr, chapterIdStr, multipleChoiceCountStr];
  413. // NSMutableArray *multipleChoiceChapterArr = [self queryQuestionWithQueryStr:multipleChoiceQueryStr].mutableCopy;
  414. // if (multipleChoiceChapterArr.count < examRuleModel.multiple_choice_count) {
  415. // NSString *multipleChoiceQueryAddStr = [NSString stringWithFormat:@"SELECT DISTINCT * FROM %@ WHERE %@ AND %@ AND question_type = 3 AND diff_degree IN (4,5) AND place_issue IS NULL %@ ORDER BY RANDOM() LIMIT %@",questionTableNameStr , queryCarTypeStr, querySubjectTypeStr, chapterIdStr, [NSString stringWithFormat:@"%ld",(long)(examRuleModel.multiple_choice_count - multipleChoiceChapterArr.count)]];
  416. // NSArray *multipleChoiceChapterAddArr = [self queryQuestionWithQueryStr:multipleChoiceQueryAddStr];
  417. // [multipleChoiceChapterArr addObjectsFromArray:multipleChoiceChapterAddArr];
  418. // return multipleChoiceChapterArr.copy;
  419. // } else {
  420. // return multipleChoiceChapterArr.copy;
  421. // }
  422. // }].toArray.rac_sequence.signal subscribeNext:^(NSArray *multipleChoiceChapterArr) {
  423. // [multipleChoiceArr addObjectsFromArray:multipleChoiceChapterArr];
  424. // } completed:^{
  425. // [subscriber sendNext:multipleChoiceArr.copy];
  426. // [subscriber sendCompleted];
  427. // }];
  428. // return [RACDisposable disposableWithBlock:^{}];
  429. // }];
  430. // return [[[RACSignal combineLatest:@[signal0] reduce:^id (NSArray *arr0){
  431. // NSMutableArray *judgeArr = [NSMutableArray array];
  432. // dispatch_semaphore_t sema = dispatch_semaphore_create(0);
  433. // [[arr0.rac_sequence.signal filter:^BOOL(RQExerciseModel *difficultQuestionModel) {
  434. // return ![judgeArr containsObject:difficultQuestionModel];
  435. // }].toArray.rac_sequence.signal subscribeNext:^(RQExerciseModel *difficultQuestionModel) {
  436. // if (difficultQuestionModel.question_type == 1) {
  437. // NSMutableArray *sortChapterArr = [judgeArr.rac_sequence.signal filter:^BOOL(RQExerciseModel *judgeQuestionModel) {
  438. // return (judgeQuestionModel.chapter_id == difficultQuestionModel.chapter_id) && ![arr0 containsObject:judgeQuestionModel];
  439. // }].toArray.mutableCopy;
  440. // if (sortChapterArr.count > 0) {
  441. // [judgeArr replaceObjectAtIndex:[judgeArr indexOfObject:sortChapterArr.lastObject] withObject:difficultQuestionModel];
  442. // }
  443. // }
  444. //// else if (difficultQuestionModel.question_type == 2) {
  445. //// NSMutableArray *sortChapterArr = [choiceArr.rac_sequence.signal filter:^BOOL(RQExerciseModel *choiceQuestionModel) {
  446. //// return (choiceQuestionModel.chapter_id == difficultQuestionModel.chapter_id) && ![arr0 containsObject:choiceQuestionModel];
  447. //// }].toArray.mutableCopy;
  448. //// if (sortChapterArr.count > 0) {
  449. //// [choiceArr replaceObjectAtIndex:[choiceArr indexOfObject:sortChapterArr.lastObject] withObject:difficultQuestionModel];
  450. //// }
  451. //// } else {
  452. //// NSMutableArray *sortChapterArr = [multipleChoiceArr.rac_sequence.signal filter:^BOOL(RQExerciseModel *multiChoiceQuestionModel) {
  453. //// return (multiChoiceQuestionModel.chapter_id == difficultQuestionModel.chapter_id) && ![arr0 containsObject:multiChoiceQuestionModel];
  454. //// }].toArray.mutableCopy;
  455. //// if (sortChapterArr.count > 0) {
  456. //// [multipleChoiceArr replaceObjectAtIndex:[multipleChoiceArr indexOfObject:sortChapterArr.lastObject] withObject:difficultQuestionModel];
  457. //// }
  458. //// }
  459. // } completed:^{
  460. // /// Key: 按照排序的key; ascending: YES为升序, NO为降序。
  461. // NSSortDescriptor *strTppeSorter = [[NSSortDescriptor alloc] initWithKey:@"chapter_id" ascending:YES];
  462. //// NSSortDescriptor *diff_degreeSorter = [NSSortDescriptor sortDescriptorWithKey:@"diff_degree" ascending:YES];
  463. // NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:strTppeSorter, nil];
  464. //
  465. // [arr addObjectsFromArray:[judgeArr sortedArrayUsingDescriptors:sortDescriptors]];
  466. //// [arr addObjectsFromArray:[choiceArr sortedArrayUsingDescriptors:sortDescriptors]];
  467. //// [arr addObjectsFromArray:[multipleChoiceArr sortedArrayUsingDescriptors:sortDescriptors]];
  468. // dispatch_semaphore_signal(sema);
  469. // }];
  470. // dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
  471. //
  472. // return arr.copy;
  473. // }] map:^id _Nullable(NSArray *examArr) {
  474. // return examArr;
  475. // }].toArray firstObject];
  476. // return arr.copy;
  477. } else if (pageType == RQHomeSubPageType_FreeTry) {
  478. queryStr = [NSString stringWithFormat:@"SELECT * FROM question_info INNER JOIN question_free ON question_info.id = question_free.id AND question_free.subject = '%@' ORDER BY %@", [RQ_COMMON_MANAGER getSubjectTypeNumStrWithSubjectType:subject],(exerciseType == RQExerciseType_Random)? @"random()" : @"question_free.free_sort + 0 ASC"];
  479. return [self queryQuestionWithQueryStr:queryStr exerciseType:exerciseType];
  480. } else if (pageType == RQHomeSubPageType_MockExamination && exerciseType == RQExerciseType_MiExam) {
  481. queryStr = [NSString stringWithFormat:@"SELECT * FROM (SELECT * FROM question_info AS a JOIN (SELECT id_ydt, MAX(id) AS id FROM question_info GROUP BY id_ydt) AS t ON a.id = t.id) AS q JOIN t_app_question_category AS c ON q.id_ydt = c.question_id AND c.kemu = %@ AND c.gs = '%@' AND c.category = %@ ORDER BY c.sort_order + 0 ASC", [RQ_COMMON_MANAGER getSubjectTypeNumStrWithSubjectType:subject],[RQ_COMMON_MANAGER getCarTypeSimpleCNStrWithCarType:carType],[RQ_COMMON_MANAGER getMiExamTypeNumStrWithMiExamType:RQ_COMMON_MANAGER.miExamType]];
  482. return [self queryQuestionWithQueryStr:queryStr];
  483. } else {
  484. return [self queryQuestionWithQueryStr:queryStr exerciseType:exerciseType];
  485. }
  486. }
  487. - (RQExerciseModel *)getQuestionWithQuestionId:(NSInteger )questionId {
  488. __block RQExerciseModel *exerciseModel;
  489. if (_databaseQueue) {
  490. [_databaseQueue inDatabase:^(FMDatabase * _Nonnull db) {
  491. exerciseModel = [self getQuestionWithDataBase:db questionId:questionId];
  492. }];
  493. }
  494. return exerciseModel;
  495. }
  496. - (void)getQuestionsWithQuestionIdArr:(NSArray *)questionIdArr complete:(VoidBlock_id)complete {
  497. NSMutableArray *arr = @[].mutableCopy;
  498. if (_databaseQueue) {
  499. [_databaseQueue inTransaction:^(FMDatabase * _Nonnull db, BOOL * _Nonnull rollback) {
  500. @try {
  501. [questionIdArr.rac_sequence.signal subscribeNext:^(NSString *questionIdStr) {
  502. RQExerciseModel *exerciseModel = [self getQuestionWithDataBase:db questionId:questionIdStr.integerValue];
  503. [arr addObject:exerciseModel];
  504. } completed:^{
  505. if (complete) {
  506. complete(arr.copy);
  507. }
  508. }];
  509. } @catch (NSException *exception) {
  510. *rollback = YES;
  511. } @finally {
  512. *rollback = NO;
  513. }
  514. }];
  515. }
  516. }
  517. #pragma mark - Private Method
  518. - (NSArray *)queryQuestionWithQueryStr:(NSString *)queryStr exerciseType:(RQExerciseType)exerciseType {
  519. NSMutableArray *arr = @[].mutableCopy;
  520. if (_databaseQueue) {
  521. [_databaseQueue inDatabase:^(FMDatabase * _Nonnull db) {
  522. FMResultSet *resultSet;
  523. resultSet = [db executeQuery:queryStr];
  524. while ([resultSet next]) {
  525. RQExerciseModel *exerciseModel = [RQExerciseModel exerciseModelWithFMResultSet:resultSet];
  526. if (exerciseType == RQExerciseType_Recitation) {
  527. exerciseModel.userAnswer = exerciseModel.answer;
  528. }
  529. [arr addObject:exerciseModel];
  530. }
  531. }];
  532. }
  533. return arr.copy;
  534. }
  535. - (NSArray *)queryQuestionWithQueryStr:(NSString *)queryStr {
  536. NSMutableArray *arr = @[].mutableCopy;
  537. if (_databaseQueue) {
  538. [_databaseQueue inDatabase:^(FMDatabase * _Nonnull db) {
  539. FMResultSet *resultSet;
  540. resultSet = [db executeQuery:queryStr];
  541. while ([resultSet next]) {
  542. RQExerciseModel *exerciseModel = [RQExerciseModel exerciseModelWithFMResultSet:resultSet];
  543. [arr addObject:exerciseModel];
  544. }
  545. }];
  546. }
  547. return arr.copy;
  548. }
  549. - (NSString *)getQuestionNumQueryStrWithCarType:(RQHomePageCarType)carType subject:(RQHomePageSubjectType)subject questionType:(RQQuestionType)questionType isNew:(BOOL)isNew {
  550. switch (subject) {
  551. case RQHomePageSubjectType_SubjectOne: {
  552. switch (questionType) {
  553. case RQQuestionType_Judgment: {
  554. switch (carType) {
  555. case RQHomePageCarType_Car:
  556. return isNew? @"random() limit 20" : @"random() limit 20";
  557. case RQHomePageCarType_Bus:
  558. return isNew? @"random() limit 20" : @"random() limit 20";
  559. case RQHomePageCarType_Truck:
  560. return isNew? @"random() limit 20" : @"random() limit 20";
  561. case RQHomePageCarType_Motorcycle:
  562. return isNew? @"random() limit 10" : @"random() limit 10";
  563. default:
  564. return isNew? @"random() limit 20" : @"random() limit 20";
  565. }
  566. }
  567. case RQQuestionType_SingleChoice: {
  568. switch (carType) {
  569. case RQHomePageCarType_Car:
  570. return isNew? @"random() limit 10" : @"random() limit 50";
  571. case RQHomePageCarType_Bus:
  572. return isNew? @"random() limit 10" : @"random() limit 50";
  573. case RQHomePageCarType_Truck:
  574. return isNew? @"random() limit 10" : @"random() limit 50";
  575. case RQHomePageCarType_Motorcycle:
  576. return isNew? @"random() limit 5" : @"random() limit 25";
  577. default:
  578. return isNew? @"random() limit 10" : @"random() limit 50";
  579. }
  580. }
  581. case RQQuestionType_MultipleChoice: {
  582. switch (carType) {
  583. case RQHomePageCarType_Car:
  584. return @"random() limit 0";
  585. case RQHomePageCarType_Bus:
  586. return @"random() limit 0";
  587. case RQHomePageCarType_Truck:
  588. return @"random() limit 0";
  589. case RQHomePageCarType_Motorcycle:
  590. return @"random() limit 0";
  591. default:
  592. return @"random() limit 0";
  593. }
  594. }
  595. }
  596. }
  597. case RQHomePageSubjectType_SubjectFour: {
  598. switch (questionType) {
  599. case RQQuestionType_Judgment: {
  600. switch (carType) {
  601. case RQHomePageCarType_Car:
  602. return @"random() limit 10";
  603. case RQHomePageCarType_Bus:
  604. return @"random() limit 10";
  605. case RQHomePageCarType_Truck:
  606. return @"random() limit 10";
  607. case RQHomePageCarType_Motorcycle:
  608. return @"random() limit 10";
  609. default:
  610. return @"random() limit 10";
  611. }
  612. }
  613. case RQQuestionType_SingleChoice: {
  614. switch (carType) {
  615. case RQHomePageCarType_Car:
  616. return @"random() limit 10";
  617. case RQHomePageCarType_Bus:
  618. return @"random() limit 10";
  619. case RQHomePageCarType_Truck:
  620. return @"random() limit 10";
  621. case RQHomePageCarType_Motorcycle:
  622. return @"random() limit 10";
  623. default:
  624. return @"random() limit 10";
  625. }
  626. }
  627. case RQQuestionType_MultipleChoice: {
  628. switch (carType) {
  629. case RQHomePageCarType_Car:
  630. return @"random() limit 5";
  631. case RQHomePageCarType_Bus:
  632. return @"random() limit 5";
  633. case RQHomePageCarType_Truck:
  634. return @"random() limit 5";
  635. case RQHomePageCarType_Motorcycle:
  636. return @"random() limit 5";
  637. default:
  638. return @"random() limit 5";
  639. }
  640. }
  641. }
  642. }
  643. default:
  644. return @"random() limit 5";
  645. }
  646. }
  647. - (RQExerciseModel *)getQuestionWithDataBase:(FMDatabase *)dataBase questionId:(NSInteger )questionId {
  648. RQExerciseModel *exerciseModel;
  649. FMResultSet *resultSet;
  650. resultSet = [dataBase executeQuery:[NSString stringWithFormat:@"select * from question_info where id = %ld", questionId]];
  651. while ([resultSet next]) {
  652. exerciseModel = [RQExerciseModel exerciseModelWithFMResultSet:resultSet];
  653. }
  654. return exerciseModel;
  655. }
  656. - (NSInteger)getQuestionVersion {
  657. __block NSInteger version = 0;
  658. if (_databaseQueue) {
  659. [_databaseQueue inDatabase:^(FMDatabase * _Nonnull db) {
  660. FMResultSet *resultSet;
  661. resultSet = [db executeQuery:@"select version_num from question_version"];
  662. while ([resultSet next]) {
  663. version = [resultSet longLongIntForColumn:@"version_num"];
  664. }
  665. }];
  666. }
  667. return version;
  668. }
  669. - (NSInteger)getQuestionVersionWithResourcePath:(NSString *)resourcePath {
  670. __block NSInteger version = 0;
  671. [[FMDatabaseQueue databaseQueueWithPath:resourcePath] inDatabase:^(FMDatabase * _Nonnull db) {
  672. FMResultSet *resultSet;
  673. resultSet = [db executeQuery:@"SELECT version_num FROM question_version"];
  674. while ([resultSet next]) {
  675. version = [resultSet longLongIntForColumn:@"version_num"];
  676. }
  677. }];
  678. return version;
  679. }
  680. - (NSArray *)getExamRuleWithCarType:(RQHomePageCarType)carType subject:(RQHomePageSubjectType)subject {
  681. NSString *queryCarTypeStr = [NSString stringWithFormat:@"gs LIKE '%%%@%%'",[RQ_COMMON_MANAGER getCarTypeSimpleCNStrWithCarType:carType]];
  682. NSString *querySubjectTypeStr = [NSString stringWithFormat:@"kemu = '%@'",[RQ_COMMON_MANAGER getSubjectTypeNumStrWithSubjectType:subject]];
  683. NSString *examRuleTableName = @"t_app_exam_rule";
  684. NSString *queryStr = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@ AND %@ AND areacode = 0 ", examRuleTableName, queryCarTypeStr, querySubjectTypeStr];
  685. return [self queryExamRuleWithQueryStr:queryStr];
  686. }
  687. - (NSArray *)queryExamRuleWithQueryStr:(NSString *)queryStr {
  688. NSMutableArray *arr = @[].mutableCopy;
  689. if (_databaseQueue) {
  690. [_databaseQueue inDatabase:^(FMDatabase * _Nonnull db) {
  691. FMResultSet *resultSet;
  692. resultSet = [db executeQuery:queryStr];
  693. while ([resultSet next]) {
  694. RQExamRuleModel *examRuleModel = [RQExamRuleModel sdjkExamRuleModelWithFMResultSet:resultSet];
  695. [arr addObject:examRuleModel];
  696. }
  697. }];
  698. }
  699. return arr.copy;
  700. }
  701. - (RQExplainModel *)getExplainWithExerciseModel:(RQExerciseModel *)exerciseModel {
  702. __block RQExplainModel *explainModel;
  703. if (_databaseQueue) {
  704. [_databaseQueue inDatabase:^(FMDatabase * _Nonnull db) {
  705. FMResultSet *resultSet;
  706. NSString *queryStr = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE questionIds = %ld", @"question_sd_js", (long)exerciseModel.id_ydt];
  707. resultSet = [db executeQuery:queryStr];
  708. while ([resultSet next]) {
  709. explainModel = [RQExplainModel questionExplainWithFMResultSet:resultSet];
  710. }
  711. }];
  712. }
  713. return explainModel;
  714. }
  715. @end