SmartEvaluationService.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. #include "StdAfx.h"
  2. #include "SmartEvaluationService.h"
  3. #include "ScoreCounter.h"
  4. #include "scan_common.h"
  5. #include "..\EvaluationUtil\HttpClient.h"
  6. #include "..\Schema\schema_struct.h"
  7. #include "SchemaLoader.h"
  8. #include "basic_struct_result.h"
  9. #include "..\Identifier\schema_struct.h"
  10. #include "ServerConfig.h"
  11. //#include "Log4cplusInitalizer.h"
  12. #include "TemplateManager.h"
  13. #include "resource.h"
  14. using namespace schema;
  15. CSmartEvaluationService::CSmartEvaluationService(void)
  16. {
  17. InitializeCriticalSection(&bantch_db_lock);
  18. m_identifor.IdentifyTaskManager(&taskManager);
  19. m_result_handler.IdentifyTaskManager(&taskManager);
  20. }
  21. CSmartEvaluationService::~CSmartEvaluationService(void)
  22. {
  23. DeleteCriticalSection(&bantch_db_lock);
  24. }
  25. //开始扫描处理函数
  26. ServiceState CSmartEvaluationService::OnStarting(void)
  27. {
  28. m_abnormal_stop = FALSE;
  29. unsigned _int64 i64FreeBytesToCaller;
  30. unsigned _int64 i64TotalBytes;
  31. unsigned _int64 i64FreeBytes;
  32. BOOL check_success = GetDiskFreeSpaceEx(m_bantch_dir, (PULARGE_INTEGER)&i64FreeBytesToCaller, (PULARGE_INTEGER)&i64TotalBytes, (PULARGE_INTEGER)&i64FreeBytes);
  33. //空余空间小于2G提示不能扫描
  34. const unsigned long long limit = 1024Ui64 * 1024 * 1024 * 2;
  35. if (check_success){
  36. if (i64FreeBytesToCaller < limit){
  37. IDENTIFOR_ERROR_MSG* msg = new IDENTIFOR_ERROR_MSG;
  38. msg->type = 1;
  39. strcpy(msg->msg, "当前空余空间不足2G,请清理磁盘再进行扫描");
  40. PostMessage(m_hwnd, WM_IDENTIFOR_ERROR, (WPARAM)msg, 0);
  41. return stoping;
  42. }
  43. }
  44. else{
  45. IDENTIFOR_ERROR_MSG* msg = new IDENTIFOR_ERROR_MSG;
  46. msg->type = 1;
  47. strcpy(msg->msg, "检查磁盘剩余空间失败!");
  48. PostMessage(m_hwnd, WM_IDENTIFOR_ERROR, (WPARAM)msg, 0);
  49. return stoping;
  50. }
  51. switch (m_feeder_type){
  52. case Folder: m_current_feeder = &m_folder_feeder; break;
  53. case Scanner: m_current_feeder = &m_twain_feeder; break;
  54. case AdjustBatch: m_current_feeder = &m_server_feeder; break;
  55. case AdjustExaminne: m_current_feeder = &m_server_feeder; break;
  56. default:m_current_feeder = NULL; break;
  57. }
  58. if (m_current_feeder != NULL){
  59. m_current_feeder->Start();
  60. m_current_feeder->SetHandlerWnd(m_hwnd);
  61. m_identifor.SetExcImgDir(m_excimg_dir);
  62. CIdentifyTask* main_task = taskManager.createTask();
  63. main_task->SetFeeder(m_current_feeder);
  64. taskManager.setMainTask(main_task);
  65. }
  66. m_identifor.Start();
  67. m_result_handler.SetImgClipsDir(m_img_clips_dir);
  68. m_result_handler.SetIdentifor(&m_identifor);
  69. m_result_handler.Start();
  70. m_result_uploader.SetResultHandler(&m_result_handler);
  71. m_student_matcher.SetResultHandler(&m_result_handler);
  72. Sleep(10);
  73. m_student_matcher.setExamId(m_examId);
  74. m_student_matcher.Start();
  75. char sql[128];
  76. sprintf_s(sql, "update database set database_state =%d where database_id =%d", DATABASE_STATE_SCANNING, m_database_id);
  77. EnterCriticalSection(database_db_lock);
  78. database_db->execDML("begin transaction");
  79. database_db->execDML(sql);
  80. database_db->execDML("commit transaction");
  81. LeaveCriticalSection(database_db_lock);
  82. if (m_hwnd != NULL)::PostMessage(m_hwnd, WM_IDENTIFOR_STARTED, 0, 0);
  83. return running;
  84. }
  85. ServiceState CSmartEvaluationService::OnRunning(void)
  86. {
  87. ServiceState nextState = IService::OnRunning();
  88. if (nextState == pausing) return nextState;
  89. if (nextState == stoping) {
  90. m_current_feeder->Stop();
  91. return nextState;
  92. }
  93. if (m_identifor.GetServiceSate() == stoped&&m_result_handler.GetServiceSate() == stoped&&m_result_uploader.GetServiceSate() == stoped){
  94. return stoping;
  95. }
  96. Sleep(10);
  97. return running;
  98. }
  99. int CSmartEvaluationService::LoadSchema(long long examId, std::string examName, long examCourseId, std::string courseName, std::string schemaPath)
  100. {
  101. m_examId = examId;
  102. m_examCourseId = examCourseId;
  103. CSchemaLoader schemaLoader;
  104. int ret = schemaLoader.Load(schemaPath, m_muban_img_dir, m_schema0, m_schema, m_handleInfo);
  105. if (ret == SCH_LOAD_SUCCESS){
  106. if (m_identifor.LoadSchema(m_schema)){
  107. saveQuestionStd(examId, examName, examCourseId, courseName, m_schema0.questions);
  108. m_result_handler.setHandlInfo(m_handleInfo);
  109. return IDF_LOAD_SUCCESS;
  110. }
  111. }
  112. else {
  113. return IDF_LOAD_CLASS_SCHEMA | ret;
  114. }
  115. return IDF_LOAD_FAILURE;
  116. }
  117. //停止扫描处理函数
  118. ServiceState CSmartEvaluationService::OnStoping(void)
  119. {
  120. if (m_current_feeder != NULL&&m_current_feeder->GetServiceSate() != stoped){
  121. m_current_feeder->Stop();
  122. }
  123. if (m_result_handler.GetServiceSate() != stoped){
  124. m_result_handler.Stop();
  125. }
  126. if (m_result_uploader.GetServiceSate() != stoped){
  127. m_result_uploader.Stop();
  128. }
  129. while ((m_current_feeder != NULL&&m_current_feeder->GetServiceSate() != stoped) || m_result_handler.GetServiceSate() != stoped || m_result_uploader.GetServiceSate() != stoped){
  130. Sleep(10);
  131. }
  132. while (m_student_matcher.GetServiceSate() != stoped){
  133. Sleep(10);
  134. }
  135. char sql[128];
  136. sprintf_s(sql, "update database set database_state =%d where database_id =%d", DATABASE_STATE_SCAN_OVER, m_database_id);
  137. EnterCriticalSection(database_db_lock);
  138. database_db->execDML("begin transaction");
  139. database_db->execDML(sql);
  140. database_db->execDML("commit transaction");
  141. LeaveCriticalSection(database_db_lock);
  142. if (m_hwnd != NULL&&m_abnormal_stop == FALSE)::PostMessage(m_hwnd, WM_IDENTIFOR_COMPLETE, 0, 0);
  143. ServiceState nextState = IService::OnStoping();
  144. if (nextState == stoped&&m_hwnd != NULL)
  145. {
  146. ::PostMessage(m_hwnd, WM_IDENTIFOR_STOPED, 0, 0);
  147. }
  148. return nextState;
  149. }
  150. //设置消息接收窗口
  151. int CSmartEvaluationService::SetHandlerWnd(HWND hwnd)
  152. {
  153. m_hwnd = hwnd;
  154. m_twain_feeder.SetHandlerWnd(m_hwnd);
  155. m_result_handler.SetHandlerWnd(m_hwnd);
  156. m_result_uploader.SetHandlerWnd(m_hwnd);
  157. m_student_matcher.SetHandlerWnd(m_hwnd);
  158. return TRUE;
  159. }
  160. //检测服务是是否可以访问
  161. bool testServerAvaiable(const CString& serverAdd){
  162. std::string response;
  163. CHttpClient httpClient;
  164. CString url;
  165. url.Format(_T("%s/course/findAllCourse"), serverAdd);
  166. httpClient.HttpGet(url, NULL, response);
  167. Json::Value root;
  168. Json::Reader(Json::Features()).parse(response, root);
  169. if (root["success"].isInt() && root["success"].asInt() == 1){
  170. return true;
  171. }
  172. return false;
  173. }
  174. int CSmartEvaluationService::ReadyScan(FEEDER_TYPE feederType, const ScanParam & param)
  175. {
  176. m_examId = param.examId;
  177. m_examCourseId = param.examCourseId;
  178. m_examName = param.examName;
  179. m_courseName = param.courseName;
  180. // Log4cplusInitalizer::initalize();
  181. std::string response;
  182. CHttpClient httpClient;
  183. CString url;
  184. url.Format(_T("%s/exam/getServerUrl?examId=%I64d"), CServerConfig::server_url, param.examId);
  185. httpClient.HttpGet(url, NULL, response);
  186. Json::Value root;
  187. Json::Reader(Json::Features()).parse(response, root);
  188. if (root["success"].isInt() && root["success"].asInt() == 1){
  189. CServerConfig::server_address_type = SAT_REMOTE;
  190. Json::Value object = root["object"];
  191. //标记本地服务器是否是不可用状态
  192. bool isLocalServerUnavailable = false;
  193. if (object["url"].isString() && object["url"].asCString() != (string)""){
  194. CServerConfig::server_url_local_in = object["url"].asCString();
  195. if (!testServerAvaiable(CServerConfig::server_url_local_in)){
  196. isLocalServerUnavailable = true;
  197. }
  198. CServerConfig::server_address_type = SAT_LOCAL_IN;
  199. }
  200. if (isLocalServerUnavailable&&object["outurl"].isString() && object["outurl"].asCString() != (string)""){
  201. CServerConfig::server_url_local_out = object["outurl"].asCString();
  202. if (testServerAvaiable(CServerConfig::server_url_local_out)){
  203. isLocalServerUnavailable = false;
  204. }
  205. else {
  206. isLocalServerUnavailable = true;
  207. }
  208. CServerConfig::server_address_type = SAT_LOCAL_OUT;
  209. }
  210. //本地服务器不可用,返回错误
  211. if (isLocalServerUnavailable)return 2;
  212. }
  213. m_identifor.Reset();
  214. m_feeder_type = feederType;
  215. CString moule_dir =CServerConfig::scan_data_dir;
  216. m_bantch_code = GetTimeString();
  217. m_bantch_dir = moule_dir + _T("\\") + m_bantch_code;
  218. m_norimg_dir = m_bantch_dir + _T("\\nor_imgs");
  219. m_excimg_dir = m_bantch_dir + _T("\\exc_imgs");
  220. m_img_down_load_dir = m_bantch_dir + _T("\\img_down_load");
  221. m_muban_img_dir = CT2A(m_bantch_dir + _T("\\muban_imgs"));
  222. m_img_clips_dir = m_bantch_dir + _T("\\clips");
  223. m_img_alynasis_dir = m_bantch_dir + _T("\\alynasis");
  224. m_img_alynasis_result_dir = m_bantch_dir + _T("\\alynasis_result");
  225. CreateDirectory(m_bantch_dir, NULL);
  226. CreateDirectory(m_norimg_dir, NULL);
  227. CreateDirectory(m_excimg_dir, NULL);
  228. CreateDirectory(m_img_clips_dir, NULL);
  229. CreateDirectory(CA2T(m_muban_img_dir.c_str()), NULL);
  230. CreateDirectory(m_img_down_load_dir, NULL);
  231. CreateDirectory(m_img_alynasis_dir, NULL);
  232. CreateDirectory(m_img_alynasis_result_dir, NULL);
  233. CString path = m_bantch_dir + _T("\\result.db3");
  234. CTemplateManager::ExtractResourceToFile(_T("database"), IDR_DATABASE_RESULT, path);
  235. char db_file_name[520];
  236. WideCharToMultiByte(CP_UTF8, 0, path, -1, db_file_name, 520, NULL, NULL);
  237. EnterCriticalSection(database_db_lock);
  238. database_db->execDML("begin transaction");
  239. char * sql = "INSERT INTO DATABASE ( database_state, create_time, db_file_name, bantch_code, bantch_dir, exam_id, exam_name, exam_course_id, course_name, total_upload_count, scan_type, exam_course_id_from, batch_code_from, examinne_id_from, server_address ) VALUES ( :database_state, :create_time, :db_file_name, :bantch_code ,:bantch_dir ,:exam_id ,:exam_name ,:exam_course_id ,:course_name ,:total_upload_count, :scan_type, :exam_course_id_from, :batch_code_from, :examinne_id_from, :server_address )";
  240. CppSQLite3Statement stmt = database_db->compileStatement(sql);
  241. CT2A szbantch_code(m_bantch_code);
  242. CT2A szbantch_dir(m_bantch_dir);
  243. CT2A server_address(CServerConfig::server_address_type == SAT_LOCAL_IN ? CServerConfig::server_url_local_in : CServerConfig::server_address_type == SAT_LOCAL_OUT ? CServerConfig::server_url_local_out : CServerConfig::server_url);
  244. stmt.bind(":database_state", DATABASE_STATE_CREATE);
  245. stmt.bind(":create_time", szbantch_code);
  246. stmt.bind(":db_file_name", db_file_name);
  247. stmt.bind(":bantch_code", szbantch_code);
  248. stmt.bind(":bantch_dir", szbantch_dir);
  249. stmt.bind(":server_address", server_address);
  250. switch (feederType&FEEDER_TYPE_MASK){
  251. case Folder:stmt.bind(":scan_type", SCAN_TASK_TYPE_NORMAL); break;
  252. case Scanner:stmt.bind(":scan_type", SCAN_TASK_TYPE_NORMAL); break;
  253. case AdjustBatch:
  254. stmt.bind(":exam_id", param.examId);
  255. stmt.bind(":exam_course_id", param.examCourseId);
  256. stmt.bind(":scan_type", SCAN_TASK_TYPE_ADJUST_BATCH);
  257. stmt.bind(":exam_course_id_from", param.examCourseIdOld);
  258. stmt.bind(":batch_code_from", param.batch.c_str());
  259. break;
  260. case AdjustExaminne:
  261. stmt.bind(":exam_id", param.examId);
  262. stmt.bind(":exam_course_id", param.examCourseId);
  263. stmt.bind(":scan_type", SCAN_TASK_TYPE_ADJUST_EXAMINNE);
  264. stmt.bind(":exam_course_id_from", param.examCourseIdOld);
  265. stmt.bind(":batch_code_from", param.batch.c_str());
  266. stmt.bind(":examinne_id_from", param.examinneid.c_str());
  267. break;
  268. }
  269. stmt.bind(":exam_name", param.examName.c_str());
  270. stmt.bind(":course_name", param.courseName.c_str());
  271. stmt.execDML();
  272. CppSQLite3Query query = database_db->execQuery("select last_insert_rowId() from DATABASE");
  273. m_database_id = query.getIntField(0);
  274. database_db->execDML("commit transaction");
  275. LeaveCriticalSection(database_db_lock);
  276. bantch_db.open(db_file_name);
  277. bantch_db.execDML("pragma journal_mode = MEMORY");
  278. m_result_handler.SetDataBase(&bantch_db_lock, &bantch_db);
  279. m_student_matcher.SetDataBase(&bantch_db_lock, &bantch_db);
  280. m_student_matcher.SetImgDir(m_norimg_dir, m_excimg_dir);
  281. m_result_uploader.SetDataBase(&bantch_db_lock, &bantch_db);
  282. m_result_uploader.SetDataBaseManager(database_db_lock, database_db, m_database_id);
  283. switch (feederType&FEEDER_TYPE_MASK){
  284. case Folder:
  285. m_folder_feeder.SetFolder(param.img_dir);
  286. break;
  287. case Scanner:
  288. m_twain_feeder.SetScannerIndex(param.scanner_id);
  289. break;
  290. case AdjustBatch:
  291. m_server_feeder.SetImageDownloadDir(m_img_down_load_dir);
  292. m_server_feeder.SetParam(param.examId, param.examCourseIdOld, CString(param.batch.c_str()));
  293. break;
  294. case AdjustExaminne:
  295. m_server_feeder.SetImageDownloadDir(m_img_down_load_dir);
  296. m_server_feeder.SetParam(param.examId, param.examCourseIdOld, CString(param.batch.c_str()), CString(param.examinneid.c_str()));
  297. break;
  298. }
  299. if (m_hwnd != NULL) ::PostMessage(m_hwnd, WM_IDENTIFOR_READY, 0, 0);
  300. return TRUE;
  301. }
  302. //查询异常试卷
  303. int CSmartEvaluationService::QueryExceptionPaper(const long exception_type, vector<STUDENT_INFO>& studentList)
  304. {
  305. EnterCriticalSection(&bantch_db_lock);
  306. char sql[512];
  307. sprintf_s(sql, "select s.student_id,s.student_code,s.class_name,s.grade_name,s.student_name,s.class_id,pp.score_total,pp.student_paper_id from student_paper pp left join student s on s.student_id=pp.student_id where not (pp.paper_state&%d) =0", exception_type);
  308. CppSQLite3Query q = bantch_db.execQuery(sql);
  309. while (!q.eof()){
  310. STUDENT_INFO si;
  311. char class_name[64];
  312. sprintf_s(class_name, "%s(%s)班", q.getStringField("grade_name"), q.getStringField("class_name"));
  313. si.class_name = class_name;
  314. si.student_id = q.getInt64Field("student_id");
  315. si.student_name = q.getStringField("student_name");
  316. si.student_code = q.getStringField("student_code");
  317. si.class_id = q.getInt64Field("class_id");
  318. si.score = (float)q.getFloatField("score_total", -1);
  319. si.paper_id = q.getIntField("student_paper_id", -1);
  320. studentList.push_back(si);
  321. q.nextRow();
  322. }
  323. LeaveCriticalSection(&bantch_db_lock);
  324. return TRUE;
  325. }
  326. //查询试卷详情,包括异常信息,试卷图像信息,试卷题目信息
  327. int CSmartEvaluationService::QueryPaperDetail(const int paper_id, PAPER_DETAIL &paper_detail, vector<PAGE_DETAIL> &pageList, vector<GROUP_QUESTION> &questionList)
  328. {
  329. EnterCriticalSection(&bantch_db_lock);
  330. char sql[512];
  331. sprintf_s(sql, "SELECT sp.student_paper_id, sp.ret_upload, img_upload, sp.paper_code, sp.student_code, sp.paper_state, sp.student_id, sp.file_name, sp.score_total, s.student_name,e.full_score,e.full_score_objective FROM student_paper sp LEFT JOIN student s ON s.student_id = sp.student_id left join exam e on 1=1 WHERE sp.student_paper_id = %d", paper_id);
  332. CppSQLite3Query q = bantch_db.execQuery(sql);
  333. if (!q.eof()){
  334. strcpy_s(paper_detail.examnumber, q.getStringField("student_code"));
  335. paper_detail.exceptionsFlag = q.getInt64Field("paper_state");
  336. strcpy_s(paper_detail.student_name, q.getStringField("student_name"));
  337. paper_detail.score = q.getFloatField("score_total");
  338. strcpy_s(paper_detail.student_id, q.getStringField("student_id"));
  339. paper_detail.fullScore = q.getFloatField("full_score");
  340. paper_detail.fullScoreObjective = q.getFloatField("full_score_objective");
  341. }
  342. else{
  343. strcpy_s(paper_detail.examnumber, "");
  344. paper_detail.exceptionsFlag = 0;
  345. strcpy_s(paper_detail.student_name, "");
  346. paper_detail.score = 0;
  347. strcpy_s(paper_detail.student_id, "");
  348. paper_detail.fullScore = 0;
  349. paper_detail.fullScoreObjective = 0;
  350. LeaveCriticalSection(&bantch_db_lock);
  351. return FALSE;
  352. }
  353. std::map<int, PAGE_DETAIL> mm;
  354. //页码信息
  355. sprintf_s(sql, "select pg.* from student_paper pp left join page pg on pg.student_paper_id =pp.student_paper_id where pp.student_paper_id =%d", paper_id);
  356. q = bantch_db.execQuery(sql);
  357. while (!q.eof()){
  358. PAGE_DETAIL pd;
  359. pd.page_id = q.getIntField("page_id");
  360. pd.page_index = q.getIntField("page_index");
  361. pd.img_path = q.getStringField("img_path");
  362. pd.phy_number = atoi(q.getStringField("phy_number"));
  363. pd.exceptions.clear();
  364. mm[pd.page_id] = pd;
  365. q.nextRow();
  366. }
  367. std::map<std::string, QUESTION_INFO> mm2;
  368. std::vector<QUESTION_INFO*> quesitons;
  369. // 题目标准
  370. sprintf_s(sql, "SELECT question_code, question_type, multi_answer, answer_all, answer_std, score_full, score_half, option_count FROM question_std ORDER BY question_code + 0");
  371. q = bantch_db.execQuery(sql);
  372. while (!q.eof()){
  373. QUESTION_INFO qi;
  374. qi.answer_std = q.getStringField("answer_std");
  375. qi.answer_stu = "";
  376. qi.is_mutil = q.getIntField("multi_answer");
  377. qi.option_count = q.getIntField("option_count");
  378. qi.question_code = q.getStringField("question_code");
  379. //qi.question_id =-1;
  380. qi.question_type = (QUESTION_TYPE)q.getIntField("question_type");
  381. qi.score_full = q.getFloatField("score_full");
  382. qi.score_half = q.getFloatField("score_half");
  383. qi.score_stu = 0;
  384. mm2[qi.question_code] = qi;
  385. quesitons.push_back(&mm2[qi.question_code]);
  386. q.nextRow();
  387. }
  388. sprintf_s(sql, "SELECT count(0) FROM student_paper pp where pp.student_paper_id =%d and not (pp.paper_state&%d)=0", paper_id, MEX_BUKECHAXUNFENSHU);
  389. if (bantch_db.execScalar(sql) <= 0){//不存在定位点异常时,查询分数
  390. // 题目得分信息
  391. sprintf_s(sql, "SELECT r.* FROM student_paper pp LEFT JOIN page pg ON pg.student_paper_id = pp.student_paper_id LEFT JOIN result r ON r.page_id = pg.page_id WHERE pp.student_paper_id = %d AND r.type>0", paper_id, paper_id);
  392. q = bantch_db.execQuery(sql);
  393. while (!q.eof()){
  394. string question_code = q.getStringField("question_code");
  395. mm2[question_code].question_state = (QUESTION_STATE)q.getIntField("question_state");
  396. mm2[question_code].score_stu = (mm2[question_code].question_state == QUESTION_STATE_NORMAL) ? q.getFloatField("score") : q.getFloatField("score_paper");
  397. mm2[question_code].answer_stu = q.getStringField("answer");
  398. q.nextRow();
  399. }
  400. }
  401. //页面异常信息
  402. sprintf_s(sql, "SELECT ex.exception_id, ex.exception_type, ex.exception_name, ex.page_id,pg.page_id FROM exception ex LEFT JOIN page pg ON pg.page_id = ex.page_id where ex.page_id is not null and ex.student_paper_id =%d", paper_id);
  403. q = bantch_db.execQuery(sql);
  404. while (!q.eof()){
  405. int page_id = q.getIntField("page_id");
  406. EXCEPTION_INFO ei;
  407. ei.exception_id = q.getIntField("exception_id");
  408. ei.type = (EXCEPTION_TYPE)q.getInt64Field("exception_type");
  409. ei.x = 0;
  410. ei.y = 0;
  411. ei.w = 0;
  412. ei.h = 0;
  413. mm[page_id].exceptions.push_back(ei);
  414. q.nextRow();
  415. }
  416. //试卷异常信息
  417. paper_detail.paper_id = paper_id;
  418. paper_detail.exceptions.clear();
  419. sprintf_s(sql, "SELECT ex.exception_id, ex.exception_type, ex.exception_name, ex.page_id FROM exception ex where ex.page_id is null and ex.student_paper_id =%d", paper_id);
  420. q = bantch_db.execQuery(sql);
  421. while (!q.eof()){
  422. EXCEPTION_INFO ei;
  423. ei.exception_id = q.getIntField("exception_id");
  424. ei.type = (EXCEPTION_TYPE)q.getInt64Field("exception_type");
  425. ei.x = 0;
  426. ei.y = 0;
  427. ei.w = 0;
  428. ei.h = 0;
  429. paper_detail.exceptions.push_back(ei);
  430. q.nextRow();
  431. }
  432. for (map<int, PAGE_DETAIL>::iterator it = mm.begin(); it != mm.end(); it++)
  433. {
  434. pageList.push_back(it->second);
  435. }
  436. LeaveCriticalSection(&bantch_db_lock);
  437. return TRUE;
  438. }
  439. //重新识别
  440. int CSmartEvaluationService::ReIdentify(const int paper_id, const std::vector<img_param>& params)
  441. {
  442. CppSQLite3Statement statm = bantch_db.compileStatement("update student_paper set paper_state =:paper_state where student_paper_id=:student_paper_id");
  443. statm.bind(":paper_state", EX_SHIJUANCHONGXINSHIBIEZHONG);
  444. statm.bind(":student_paper_id", paper_id);
  445. statm.execDML();
  446. m_manualmatch_feeder.SetImgList(params);
  447. m_feeder_type = (FEEDER_TYPE)(ManualMatch | (m_feeder_type&AutoSchemaFlag));
  448. CIdentifyTask* task = taskManager.createTask();
  449. m_manualmatch_feeder.SetHandlerWnd(m_hwnd);
  450. m_manualmatch_feeder.Start();
  451. task->SetFeeder(&m_manualmatch_feeder);
  452. taskManager.ExcuTask(task);
  453. return Start();
  454. }
  455. //更新试卷对应考试
  456. int CSmartEvaluationService::UpdatePaperStudent(const int paper_id, const std::string examinee_id, const std::string student_code, const std::string studentName, const long schoolId)
  457. {
  458. EnterCriticalSection(&bantch_db_lock);
  459. char sql[512];
  460. long exceptions = MEX_KAOHAOYICHANG;
  461. sprintf_s(sql, "select sp.student_paper_id,sp.paper_state,sp.student_id from student_paper sp where sp.student_paper_id = %d", paper_id);
  462. CppSQLite3Query query_student_paper = bantch_db.execQuery(sql);
  463. if (query_student_paper.eof()){ LeaveCriticalSection(&bantch_db_lock); return FALSE; }
  464. const std::string student_id_old = query_student_paper.getStringField("student_id");
  465. long paper_state = query_student_paper.getInt64Field("paper_state");
  466. bantch_db.execDML("begin transaction");
  467. char * sql3 = "INSERT INTO student ( student_id, student_code, class_name, school_id, grade_name, student_name, class_id, score_total ) SELECT t.student_id, t.student_code, t.class_name, t.school_id, t.grade_name, t.student_name, t.class_id, t.score_total FROM ( SELECT :student_id student_id, :student_code student_code, :class_name class_name, :school_id school_id, :grade_name grade_name, :student_name student_name, :class_id class_id, :score_total score_total ) t LEFT JOIN student s ON s.student_id = t.student_id WHERE s.student_id IS NULL";
  468. CppSQLite3Statement statement = bantch_db.compileStatement(sql3);
  469. statement.bind(":student_id", examinee_id.c_str());
  470. statement.bind(":student_code", student_code.c_str());
  471. statement.bind(":school_id", schoolId);
  472. statement.bind(":student_name", studentName.c_str());
  473. statement.execDML();
  474. if (paper_state&EX_KAOHAOCHONGTU){
  475. sprintf_s(sql, "select sp.student_paper_id,sp.paper_state,sp.student_id from student_paper sp where sp.student_id = '%s' and not sp.student_paper_id = %d", student_id_old, paper_id);
  476. CppSQLite3Query q2 = bantch_db.execQuery(sql);
  477. vector<int> resolved_ids;
  478. int same_code_count = 0;
  479. while (!q2.eof()){
  480. long paper_state_t = q2.getInt64Field("paper_state");
  481. if (paper_state_t&EX_KAOHAOCHONGTU)
  482. resolved_ids.push_back(q2.getIntField("student_paper_id"));
  483. same_code_count++;
  484. q2.nextRow();
  485. }
  486. if (same_code_count == 1 && resolved_ids.size() == 1){//解决了考号冲突
  487. sprintf_s(sql, "update student_paper set paper_state =paper_state-(paper_state&%d) where student_paper_id=%d", EX_KAOHAOCHONGTU, resolved_ids[0]);
  488. bantch_db.execDML(sql);
  489. sprintf_s(sql, "delete from exception where student_paper_id = %d and exception_type in(%d)", resolved_ids[0], SHIFT_KAOHAOCHONGTU);
  490. bantch_db.execDML(sql);
  491. //updatefile(&bantch_db, resolved_ids[0], (string)CT2A(m_norimg_dir), (string)CT2A(m_excimg_dir));
  492. }
  493. }
  494. sprintf_s(sql, "update student_paper set student_id ='%s',student_code=(select student_code from student where student_id='%s'),paper_state =paper_state-(paper_state&%d) where student_paper_id=%d", examinee_id.c_str(), examinee_id.c_str(), exceptions, paper_id);
  495. bantch_db.execDML(sql);
  496. sprintf_s(sql, "delete from exception where student_paper_id = %d and exception_type in(%d,%d,%d)", paper_id, SHIFT_KAOHAOBUCUNZAI, SHIFT_KAOHAOCHONGTU, SHIFT_KAOHAOWEISHIBIE);
  497. bantch_db.execDML(sql);
  498. //updatefile(&bantch_db, paper_id, (string)CT2A(m_norimg_dir), (string)CT2A(m_excimg_dir));
  499. vector<int> conflict_ids;
  500. {//更新考号后导致其他试卷考号冲突情况
  501. sprintf_s(sql, "select sp.student_paper_id,sp.paper_state,sp.student_id from student_paper sp where sp.student_id = '%s' and not sp.student_paper_id = %d", examinee_id.c_str(), paper_id);
  502. CppSQLite3Query q2 = bantch_db.execQuery(sql);
  503. while (!q2.eof()){
  504. long paper_state_t = q2.getInt64Field("paper_state");
  505. if (!(paper_state_t&EX_KAOHAOCHONGTU))
  506. conflict_ids.push_back(q2.getIntField("student_paper_id"));
  507. q2.nextRow();
  508. }
  509. for (int m = 0; m < conflict_ids.size(); m++)
  510. {
  511. sprintf_s(sql, "update student_paper set paper_state =paper_state|%d where student_paper_id=%d", EX_KAOHAOCHONGTU, conflict_ids[m]);
  512. bantch_db.execDML(sql);
  513. CppSQLite3Statement stmt3 = bantch_db.compileStatement("insert into exception (exception_type ,exception_name,page_id,student_paper_id) values(:exception_type ,:exception_name,:page_id,:student_paper_id)");
  514. stmt3.bind(":student_paper_id", conflict_ids[m]);
  515. stmt3.bind(":exception_type", SHIFT_KAOHAOCHONGTU);
  516. stmt3.bind(":exception_name", "考号冲突");
  517. stmt3.execDML();
  518. //updatefile(&bantch_db, conflict_ids[m], (string)CT2A(m_norimg_dir), (string)CT2A(m_excimg_dir));
  519. }
  520. }
  521. bantch_db.execDML("commit transaction");
  522. LeaveCriticalSection(&bantch_db_lock);
  523. for (int m = 0; m < conflict_ids.size(); m++)
  524. {
  525. if (m_hwnd != NULL)::PostMessage(m_hwnd, WM_IDENTIFOR_PAPER_STATE_CHAGED, (WPARAM)NULL, (LPARAM)conflict_ids[m]);
  526. }
  527. return TRUE;
  528. }
  529. //忽略试卷
  530. int CSmartEvaluationService::IgnorePaper(const int paper_id)
  531. {
  532. char sql1[512];
  533. char sql2[512];
  534. char sql3[512];
  535. char sql4[512];
  536. sprintf_s(sql1, "delete from exception where student_paper_id =%d ", paper_id);
  537. sprintf_s(sql2, "delete from result where page_id in (select pg.page_id from page pg where pg.student_paper_id =%d)", paper_id);
  538. sprintf_s(sql3, "delete from page where student_paper_id =%d", paper_id);
  539. sprintf_s(sql4, "delete from student_paper where student_paper_id =%d", paper_id);
  540. EnterCriticalSection(&bantch_db_lock);
  541. bantch_db.execDML(sql1);
  542. bantch_db.execDML(sql2);
  543. bantch_db.execDML(sql3);
  544. bantch_db.execDML(sql4);
  545. LeaveCriticalSection(&bantch_db_lock);
  546. return TRUE;
  547. }
  548. //忽略某类型的异常
  549. int CSmartEvaluationService::IgnoreException(const long exceptions)
  550. {
  551. char number_string[10];
  552. //忽略必须处理的异常将删除试卷
  553. EnterCriticalSection(&bantch_db_lock);
  554. if (exceptions&MEX_BIXUCHULIYICHANG){
  555. char sql0[512];
  556. sprintf_s(sql0, "update student_paper set paper_state=(paper_state|%d) where paper_state&%d=0 and paper_state&%d>0", EX_SHIJUANSHANCHU, EX_SHIJUANSHANCHU, MEX_BIXUCHULIYICHANG);
  557. bantch_db.execDML(sql0);
  558. }
  559. //忽略非必须处理异常,只删除异常
  560. const long non_must_handle_exceptions[3] = { EX_LOUTU, EX_LOUPI, EX_WUPAN };
  561. const long non_must_handle_exception_shifts[3] = { SHIFT_LOUTU, SHIFT_LOUPI, SHIFT_WUPAN };
  562. if (exceptions&MEX_FEIBIXUCHULIYICHANG){
  563. char sql0[512];
  564. sprintf_s(sql0, "update student_paper set paper_state=paper_state-(paper_state&%d) where paper_state&%d=0 and paper_state&%d>0", MEX_FEIBIXUCHULIYICHANG, EX_SHIJUANSHANCHU, MEX_FEIBIXUCHULIYICHANG);
  565. bantch_db.execDML(sql0);
  566. }
  567. LeaveCriticalSection(&bantch_db_lock);
  568. return TRUE;
  569. }
  570. //开始上传成绩
  571. int CSmartEvaluationService::StartUploadPaper(HWND hWnd)
  572. {
  573. if (hWnd != NULL)m_result_uploader.SetHandlerWnd(hWnd);
  574. return m_result_uploader.Start();
  575. }
  576. //是否支持暂停
  577. BOOL CSmartEvaluationService::SupportPause(void)
  578. {
  579. BOOL supportPause = FALSE;
  580. switch (m_feeder_type){
  581. case Folder:supportPause = m_folder_feeder.SupportPause(); break;
  582. case Scanner:supportPause = m_twain_feeder.SupportPause(); break;
  583. //case Restart:supportPause = m_restart_feeder.SupportPause(); break;
  584. case AdjustBatch: supportPause = m_server_feeder.SupportPause(); break;
  585. case AdjustExaminne: supportPause = m_server_feeder.SupportPause(); break;
  586. case ManualMatch: supportPause = (m_current_feeder==0)?FALSE:m_current_feeder->SupportPause(); break;
  587. }
  588. return supportPause;
  589. }
  590. //暂停处理
  591. ServiceState CSmartEvaluationService::OnPausing(void)
  592. {
  593. m_current_feeder->Pause();
  594. while (m_current_feeder->GetServiceSate() == pausing || m_current_feeder->GetServiceSate() == running){
  595. Sleep(10);
  596. }
  597. ServiceState nextState = IService::OnPausing();
  598. if (nextState == paused&&m_hwnd != NULL)::PostMessage(m_hwnd, WM_IDENTIFOR_PAUSED, 0, 0);
  599. return nextState;
  600. }
  601. //恢复扫描
  602. ServiceState CSmartEvaluationService::OnResuming(void)
  603. {
  604. m_current_feeder->Resume();
  605. while (m_current_feeder->GetServiceSate() == resuming){
  606. Sleep(10);
  607. }
  608. ServiceState nextState = IService::OnResuming();
  609. if (nextState == running&&m_hwnd != NULL)::PostMessage(m_hwnd, WM_IDENTIFOR_RESUMED, 0, 0);
  610. return nextState;
  611. }
  612. //放弃本次考试
  613. int CSmartEvaluationService::GiveUpCurrentBatch()
  614. {
  615. char sql[128];
  616. sprintf_s(sql, "update database set database_state =%d where database_id =%d", DATABASE_STATE_GIVEUP, m_database_id);
  617. EnterCriticalSection(database_db_lock);
  618. database_db->execDML("begin transaction");
  619. database_db->execDML(sql);
  620. database_db->execDML("commit transaction");
  621. LeaveCriticalSection(database_db_lock);
  622. return TRUE;
  623. }
  624. //设置继续扫描文件夹路径
  625. int CSmartEvaluationService::SetFolderScanDir(const std::string& img_dir)
  626. {
  627. m_folder_feeder.SetFolder(img_dir);
  628. m_feeder_type = (FEEDER_TYPE)(Folder | (m_feeder_type&AutoSchemaFlag));
  629. return TRUE;
  630. }
  631. //停止服务
  632. BOOL CSmartEvaluationService::Stop(void)
  633. {
  634. if (IService::Stop()){
  635. m_abnormal_stop = TRUE;
  636. return TRUE;
  637. }
  638. return FALSE;
  639. }
  640. int CSmartEvaluationService::QueryExptionPaperCount(int & total_count)
  641. {
  642. EnterCriticalSection(&bantch_db_lock);
  643. total_count = bantch_db.execScalar("select count(0) from student_paper pp where not pp.paper_state = 0");
  644. LeaveCriticalSection(&bantch_db_lock);
  645. return TRUE;
  646. }
  647. //查询异常类型信息
  648. int CSmartEvaluationService::QueryExptionTypeInfo(vector<EXCEPTION_TYPE_INFO> & infos)
  649. {
  650. EnterCriticalSection(&bantch_db_lock);
  651. CppSQLite3Query query = bantch_db.execQuery("SELECT pe.exception_type, count(DISTINCT pe.student_paper_id) exception_paper_count FROM exception pe GROUP BY pe.exception_type");
  652. while (!query.eof()){
  653. EXCEPTION_TYPE_INFO ex_type_info;
  654. ex_type_info.exception_type = (1 << query.getInt64Field("exception_type"));
  655. ex_type_info.exception_count = query.getIntField("exception_paper_count");
  656. switch (ex_type_info.exception_type){
  657. case EX_DINGWEIDIAN:strcpy(ex_type_info.exception_name, "定位点异常"); break;
  658. case EX_FEIFASHIJUAN:strcpy(ex_type_info.exception_name, "非法试卷"); break;
  659. case EX_KAOHAOWEISHIBIE:strcpy(ex_type_info.exception_name, "考号未识别"); break;
  660. //case EX_KAOHAOBUCUNZAI:strcpy(ex_type_info.exception_name, "考号不存在"); break;
  661. case EX_KAOHAOCHONGTU:strcpy(ex_type_info.exception_name, "考号冲突"); break;
  662. case EX_LOUTU:strcpy(ex_type_info.exception_name, "考生漏涂"); break;
  663. case EX_LOUPI:strcpy(ex_type_info.exception_name, "教师漏批"); break;
  664. case EX_WUPAN:strcpy(ex_type_info.exception_name, "教师误判"); break;
  665. case EX_WUFASHIBIE_ZHUGUANTI:strcpy(ex_type_info.exception_name, "无法识别解答题"); break;
  666. case EX_SHIJUANQUEYE:strcpy(ex_type_info.exception_name, "试卷缺页"); break;
  667. //case EX_KEGUANTIYICHANG:strcpy(ex_type_info.exception_name, "客观题异常"); break;
  668. default: strcpy(ex_type_info.exception_name, "未知异常类型"); break;
  669. }
  670. infos.push_back(ex_type_info);
  671. query.nextRow();
  672. }
  673. CppSQLite3Query query2 = bantch_db.execQuery("SELECT count(DISTINCT student_paper_id) exception_paper_count FROM student_paper where paper_state&64>0");
  674. if (!query.eof())
  675. {
  676. EXCEPTION_TYPE_INFO ex_type_info;
  677. strcpy(ex_type_info.exception_name, "考号不存在");
  678. ex_type_info.exception_type = 6;
  679. ex_type_info.exception_count = query2.getIntField("exception_paper_count");
  680. infos.push_back(ex_type_info);
  681. }
  682. CppSQLite3Query query3 = bantch_db.execQuery("SELECT count(DISTINCT student_paper_id) exception_paper_count FROM student_paper where paper_state&32768>0");
  683. if (!query3.eof())
  684. {
  685. EXCEPTION_TYPE_INFO ex_type_info;
  686. strcpy(ex_type_info.exception_name, "客观题异常");
  687. ex_type_info.exception_type = 15;
  688. ex_type_info.exception_count = query3.getIntField("exception_paper_count");
  689. infos.push_back(ex_type_info);
  690. }
  691. LeaveCriticalSection(&bantch_db_lock);
  692. return TRUE;
  693. }
  694. int CSmartEvaluationService::SetCookie(CString path, CString name, CString value)
  695. {
  696. return InternetSetCookie(path, name, value);
  697. }
  698. int CSmartEvaluationService::SetLocalServerCookie(CString name, CString value)
  699. {
  700. switch (CServerConfig::server_address_type){
  701. case SAT_LOCAL_IN:InternetSetCookie(CServerConfig::server_url_local_in, name, value); break;
  702. case SAT_LOCAL_OUT:InternetSetCookie(CServerConfig::server_url_local_out, name, value); break;
  703. }
  704. return TRUE;
  705. }
  706. void CSmartEvaluationService::saveQuestionStd(long long examId, std::string examName, long examCourseId, std::string courseName, std::vector<schema::SCHEMA_QUESTION> &questions)
  707. {
  708. CppSQLite3DB* bantch_db = &this->bantch_db;
  709. const char* sql_clear = "delete from question_std";
  710. bantch_db->execDML(sql_clear);
  711. const char* sql_clear1 = "delete from exam";
  712. bantch_db->execDML(sql_clear1);
  713. const char* sql_exam = "INSERT INTO exam ( exam_id, exam_name, exam_course_id, course_name, full_score ,full_score_objective) VALUES ( :exam_id, :exam_name, :exam_course_id, :course_name, :full_score ,:full_score_objective)";
  714. CppSQLite3Statement statement_exam = bantch_db->compileStatement(sql_exam);
  715. const char* sql = "INSERT INTO question_std ( question_code, question_type, multi_answer, answer_all, answer_std, score_full, score_half, option_count ) VALUES ( :question_code, :question_type, :multi_answer, :answer_all, :answer_std, :score_full, :score_half, :option_count )";
  716. CppSQLite3Statement statement = bantch_db->compileStatement(sql);
  717. bantch_db->execDML("begin transaction");
  718. float full_score = 0;
  719. float full_score_keguanti = 0;
  720. for (int i = 0; i < questions.size(); i++)
  721. {
  722. schema::SCHEMA_QUESTION& row = questions[i];
  723. full_score += row.score;
  724. int question_type = row.questionType&schema::QTF_QUESTION_TYPE_MASK;
  725. if (question_type == schema::DANXUANTI || question_type == schema::DUOXUANTI || question_type == schema::PANDUANTI)full_score_keguanti += row.score;
  726. statement.bind(":question_code", row.question_code);
  727. statement.bind(":question_type", row.questionType);
  728. statement.bind(":multi_answer", question_type == schema::QuestionType::DUOXUANTI);
  729. statement.bind(":answer_all", row.answers.c_str());
  730. statement.bind(":answer_std", row.answerA.c_str());
  731. statement.bind(":score_full", row.score);
  732. statement.bind(":score_half", row.halfScore);
  733. statement.bind(":option_count", 3);
  734. statement.execDML();
  735. }
  736. statement_exam.bind(":exam_id", examId);
  737. statement_exam.bind(":exam_name", examName.c_str());
  738. statement_exam.bind(":exam_course_id", examCourseId);
  739. statement_exam.bind(":course_name", courseName.c_str());
  740. statement_exam.bind(":full_score", full_score);
  741. statement_exam.bind(":full_score_objective", full_score_keguanti);
  742. statement_exam.execDML();
  743. bantch_db->execDML("commit transaction");
  744. }
  745. int CSmartEvaluationService::QueryNormalPaper(vector<STUDENT_INFO> & studentList)
  746. {
  747. EnterCriticalSection(&bantch_db_lock);
  748. string sql = "select s.student_id,s.student_code,s.class_name,s.grade_name,s.student_name,s.class_id,pp.score_total,pp.student_paper_id from student_paper pp left join student s on s.student_id=pp.student_id where pp.paper_state =0";
  749. CppSQLite3Query q = bantch_db.execQuery(sql.c_str());
  750. while (!q.eof()){
  751. STUDENT_INFO si;
  752. char class_name[64];
  753. sprintf_s(class_name, "%s(%s)班", q.getStringField("grade_name"), q.getStringField("class_name"));
  754. si.class_name = class_name;
  755. si.student_id = q.getInt64Field("student_id");
  756. si.student_name = q.getStringField("student_name");
  757. si.student_code = q.getStringField("student_code");
  758. si.class_id = q.getInt64Field("class_id");
  759. si.score = (float)q.getFloatField("score_total", -1);
  760. si.paper_id = q.getIntField("student_paper_id", -1);
  761. studentList.push_back(si);
  762. q.nextRow();
  763. }
  764. LeaveCriticalSection(&bantch_db_lock);
  765. return TRUE;
  766. }
  767. int CSmartEvaluationService::QueryMubanImgPath(int page_index, std::string& imgPath)
  768. {
  769. CString imgFilePath;
  770. imgFilePath.Format(_T("%s\\%05d.jpg"), CString(m_muban_img_dir.c_str()), page_index);
  771. char fff[1024];
  772. WideCharToMultiByte(CP_ACP, 0, imgFilePath, -1, fff, 1024, NULL, NULL);
  773. imgPath = fff;
  774. return TRUE;
  775. }
  776. int CSmartEvaluationService::QueryMubanImgCount(int& page_count)
  777. {
  778. return page_count = m_identifor.GetMubanCount();
  779. }