BatchInfo.cpp 115 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663
  1. #include "stdafx.h"
  2. #include "BatchInfo.h"
  3. #include "log.h"
  4. #include "io.h"
  5. //#include "qcloud.h"
  6. #include "Util.h"
  7. #include "../cloud/CloudApi.h"
  8. #include "sys/stat.h"
  9. #include "../Util/typedef_struct.h"
  10. #include <codecvt>
  11. #include <algorithm>
  12. extern CLog g_log;
  13. extern HWND g_MsgWnd;
  14. extern string g_SchoolId;
  15. extern string g_ServerUrl;
  16. volatile bool g_ScanThreadRun = true;
  17. volatile bool g_IsPagesMissed = false;
  18. static string getBatchCode(string workDir)
  19. {
  20. vector<string> strs = splitEx(workDir, "/");
  21. return strs[strs.size() - 1];
  22. }
  23. bool testServerAvaiable3(const CString& serverAdd)
  24. {
  25. std::string response;
  26. CHttpClient httpClient;
  27. CString url = _T("http://124.71.233.218:17002/teacher/third/card/location?cardId=106&taskId=");
  28. //url.Format(_T("%s/course/findAllCourse"), serverAdd);
  29. //httpClient.SetSendHeader(L"");
  30. httpClient.HttpGet(url, NULL, response);
  31. Json::Value root;
  32. Json::Reader(Json::Features()).parse(response, root);
  33. if (root["success"].isInt() && root["success"].asInt() == 1){
  34. return true;
  35. }
  36. return false;
  37. }
  38. string UtfToGbk(string strValue)
  39. {
  40. int len = MultiByteToWideChar(CP_UTF8, 0, strValue.c_str(), -1, NULL, 0);
  41. wchar_t* wstr = new wchar_t[len + 1];
  42. memset(wstr, 0, len + 1);
  43. MultiByteToWideChar(CP_UTF8, 0, strValue.c_str(), -1, wstr, len);
  44. len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
  45. char* str = new char[len + 1];
  46. memset(str, 0, len + 1);
  47. WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);
  48. if (wstr)
  49. delete[] wstr;
  50. string strRet = string(str);
  51. if (str)
  52. delete[] str;
  53. return strRet;
  54. }
  55. std::wstring ANSIToUnicode(const std::string & str)
  56. {
  57. std::wstring ret;
  58. std::mbstate_t state = {};
  59. const char *src = str.data();
  60. size_t len = std::mbsrtowcs(nullptr, &src, 0, &state);
  61. if (static_cast<size_t>(-1) != len) {
  62. std::unique_ptr< wchar_t[] > buff(new wchar_t[len + 1]);
  63. len = std::mbsrtowcs(buff.get(), &src, len, &state);
  64. if (static_cast<size_t>(-1) != len) {
  65. ret.assign(buff.get(), len);
  66. }
  67. }
  68. return ret;
  69. }
  70. string UnicodeToUTF8(const std::wstring & wstr)
  71. {
  72. std::string ret;
  73. try {
  74. std::wstring_convert< std::codecvt_utf8<wchar_t> > wcv;
  75. ret = wcv.to_bytes(wstr);
  76. }
  77. catch (const std::exception & e) {
  78. std::cerr << e.what() << std::endl;
  79. }
  80. return ret;
  81. }
  82. WCHAR *ToUnicode(const char *zFilename)
  83. {
  84. int nByte;
  85. WCHAR *zMbcsFilename;
  86. int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
  87. nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, NULL, 0)*sizeof(WCHAR);
  88. zMbcsFilename = (WCHAR *)malloc(nByte*sizeof(zMbcsFilename[0]));
  89. if (zMbcsFilename == 0)
  90. {
  91. return 0;
  92. }
  93. nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, nByte);
  94. if (nByte == 0)
  95. {
  96. free(zMbcsFilename);
  97. zMbcsFilename = 0;
  98. }
  99. return zMbcsFilename;
  100. }
  101. string ToUtf8(const string strSrc)
  102. {
  103. string strRet;
  104. strRet = UnicodeToUTF8(ToUnicode(strSrc.c_str()));
  105. return strRet;
  106. }
  107. //void CopyAllFile(CString dest, CString source)
  108. //{
  109. // //AfxMessageBox("创建文件夹"+target);
  110. // CFileFind finder;
  111. // CString path;
  112. // path.Format(_T("%s/*.*"), source);
  113. // BOOL bWorking = finder.FindFile(path);
  114. // while (bWorking){
  115. // bWorking = finder.FindNextFile();
  116. // if (finder.IsDirectory() && !finder.IsDots()){ //是文件夹 而且 名称不含 . 或 ..
  117. // CString fTemp;
  118. // fTemp = dest + finder.GetFileName() + _T("\\");
  119. // CreateDirectory(fTemp, NULL);
  120. // CopyAllFile(fTemp, finder.GetFilePath()); //递归创建文件夹+"/"+finder.GetFileName()
  121. // }
  122. // else{ //是文件 拷贝文件
  123. // CopyFile(finder.GetFilePath(), dest + finder.GetFileName(), FALSE);
  124. // }
  125. // }
  126. // RemoveDirectory(source);
  127. //}
  128. //
  129. //void CBatchService::getStdAnswerAndScore()
  130. //{
  131. // CppSQLite3DB* bantch_db = &this->bantch_db;
  132. // CHttpClient httpClient;
  133. // CString url_str_findPaperInfo, postData, strPaperId;
  134. // string response;
  135. // url_str_findPaperInfo.Format(_T("%s/coachio/iointerface/downLoadThirdPaperSheet"), CServerConfig::server_url);
  136. //
  137. // readPaperId(strPaperId);
  138. // logForDbg("getStdAnswerAndScore");
  139. // postData.Format(_T("paperIdStr="));
  140. // postData += strPaperId;
  141. // httpClient.SetSendHeader(MarkHttpHeaderData());
  142. // httpClient.HttpPost(url_str_findPaperInfo, postData, response);
  143. // Json::Features features;
  144. // Json::Reader re(features);
  145. // Json::Value root;
  146. // re.parse(response, root);
  147. //
  148. // if (root["success"].isInt() && root["success"].asInt()){
  149. // Json::Value objects = root["object"];
  150. // Json::Value object = objects["paper_info"];
  151. // // for (int m = 0; m<object.size(); m++)
  152. // {
  153. // // Json::Value ob = object[m];
  154. // Json::Value rows = object["questions"];
  155. // int array_size = 0;
  156. // array_size = rows.size();
  157. // for (int i = 0; i < array_size; i++)
  158. // {
  159. // Json::Value row = rows[i];
  160. // CppSQLite3Statement stmt = bantch_db->compileStatement("update question_std set answer_std=:answer_std,score_full=:score_full where question_code=:question_code");
  161. // stmt.bind(":question_code", row["questionNum"].asString().c_str());
  162. // stmt.bind(":answer_std", row["answer"].asString().c_str());
  163. // stmt.bind(":score_full", row["fullScore"].asDouble());
  164. // logForDbg("question_code:" + row["questionNum"].asString());
  165. // logForDbg("answer_std:" + row["answer"].asString());
  166. // char strTemp[5] = { "\0" };
  167. // string str;
  168. // sprintf(strTemp, "%.1f", row["fullScore"].asDouble());
  169. // str = strTemp;
  170. // logForDbg("score_full:" + str);
  171. // stmt.execDML();
  172. // }
  173. // }
  174. // }
  175. //}
  176. batch_info GetBatchInfo(int batch_id)
  177. {
  178. batch_info info;
  179. CppSQLite3DB index_db;
  180. try
  181. {
  182. //将数据库文件的路径转换为utf-8编码,以解决中文路径下扫描程序崩溃的问题
  183. index_db.open(ToUtf8(g_Indexdb).c_str());
  184. }
  185. catch (CException* e)
  186. {
  187. g_log.PutMsg(LogLvlFailed, "开启index.db3失败 ");
  188. return info;
  189. }
  190. CppSQLite3Query query0;
  191. char sql[256];
  192. sprintf_s(sql, "select * from batchs where id=%d", batch_id);
  193. query0 = index_db.execQuery(sql);
  194. string strVal;
  195. if (!query0.eof())
  196. {
  197. info.id = batch_id;
  198. strcpy_s(info.create_time, query0.getStringField("create_time"));
  199. strVal = query0.getStringField("batchdb_path");
  200. strVal = ToUtf8(UtfToGbk(strVal));
  201. strcpy_s(info.batchdb_path, strVal.c_str());
  202. strVal = query0.getStringField("work_dir");
  203. //strVal = UtfToGbk(strVal);
  204. strcpy_s(info.work_dir, strVal.c_str());
  205. info.state = query0.getIntField("state");
  206. info.total_cnt = query0.getIntField("total_cnt");
  207. info.success_cnt = query0.getIntField("success_cnt");
  208. }
  209. query0.finalize();
  210. index_db.close();
  211. return info;
  212. }
  213. bool ParseTemplateFromJson(const std::string&fileName, OnLineCard::PaperTemplate* pOnlineCardTemplate)
  214. {
  215. CUnZipFile uzip(CString(fileName.c_str()));
  216. std::map<CString, std::vector<unsigned char>> map;
  217. while (uzip.HasMoreEntry()){
  218. CString fileNam;
  219. uzip.GetNextEntry(fileNam);
  220. char buffer[1024 * 8];
  221. int len;
  222. std::vector<unsigned char>& data = map[fileNam];
  223. data.reserve(1024 * 128);
  224. while ((len = uzip.Read(buffer, 1024 * 8)) > 0){
  225. if (data.capacity() < data.size() + len){
  226. int c = data.capacity() + 1024 * 128;
  227. data.reserve(c);
  228. }
  229. int oldSize = data.size();
  230. data.resize(oldSize + len);
  231. char * dst = (char *)data.data() + oldSize;
  232. memcpy(dst, buffer, len);
  233. }
  234. }
  235. uzip.Close();
  236. auto schemabytes = map.find(_T("json.txt"));
  237. if (schemabytes == map.end()){
  238. return SCH_LOAD_ERR_MISSINGFORMAT;
  239. }
  240. std::vector<unsigned char>& data = schemabytes->second;
  241. auto strJson = std::string((char *)data.data(), data.size());
  242. if (!pOnlineCardTemplate) return false;
  243. pOnlineCardTemplate->pages.clear();
  244. auto pfGetPos = [](const rapidjson::Value&value)->std::tuple<bool, Pos>{
  245. bool bRet = false;
  246. double x = 0.0, y = 0.0, w = 0.0, h = 0.0;
  247. auto itX = value.FindMember("x");
  248. if (itX != value.MemberEnd() && (itX->value.IsInt() || itX->value.IsDouble())){
  249. x = itX->value.GetDouble();
  250. }
  251. auto itY = value.FindMember("y");
  252. if (itY != value.MemberEnd() && (itY->value.IsInt() || itY->value.IsDouble())){
  253. y = itY->value.GetDouble();
  254. }
  255. auto itW = value.FindMember("width");
  256. if (itW != value.MemberEnd() && (itW->value.IsInt() || itW->value.IsDouble())){
  257. w = itW->value.GetDouble();
  258. }
  259. auto itH = value.FindMember("height");
  260. if (itH != value.MemberEnd() && (itH->value.IsInt() || itH->value.IsDouble())){
  261. h = itH->value.GetDouble();
  262. bRet = true;
  263. }
  264. return std::tie(bRet, Pos{ x, y, w, h });
  265. };
  266. rapidjson::Document doc;
  267. doc.Parse(strJson.c_str());
  268. if (doc.HasParseError()) return false;
  269. pOnlineCardTemplate->subject_id = 0;
  270. pOnlineCardTemplate->_version = "old";
  271. // 检测版本号
  272. auto it_version = doc.FindMember("online_card_version");
  273. if (it_version != doc.MemberEnd() && it_version->value.IsString()){
  274. pOnlineCardTemplate->_version = it_version->value.GetString();
  275. }
  276. LOGFMTI("在线答题卡版本号:%s", pOnlineCardTemplate->_version.c_str());
  277. if (pOnlineCardTemplate->_version == "old"){
  278. // 总页数
  279. auto itTotalPage = doc.FindMember("totalPage");
  280. if (itTotalPage != doc.MemberEnd() && itTotalPage->value.IsInt()){
  281. pOnlineCardTemplate->totalPage = itTotalPage->value.GetInt();
  282. }
  283. // 是否使用二维码
  284. auto itUseQrCode = doc.FindMember("useQrCode");
  285. if (itUseQrCode != doc.MemberEnd() && itUseQrCode->value.IsBool()){
  286. pOnlineCardTemplate->useQrCode = itUseQrCode->value.GetBool();
  287. }
  288. if (itUseQrCode != doc.MemberEnd() && itUseQrCode->value.IsInt()){
  289. pOnlineCardTemplate->useQrCode = (itUseQrCode->value.GetInt() != 0);
  290. }
  291. // 学校状态
  292. auto itSchoolStatus = doc.FindMember("school_card_status");
  293. if (itSchoolStatus != doc.MemberEnd() && itSchoolStatus->value.IsInt()){
  294. pOnlineCardTemplate->schoolCardStatus = itSchoolStatus->value.GetInt();
  295. }
  296. int n_duo_xuanti_index = 0;
  297. // 页
  298. auto itPages = doc.FindMember("pages");
  299. if (itPages != doc.MemberEnd() && itPages->value.IsArray() && itPages->value.Size() == pOnlineCardTemplate->totalPage){
  300. for (auto itPage = itPages->value.Begin(); itPage != itPages->value.End(); ++itPage){
  301. if (!itPage->IsObject()) return false;
  302. PageTemplate page;
  303. // 页号
  304. auto itPageNo = itPage->FindMember("pageNo");
  305. if (itPageNo != itPage->MemberEnd() && itPageNo->value.IsInt()){
  306. page.pageNo = itPageNo->value.GetInt();
  307. }
  308. else {
  309. return false;
  310. }
  311. // 定位点
  312. auto itLocations = itPage->FindMember("location");
  313. if (itLocations != itPage->MemberEnd() && itLocations->value.IsArray()){
  314. for (auto it = itLocations->value.Begin(); it != itLocations->value.End(); ++it){
  315. Location lc;
  316. auto itType = it->FindMember("type");
  317. if (itType != it->MemberEnd() && itType->value.IsInt()){
  318. lc.type = itType->value.GetInt();
  319. }
  320. auto tm = pfGetPos(*it);
  321. if (std::get<0>(tm)){
  322. lc.pos = std::get<1>(tm);
  323. }
  324. page.location.push_back(lc);
  325. }
  326. }
  327. if (page.pageNo == 1){
  328. if (!pOnlineCardTemplate->useQrCode){
  329. // 条形码
  330. auto itBar = itPage->FindMember("studentcode_bar");
  331. if (itBar != itPage->MemberEnd() && itBar->value.IsObject()){
  332. auto itObj = itBar->value.FindMember("object");
  333. if (itObj != itBar->value.MemberEnd() && itObj->value.IsObject()){
  334. auto t = pfGetPos(itObj->value);
  335. page.studentcode_bar = std::get<1>(t);
  336. }
  337. }
  338. // 填涂考号
  339. auto itFill = itPage->FindMember("studentcode_fill");
  340. if (itFill != itPage->MemberEnd() && itFill->value.IsObject()){
  341. auto itObj = itFill->value.FindMember("object");
  342. if (itObj != itFill->value.MemberEnd() && itObj->value.IsArray()){
  343. for (auto itRow = itObj->value.Begin(); itRow != itObj->value.End(); ++itRow){
  344. auto itGroup = itRow->FindMember("group");
  345. if (itGroup != itRow->MemberEnd() && itGroup->value.IsArray()){
  346. std::vector<Opt> _vctOpt;
  347. for (auto itCol = itGroup->value.Begin(); itCol != itGroup->value.End(); ++itCol){
  348. Opt opt;
  349. auto itOptName = itCol->FindMember("optName");
  350. if (itOptName != itCol->MemberEnd() && itOptName->value.IsInt())
  351. opt.optName = std::to_string(itOptName->value.GetInt());
  352. auto t = pfGetPos(*itCol);
  353. if (std::get<0>(t))
  354. opt.pos = std::get<1>(t);
  355. _vctOpt.push_back(opt);
  356. }
  357. page.studentcode_fill.push_back(_vctOpt);
  358. }
  359. }
  360. }
  361. }
  362. }
  363. // 缺考标记
  364. auto itAbsent = itPage->FindMember("absent");
  365. if (itAbsent != itPage->MemberEnd() && itAbsent->value.IsObject()){
  366. auto t = pfGetPos(itAbsent->value);
  367. if (std::get<0>(t)){
  368. page.absent = std::get<1>(t);
  369. }
  370. }
  371. // 二维码
  372. auto itQrCode = itPage->FindMember("QrCode");
  373. if (itQrCode != itPage->MemberEnd() && itQrCode->value.IsObject()){
  374. auto t = pfGetPos(itQrCode->value);
  375. if (std::get<0>(t)){
  376. page.QrCode = std::get<1>(t);
  377. }
  378. }
  379. } // end if page.pageNo == 0
  380. // 长宽
  381. auto itImge = itPage->FindMember("imge");
  382. if (itImge != itPage->MemberEnd()){
  383. auto t = std::get<1>(pfGetPos(itImge->value));
  384. page.w = t.w;
  385. page.h = t.h;
  386. }
  387. else{
  388. return false;
  389. }
  390. // 题目
  391. auto itQuestion = itPage->FindMember("questions");
  392. if (itQuestion != itPage->MemberEnd() && itQuestion->value.IsArray()){
  393. for (auto it = itQuestion->value.Begin(); it != itQuestion->value.End(); ++it){
  394. question q;
  395. // 题目类型
  396. auto itType = it->FindMember("type");
  397. if (itType != it->MemberEnd() && itType->value.IsInt()){
  398. q.type = itType->value.GetInt();
  399. }
  400. else{
  401. return false;
  402. }
  403. q.marktype = 0;
  404. // 题目类型
  405. auto itMarktype = it->FindMember("marktype");
  406. if (itMarktype != it->MemberEnd() && itMarktype->value.IsInt()){
  407. q.marktype = itMarktype->value.GetInt();
  408. }
  409. // 分数
  410. auto itScore = it->FindMember("score");
  411. if (itScore != it->MemberEnd() && itScore->value.IsObject()){
  412. auto itFull = itScore->value.FindMember("full");
  413. if (itFull != itScore->value.MemberEnd() && (itFull->value.IsDouble() || itFull->value.IsInt()))
  414. q.score = itFull->value.GetDouble();
  415. else if (itFull != itScore->value.MemberEnd() && itFull->value.IsString())
  416. q.score = atof(itFull->value.GetString());
  417. }
  418. // 题目编号 2选做题
  419. auto itId = it->FindMember(q.type == 2 ? "editorId" : "id");
  420. if (itId != it->MemberEnd() && itId->value.IsString()){
  421. q.id = itId->value.GetString();
  422. }
  423. if (q.type == 2){
  424. auto itAllID = it->FindMember("id");
  425. if (itAllID != it->MemberEnd() && itAllID->value.IsString()){
  426. q.all_id = itAllID->value.GetString();
  427. }
  428. }
  429. // 目前应该只有填空题有这个参数
  430. auto itSmallQtNo = it->FindMember("smallQtNo");
  431. if (itSmallQtNo != it->MemberEnd() && !(itSmallQtNo->value.IsNull()))
  432. {
  433. q.smallQtNo = itSmallQtNo->value.GetInt();
  434. }
  435. else
  436. {
  437. q.smallQtNo = -1;
  438. }
  439. // 打分区域
  440. auto itScoreBox = it->FindMember("scorebox");
  441. if (itScoreBox != it->MemberEnd() && itScoreBox->value.IsObject()){
  442. // 打分框类型
  443. auto itType = itScoreBox->value.FindMember("type");
  444. if (itType != itScoreBox->value.MemberEnd() && itType->value.IsString()){
  445. q.scoreBox.type = std::stoi(itType->value.GetString());
  446. }
  447. else if (itType != itScoreBox->value.MemberEnd() && itType->value.IsInt()){
  448. q.scoreBox.type = itType->value.GetInt();
  449. }
  450. else{
  451. return false;
  452. }
  453. // 分数上限
  454. auto itLimit = itScoreBox->value.FindMember("limit");
  455. if (itLimit != itScoreBox->value.MemberEnd() && itLimit->value.IsString())
  456. q.scoreBox.limit = std::stoi(itLimit->value.GetString());
  457. // 最后一个格子是否为小数 1是 2否
  458. auto itPoint = itScoreBox->value.FindMember("point");
  459. if (itPoint != itScoreBox->value.MemberEnd()){
  460. if (itPoint->value.IsInt()){
  461. if (itPoint->value.GetInt() == 1 || itPoint->value.GetInt() == 2)
  462. q.scoreBox.bPoint = (itPoint->value.GetInt() == 1);
  463. }
  464. else if (itPoint->value.IsString()){
  465. std::string str = itPoint->value.GetString();
  466. if (str == "1" || str == "2")
  467. q.scoreBox.bPoint = (str == "1");
  468. }
  469. }
  470. // 填空题带打分
  471. if (q.scoreBox.type == 3){
  472. auto itScore = itScoreBox->value.FindMember("Score");
  473. if (itScore != itScoreBox->value.MemberEnd() && itScore->value.IsArray()){
  474. for (auto it = itScore->value.Begin(); it != itScore->value.End(); ++it){
  475. if (it->IsString()){
  476. std::string str = it->GetString();
  477. if (!str.empty())
  478. q.scoreBox.vctScore.push_back(std::stoi(str));
  479. }
  480. }
  481. }
  482. }
  483. // 打分位置
  484. auto t = pfGetPos(itScoreBox->value);
  485. if (std::get<0>(t))
  486. q.scoreBox.pos = std::get<1>(t);
  487. }
  488. // 剪裁区域
  489. if (q.type == 1 || q.type == 3){
  490. auto itCut = it->FindMember("cut");
  491. if (itCut != it->MemberEnd() && itCut->value.IsObject()){
  492. auto itLink = itCut->value.FindMember("linkparm");
  493. if (itLink != itCut->value.MemberEnd() && itLink->value.IsInt())
  494. q.cut.linkparm = itLink->value.GetInt();
  495. auto t = pfGetPos(itCut->value);
  496. if (std::get<0>(t))
  497. q.cut.pos = std::get<1>(t);
  498. }
  499. }
  500. else if (q.type == 2){ // 选做题
  501. rapidjson::Value::ConstMemberIterator itSel = it->FindMember("select");
  502. if (itSel != it->MemberEnd() && itSel->value.IsInt()){
  503. q.selItem = itSel->value.GetInt();
  504. }
  505. rapidjson::Value::ConstMemberIterator itTotal = it->FindMember("total");
  506. if (itTotal != it->MemberEnd() && itTotal->value.IsInt()){
  507. q.selTotal = itTotal->value.GetInt();
  508. }
  509. auto itSelectqts = it->FindMember("selectqts");
  510. if (itSelectqts != it->MemberEnd() && itSelectqts->value.IsArray() && itSelectqts->value.Size() > 0){
  511. rapidjson::Value::ConstMemberIterator itCut = itSelectqts->value.Begin()->FindMember("cut");
  512. if (itCut != itSelectqts->value.Begin()->MemberEnd() && itCut->value.IsObject()){
  513. rapidjson::Value::ConstMemberIterator itLink = itCut->value.FindMember("linkparm");
  514. if (itLink != itCut->value.MemberEnd() && itLink->value.IsInt())
  515. q.cut.linkparm = itLink->value.GetInt();
  516. auto t = pfGetPos(itCut->value);
  517. if (std::get<0>(t))
  518. q.cut.pos = std::get<1>(t);
  519. }
  520. }
  521. if (q.cut.linkparm < 2){
  522. std::vector<std::string> split_qr;
  523. split(q.all_id, (std::string)",", &split_qr);
  524. if (n_duo_xuanti_index < split_qr.size())
  525. q.id = split_qr[n_duo_xuanti_index++];
  526. }
  527. else
  528. {
  529. std::vector<std::string> split_qr;
  530. split(q.all_id, (std::string)",", &split_qr);
  531. if (n_duo_xuanti_index - 1 >= 0 && n_duo_xuanti_index - 1 < split_qr.size())
  532. q.id = split_qr[n_duo_xuanti_index - 1];
  533. }
  534. }
  535. // 选项 单选题 多选题
  536. if (q.type == 0 || q.type == 8 || q.type == 5){
  537. auto itOpts = it->FindMember("opt");
  538. if (itOpts != it->MemberEnd() && itOpts->value.IsArray()){
  539. int i = 0;
  540. for (auto itOpt = itOpts->value.Begin(); itOpt != itOpts->value.End(); ++itOpt, ++i){
  541. Opt opt;
  542. auto t = pfGetPos(*itOpt);
  543. if (std::get<0>(t))
  544. opt.pos = std::get<1>(t);
  545. auto itOptName = itOpt->FindMember("optName");
  546. if (itOptName != itOpt->MemberEnd() && itOptName->value.IsString())
  547. opt.optName = itOptName->value.GetString();
  548. q.opt.push_back(opt);
  549. }
  550. }
  551. }
  552. else if (q.type == 2){ // 多选题
  553. auto itSelectqts = it->FindMember("selectqts");
  554. if (itSelectqts != it->MemberEnd() && itSelectqts->value.IsArray() && itSelectqts->value.Size() > 0){
  555. auto itOpts = itSelectqts->value.Begin()->FindMember("opt");
  556. if (itOpts != itSelectqts->value.Begin()->MemberEnd() && itOpts->value.IsArray()){
  557. q.selTotal = itOpts->value.Size();
  558. for (auto itOpt = itOpts->value.Begin(); itOpt != itOpts->value.End(); ++itOpt){
  559. Opt opt;
  560. auto t = pfGetPos(*itOpt);
  561. if (std::get<0>(t))
  562. opt.pos = std::get<1>(t);
  563. auto itOptName = itOpt->FindMember("optName");
  564. if (itOptName != itOpt->MemberEnd() && itOptName->value.IsString())
  565. opt.optName = itOptName->value.GetString();
  566. q.opt.push_back(opt);
  567. }
  568. }
  569. }
  570. }
  571. page.vctQuestions.push_back(q);
  572. }
  573. }
  574. pOnlineCardTemplate->pages.insert(std::make_pair(page.pageNo, page));
  575. }
  576. }
  577. else{
  578. return false;
  579. }
  580. }
  581. else{
  582. // 总页数
  583. auto itTotalPage = doc.FindMember("totalPage");
  584. if (itTotalPage != doc.MemberEnd() && itTotalPage->value.IsInt()){
  585. pOnlineCardTemplate->totalPage = itTotalPage->value.GetInt();
  586. }
  587. // 是否使用二维码
  588. auto itUseQrCode = doc.FindMember("useQrCode");
  589. if (itUseQrCode != doc.MemberEnd() && itUseQrCode->value.IsBool()){
  590. pOnlineCardTemplate->useQrCode = itUseQrCode->value.GetBool();
  591. }
  592. if (itUseQrCode != doc.MemberEnd() && itUseQrCode->value.IsInt()){
  593. pOnlineCardTemplate->useQrCode = (itUseQrCode->value.GetInt() != 0);
  594. }
  595. // 学校状态
  596. auto itSchoolStatus = doc.FindMember("school_card_status");
  597. if (itSchoolStatus != doc.MemberEnd() && itSchoolStatus->value.IsInt()){
  598. pOnlineCardTemplate->schoolCardStatus = itSchoolStatus->value.GetInt();
  599. }
  600. int n_duo_xuanti_index = 0;
  601. std::string temp_all_id = "";
  602. // 页
  603. auto itPages = doc.FindMember("pages");
  604. if (itPages != doc.MemberEnd() && itPages->value.IsArray()/* && itPages->value.Size() == m_onlineCardTemplate->totalPage*/){
  605. for (auto itPage = itPages->value.Begin(); itPage != itPages->value.End(); ++itPage){
  606. if (!itPage->IsObject()) return false;
  607. PageTemplate page;
  608. // 页号
  609. auto itPageNo = itPage->FindMember("pageNo");
  610. if (itPageNo != itPage->MemberEnd() && itPageNo->value.IsInt()){
  611. page.pageNo = itPageNo->value.GetInt();
  612. }
  613. else {
  614. return false;
  615. }
  616. // 定位点
  617. auto itLocations = itPage->FindMember("location");
  618. if (itLocations != itPage->MemberEnd() && itLocations->value.IsArray()){
  619. for (auto it = itLocations->value.Begin(); it != itLocations->value.End(); ++it){
  620. Location lc;
  621. auto itType = it->FindMember("type");
  622. if (itType != it->MemberEnd() && itType->value.IsInt()){
  623. lc.type = itType->value.GetInt();
  624. }
  625. auto tm = pfGetPos(*it);
  626. if (std::get<0>(tm)){
  627. lc.pos = std::get<1>(tm);
  628. }
  629. page.location.push_back(lc);
  630. }
  631. }
  632. if (page.pageNo == 1){
  633. if (!pOnlineCardTemplate->useQrCode){
  634. // 条形码
  635. auto itBar = itPage->FindMember("studentcode_bar");
  636. if (itBar != itPage->MemberEnd() && itBar->value.IsObject()){
  637. auto itObj = itBar->value.FindMember("object");
  638. if (itObj != itBar->value.MemberEnd() && itObj->value.IsObject()){
  639. auto t = pfGetPos(itObj->value);
  640. page.studentcode_bar = std::get<1>(t);
  641. }
  642. }
  643. // 填涂考号
  644. auto itFill = itPage->FindMember("studentcode_fill");
  645. if (itFill != itPage->MemberEnd() && itFill->value.IsObject()){
  646. auto itObj = itFill->value.FindMember("object");
  647. if (itObj != itFill->value.MemberEnd() && itObj->value.IsArray()){
  648. for (auto itRow = itObj->value.Begin(); itRow != itObj->value.End(); ++itRow){
  649. auto itGroup = itRow->FindMember("group");
  650. if (itGroup != itRow->MemberEnd() && itGroup->value.IsArray()){
  651. std::vector<Opt> _vctOpt;
  652. for (auto itCol = itGroup->value.Begin(); itCol != itGroup->value.End(); ++itCol){
  653. Opt opt;
  654. auto itOptName = itCol->FindMember("optName");
  655. if (itOptName != itCol->MemberEnd() && itOptName->value.IsInt())
  656. opt.optName = std::to_string(itOptName->value.GetInt());
  657. auto t = pfGetPos(*itCol);
  658. if (std::get<0>(t))
  659. opt.pos = std::get<1>(t);
  660. _vctOpt.push_back(opt);
  661. }
  662. page.studentcode_fill.push_back(_vctOpt);
  663. }
  664. }
  665. }
  666. }
  667. }
  668. // 缺考标记
  669. auto itAbsent = itPage->FindMember("absent");
  670. if (itAbsent != itPage->MemberEnd() && itAbsent->value.IsObject()){
  671. auto t = pfGetPos(itAbsent->value);
  672. if (std::get<0>(t)){
  673. page.absent = std::get<1>(t);
  674. }
  675. }
  676. // 二维码
  677. auto itQrCode = itPage->FindMember("QrCode");
  678. if (itQrCode != itPage->MemberEnd() && itQrCode->value.IsObject()){
  679. auto t = pfGetPos(itQrCode->value);
  680. if (std::get<0>(t)){
  681. page.QrCode = std::get<1>(t);
  682. }
  683. }
  684. } // end if page.pageNo == 0
  685. // 长宽
  686. auto itImge = itPage->FindMember("imge");
  687. if (itImge != itPage->MemberEnd()){
  688. auto t = std::get<1>(pfGetPos(itImge->value));
  689. page.w = t.w;
  690. page.h = t.h;
  691. }
  692. else{
  693. return false;
  694. }
  695. // 题目
  696. auto itQuestion = itPage->FindMember("questions");
  697. if (itQuestion != itPage->MemberEnd() && itQuestion->value.IsArray()){
  698. for (auto it = itQuestion->value.Begin(); it != itQuestion->value.End(); ++it){
  699. question q;
  700. // 题目类型
  701. auto itType = it->FindMember("type");
  702. if (itType != it->MemberEnd() && itType->value.IsInt()){
  703. q.type = itType->value.GetInt();
  704. }
  705. else{
  706. return false;
  707. }
  708. q.marktype = 0;
  709. // 题目类型
  710. auto itMarktype = it->FindMember("marktype");
  711. if (itMarktype != it->MemberEnd() && itMarktype->value.IsInt()){
  712. q.marktype = itMarktype->value.GetInt();
  713. }
  714. // 分数
  715. auto itScore = it->FindMember("score");
  716. if (itScore != it->MemberEnd() && itScore->value.IsObject()){
  717. auto itFull = itScore->value.FindMember("full");
  718. if (itFull != itScore->value.MemberEnd() && (itFull->value.IsDouble() || itFull->value.IsInt()))
  719. q.score = itFull->value.GetDouble();
  720. else if (itFull != itScore->value.MemberEnd() && itFull->value.IsString())
  721. q.score = atof(itFull->value.GetString());
  722. }
  723. // 题目编号 2选做题 4题组
  724. auto itId = it->FindMember((q.type == 2 || q.type == 4) ? "editorId" : "id");
  725. if (itId != it->MemberEnd() && itId->value.IsString()){
  726. q.id = itId->value.GetString();
  727. }
  728. if (itId != it->MemberEnd() && itId->value.IsInt()){
  729. q.id = std::to_string(itId->value.GetInt());
  730. }
  731. if (q.type == 2 || q.type == 4){
  732. auto itAllID = it->FindMember("id");
  733. if (itAllID != it->MemberEnd() && itAllID->value.IsString()){
  734. q.all_id = itAllID->value.GetString();
  735. }
  736. }
  737. auto itSmallQtNo = it->FindMember("smallQtNo");
  738. if (itSmallQtNo != it->MemberEnd() && !(itSmallQtNo->value.IsNull()))
  739. {
  740. q.smallQtNo = itSmallQtNo->value.GetInt();
  741. }
  742. else
  743. {
  744. q.smallQtNo = -1;
  745. }
  746. auto itNickID = it->FindMember("name");
  747. if (itNickID != it->MemberEnd() && !(itNickID->value.IsNull()) && itNickID->value.IsInt())
  748. {
  749. }
  750. // 打分区域
  751. auto itScoreBox = it->FindMember("scorebox");
  752. if (itScoreBox != it->MemberEnd() && itScoreBox->value.IsObject()){
  753. // 打分框类型
  754. auto itType = itScoreBox->value.FindMember("type");
  755. if (itType != itScoreBox->value.MemberEnd() && itType->value.IsString()){
  756. q.scoreBox.type = std::stoi(itType->value.GetString());
  757. }
  758. else if (itType != itScoreBox->value.MemberEnd() && itType->value.IsInt()){
  759. q.scoreBox.type = itType->value.GetInt();
  760. }
  761. else{
  762. return false;
  763. }
  764. if (q.smallQtNo != -1)
  765. {
  766. // 小问最大分值
  767. auto itmaxScore = itScoreBox->value.FindMember("maxscore");
  768. if (itmaxScore != itScoreBox->value.MemberEnd() && itmaxScore->value.IsString()){
  769. q.scoreBox.maxsorce = std::stod(itmaxScore->value.GetString());
  770. }
  771. else if (itmaxScore != itScoreBox->value.MemberEnd() && itmaxScore->value.IsDouble()){
  772. q.scoreBox.maxsorce = itScoreBox->value.GetDouble();
  773. }
  774. else if (itmaxScore != itScoreBox->value.MemberEnd() && itmaxScore->value.IsInt()){
  775. q.scoreBox.maxsorce = itmaxScore->value.GetInt();
  776. }
  777. else{
  778. q.scoreBox.maxsorce = 0.0;
  779. }
  780. }
  781. else
  782. {
  783. q.scoreBox.maxsorce = 0.0;
  784. }
  785. // 分数上限
  786. auto itLimit = itScoreBox->value.FindMember("limit");
  787. if (itLimit != itScoreBox->value.MemberEnd() && itLimit->value.IsString())
  788. q.scoreBox.limit = std::stoi(itLimit->value.GetString());
  789. if (itLimit != itScoreBox->value.MemberEnd() && itLimit->value.IsInt())
  790. q.scoreBox.limit = itLimit->value.GetInt();
  791. // 最后一个格子是否为小数 1是 2否
  792. auto itPoint = itScoreBox->value.FindMember("point");
  793. if (itPoint != itScoreBox->value.MemberEnd()){
  794. if (itPoint->value.IsInt()){
  795. q.scoreBox.bPoint = (itPoint->value.GetInt() == 1);
  796. }
  797. else if (itPoint->value.IsString()){
  798. std::string str = itPoint->value.GetString();
  799. q.scoreBox.bPoint = (str == "1");
  800. }
  801. }
  802. // 填空题带打分
  803. if (q.scoreBox.type == 3){
  804. auto itScore = itScoreBox->value.FindMember("Score");
  805. if (itScore != itScoreBox->value.MemberEnd() && itScore->value.IsArray()){
  806. for (auto it = itScore->value.Begin(); it != itScore->value.End(); ++it){
  807. if (it->IsString()){
  808. std::string str = it->GetString();
  809. if (!str.empty())
  810. q.scoreBox.vctScore.push_back(std::stoi(str));
  811. }
  812. }
  813. }
  814. }
  815. // 打分位置
  816. auto t = pfGetPos(itScoreBox->value);
  817. if (std::get<0>(t))
  818. q.scoreBox.pos = std::get<1>(t);
  819. }
  820. // 几选几
  821. if (q.type == 2 || q.type == 4){ // 选做题
  822. rapidjson::Value::ConstMemberIterator itSel = it->FindMember("select");
  823. if (itSel != it->MemberEnd() && itSel->value.IsInt()){
  824. q.selItem = itSel->value.GetInt();
  825. }
  826. rapidjson::Value::ConstMemberIterator itTotal = it->FindMember("total");
  827. if (itTotal != it->MemberEnd() && itTotal->value.IsInt()){
  828. q.selTotal = itTotal->value.GetInt();
  829. }
  830. }
  831. // 剪裁区域
  832. if (q.type == 1 || q.type == 3 || q.type == 2 || q.type == 4){ // 1 解答题 2 选做题 3 填空题
  833. auto itCut = it->FindMember("cut");
  834. if (itCut != it->MemberEnd() && itCut->value.IsObject()){
  835. auto itLink = itCut->value.FindMember("linkparm");
  836. if (itLink != itCut->value.MemberEnd() && itLink->value.IsInt())
  837. q.cut.linkparm = itLink->value.GetInt();
  838. if (itLink != itCut->value.MemberEnd() && itLink->value.IsString())
  839. q.cut.linkparm = std::stoi(itLink->value.GetString());
  840. auto t = pfGetPos(itCut->value);
  841. if (std::get<0>(t))
  842. q.cut.pos = std::get<1>(t);
  843. if (q.type == 3 && pOnlineCardTemplate->subject_id == 8)
  844. {
  845. TCHAR FilePath[MAX_PATH];
  846. GetModuleFileName(NULL, FilePath, MAX_PATH);
  847. (_tcsrchr(FilePath, '\\'))[1] = 0;
  848. lstrcat(FilePath, _T("config.ini"));
  849. int english = GetPrivateProfileInt(_T("USER"), _T("english_height"), 30, FilePath);//英语填空题高度加大比例
  850. if (english > 0 && english <= 30)
  851. {
  852. q.cut.pos.h = q.cut.pos.h* (1.0 + english / 100.0);
  853. }
  854. }
  855. }
  856. if (q.type == 2){
  857. if (temp_all_id != q.all_id)
  858. {
  859. temp_all_id = q.all_id;
  860. n_duo_xuanti_index = 0;
  861. }
  862. if (q.cut.linkparm < 2){
  863. std::vector<std::string> split_qr;
  864. split(q.all_id, (std::string)",", &split_qr);
  865. if (n_duo_xuanti_index < split_qr.size())
  866. q.id = split_qr[n_duo_xuanti_index++];
  867. }
  868. else
  869. {
  870. std::vector<std::string> split_qr;
  871. split(q.all_id, (std::string)",", &split_qr);
  872. if (n_duo_xuanti_index - 1 >= 0 && n_duo_xuanti_index - 1 < split_qr.size())
  873. q.id = split_qr[n_duo_xuanti_index - 1];
  874. }
  875. }
  876. else if (q.type == 4)
  877. {
  878. if (temp_all_id != q.all_id)
  879. {
  880. temp_all_id = q.all_id;
  881. n_duo_xuanti_index = 0;
  882. }
  883. if (q.cut.linkparm < 1){
  884. std::vector<std::string> split_qr;
  885. split(q.all_id, (std::string)",", &split_qr);
  886. if (n_duo_xuanti_index < split_qr.size())
  887. q.id = split_qr[n_duo_xuanti_index++];
  888. }
  889. else
  890. {
  891. std::vector<std::string> split_qr;
  892. split(q.all_id, (std::string)",", &split_qr);
  893. if (n_duo_xuanti_index - 1 >= 0 && n_duo_xuanti_index - 1 < split_qr.size())
  894. q.id = split_qr[n_duo_xuanti_index - 1];
  895. }
  896. }
  897. }
  898. // 选项 单选题 多选题
  899. if (q.type == 0 || q.type == 8 || q.type == 5){
  900. auto itOpts = it->FindMember("opt");
  901. if (itOpts != it->MemberEnd() && itOpts->value.IsArray()){
  902. for (auto itOpt = itOpts->value.Begin(); itOpt != itOpts->value.End(); ++itOpt){
  903. Opt opt;
  904. auto t = pfGetPos(*itOpt);
  905. if (std::get<0>(t))
  906. opt.pos = std::get<1>(t);
  907. auto itOptName = itOpt->FindMember("optName");
  908. if (itOptName != itOpt->MemberEnd() && itOptName->value.IsString())
  909. opt.optName = itOptName->value.GetString();
  910. q.opt.push_back(opt);
  911. }
  912. }
  913. }
  914. else if (q.type == 2 || q.type == 4){ // 多选题
  915. auto itSelectqts = it->FindMember("selectqts");
  916. if (itSelectqts != it->MemberEnd() && itSelectqts->value.IsArray() && itSelectqts->value.Size() > 0){
  917. for (auto itOpt = itSelectqts->value.Begin(); itOpt != itSelectqts->value.End(); ++itOpt){
  918. Opt opt;
  919. auto t = pfGetPos(*itOpt);
  920. if (std::get<0>(t))
  921. opt.pos = std::get<1>(t);
  922. auto itOptName = itOpt->FindMember("optName");
  923. if (itOptName != itOpt->MemberEnd() && itOptName->value.IsString())
  924. opt.optName = itOptName->value.GetString();
  925. q.opt.push_back(opt);
  926. }
  927. }
  928. }
  929. page.vctQuestions.push_back(q);
  930. }
  931. }
  932. pOnlineCardTemplate->pages.insert(std::make_pair(page.pageNo, page));
  933. }
  934. }
  935. else{
  936. return false;
  937. }
  938. }
  939. pOnlineCardTemplate->open_save_debug_img = false;
  940. pOnlineCardTemplate->dingweidian_range_top = 300; //上定位点范围
  941. pOnlineCardTemplate->dingweidian_rang_buttom = 300;// 下定位点范围
  942. pOnlineCardTemplate->dingweidian_w_max_rate = 1.0;
  943. pOnlineCardTemplate->dingweidian_h_max_rate = 1.0;
  944. pOnlineCardTemplate->dingweidian_w_min_rate = 0.7;
  945. pOnlineCardTemplate->dingweidian_h_min_rate = 0.7;
  946. return true;
  947. }
  948. bool CBatch_Server::ParseTemplateFromJsonAll(const std::string&fileName, OnLineCard::PaperTemplate* pOnlineCardTemplate)//全学科在线答题卡
  949. {
  950. qid_name.clear();
  951. //1 单选 2 小题单选 3 多选 4 小题多选 5 单空 6 多空 7 小题多空 8 解答 9 小题解答 10 英语作文 11 语文作文 12 判断题
  952. //0选择 1解答 2选作 3填空 4编组 5不定项 8不定项
  953. map<string, int> type_map;//新旧题型对应
  954. type_map["1"] = 0; type_map["2"] = 0; type_map["3"] = 5; type_map["4"] = 5; type_map["5"] = 3; type_map["6"] = 3;
  955. type_map["7"] = 3; type_map["8"] = 1; type_map["9"] = 1; type_map["12"] = 0; type_map["10"] = 1; type_map["11"] = 1; type_map["12"] = 0;
  956. /*CUnZipFile uzip(CString(fileName.c_str()));
  957. std::map<CString, std::vector<unsigned char>> map1;
  958. while (uzip.HasMoreEntry()){
  959. CString fileNam;
  960. uzip.GetNextEntry(fileNam);
  961. char buffer[1024 * 8];
  962. int len;
  963. std::vector<unsigned char>& data = map1[fileNam];
  964. data.reserve(1024 * 128);
  965. while ((len = uzip.Read(buffer, 1024 * 8)) > 0){
  966. if (data.capacity() < data.size() + len){
  967. int c = data.capacity() + 1024 * 128;
  968. data.reserve(c);
  969. }
  970. int oldSize = data.size();
  971. data.resize(oldSize + len);
  972. char * dst = (char *)data.data() + oldSize;
  973. memcpy(dst, buffer, len);
  974. }
  975. }
  976. uzip.Close();
  977. auto schemabytes = map1.find(_T("json.txt"));
  978. if (schemabytes == map1.end()){
  979. return SCH_LOAD_ERR_MISSINGFORMAT;
  980. }
  981. std::vector<unsigned char>& data = schemabytes->second;
  982. auto strJson = std::string((char *)data.data(), data.size());*/
  983. string strJson = fileName;
  984. if (!pOnlineCardTemplate) return false;
  985. pOnlineCardTemplate->pages.clear();
  986. auto pfGetPos = [](const rapidjson::Value&value)->std::tuple<bool, Pos>{
  987. bool bRet = false;
  988. double x = 0.0, y = 0.0, w = 0.0, h = 0.0;
  989. auto itX = value.FindMember("x");
  990. if (itX != value.MemberEnd() && (itX->value.IsInt() || itX->value.IsDouble())){
  991. x = itX->value.GetDouble();
  992. }
  993. auto itY = value.FindMember("y");
  994. if (itY != value.MemberEnd() && (itY->value.IsInt() || itY->value.IsDouble())){
  995. y = itY->value.GetDouble();
  996. }
  997. auto itW = value.FindMember("width");
  998. if (itW != value.MemberEnd() && (itW->value.IsInt() || itW->value.IsDouble())){
  999. w = itW->value.GetDouble();
  1000. }
  1001. auto itH = value.FindMember("height");
  1002. if (itH != value.MemberEnd() && (itH->value.IsInt() || itH->value.IsDouble())){
  1003. h = itH->value.GetDouble();
  1004. bRet = true;
  1005. }
  1006. if (x<0 || y<0 || w<0 || h<0)
  1007. {
  1008. throw "pos illegal";
  1009. }
  1010. return std::tie(bRet, Pos{ x, y, w, h });
  1011. };
  1012. rapidjson::Document root;
  1013. root.Parse(strJson.c_str());
  1014. if (root.HasParseError()) return false;
  1015. pOnlineCardTemplate->subject_id = 0;
  1016. pOnlineCardTemplate->_version = "3.1.0";
  1017. auto data = root.FindMember("data");
  1018. if (data == root.MemberEnd())
  1019. {
  1020. return false;
  1021. }
  1022. //auto doc = data->value.FindMember;
  1023. // 检测版本号
  1024. auto it_version = data->value.FindMember("online_card_version");
  1025. if (it_version != data->value.MemberEnd() && it_version->value.IsString()){
  1026. pOnlineCardTemplate->_version = it_version->value.GetString();
  1027. }
  1028. {
  1029. // 总页数
  1030. auto itTotalPage = data->value.FindMember("totalPage");
  1031. if (itTotalPage != data->value.MemberEnd() && itTotalPage->value.IsInt()){
  1032. pOnlineCardTemplate->totalPage = itTotalPage->value.GetInt();
  1033. }
  1034. // 是否使用二维码
  1035. auto itUseQrCode = data->value.FindMember("useQrCode");
  1036. if (itUseQrCode != data->value.MemberEnd() && itUseQrCode->value.IsBool()){
  1037. pOnlineCardTemplate->useQrCode = itUseQrCode->value.GetBool();
  1038. }
  1039. if (itUseQrCode != data->value.MemberEnd() && itUseQrCode->value.IsInt()){
  1040. pOnlineCardTemplate->useQrCode = (itUseQrCode->value.GetInt() != 0);
  1041. }
  1042. // 学科名
  1043. auto itSubject = data->value.FindMember("subject_name");
  1044. if (itSubject != data->value.MemberEnd() && itSubject->value.IsString()){
  1045. pOnlineCardTemplate->subject_name = itSubject->value.GetString();
  1046. }
  1047. // 考试名
  1048. auto itCardName = data->value.FindMember("cardName");
  1049. if (itCardName != data->value.MemberEnd() && itCardName->value.IsString()){
  1050. pOnlineCardTemplate->exam_name = itCardName->value.GetString();
  1051. }
  1052. pOnlineCardTemplate->useQrCode = false;
  1053. // 学校状态
  1054. auto itSchoolStatus = data->value.FindMember("school_card_status");
  1055. if (itSchoolStatus != data->value.MemberEnd() && itSchoolStatus->value.IsInt()){
  1056. pOnlineCardTemplate->schoolCardStatus = itSchoolStatus->value.GetInt();
  1057. }
  1058. int n_duo_xuanti_index = 0;
  1059. std::string temp_all_id = "";
  1060. // 页
  1061. auto itPages = data->value.FindMember("pages");
  1062. if (itPages != data->value.MemberEnd() && itPages->value.IsArray()/* && itPages->value.Size() == m_onlineCardTemplate->totalPage*/){
  1063. for (auto itPage = itPages->value.Begin(); itPage != itPages->value.End(); ++itPage){
  1064. if (!itPage->IsObject()) return false;
  1065. PageTemplate page;
  1066. // 页号
  1067. auto itPageNo = itPage->FindMember("pageNo");
  1068. if (itPageNo != itPage->MemberEnd() && itPageNo->value.IsInt()){
  1069. page.pageNo = itPageNo->value.GetInt();
  1070. }
  1071. else {
  1072. return false;
  1073. }
  1074. // 定位点
  1075. auto itLocations = itPage->FindMember("location");
  1076. if (itLocations != itPage->MemberEnd() && itLocations->value.IsArray()){
  1077. for (auto it = itLocations->value.Begin(); it != itLocations->value.End(); ++it){
  1078. Location lc;
  1079. auto itType = it->FindMember("type");
  1080. if (itType != it->MemberEnd() && itType->value.IsInt()){
  1081. lc.type = itType->value.GetInt();
  1082. }
  1083. auto tm = pfGetPos(*it);
  1084. if (std::get<0>(tm)){
  1085. lc.pos = std::get<1>(tm);
  1086. }
  1087. page.location.push_back(lc);
  1088. }
  1089. }
  1090. if (page.pageNo == 1){
  1091. if (!pOnlineCardTemplate->useQrCode){
  1092. // 条形码
  1093. auto itBar = itPage->FindMember("studentcode_bar");
  1094. if (itBar != itPage->MemberEnd() && itBar->value.IsObject()){
  1095. auto itObj = itBar->value.FindMember("object");
  1096. if (itObj != itBar->value.MemberEnd() && itObj->value.IsObject()){
  1097. auto t = pfGetPos(itObj->value);
  1098. page.studentcode_bar = std::get<1>(t);
  1099. }
  1100. }
  1101. // 填涂考号
  1102. auto itFill = itPage->FindMember("studentcode_fill");
  1103. if (itFill != itPage->MemberEnd() && itFill->value.IsObject()){
  1104. auto itObj = itFill->value.FindMember("object");
  1105. if (itObj != itFill->value.MemberEnd() && itObj->value.IsArray()){
  1106. for (auto itRow = itObj->value.Begin(); itRow != itObj->value.End(); ++itRow){
  1107. auto itGroup = itRow->FindMember("group");
  1108. if (itGroup != itRow->MemberEnd() && itGroup->value.IsArray()){
  1109. std::vector<Opt> _vctOpt;
  1110. for (auto itCol = itGroup->value.Begin(); itCol != itGroup->value.End(); ++itCol){
  1111. Opt opt;
  1112. auto itOptName = itCol->FindMember("optName");
  1113. if (itOptName != itCol->MemberEnd() && itOptName->value.IsInt())
  1114. opt.optName = std::to_string(itOptName->value.GetInt());
  1115. auto t = pfGetPos(*itCol);
  1116. if (std::get<0>(t))
  1117. opt.pos = std::get<1>(t);
  1118. _vctOpt.push_back(opt);
  1119. }
  1120. page.studentcode_fill.push_back(_vctOpt);
  1121. }
  1122. }
  1123. }
  1124. }
  1125. }
  1126. // 缺考标记
  1127. auto itAbsent = itPage->FindMember("absent");
  1128. if (itAbsent != itPage->MemberEnd() && itAbsent->value.IsObject()){
  1129. auto t = pfGetPos(itAbsent->value);
  1130. if (std::get<0>(t)){
  1131. page.absent = std::get<1>(t);
  1132. }
  1133. }
  1134. // 二维码
  1135. auto itQrCode = itPage->FindMember("QrCode");
  1136. if (itQrCode != itPage->MemberEnd() && itQrCode->value.IsObject()){
  1137. auto t = pfGetPos(itQrCode->value);
  1138. if (std::get<0>(t)){
  1139. page.QrCode = std::get<1>(t);
  1140. }
  1141. }
  1142. } // end if page.pageNo == 0
  1143. // 长宽
  1144. auto itImge = itPage->FindMember("imge");
  1145. if (itImge != itPage->MemberEnd()){
  1146. auto t = std::get<1>(pfGetPos(itImge->value));
  1147. page.w = t.w;
  1148. page.h = t.h;
  1149. }
  1150. else{
  1151. return false;
  1152. }
  1153. // 题目
  1154. auto itQuestion = itPage->FindMember("questions");
  1155. if (itQuestion != itPage->MemberEnd() && itQuestion->value.IsArray())
  1156. {
  1157. for (auto it = itQuestion->value.Begin(); it != itQuestion->value.End(); ++it)
  1158. {
  1159. question q;
  1160. q.cut.linkparm = 0;
  1161. // 题目类型
  1162. auto itType = it->FindMember("type");
  1163. string qType = "1";
  1164. if (itType != it->MemberEnd() && itType->value.IsString())
  1165. {
  1166. qType = itType->value.GetString();
  1167. if (type_map.find(qType) != type_map.end())
  1168. {
  1169. q.type = type_map[qType];
  1170. }
  1171. }
  1172. else if (itType != it->MemberEnd() && itType->value.IsInt())
  1173. {
  1174. qType = to_string(itType->value.GetInt());
  1175. if (type_map.find(qType) != type_map.end())
  1176. {
  1177. q.type = type_map[qType];
  1178. }
  1179. }
  1180. else
  1181. {
  1182. return false;
  1183. }
  1184. auto itName = it->FindMember("name");
  1185. if (itType != it->MemberEnd() && itName->value.IsString())
  1186. {
  1187. q.name = itName->value.GetString();
  1188. }
  1189. else if (itName != it->MemberEnd() && itName->value.IsInt())
  1190. {
  1191. q.name = to_string(itName->value.GetInt());
  1192. }
  1193. q.marktype = 0;
  1194. // 题目类型
  1195. auto itMarktype = it->FindMember("marktype");
  1196. if (itMarktype != it->MemberEnd() && itMarktype->value.IsInt()){
  1197. q.marktype = itMarktype->value.GetInt();
  1198. }
  1199. //if (qType == "10")//英文作文
  1200. //{
  1201. // q.marktype = 10;
  1202. // q.type = 1;
  1203. //}
  1204. //else if (qType == "11")//语文作文
  1205. //{
  1206. // q.marktype = 4;
  1207. // q.type = 1;
  1208. //}
  1209. /*else*/
  1210. //if (qType == "12")//判断
  1211. //{
  1212. // q.type = 0;
  1213. //}
  1214. // 分数
  1215. auto itScore = it->FindMember("score");
  1216. if (itScore != it->MemberEnd() && itScore->value.IsObject()){
  1217. auto itFull = itScore->value.FindMember("full");
  1218. if (itFull != itScore->value.MemberEnd() && (itFull->value.IsDouble() || itFull->value.IsInt()))
  1219. q.score = itFull->value.GetDouble();
  1220. else if (itFull != itScore->value.MemberEnd() && itFull->value.IsString())
  1221. q.score = atof(itFull->value.GetString());
  1222. }
  1223. // 题目编号 2选做题
  1224. auto itId = it->FindMember((q.type == 2 || q.type == 4) ? "editorId" : "id");
  1225. if (itId != it->MemberEnd() && itId->value.IsString()){
  1226. q.id = itId->value.GetString();
  1227. }
  1228. if (itId != it->MemberEnd() && itId->value.IsInt()){
  1229. q.id = std::to_string(itId->value.GetInt());
  1230. }
  1231. if (q.type == 2 || q.type == 4){
  1232. auto itAllID = it->FindMember("id");
  1233. if (itAllID != it->MemberEnd() && itAllID->value.IsString()){
  1234. q.all_id = itAllID->value.GetString();
  1235. }
  1236. }
  1237. auto itSmallQtNo = it->FindMember("smallQtNo");
  1238. if (itSmallQtNo != it->MemberEnd() && !(itSmallQtNo->value.IsNull()))
  1239. {
  1240. q.smallQtNo = itSmallQtNo->value.GetInt();
  1241. }
  1242. else
  1243. {
  1244. q.smallQtNo = -1;
  1245. }
  1246. auto itNickID = it->FindMember("name");
  1247. if (itNickID != it->MemberEnd() && !(itNickID->value.IsNull()) && itNickID->value.IsString())
  1248. {
  1249. //m_mapKeguantiNickName[q.id] = itNickID->value.GetString();
  1250. }
  1251. // 打分区域
  1252. auto itScoreBox = it->FindMember("scorebox");
  1253. if (itScoreBox != it->MemberEnd() && itScoreBox->value.IsObject()){
  1254. // 打分框类型
  1255. auto itType = itScoreBox->value.FindMember("type");
  1256. if (itType != itScoreBox->value.MemberEnd() && itType->value.IsString()){
  1257. q.scoreBox.type = std::stoi(itType->value.GetString());
  1258. }
  1259. else if (itType != itScoreBox->value.MemberEnd() && itType->value.IsInt()){
  1260. q.scoreBox.type = itType->value.GetInt();
  1261. }
  1262. else{
  1263. g_log.PutMsg(LogLvlFailed, "错误 打分框无类型 %s 题号=%s ", m_batchDbPath.c_str(), q.id.c_str());
  1264. return false;
  1265. }
  1266. //if (q.smallQtNo != -1)
  1267. {
  1268. // 小问最大分值
  1269. auto itmaxScore = itScoreBox->value.FindMember("maxscore");
  1270. if (itmaxScore != itScoreBox->value.MemberEnd() && itmaxScore->value.IsString()){
  1271. q.scoreBox.maxsorce = std::stod(itmaxScore->value.GetString());
  1272. }
  1273. else if (itmaxScore != itScoreBox->value.MemberEnd() && itmaxScore->value.IsDouble()){
  1274. q.scoreBox.maxsorce = itScoreBox->value.GetDouble();
  1275. }
  1276. else if (itmaxScore != itScoreBox->value.MemberEnd() && itmaxScore->value.IsInt()){
  1277. q.scoreBox.maxsorce = itmaxScore->value.GetInt();
  1278. }
  1279. else{
  1280. q.scoreBox.maxsorce = 0.0;
  1281. }
  1282. }
  1283. /* else
  1284. {
  1285. q.scoreBox.maxsorce = 0.0;
  1286. }*/
  1287. // 分数上限
  1288. auto itLimit = itScoreBox->value.FindMember("limit");
  1289. if (itLimit != itScoreBox->value.MemberEnd() && itLimit->value.IsString())
  1290. q.scoreBox.limit = std::stoi(itLimit->value.GetString());
  1291. if (itLimit != itScoreBox->value.MemberEnd() && itLimit->value.IsInt())
  1292. q.scoreBox.limit = itLimit->value.GetInt();
  1293. // 最后一个格子是否为小数 1是 2否
  1294. auto itPoint = itScoreBox->value.FindMember("point");
  1295. if (itPoint != itScoreBox->value.MemberEnd()){
  1296. if (itPoint->value.IsInt()){
  1297. q.scoreBox.bPoint = (itPoint->value.GetInt() == 1);
  1298. }
  1299. else if (itPoint->value.IsString()){
  1300. std::string str = itPoint->value.GetString();
  1301. q.scoreBox.bPoint = (str == "1");
  1302. }
  1303. }
  1304. // 填空题带打分
  1305. if (q.scoreBox.type == 3){
  1306. auto itScore = itScoreBox->value.FindMember("Score");
  1307. if (itScore != itScoreBox->value.MemberEnd() && itScore->value.IsArray()){
  1308. for (auto it = itScore->value.Begin(); it != itScore->value.End(); ++it){
  1309. if (it->IsString()){
  1310. std::string str = it->GetString();
  1311. if (!str.empty())
  1312. q.scoreBox.vctScore.push_back(std::stoi(str));
  1313. }
  1314. }
  1315. }
  1316. }
  1317. // 打分位置
  1318. auto t = pfGetPos(itScoreBox->value);
  1319. if (std::get<0>(t))
  1320. q.scoreBox.pos = std::get<1>(t);
  1321. }
  1322. // 几选几
  1323. if (q.type == 2 || q.type == 4){ // 选做题
  1324. rapidjson::Value::ConstMemberIterator itSel = it->FindMember("select");
  1325. if (itSel != it->MemberEnd() && itSel->value.IsInt()){
  1326. q.selItem = itSel->value.GetInt();
  1327. }
  1328. rapidjson::Value::ConstMemberIterator itTotal = it->FindMember("total");
  1329. if (itTotal != it->MemberEnd() && itTotal->value.IsInt()){
  1330. q.selTotal = itTotal->value.GetInt();
  1331. }
  1332. }
  1333. // 剪裁区域
  1334. if (q.type == 1 || q.type == 3 || q.type == 2 || q.type == 4){ // 1 解答题 2 选做题 3 填空题
  1335. auto itCut = it->FindMember("cut");
  1336. if (itCut != it->MemberEnd() && itCut->value.IsObject()){
  1337. auto itLink = itCut->value.FindMember("linkparm");
  1338. if (itLink != itCut->value.MemberEnd() && itLink->value.IsInt())
  1339. q.cut.linkparm = itLink->value.GetInt();
  1340. if (itLink != itCut->value.MemberEnd() && itLink->value.IsString())
  1341. q.cut.linkparm = std::stoi(itLink->value.GetString());
  1342. auto t = pfGetPos(itCut->value);
  1343. if (std::get<0>(t))
  1344. q.cut.pos = std::get<1>(t);
  1345. if (q.type == 3 && pOnlineCardTemplate->subject_id == 8)
  1346. {
  1347. TCHAR FilePath[MAX_PATH];
  1348. GetModuleFileName(NULL, FilePath, MAX_PATH);
  1349. (_tcsrchr(FilePath, '\\'))[1] = 0;
  1350. lstrcat(FilePath, _T("config.ini"));
  1351. int english = GetPrivateProfileInt(_T("USER"), _T("english_height"), 30, FilePath);//英语填空题高度加大比例
  1352. if (english > 0 && english <= 30)
  1353. {
  1354. q.cut.pos.h = q.cut.pos.h* (1.0 + english / 100.0);
  1355. }
  1356. }
  1357. }
  1358. if (q.type == 2){
  1359. if (temp_all_id != q.all_id)
  1360. {
  1361. temp_all_id = q.all_id;
  1362. n_duo_xuanti_index = 0;
  1363. }
  1364. if (q.cut.linkparm < 2){
  1365. std::vector<std::string> split_qr;
  1366. split(q.all_id, (std::string)",", &split_qr);
  1367. if (n_duo_xuanti_index < split_qr.size())
  1368. q.id = split_qr[n_duo_xuanti_index++];
  1369. }
  1370. else
  1371. {
  1372. std::vector<std::string> split_qr;
  1373. split(q.all_id, (std::string)",", &split_qr);
  1374. if (n_duo_xuanti_index - 1 >= 0 && n_duo_xuanti_index - 1 < split_qr.size())
  1375. q.id = split_qr[n_duo_xuanti_index - 1];
  1376. }
  1377. }
  1378. else if (q.type == 4)
  1379. {
  1380. if (temp_all_id != q.all_id)
  1381. {
  1382. temp_all_id = q.all_id;
  1383. n_duo_xuanti_index = 0;
  1384. }
  1385. if (q.cut.linkparm < 1){
  1386. std::vector<std::string> split_qr;
  1387. split(q.all_id, (std::string)",", &split_qr);
  1388. if (n_duo_xuanti_index < split_qr.size())
  1389. q.id = split_qr[n_duo_xuanti_index++];
  1390. }
  1391. else
  1392. {
  1393. std::vector<std::string> split_qr;
  1394. split(q.all_id, (std::string)",", &split_qr);
  1395. if (n_duo_xuanti_index - 1 >= 0 && n_duo_xuanti_index - 1 < split_qr.size())
  1396. q.id = split_qr[n_duo_xuanti_index - 1];
  1397. }
  1398. }
  1399. }
  1400. // 选项 单选题 多选题
  1401. if (q.type == 0 || q.type == 8 || q.type == 5){
  1402. auto itOpts = it->FindMember("opt");
  1403. if (itOpts != it->MemberEnd() && itOpts->value.IsArray()){
  1404. for (auto itOpt = itOpts->value.Begin(); itOpt != itOpts->value.End(); ++itOpt){
  1405. Opt opt;
  1406. auto t = pfGetPos(*itOpt);
  1407. if (std::get<0>(t))
  1408. opt.pos = std::get<1>(t);
  1409. auto itOptName = itOpt->FindMember("optName");
  1410. if (itOptName != itOpt->MemberEnd() && itOptName->value.IsString())
  1411. opt.optName = itOptName->value.GetString();
  1412. q.opt.push_back(opt);
  1413. }
  1414. }
  1415. }
  1416. else if (q.type == 2 || q.type == 4){ // 选作
  1417. auto itSelectqts = it->FindMember("selectqts");
  1418. if (itSelectqts != it->MemberEnd() && itSelectqts->value.IsArray() && itSelectqts->value.Size() > 0){
  1419. for (auto itOpt = itSelectqts->value.Begin(); itOpt != itSelectqts->value.End(); ++itOpt){
  1420. Opt opt;
  1421. auto t = pfGetPos(*itOpt);
  1422. if (std::get<0>(t))
  1423. opt.pos = std::get<1>(t);
  1424. auto itOptName = itOpt->FindMember("optName");
  1425. if (itOptName != itOpt->MemberEnd() && itOptName->value.IsString())
  1426. opt.optName = itOptName->value.GetString();
  1427. q.opt.push_back(opt);
  1428. }
  1429. }
  1430. }
  1431. qid_name[q.id] = q.name;
  1432. page.vctQuestions.push_back(q);
  1433. }
  1434. }
  1435. pOnlineCardTemplate->pages.insert(std::make_pair(page.pageNo, page));
  1436. }
  1437. }
  1438. else{
  1439. return false;
  1440. }
  1441. }
  1442. pOnlineCardTemplate->open_save_debug_img = false;
  1443. pOnlineCardTemplate->dingweidian_range_top = 300; //上定位点范围
  1444. pOnlineCardTemplate->dingweidian_rang_buttom = 300;// 下定位点范围
  1445. pOnlineCardTemplate->dingweidian_w_max_rate = 1.0;
  1446. pOnlineCardTemplate->dingweidian_h_max_rate = 1.1;
  1447. pOnlineCardTemplate->dingweidian_w_min_rate = 0.7;
  1448. pOnlineCardTemplate->dingweidian_h_min_rate = 0.7;
  1449. pOnlineCardTemplate->useQrCode = false;
  1450. return true;
  1451. }
  1452. bool ParseTemplateFromJsonAll2(const std::string&fileName, OnLineCard::PaperTemplate* pOnlineCardTemplate)//全学科在线答题卡
  1453. {
  1454. //1 单选 2 小题单选 3 多选 4 小题多选 5 单空 6 多空 7 小题多空 8 解答 9 小题解答 10 英语作文 11 语文作文 12 判断题
  1455. //0选择 1解答 2选作 3填空 4编组 5不定项 8不定项
  1456. map<string, int> type_map;//新旧题型对应
  1457. type_map["1"] = 0; type_map["2"] = 0; type_map["3"] = 5; type_map["4"] = 5; type_map["5"] = 3; type_map["6"] = 3;
  1458. type_map["7"] = 3; type_map["8"] = 1; type_map["9"] = 1; type_map["12"] = 0; /*type_map["10"] = 1; type_map["11"] = 1; */
  1459. CUnZipFile uzip(CString(fileName.c_str()));
  1460. std::map<CString, std::vector<unsigned char>> map1;
  1461. while (uzip.HasMoreEntry()){
  1462. CString fileNam;
  1463. uzip.GetNextEntry(fileNam);
  1464. char buffer[1024 * 8];
  1465. int len;
  1466. std::vector<unsigned char>& data = map1[fileNam];
  1467. data.reserve(1024 * 128);
  1468. while ((len = uzip.Read(buffer, 1024 * 8)) > 0){
  1469. if (data.capacity() < data.size() + len){
  1470. int c = data.capacity() + 1024 * 128;
  1471. data.reserve(c);
  1472. }
  1473. int oldSize = data.size();
  1474. data.resize(oldSize + len);
  1475. char * dst = (char *)data.data() + oldSize;
  1476. memcpy(dst, buffer, len);
  1477. }
  1478. }
  1479. uzip.Close();
  1480. auto schemabytes = map1.find(_T("json.txt"));
  1481. if (schemabytes == map1.end()){
  1482. return SCH_LOAD_ERR_MISSINGFORMAT;
  1483. }
  1484. std::vector<unsigned char>& data = schemabytes->second;
  1485. auto strJson = std::string((char *)data.data(), data.size());
  1486. if (!pOnlineCardTemplate) return false;
  1487. pOnlineCardTemplate->pages.clear();
  1488. auto pfGetPos = [](const rapidjson::Value&value)->std::tuple<bool, Pos>{
  1489. bool bRet = false;
  1490. double x = 0.0, y = 0.0, w = 0.0, h = 0.0;
  1491. auto itX = value.FindMember("x");
  1492. if (itX != value.MemberEnd() && (itX->value.IsInt() || itX->value.IsDouble())){
  1493. x = itX->value.GetDouble();
  1494. }
  1495. auto itY = value.FindMember("y");
  1496. if (itY != value.MemberEnd() && (itY->value.IsInt() || itY->value.IsDouble())){
  1497. y = itY->value.GetDouble();
  1498. }
  1499. auto itW = value.FindMember("width");
  1500. if (itW != value.MemberEnd() && (itW->value.IsInt() || itW->value.IsDouble())){
  1501. w = itW->value.GetDouble();
  1502. }
  1503. auto itH = value.FindMember("height");
  1504. if (itH != value.MemberEnd() && (itH->value.IsInt() || itH->value.IsDouble())){
  1505. h = itH->value.GetDouble();
  1506. bRet = true;
  1507. }
  1508. return std::tie(bRet, Pos{ x, y, w, h });
  1509. };
  1510. rapidjson::Document doc;
  1511. doc.Parse(strJson.c_str());
  1512. if (doc.HasParseError()) return false;
  1513. pOnlineCardTemplate->subject_id = 0;
  1514. pOnlineCardTemplate->_version = "3.1.0";
  1515. // 检测版本号
  1516. auto it_version = doc.FindMember("online_card_version");
  1517. if (it_version != doc.MemberEnd() && it_version->value.IsString()){
  1518. pOnlineCardTemplate->_version = it_version->value.GetString();
  1519. }
  1520. LOGFMTI("在线答题卡版本号:%s", pOnlineCardTemplate->_version.c_str());
  1521. {
  1522. // 总页数
  1523. auto itTotalPage = doc.FindMember("totalPage");
  1524. if (itTotalPage != doc.MemberEnd() && itTotalPage->value.IsInt()){
  1525. pOnlineCardTemplate->totalPage = itTotalPage->value.GetInt();
  1526. }
  1527. // 是否使用二维码
  1528. auto itUseQrCode = doc.FindMember("useQrCode");
  1529. if (itUseQrCode != doc.MemberEnd() && itUseQrCode->value.IsBool()){
  1530. pOnlineCardTemplate->useQrCode = itUseQrCode->value.GetBool();
  1531. }
  1532. if (itUseQrCode != doc.MemberEnd() && itUseQrCode->value.IsInt()){
  1533. pOnlineCardTemplate->useQrCode = (itUseQrCode->value.GetInt() != 0);
  1534. }
  1535. // 学校状态
  1536. auto itSchoolStatus = doc.FindMember("school_card_status");
  1537. if (itSchoolStatus != doc.MemberEnd() && itSchoolStatus->value.IsInt()){
  1538. pOnlineCardTemplate->schoolCardStatus = itSchoolStatus->value.GetInt();
  1539. }
  1540. int n_duo_xuanti_index = 0;
  1541. std::string temp_all_id = "";
  1542. // 页
  1543. auto itPages = doc.FindMember("pages");
  1544. if (itPages != doc.MemberEnd() && itPages->value.IsArray()/* && itPages->value.Size() == m_onlineCardTemplate->totalPage*/){
  1545. for (auto itPage = itPages->value.Begin(); itPage != itPages->value.End(); ++itPage){
  1546. if (!itPage->IsObject()) return false;
  1547. PageTemplate page;
  1548. // 页号
  1549. auto itPageNo = itPage->FindMember("pageNo");
  1550. if (itPageNo != itPage->MemberEnd() && itPageNo->value.IsInt()){
  1551. page.pageNo = itPageNo->value.GetInt();
  1552. }
  1553. else {
  1554. return false;
  1555. }
  1556. // 定位点
  1557. auto itLocations = itPage->FindMember("location");
  1558. if (itLocations != itPage->MemberEnd() && itLocations->value.IsArray()){
  1559. for (auto it = itLocations->value.Begin(); it != itLocations->value.End(); ++it){
  1560. Location lc;
  1561. auto itType = it->FindMember("type");
  1562. if (itType != it->MemberEnd() && itType->value.IsInt()){
  1563. lc.type = itType->value.GetInt();
  1564. }
  1565. auto tm = pfGetPos(*it);
  1566. if (std::get<0>(tm)){
  1567. lc.pos = std::get<1>(tm);
  1568. }
  1569. page.location.push_back(lc);
  1570. }
  1571. }
  1572. if (page.pageNo == 1){
  1573. if (!pOnlineCardTemplate->useQrCode){
  1574. // 条形码
  1575. auto itBar = itPage->FindMember("studentcode_bar");
  1576. if (itBar != itPage->MemberEnd() && itBar->value.IsObject()){
  1577. auto itObj = itBar->value.FindMember("object");
  1578. if (itObj != itBar->value.MemberEnd() && itObj->value.IsObject()){
  1579. auto t = pfGetPos(itObj->value);
  1580. page.studentcode_bar = std::get<1>(t);
  1581. }
  1582. }
  1583. // 填涂考号
  1584. auto itFill = itPage->FindMember("studentcode_fill");
  1585. if (itFill != itPage->MemberEnd() && itFill->value.IsObject()){
  1586. auto itObj = itFill->value.FindMember("object");
  1587. if (itObj != itFill->value.MemberEnd() && itObj->value.IsArray()){
  1588. for (auto itRow = itObj->value.Begin(); itRow != itObj->value.End(); ++itRow){
  1589. auto itGroup = itRow->FindMember("group");
  1590. if (itGroup != itRow->MemberEnd() && itGroup->value.IsArray()){
  1591. std::vector<Opt> _vctOpt;
  1592. for (auto itCol = itGroup->value.Begin(); itCol != itGroup->value.End(); ++itCol){
  1593. Opt opt;
  1594. auto itOptName = itCol->FindMember("optName");
  1595. if (itOptName != itCol->MemberEnd() && itOptName->value.IsInt())
  1596. opt.optName = std::to_string(itOptName->value.GetInt());
  1597. auto t = pfGetPos(*itCol);
  1598. if (std::get<0>(t))
  1599. opt.pos = std::get<1>(t);
  1600. _vctOpt.push_back(opt);
  1601. }
  1602. page.studentcode_fill.push_back(_vctOpt);
  1603. }
  1604. }
  1605. }
  1606. }
  1607. }
  1608. // 缺考标记
  1609. auto itAbsent = itPage->FindMember("absent");
  1610. if (itAbsent != itPage->MemberEnd() && itAbsent->value.IsObject()){
  1611. auto t = pfGetPos(itAbsent->value);
  1612. if (std::get<0>(t)){
  1613. page.absent = std::get<1>(t);
  1614. }
  1615. }
  1616. // 二维码
  1617. auto itQrCode = itPage->FindMember("QrCode");
  1618. if (itQrCode != itPage->MemberEnd() && itQrCode->value.IsObject()){
  1619. auto t = pfGetPos(itQrCode->value);
  1620. if (std::get<0>(t)){
  1621. page.QrCode = std::get<1>(t);
  1622. }
  1623. }
  1624. } // end if page.pageNo == 0
  1625. // 长宽
  1626. auto itImge = itPage->FindMember("imge");
  1627. if (itImge != itPage->MemberEnd()){
  1628. auto t = std::get<1>(pfGetPos(itImge->value));
  1629. page.w = t.w;
  1630. page.h = t.h;
  1631. }
  1632. else{
  1633. return false;
  1634. }
  1635. // 题目
  1636. auto itQuestion = itPage->FindMember("questions");
  1637. if (itQuestion != itPage->MemberEnd() && itQuestion->value.IsArray())
  1638. {
  1639. for (auto it = itQuestion->value.Begin(); it != itQuestion->value.End(); ++it)
  1640. {
  1641. question q;
  1642. // 题目类型
  1643. auto itType = it->FindMember("type");
  1644. string qType = "1";
  1645. if (itType != it->MemberEnd() && itType->value.IsString())
  1646. {
  1647. qType = itType->value.GetString();
  1648. if (type_map.find(qType) != type_map.end())
  1649. {
  1650. q.type = type_map[qType];
  1651. }
  1652. }
  1653. else if (itType != it->MemberEnd() && itType->value.IsInt())
  1654. {
  1655. qType = to_string(itType->value.GetInt());
  1656. if (type_map.find(qType) != type_map.end())
  1657. {
  1658. q.type = type_map[qType];
  1659. }
  1660. }
  1661. else
  1662. {
  1663. return false;
  1664. }
  1665. q.marktype = 0;
  1666. // 题目类型
  1667. auto itMarktype = it->FindMember("marktype");
  1668. if (itMarktype != it->MemberEnd() && itMarktype->value.IsInt()){
  1669. q.marktype = itMarktype->value.GetInt();
  1670. }
  1671. if (qType == "10")//英文作文
  1672. {
  1673. q.marktype = 10;
  1674. q.type = 1;
  1675. }
  1676. else if (qType == "11")//语文作文
  1677. {
  1678. q.marktype = 4;
  1679. q.type = 1;
  1680. }
  1681. else if (qType == "12")//判断
  1682. {
  1683. q.type = 0;
  1684. }
  1685. // 分数
  1686. auto itScore = it->FindMember("score");
  1687. if (itScore != it->MemberEnd() && itScore->value.IsObject()){
  1688. auto itFull = itScore->value.FindMember("full");
  1689. if (itFull != itScore->value.MemberEnd() && (itFull->value.IsDouble() || itFull->value.IsInt()))
  1690. q.score = itFull->value.GetDouble();
  1691. else if (itFull != itScore->value.MemberEnd() && itFull->value.IsString())
  1692. q.score = atof(itFull->value.GetString());
  1693. }
  1694. // 题目编号 2选做题
  1695. auto itId = it->FindMember((q.type == 2 || q.type == 4) ? "editorId" : "id");
  1696. if (itId != it->MemberEnd() && itId->value.IsString()){
  1697. q.id = itId->value.GetString();
  1698. }
  1699. if (itId != it->MemberEnd() && itId->value.IsInt()){
  1700. q.id = std::to_string(itId->value.GetInt());
  1701. }
  1702. if (q.type == 2 || q.type == 4){
  1703. auto itAllID = it->FindMember("id");
  1704. if (itAllID != it->MemberEnd() && itAllID->value.IsString()){
  1705. q.all_id = itAllID->value.GetString();
  1706. }
  1707. }
  1708. auto itSmallQtNo = it->FindMember("smallQtNo");
  1709. if (itSmallQtNo != it->MemberEnd() && !(itSmallQtNo->value.IsNull()))
  1710. {
  1711. q.smallQtNo = itSmallQtNo->value.GetInt();
  1712. }
  1713. else
  1714. {
  1715. q.smallQtNo = -1;
  1716. }
  1717. auto itNickID = it->FindMember("name");
  1718. if (itNickID != it->MemberEnd() && !(itNickID->value.IsNull()) && itNickID->value.IsString())
  1719. {
  1720. //m_mapKeguantiNickName[q.id] = itNickID->value.GetString();
  1721. }
  1722. // 打分区域
  1723. auto itScoreBox = it->FindMember("scorebox");
  1724. if (itScoreBox != it->MemberEnd() && itScoreBox->value.IsObject()){
  1725. // 打分框类型
  1726. auto itType = itScoreBox->value.FindMember("type");
  1727. if (itType != itScoreBox->value.MemberEnd() && itType->value.IsString()){
  1728. q.scoreBox.type = std::stoi(itType->value.GetString());
  1729. }
  1730. else if (itType != itScoreBox->value.MemberEnd() && itType->value.IsInt()){
  1731. q.scoreBox.type = itType->value.GetInt();
  1732. }
  1733. else{
  1734. return false;
  1735. }
  1736. if (q.smallQtNo != -1)
  1737. {
  1738. // 小问最大分值
  1739. auto itmaxScore = itScoreBox->value.FindMember("maxscore");
  1740. if (itmaxScore != itScoreBox->value.MemberEnd() && itmaxScore->value.IsString()){
  1741. q.scoreBox.maxsorce = std::stod(itmaxScore->value.GetString());
  1742. }
  1743. else if (itmaxScore != itScoreBox->value.MemberEnd() && itmaxScore->value.IsDouble()){
  1744. q.scoreBox.maxsorce = itScoreBox->value.GetDouble();
  1745. }
  1746. else if (itmaxScore != itScoreBox->value.MemberEnd() && itmaxScore->value.IsInt()){
  1747. q.scoreBox.maxsorce = itmaxScore->value.GetInt();
  1748. }
  1749. else{
  1750. q.scoreBox.maxsorce = 0.0;
  1751. }
  1752. }
  1753. else
  1754. {
  1755. q.scoreBox.maxsorce = 0.0;
  1756. }
  1757. // 分数上限
  1758. auto itLimit = itScoreBox->value.FindMember("limit");
  1759. if (itLimit != itScoreBox->value.MemberEnd() && itLimit->value.IsString())
  1760. q.scoreBox.limit = std::stoi(itLimit->value.GetString());
  1761. if (itLimit != itScoreBox->value.MemberEnd() && itLimit->value.IsInt())
  1762. q.scoreBox.limit = itLimit->value.GetInt();
  1763. // 最后一个格子是否为小数 1是 2否
  1764. auto itPoint = itScoreBox->value.FindMember("point");
  1765. if (itPoint != itScoreBox->value.MemberEnd()){
  1766. if (itPoint->value.IsInt()){
  1767. q.scoreBox.bPoint = (itPoint->value.GetInt() == 1);
  1768. }
  1769. else if (itPoint->value.IsString()){
  1770. std::string str = itPoint->value.GetString();
  1771. q.scoreBox.bPoint = (str == "1");
  1772. }
  1773. }
  1774. // 填空题带打分
  1775. if (q.scoreBox.type == 3){
  1776. auto itScore = itScoreBox->value.FindMember("Score");
  1777. if (itScore != itScoreBox->value.MemberEnd() && itScore->value.IsArray()){
  1778. for (auto it = itScore->value.Begin(); it != itScore->value.End(); ++it){
  1779. if (it->IsString()){
  1780. std::string str = it->GetString();
  1781. if (!str.empty())
  1782. q.scoreBox.vctScore.push_back(std::stoi(str));
  1783. }
  1784. }
  1785. }
  1786. }
  1787. // 打分位置
  1788. auto t = pfGetPos(itScoreBox->value);
  1789. if (std::get<0>(t))
  1790. q.scoreBox.pos = std::get<1>(t);
  1791. }
  1792. // 几选几
  1793. if (q.type == 2 || q.type == 4){ // 选做题
  1794. rapidjson::Value::ConstMemberIterator itSel = it->FindMember("select");
  1795. if (itSel != it->MemberEnd() && itSel->value.IsInt()){
  1796. q.selItem = itSel->value.GetInt();
  1797. }
  1798. rapidjson::Value::ConstMemberIterator itTotal = it->FindMember("total");
  1799. if (itTotal != it->MemberEnd() && itTotal->value.IsInt()){
  1800. q.selTotal = itTotal->value.GetInt();
  1801. }
  1802. }
  1803. // 剪裁区域
  1804. if (q.type == 1 || q.type == 3 || q.type == 2 || q.type == 4){ // 1 解答题 2 选做题 3 填空题
  1805. auto itCut = it->FindMember("cut");
  1806. if (itCut != it->MemberEnd() && itCut->value.IsObject()){
  1807. auto itLink = itCut->value.FindMember("linkparm");
  1808. if (itLink != itCut->value.MemberEnd() && itLink->value.IsInt())
  1809. q.cut.linkparm = itLink->value.GetInt();
  1810. if (itLink != itCut->value.MemberEnd() && itLink->value.IsString())
  1811. q.cut.linkparm = std::stoi(itLink->value.GetString());
  1812. auto t = pfGetPos(itCut->value);
  1813. if (std::get<0>(t))
  1814. q.cut.pos = std::get<1>(t);
  1815. if (q.type == 3 && pOnlineCardTemplate->subject_id == 8)
  1816. {
  1817. TCHAR FilePath[MAX_PATH];
  1818. GetModuleFileName(NULL, FilePath, MAX_PATH);
  1819. (_tcsrchr(FilePath, '\\'))[1] = 0;
  1820. lstrcat(FilePath, _T("config.ini"));
  1821. int english = GetPrivateProfileInt(_T("USER"), _T("english_height"), 30, FilePath);//英语填空题高度加大比例
  1822. if (english > 0 && english <= 30)
  1823. {
  1824. q.cut.pos.h = q.cut.pos.h* (1.0 + english / 100.0);
  1825. }
  1826. }
  1827. }
  1828. if (q.type == 2){
  1829. if (temp_all_id != q.all_id)
  1830. {
  1831. temp_all_id = q.all_id;
  1832. n_duo_xuanti_index = 0;
  1833. }
  1834. if (q.cut.linkparm < 2){
  1835. std::vector<std::string> split_qr;
  1836. split(q.all_id, (std::string)",", &split_qr);
  1837. if (n_duo_xuanti_index < split_qr.size())
  1838. q.id = split_qr[n_duo_xuanti_index++];
  1839. }
  1840. else
  1841. {
  1842. std::vector<std::string> split_qr;
  1843. split(q.all_id, (std::string)",", &split_qr);
  1844. if (n_duo_xuanti_index - 1 >= 0 && n_duo_xuanti_index - 1 < split_qr.size())
  1845. q.id = split_qr[n_duo_xuanti_index - 1];
  1846. }
  1847. }
  1848. else if (q.type == 4)
  1849. {
  1850. if (temp_all_id != q.all_id)
  1851. {
  1852. temp_all_id = q.all_id;
  1853. n_duo_xuanti_index = 0;
  1854. }
  1855. if (q.cut.linkparm < 1){
  1856. std::vector<std::string> split_qr;
  1857. split(q.all_id, (std::string)",", &split_qr);
  1858. if (n_duo_xuanti_index < split_qr.size())
  1859. q.id = split_qr[n_duo_xuanti_index++];
  1860. }
  1861. else
  1862. {
  1863. std::vector<std::string> split_qr;
  1864. split(q.all_id, (std::string)",", &split_qr);
  1865. if (n_duo_xuanti_index - 1 >= 0 && n_duo_xuanti_index - 1 < split_qr.size())
  1866. q.id = split_qr[n_duo_xuanti_index - 1];
  1867. }
  1868. }
  1869. }
  1870. // 选项 单选题 多选题
  1871. if (q.type == 0 || q.type == 8 || q.type == 5){
  1872. auto itOpts = it->FindMember("opt");
  1873. if (itOpts != it->MemberEnd() && itOpts->value.IsArray()){
  1874. for (auto itOpt = itOpts->value.Begin(); itOpt != itOpts->value.End(); ++itOpt){
  1875. Opt opt;
  1876. auto t = pfGetPos(*itOpt);
  1877. if (std::get<0>(t))
  1878. opt.pos = std::get<1>(t);
  1879. auto itOptName = itOpt->FindMember("optName");
  1880. if (itOptName != itOpt->MemberEnd() && itOptName->value.IsString())
  1881. opt.optName = itOptName->value.GetString();
  1882. q.opt.push_back(opt);
  1883. }
  1884. }
  1885. }
  1886. else if (q.type == 2 || q.type == 4){ // 选作
  1887. auto itSelectqts = it->FindMember("selectqts");
  1888. if (itSelectqts != it->MemberEnd() && itSelectqts->value.IsArray() && itSelectqts->value.Size() > 0){
  1889. for (auto itOpt = itSelectqts->value.Begin(); itOpt != itSelectqts->value.End(); ++itOpt){
  1890. Opt opt;
  1891. auto t = pfGetPos(*itOpt);
  1892. if (std::get<0>(t))
  1893. opt.pos = std::get<1>(t);
  1894. auto itOptName = itOpt->FindMember("optName");
  1895. if (itOptName != itOpt->MemberEnd() && itOptName->value.IsString())
  1896. opt.optName = itOptName->value.GetString();
  1897. q.opt.push_back(opt);
  1898. }
  1899. }
  1900. }
  1901. page.vctQuestions.push_back(q);
  1902. }
  1903. }
  1904. pOnlineCardTemplate->pages.insert(std::make_pair(page.pageNo, page));
  1905. }
  1906. }
  1907. else{
  1908. return false;
  1909. }
  1910. }
  1911. pOnlineCardTemplate->open_save_debug_img = false;
  1912. pOnlineCardTemplate->dingweidian_range_top = 300; //上定位点范围
  1913. pOnlineCardTemplate->dingweidian_rang_buttom = 300;// 下定位点范围
  1914. pOnlineCardTemplate->dingweidian_w_max_rate = 1.0;
  1915. pOnlineCardTemplate->dingweidian_h_max_rate = 1.0;
  1916. pOnlineCardTemplate->dingweidian_w_min_rate = 0.7;
  1917. pOnlineCardTemplate->dingweidian_h_min_rate = 0.7;
  1918. pOnlineCardTemplate->useQrCode = false;
  1919. return true;
  1920. }
  1921. bool CreateDir(char* path)
  1922. {
  1923. if (_access(path, 0) == 0)
  1924. {
  1925. return true;
  1926. }
  1927. int ret = 0;
  1928. char* szBefore = path;
  1929. while (*szBefore)
  1930. {
  1931. if (*szBefore == '/' || *szBefore == '\\')
  1932. {
  1933. char szDir[512] = { 0 };
  1934. strncpy_s(szDir, 512, path, szBefore - path);
  1935. if (_access(szDir, 0) != 0)
  1936. {
  1937. ret = _mkdir(szDir);
  1938. }
  1939. }
  1940. szBefore++;
  1941. }
  1942. if (_access(path, 0) != 0)
  1943. {
  1944. ret = _mkdir(path);
  1945. }
  1946. return true;
  1947. }
  1948. wstring strA2W(const string &str)
  1949. {
  1950. int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
  1951. wchar_t *wstr = new wchar_t[len + 2];
  1952. memset(wstr, 0, (2 + len)*sizeof(wchar_t));
  1953. MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, wstr, len);
  1954. wstring cstrDestW = wstr;
  1955. delete[] wstr;
  1956. return cstrDestW;
  1957. }
  1958. string strW2A(const wstring &wstr)
  1959. {
  1960. int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
  1961. char *str = new char[len + 2];
  1962. memset(str, 0, len + 2);
  1963. WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, str, len, NULL, NULL);
  1964. string cstrDestA = str;
  1965. delete[] str;
  1966. return cstrDestA;
  1967. }
  1968. vector<string> splitEx(const string& src, string separate_character)
  1969. {
  1970. vector<string> strs;
  1971. int separate_characterLen = separate_character.size();//分割字符串的长度,这样就可以支持如“,,”多字符串的分隔符
  1972. int lastPosition = 0, index = -1;
  1973. while (-1 != (index = src.find(separate_character, lastPosition)))
  1974. {
  1975. strs.push_back(src.substr(lastPosition, index - lastPosition));
  1976. lastPosition = index + separate_characterLen;
  1977. }
  1978. string lastString = src.substr(lastPosition);//截取最后一个分隔符后的内容
  1979. if (!lastString.empty())
  1980. strs.push_back(lastString);//如果最后一个分隔符后还有内容就入队
  1981. return strs;
  1982. }
  1983. //处理字符串中的单引号,以解决执行sql语句是因字段包含单引号而异常的问题
  1984. string handleApostrophe(const string & strSrc)
  1985. {
  1986. vector<string> strVec = splitEx(strSrc, "'");
  1987. string strRet;
  1988. if (strVec.size() == 1)
  1989. strRet = strSrc;
  1990. else
  1991. {
  1992. int i = 0;
  1993. const int nSize = strVec.size();
  1994. for (; i < nSize; i++)
  1995. {
  1996. strRet += strVec.at(i);
  1997. if (i < nSize - 1)
  1998. strRet += "''";
  1999. }
  2000. }
  2001. return strRet;
  2002. }
  2003. DWORD WINAPI SaveCutImageThread(void* param)
  2004. {
  2005. saveImgesPara *para = (saveImgesPara *)param;
  2006. vector<CUT_AREA_RESULT*> *area_results = para->area_rst;
  2007. CString dir = para->dir;
  2008. bool flag = para->flag;
  2009. int subjectID = para->subjectID;
  2010. std::string area_name;
  2011. CString savePath;
  2012. CFile file;
  2013. try
  2014. {
  2015. if ((*area_results)[0]->area_name == "37")
  2016. {
  2017. int a = 1;
  2018. a++;
  2019. }
  2020. if ((*area_results)[0]->area_name == "")
  2021. {
  2022. area_name = (*area_results)[0]->area_name;
  2023. int idx;
  2024. area_name = ((idx = area_name.find('.')) < 0) ? area_name : area_name.substr(0, idx);
  2025. CString question_code;
  2026. question_code.Format(_T("\\%s.jpg"), CString(area_name.c_str()));
  2027. savePath = dir + question_code;
  2028. }
  2029. else
  2030. {
  2031. area_name = (*area_results)[0]->area_name;
  2032. CString question_code;
  2033. question_code.Format(_T("\\%s.jpg"), CString(area_name.c_str()));
  2034. savePath = dir + question_code;
  2035. }
  2036. if ((*area_results).size() > 1 && (*area_results)[0]->is_cut > 0){
  2037. int width = 0;
  2038. int height = 0;
  2039. for (int jj = 0; jj < (*area_results).size(); jj++)
  2040. {
  2041. if ((*area_results)[jj]->width > width)width = (*area_results)[jj]->width;
  2042. height += (*area_results)[jj]->height;
  2043. }
  2044. cv::Mat img_big(cv::Size(width, height), CV_8UC3, cv::Scalar(255, 255, 255));
  2045. for (int ii = 0, top = 0; ii < (*area_results).size(); ii++)
  2046. {
  2047. Mat ff = Mat(1, (*area_results)[ii]->img_data.size(), CV_8U, (*area_results)[ii]->img_data.data());
  2048. Mat temp_img = imdecode(ff, CV_LOAD_IMAGE_COLOR);
  2049. cv::Rect rc_tmp(0, top, temp_img.cols, temp_img.rows);
  2050. Mat cut = img_big(rc_tmp);
  2051. temp_img.copyTo(cut);
  2052. top += temp_img.rows;
  2053. }
  2054. //////////////////////////////////////////////////////////////////////////
  2055. vector<uchar> dst;
  2056. vector<int> compression_params;
  2057. compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
  2058. compression_params.push_back(25);
  2059. imencode(".jpg", img_big, dst, compression_params);
  2060. file.Open(savePath, CFile::modeCreate | CFile::modeWrite);
  2061. file.Write(dst.data(), dst.size());
  2062. file.Close();
  2063. if (!(subjectID != 0) && (*area_results)[0]->is_cut == 1)
  2064. {
  2065. CString question_code;
  2066. question_code.Format(_T("\\%sf.jpg"), CString(area_name.c_str()));
  2067. savePath = dir + question_code;
  2068. //file.Open(savePath, CFile::modeCreate | CFile::modeWrite);
  2069. //file.Write(dst.data(), dst.size());
  2070. //file.Close();
  2071. }
  2072. }
  2073. else
  2074. {
  2075. if ((*area_results)[0]->is_cut > 0)
  2076. {
  2077. if (file.Open(savePath, CFile::modeCreate | CFile::modeWrite)){
  2078. file.Write((*area_results)[0]->img_data.data(), (*area_results)[0]->img_data.size());
  2079. file.Close();
  2080. }
  2081. else{
  2082. auto e = GetLastError();
  2083. int n = 0; ++n;
  2084. }
  2085. if (!(subjectID != 0) && (*area_results)[0]->is_cut == 1)
  2086. {
  2087. CString question_code;
  2088. question_code.Format(_T("\\%sf.jpg"), CString(area_name.c_str()));
  2089. savePath = dir + question_code;
  2090. //file.Open(savePath, CFile::modeCreate | CFile::modeWrite);
  2091. //file.Write((*area_results)[0]->img_data.data(), (*area_results)[0]->img_data.size());
  2092. //file.Close();
  2093. }
  2094. }
  2095. else
  2096. {
  2097. file.Open(savePath, CFile::modeCreate | CFile::modeWrite);
  2098. file.Write((*area_results)[0]->img_data.data(), (*area_results)[0]->img_data.size());
  2099. file.Close();
  2100. }
  2101. }
  2102. if (flag && (*area_results).size() > 1 && (*area_results)[0]->is_cut > 0){
  2103. vector<int> compression_params_low;
  2104. compression_params_low.push_back(CV_IMWRITE_JPEG_QUALITY);
  2105. compression_params_low.push_back(40);
  2106. vector<int> compression_params_high;
  2107. compression_params_high.push_back(CV_IMWRITE_JPEG_QUALITY);
  2108. compression_params_high.push_back(60);
  2109. for (int jj = 0; jj < (*area_results).size(); jj++)
  2110. {
  2111. CString question_code;
  2112. question_code.Format(_T("\\%s_%d.jpg"), CString((*area_results)[0]->area_name.c_str()), jj);
  2113. savePath = dir + question_code;
  2114. file.Open(savePath, CFile::modeCreate | CFile::modeWrite);
  2115. file.Write((*area_results)[jj]->img_data.data(), (*area_results)[jj]->img_data.size());
  2116. file.Close();
  2117. }
  2118. }
  2119. para->path1 = area_name;
  2120. para->bSaved = true;
  2121. }
  2122. catch (CMemoryException* e)
  2123. {
  2124. }
  2125. catch (CFileException* e)
  2126. {
  2127. para->bSaved = true;
  2128. }
  2129. catch (CException* e)
  2130. {
  2131. }
  2132. return 0;
  2133. }
  2134. DWORD WINAPI UploadImageThread(void* param)
  2135. {
  2136. uploadImgPara *para = (uploadImgPara *)param;
  2137. return 0;
  2138. }
  2139. int ScanPaper(CBatch_Server* batchInfo, Paper_Page* paper)
  2140. {
  2141. CreateDir((char*)paper->result_dir.c_str());
  2142. paper->scan_time = std::time(0);
  2143. DWORD t0 = GetTickCount();
  2144. for (int i = 0; i < 2; i++)
  2145. {
  2146. PageIdentify identify;
  2147. identify.SetTemplate(batchInfo->m_onlineCardTemplate);
  2148. OMR_RESULT *result_buffer = paper->result[i];
  2149. string strPath = /*UtfToGbk*/(paper->path[i]);
  2150. IplImage *src = cvLoadImage(strPath.c_str());
  2151. if (src == NULL)
  2152. {
  2153. paper->exc_code = paper_exc_open_fail;
  2154. paper->err_msg = "paper_exc_open_fail";
  2155. return IDF_FAILURE;
  2156. }
  2157. IplImage * dst = NULL;
  2158. SchemaPage* pschemaPage1 = NULL;
  2159. CvMemStorage* storage = cvCreateMemStorage(0);
  2160. auto act1 = finally([&]
  2161. {
  2162. if (src != NULL)cvReleaseImage(&src);
  2163. src = NULL;
  2164. if (dst != NULL)cvReleaseImage(&dst);
  2165. dst = NULL;
  2166. if (pschemaPage1 != NULL)delete pschemaPage1;
  2167. pschemaPage1 = NULL;
  2168. cvReleaseMemStorage(&storage);
  2169. storage = NULL;
  2170. });
  2171. {
  2172. std::chrono::time_point<std::chrono::system_clock, std::chrono::microseconds> tp = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now());
  2173. auto tmp = std::chrono::duration_cast<std::chrono::microseconds>(tp.time_since_epoch());
  2174. std::time_t timestamp = tmp.count();
  2175. std::string imagePath = paper->result_dir + "schema/";
  2176. CreateDirectoryA(imagePath.c_str(), NULL);
  2177. std::string path = imagePath + std::to_string(timestamp) + ".jpg";
  2178. paper->path_jiaozheng[i] = path;
  2179. }
  2180. int ret = identify.createSchema(src, &dst, &pschemaPage1, paper->result_dir.c_str(), paper->path_jiaozheng[i], false);
  2181. if (ret != identify::result::IDF_SUCCESS) {
  2182. return ret;
  2183. }
  2184. identify.out_result = result_buffer;
  2185. identify.omr_result = (identify::result::OMR_RESULT*)identify.out_result;
  2186. SchemaPage& schemaPage = *pschemaPage1;
  2187. identify.omr_result->is_front_page = schemaPage.is_front_page;
  2188. identify.omr_result->examid_by_qr_code = schemaPage.examid_by_qr_code;
  2189. identify.omr_result->strMagicStudentId = schemaPage.student_code;
  2190. /************************读取学生学号*********************************************/
  2191. if (schemaPage.is_front_page)
  2192. {
  2193. identify.ReadStudentID(schemaPage, dst);
  2194. if (identify.omr_result->qr_result.size()>0)
  2195. {
  2196. paper->student_code = identify.omr_result->qr_result[0].qr_str;
  2197. }
  2198. /************************读取缺考标记*********************************************/
  2199. identify.omr_result->quekaoFlag = identify.ReadQuekaoFlag(schemaPage, dst);
  2200. /************************客观题()*********************************************/
  2201. paper->qr_code = schemaPage.paper_id;
  2202. //paper->student_code=schemaPage.
  2203. }
  2204. identify.ReadKeGuanTi(schemaPage, dst);
  2205. //LOGI("Identify_impl 3");
  2206. /************************查找题目定位点,准备定位数据*********************************************/
  2207. //ret = identify.FindQuestionLocatePoints(schemaPage, dst);
  2208. //if (ret != identify::result::IDF_SUCCESS) {
  2209. // return;
  2210. //}
  2211. //LOGI("Identify_impl 4");
  2212. /************************阅卷读取*************************************************/
  2213. identify.ReadQuestionScore(schemaPage, dst, storage);
  2214. //LOGI("Identify_impl 6");
  2215. /************************根据给定区域切割图片*********************************************/
  2216. identify.ClipImg(schemaPage, dst);
  2217. identify.omr_result->card_index = schemaPage.index;
  2218. {
  2219. IplImage*src_debug = cvCloneImage(dst);
  2220. batchInfo->DrawSchema(src_debug, &schemaPage, identify.omr_result);
  2221. cvSaveImage(paper->path_jiaozheng[i].c_str(), src_debug);
  2222. cvReleaseImage(&src_debug);
  2223. }
  2224. }
  2225. if (paper->result[0]->is_front_page == paper->result[1]->is_front_page)
  2226. {
  2227. paper->exc_code = paper_exc_pages_missed;
  2228. return IDF_FAILURE;
  2229. }
  2230. vector<saveImgesPara*> vct_saveImges;
  2231. map<string, int> cut_area_map;
  2232. if (paper->result[0]->is_front_page == false)
  2233. {
  2234. OMR_RESULT* restemp = paper->result[0];
  2235. paper->result[0] = paper->result[1];
  2236. paper->result[1] = restemp;
  2237. string pathtemp = paper->path[0];
  2238. paper->path[0] = paper->path[1];
  2239. paper->path[1] = pathtemp;
  2240. pathtemp = paper->path_jiaozheng[0];
  2241. paper->path_jiaozheng[0] = paper->path_jiaozheng[1];
  2242. paper->path_jiaozheng[1] = pathtemp;
  2243. }
  2244. for (int i = 0; i < 2; i++)
  2245. {
  2246. OMR_RESULT *m_result_buffer = paper->result[i];
  2247. for (int j = 0; j < m_result_buffer->cut_area_result.size(); j++)
  2248. {
  2249. if (cut_area_map.find(m_result_buffer->cut_area_result[j].area_name) != cut_area_map.end())//已经生成过了
  2250. {
  2251. continue;
  2252. }
  2253. string cut_name = m_result_buffer->cut_area_result[j].area_name;
  2254. vector<CUT_AREA_RESULT*>* area_rst = new vector<CUT_AREA_RESULT*>;
  2255. for (int i2 = 0; i2 < 2; i2++)
  2256. {
  2257. OMR_RESULT *m_result_buffer2 = paper->result[i2];
  2258. for (int j2 = 0; j2 < m_result_buffer2->cut_area_result.size(); j2++)
  2259. {
  2260. if (m_result_buffer2->cut_area_result[j2].area_name == cut_name)//
  2261. {
  2262. area_rst->push_back(&m_result_buffer2->cut_area_result[j2]);
  2263. }
  2264. }
  2265. }
  2266. cut_area_map[cut_name] = 0;
  2267. bool flag = false;
  2268. if (area_rst->size() > 1)
  2269. {
  2270. flag = true;
  2271. }
  2272. wstring strw = strA2W(paper->result_dir);
  2273. saveImgesPara *para = new saveImgesPara(area_rst, strw.c_str(), 0, flag);
  2274. paper->qid_cut_map[(*area_rst)[0]->area_name] = area_rst->size();
  2275. vct_saveImges.push_back(para);
  2276. QueueUserWorkItem(SaveCutImageThread, para, WT_EXECUTELONGFUNCTION);
  2277. }
  2278. }
  2279. string jpgname = paper->result_dir + "/" + "jpgname.txt";
  2280. FILE* pf = fopen(jpgname.c_str(), "wb");
  2281. string jpgpath = "";
  2282. while (true)
  2283. {
  2284. if (vct_saveImges.size() == 0)
  2285. {
  2286. break;
  2287. }
  2288. if (vct_saveImges[0]->bSaved)
  2289. {
  2290. if (vct_saveImges[0]->area_rst->size()>1)
  2291. {
  2292. for (int i = 0; i < vct_saveImges[0]->area_rst->size(); i++)
  2293. {
  2294. saveImgesPara *para = (saveImgesPara *)vct_saveImges[0];
  2295. vector<CUT_AREA_RESULT*> *area_results = para->area_rst;
  2296. char buf[64] = { 0 };
  2297. sprintf_s(buf, "%s_%d", (*area_results)[i]->area_name.c_str(), i);
  2298. jpgpath += buf;
  2299. jpgpath += ",";
  2300. }
  2301. }
  2302. jpgpath += vct_saveImges[0]->path1;
  2303. jpgpath += ",";
  2304. delete vct_saveImges[0]->area_rst;
  2305. vct_saveImges.erase(vct_saveImges.begin());
  2306. continue;
  2307. }
  2308. else
  2309. {
  2310. Sleep(10);
  2311. }
  2312. }
  2313. if (jpgpath.length() > 0)
  2314. {
  2315. jpgpath.erase(jpgpath.end() - 1);
  2316. }
  2317. fwrite(jpgpath.c_str(), 1, jpgpath.length(), pf);
  2318. fclose(pf);
  2319. DWORD t1 = GetTickCount() - t0;
  2320. printf("t1=%d \r\n", t1);
  2321. return identify::result::IDF_SUCCESS;
  2322. }
  2323. unsigned _stdcall ScanThread(void* param)
  2324. {
  2325. CBatch_Server* bInfo = (CBatch_Server*)param;
  2326. if (!bInfo)
  2327. {
  2328. return 0;
  2329. }
  2330. while (g_ScanThreadRun)
  2331. {
  2332. //{
  2333. // g_count++;
  2334. // char buf[128] = { 0 };
  2335. // sprintf_s(buf, 128, "update papers set state = %d", GetTickCount());
  2336. // bInfo->m_batch_db.execDML(buf);
  2337. // continue;
  2338. //}
  2339. Paper_Page* paper = bInfo->ReadNextPaper();
  2340. if (paper == NULL)
  2341. {
  2342. return 0;
  2343. }
  2344. auto act1 = finally([&]
  2345. {
  2346. if (paper != NULL)
  2347. {
  2348. delete paper; paper = NULL;
  2349. }
  2350. });
  2351. if (paper->scan_cnt >= 1)
  2352. {
  2353. paper->exc_code = paper_exc_locate;
  2354. bInfo->UpdatePaper(paper);
  2355. continue;
  2356. }
  2357. paper->scan_cnt++;
  2358. int res = ScanPaper(bInfo, paper);
  2359. if (res == IDF_SUCCESS)
  2360. {
  2361. if (bInfo->m_bUseInputExam)
  2362. {
  2363. bInfo->MakeResultJsonAndUpload(paper);
  2364. }
  2365. else
  2366. {
  2367. string qr_code = paper->qr_code;
  2368. if (qr_code.length() == 0)
  2369. {
  2370. paper->exc_code = paper_exc_qrcode_unmatch;
  2371. bInfo->UpdatePaper(paper);
  2372. }
  2373. else
  2374. {
  2375. vector<string> strs = splitEx(qr_code, ",");
  2376. if (strs[0] != bInfo->m_exam_id)
  2377. {
  2378. paper->exc_code = paper_exc_qrcode_unmatch;
  2379. bInfo->UpdatePaper(paper);
  2380. }
  2381. else
  2382. {
  2383. bInfo->MakeResultJsonAndUpload(paper);
  2384. }
  2385. }
  2386. }
  2387. }
  2388. else
  2389. {
  2390. if (paper->exc_code == paper_exc_pages_missed)
  2391. {
  2392. g_ScanThreadRun = false;
  2393. g_IsPagesMissed = true;
  2394. }
  2395. else
  2396. {
  2397. paper->exc_code = paper_exc_locate;
  2398. }
  2399. bInfo->UpdatePaper(paper);
  2400. }
  2401. }
  2402. }
  2403. bool CBatch_Server::OpenBatchDb()
  2404. {
  2405. if (m_batch_db.is_open())
  2406. {
  2407. return true;
  2408. }
  2409. //判断文件是否存在
  2410. struct stat buffer;
  2411. try
  2412. {
  2413. m_batch_db.open(m_batchDbPath.c_str());
  2414. }
  2415. catch (CException* e)
  2416. {
  2417. g_log.PutMsg(LogLvlFailed, "开启批次数据库失败 %s", m_batchDbPath.c_str());
  2418. return false;
  2419. }
  2420. m_batch_db.execDML("pragma journal_mode = MEMORY");
  2421. m_batch_db.execDML("PRAGMA synchronous = OFF");
  2422. m_total_cnt = m_batch_db.execScalar("SELECT count(0) FROM papers");
  2423. /*{
  2424. m_batch_db.execDML("update papers set state = 0");
  2425. }*/
  2426. return true;
  2427. }
  2428. string CBatch_Server::ReadQRcode(Paper_Page* paper)
  2429. {
  2430. PageIdentify identify;
  2431. string ret = "";
  2432. for (int i = 0; i < 2; i++)
  2433. {
  2434. string strPath = /*UtfToGbk*/(paper->path[i]);
  2435. IplImage *src = cvLoadImage(strPath.c_str());
  2436. if (src == NULL)
  2437. {
  2438. continue;
  2439. }
  2440. auto act1 = finally([&]
  2441. {
  2442. if (src != NULL)cvReleaseImage(&src);
  2443. src = NULL;
  2444. });
  2445. ret = identify.ReadQrCode(src);
  2446. if (ret.length()>0)
  2447. {
  2448. return ret;
  2449. }
  2450. }
  2451. return ret;
  2452. }
  2453. CBatch_Server::CBatch_Server()
  2454. {
  2455. m_onlineCardTemplate = new OnLineCard::PaperTemplate;
  2456. m_onlineCardTemplate->useQrCode = false;
  2457. m_thread_cnt = 1;
  2458. m_bOffline_score = false;
  2459. m_regionQQ = "ap-shanghai";
  2460. m_bucket_nameQQ = "zxhx-1302712961";
  2461. m_hostHuawei = "obs.cn-north-4.myhuaweicloud.com";
  2462. m_bucketHuawei = "obs-cs-1";
  2463. m_indexDbPath = g_Indexdb;
  2464. m_bUseInputExam = false;
  2465. {
  2466. TCHAR FilePath[MAX_PATH];
  2467. GetModuleFileName(NULL, FilePath, MAX_PATH);
  2468. (_tcsrchr(FilePath, '\\'))[1] = 0;
  2469. lstrcat(FilePath, _T("config.ini"));
  2470. m_bDrawSchema = GetPrivateProfileInt(_T("USER"), _T("DrawSchema"), 1, FilePath);//
  2471. m_bDrawResult = GetPrivateProfileInt(_T("USER"), _T("DrawResult"), 0, FilePath);//
  2472. m_yunType = GetPrivateProfileInt(_T("USER"), _T("YunType"), 0, FilePath);
  2473. }
  2474. CloudSetYunType(m_yunType);
  2475. if (m_yunType == 1)
  2476. InitHuaweiCLoud(const_cast<char *>(m_hostHuawei.c_str()), "XOO6T5NG2ROM3Y8ZIWKT", "IqJjwHmgMPgomZtHYkCUaqbw0oAumWcoq8Typse8", const_cast<char *>(m_bucketHuawei.c_str()));
  2477. else if (m_yunType == 0)
  2478. InitQCLoud(1302712961, "AKIDC9pETRbZfWBbmhoglkT4PUJGzRjmj3Ia", "C6jlX4LKfleGdmfQvGNgj74lESRpBIEJ", const_cast<char *>(m_regionQQ.c_str()), const_cast<char *>(m_bucket_nameQQ.c_str()));
  2479. }
  2480. CBatch_Server::~CBatch_Server()
  2481. {
  2482. if (m_batch_db.is_open())
  2483. m_batch_db.close();
  2484. }
  2485. bool CBatch_Server::GetCardTemplate(string exam_id, string task_id)
  2486. {
  2487. std::string response;
  2488. CHttpClient httpClient;
  2489. CString url;
  2490. url.Format(_T("%s/teacher/third/card/location?cardId=%s&taskId=%s&schoolId=%s"), strA2W(g_ServerUrl).c_str(), strA2W(exam_id).c_str(), strA2W(task_id).c_str(), strA2W(g_SchoolId).c_str());
  2491. //httpClient.SetSendHeader(L"");
  2492. httpClient.HttpGet(url, NULL, response);
  2493. if (response.length() == 0)
  2494. {
  2495. g_log.PutMsg(LogLvlFailed, "模板下载失败 批次ID=%s", m_batch_id.c_str());
  2496. return false;
  2497. }
  2498. Json::Value root;
  2499. Json::Reader(Json::Features()).parse(response, root);
  2500. if (root["code"].isInt() && root["code"].asInt() != 200){
  2501. g_log.PutMsg(LogLvlFailed, "模板不正确 code!=200 批次ID=%s", m_batch_id.c_str());
  2502. return false;
  2503. }
  2504. FILE* pschema = fopen("schema.json", "wb");
  2505. if (pschema)
  2506. {
  2507. fwrite(response.c_str(), 1, response.length(), pschema);
  2508. fclose(pschema);
  2509. }
  2510. //return ParseTemplateFromJsonAll2("D:\\thirdNanCang\\Win32\\Debug\\1111.zip", m_onlineCardTemplate);
  2511. try
  2512. {
  2513. return ParseTemplateFromJsonAll(response, m_onlineCardTemplate);
  2514. }
  2515. catch (const char* msg)
  2516. {
  2517. g_log.PutMsg(LogLvlFailed, "模板不正确 区域位置有负值 批次ID=%s", m_batch_id.c_str());
  2518. return false;
  2519. }
  2520. }
  2521. Paper_Page* CBatch_Server::ReadNextPaper()
  2522. {
  2523. PBQAutoLock autolock(m_lockPageVec);
  2524. if (m_PageVec.size()>0)
  2525. {
  2526. Paper_Page* p = m_PageVec[0];
  2527. m_PageVec.erase(m_PageVec.begin());
  2528. return p;
  2529. }
  2530. else
  2531. {
  2532. return NULL;
  2533. }
  2534. }
  2535. void CBatch_Server::ReadExamInfo()
  2536. {
  2537. OpenBatchDb();
  2538. CppSQLite3Query query0;
  2539. char sql[256];
  2540. sprintf_s(sql, "select * from batchinfo");
  2541. query0 = m_batch_db.execQuery(sql);
  2542. if (!query0.eof())//表示有先扫后传的原图上传
  2543. {
  2544. m_exam_id = query0.getStringField("exam_id");
  2545. m_task_id = query0.getStringField("task_id");
  2546. }
  2547. query0.finalize();
  2548. }
  2549. void CBatch_Server::GetUnScanPapersFromDB()
  2550. {
  2551. CppSQLite3Query query0;
  2552. char sql[256];
  2553. sprintf_s(sql, "select * from papers where state in(0)");
  2554. query0 = m_batch_db.execQuery(sql);
  2555. while (!query0.eof())//表示有先扫后传的原图上传
  2556. {
  2557. Paper_Page* paper = new Paper_Page;
  2558. //paper->Init_result();
  2559. paper->id = query0.getIntField("id");
  2560. paper->scan_cnt = query0.getIntField("scan_cnt");
  2561. paper->path[0] = UtfToGbk(query0.getStringField("page0"));
  2562. paper->path[1] = UtfToGbk(query0.getStringField("page1"));
  2563. paper->path_jiaozheng[0] = query0.getStringField("jiaozheng0");
  2564. paper->path_jiaozheng[1] = query0.getStringField("jiaozheng1");
  2565. paper->result_dir = m_work_dir + "result/" + to_string(paper->id) + "/";
  2566. paper->result_json = paper->result_dir + "result.json";
  2567. paper->yun_header = query0.getStringField("yun_header");
  2568. if (paper->yun_header.length() == 0)
  2569. {
  2570. paper->yun_header = to_string(GetTickCount() + paper->id);
  2571. }
  2572. m_PageVec.push_back(paper);
  2573. query0.nextRow();
  2574. }
  2575. query0.finalize();
  2576. }
  2577. Paper_Page* CBatch_Server::GetPaperFromDB(int paper_id)
  2578. {
  2579. CppSQLite3Query query0;
  2580. char sql[256];
  2581. sprintf_s(sql, "select * from papers where id ='%d'", paper_id);
  2582. query0 = m_batch_db.execQuery(sql);
  2583. Paper_Page* paper = NULL;
  2584. if (!query0.eof())
  2585. {
  2586. paper = new Paper_Page;
  2587. paper->id = query0.getIntField("id");
  2588. paper->scan_cnt = query0.getIntField("scan_cnt");
  2589. paper->path[0] = UtfToGbk(query0.getStringField("page0"));
  2590. paper->path[1] = UtfToGbk(query0.getStringField("page1"));
  2591. paper->path_jiaozheng[0] = query0.getStringField("jiaozheng0");
  2592. paper->path_jiaozheng[1] = query0.getStringField("jiaozheng1");
  2593. paper->result_dir = m_work_dir + "result/" + to_string(paper->id) + "/";
  2594. paper->result_json = paper->result_dir + "result.json";
  2595. paper->yun_header = query0.getStringField("yun_header");
  2596. if (paper->yun_header.length() == 0)
  2597. {
  2598. paper->yun_header = to_string(GetTickCount() + paper->id);
  2599. }
  2600. }
  2601. query0.finalize();
  2602. return paper;
  2603. }
  2604. void CBatch_Server::ReBatchScan(int batch_id, string exam_id)
  2605. {
  2606. batch_info info = GetBatchInfo(batch_id);
  2607. if (info.id == -1)
  2608. {
  2609. g_log.PutMsg(LogLvlFailed, "StartScan 未查到批次=%d", batch_id);
  2610. return;
  2611. }
  2612. m_batch_id = to_string(batch_id);
  2613. m_batchDbPath = info.batchdb_path;
  2614. m_total_cnt = info.total_cnt;
  2615. m_work_dir = UtfToGbk(info.work_dir);
  2616. m_batch_code = getBatchCode(info.work_dir);
  2617. if (!OpenBatchDb())
  2618. {
  2619. return;
  2620. }
  2621. {//重置DB
  2622. char sql[1024] = { 0 };
  2623. sprintf_s(sql, "update papers set scan_cnt=0 ");
  2624. m_batch_db.execDML("begin transaction");
  2625. m_batch_db.execDML(sql);
  2626. m_batch_db.execDML("commit transaction");
  2627. }
  2628. GetUnScanPapersFromDB();
  2629. string qr_code = exam_id;
  2630. if (qr_code.length() == 0)
  2631. {
  2632. g_log.PutErrMsg("ReBatchScan 请输入正确考试号 batch_id=%s", m_batch_id.c_str());
  2633. return;
  2634. }
  2635. vector<string> strs = splitEx(qr_code, ",");
  2636. if (strs.size() == 2)
  2637. {
  2638. m_exam_id = strs[0];
  2639. m_task_id = strs[1];
  2640. }
  2641. else
  2642. {
  2643. m_exam_id = strs[0];
  2644. }
  2645. {
  2646. char sql[1024] = { 0 };
  2647. sprintf_s(sql, "update batchinfo set exam_id ='%s', task_id ='%s'", m_exam_id.c_str(), m_task_id.c_str());
  2648. m_batch_db.execDML("begin transaction");
  2649. m_batch_db.execDML(sql);
  2650. m_batch_db.execDML("commit transaction");
  2651. }
  2652. if (!GetCardTemplate(m_exam_id, m_task_id))
  2653. {
  2654. g_log.PutMsg(LogLvlFailed, "模板解析失败 批次ID=%s", m_batch_id.c_str());
  2655. UpdateIndexDb(m_batch_id, batch_exc_invalid_qrcode);
  2656. return;
  2657. }
  2658. else
  2659. {
  2660. char sql[1024] = { 0 };
  2661. string strExamName = handleApostrophe(m_onlineCardTemplate->exam_name);
  2662. string strSubName = handleApostrophe(m_onlineCardTemplate->subject_name);
  2663. sprintf_s(sql, "update batchinfo set exam_name ='%s', subject_name ='%s'", strExamName.c_str(), strSubName.c_str());
  2664. m_batch_db.execDML("begin transaction");
  2665. m_batch_db.execDML(sql);
  2666. m_batch_db.execDML("commit transaction");
  2667. }
  2668. if (exam_id.length() > 0)
  2669. {
  2670. m_bUseInputExam = true;
  2671. }
  2672. for (int i = 0; i < m_thread_cnt; i++)
  2673. {
  2674. m_thread_handle[i] = (HANDLE)_beginthreadex(NULL, 0, ScanThread, this, NULL, NULL);
  2675. if (m_thread_handle[i] == NULL)
  2676. {
  2677. g_log.PutErrMsg("扫描线程创建失败 batch_id=%s", m_batch_id.c_str());
  2678. return;
  2679. }
  2680. }
  2681. for (int i = 0; i < m_thread_cnt; i++)
  2682. {
  2683. WaitForSingleObject(m_thread_handle[i], INFINITE);
  2684. CloseHandle(m_thread_handle[i]);
  2685. }
  2686. StatisticsBatchInfo(m_batch_id);
  2687. }
  2688. void CBatch_Server::StartScan(int batch_id)//函数返回 扫描结束
  2689. {
  2690. //本地调试时可取消这一句的注释,版本上线时须注释
  2691. //Reset(batch_id);
  2692. batch_info info = GetBatchInfo(batch_id);
  2693. if (info.id == -1)
  2694. {
  2695. g_log.PutMsg(LogLvlFailed, "StartScan 未查到批次=%d", batch_id);
  2696. return;
  2697. }
  2698. m_batch_id = to_string(batch_id);
  2699. m_batchDbPath = info.batchdb_path;
  2700. m_total_cnt = info.total_cnt;
  2701. m_work_dir = UtfToGbk(info.work_dir);
  2702. m_batch_code = getBatchCode(info.work_dir);
  2703. if (!OpenBatchDb())
  2704. {
  2705. return;
  2706. }
  2707. GetUnScanPapersFromDB();
  2708. string qr_code = "";
  2709. bool isJsonOk = false;
  2710. for (int i = 0; i < MIN(m_PageVec.size(), 3); i++)
  2711. {
  2712. Paper_Page* paper = m_PageVec[i];
  2713. if (paper == NULL)
  2714. {
  2715. break;
  2716. }
  2717. qr_code = ReadQRcode(paper);
  2718. if (qr_code.length() == 0)
  2719. {
  2720. continue;
  2721. }
  2722. vector<string> strs = splitEx(qr_code, ",");
  2723. if (strs.size() == 2)
  2724. {
  2725. m_exam_id = strs[0];
  2726. m_task_id = strs[1];
  2727. }
  2728. else
  2729. {
  2730. m_exam_id = strs[0];
  2731. }
  2732. if (!GetCardTemplate(m_exam_id, m_task_id))
  2733. {
  2734. continue;
  2735. }
  2736. else
  2737. {
  2738. isJsonOk = true;
  2739. break;
  2740. }
  2741. }
  2742. if (qr_code.length() == 0)
  2743. {
  2744. g_log.PutErrMsg("未找到二维码 batch_id=%s", m_batch_id.c_str());
  2745. UpdateIndexDb(m_batch_id, batch_exc_invalid_qrcode);
  2746. return;
  2747. }
  2748. else if (isJsonOk == false)
  2749. {
  2750. g_log.PutMsg(LogLvlFailed, "模板解析失败 批次ID=%s", m_batch_id.c_str());
  2751. UpdateIndexDb(m_batch_id, batch_exc_invalid_qrcode);
  2752. return;
  2753. }
  2754. {
  2755. char sql[1024] = { 0 };
  2756. string strExamName = handleApostrophe(m_onlineCardTemplate->exam_name);
  2757. string strSubName = handleApostrophe(m_onlineCardTemplate->subject_name);
  2758. sprintf_s(sql, "update batchinfo set exam_id ='%s', task_id ='%s',exam_name ='%s', subject_name ='%s'", m_exam_id.c_str(), m_task_id.c_str(),
  2759. strExamName.c_str(), strSubName.c_str());
  2760. m_batch_db.execDML("begin transaction");
  2761. m_batch_db.execDML(sql);
  2762. m_batch_db.execDML("commit transaction");
  2763. }
  2764. for (int i = 0; i < m_thread_cnt; i++)
  2765. {
  2766. m_thread_handle[i] = (HANDLE)_beginthreadex(NULL, 0, ScanThread, this, NULL, NULL);
  2767. if (m_thread_handle[i] == NULL)
  2768. {
  2769. g_log.PutErrMsg("扫描线程创建失败 batch_id=%s", m_batch_id.c_str());
  2770. return;
  2771. }
  2772. }
  2773. for (int i = 0; i < m_thread_cnt; i++)
  2774. {
  2775. WaitForSingleObject(m_thread_handle[i], INFINITE);
  2776. CloseHandle(m_thread_handle[i]);
  2777. }
  2778. StatisticsBatchInfo(m_batch_id);
  2779. }
  2780. void CBatch_Server::ReScan(int batch_id, int paper_id, char* page0, char* page1, string exam_id)
  2781. {
  2782. batch_info info = GetBatchInfo(batch_id);
  2783. if (info.id == -1)
  2784. {
  2785. g_log.PutMsg(LogLvlFailed, "ReScan 未查到批次=%d", batch_id);
  2786. return;
  2787. }
  2788. m_batch_id = to_string(batch_id);
  2789. m_batchDbPath = info.batchdb_path;
  2790. m_total_cnt = info.total_cnt;
  2791. m_work_dir = UtfToGbk(info.work_dir);
  2792. m_batch_code = getBatchCode(info.work_dir);
  2793. if (!OpenBatchDb())
  2794. {
  2795. return;
  2796. }
  2797. {//重置DB
  2798. char sql[1024] = { 0 };
  2799. sprintf_s(sql, "update papers set scan_cnt=0 where id = %d", paper_id);
  2800. m_batch_db.execDML("begin transaction");
  2801. m_batch_db.execDML(sql);
  2802. m_batch_db.execDML("commit transaction");
  2803. }
  2804. Paper_Page* paper = GetPaperFromDB(paper_id);
  2805. if (!paper)
  2806. {
  2807. return;
  2808. }
  2809. paper->path[0] = UtfToGbk(page0);
  2810. paper->path[1] = UtfToGbk(page1);
  2811. m_PageVec.push_back(paper);
  2812. if (exam_id.length() == 0)
  2813. {
  2814. ReadExamInfo();
  2815. }
  2816. else
  2817. {
  2818. vector<string> strs = splitEx(exam_id, ",");
  2819. if (strs.size() == 2)
  2820. {
  2821. m_exam_id = strs[0];
  2822. m_task_id = strs[1];
  2823. }
  2824. else
  2825. {
  2826. m_exam_id = strs[0];
  2827. }
  2828. m_bUseInputExam = true;
  2829. }
  2830. if (!GetCardTemplate(m_exam_id, m_task_id))
  2831. {
  2832. g_log.PutMsg(LogLvlFailed, "模板解析失败 批次ID=%s", m_batch_id.c_str());
  2833. return;
  2834. }
  2835. for (int i = 0; i < m_thread_cnt; i++)
  2836. {
  2837. m_thread_handle[i] = (HANDLE)_beginthreadex(NULL, 0, ScanThread, this, NULL, NULL);
  2838. if (m_thread_handle[i] == NULL)
  2839. {
  2840. g_log.PutErrMsg("扫描线程创建失败 batch_id=%s", m_batch_id.c_str());
  2841. return;
  2842. }
  2843. }
  2844. for (int i = 0; i < m_thread_cnt; i++)
  2845. {
  2846. WaitForSingleObject(m_thread_handle[i], INFINITE);
  2847. CloseHandle(m_thread_handle[i]);
  2848. }
  2849. StatisticsBatchInfo(m_batch_id);
  2850. }
  2851. void CBatch_Server::ReScan(int batch_id, vector<int> paper_ids, char* exam_id)
  2852. {
  2853. }
  2854. string CBatch_Server::MakeResultJsonAndUpload(Paper_Page* paper)//调用该函数前Paper_Page必须是识别完成的,本函数不较验
  2855. {
  2856. UpdatePaper(paper);
  2857. CString jsonPath;
  2858. string url_head = "";
  2859. if (m_yunType == 0)
  2860. {
  2861. url_head = "http://" + m_bucket_nameQQ + ".cos." + m_regionQQ + ".myqcloud.com/" + paper->yun_header + "/";
  2862. }
  2863. else
  2864. {
  2865. //m_hostHuawei = "obs.cn-north-4.myhuaweicloud.com";
  2866. //m_bucketHuawei = "obs-cs-1";
  2867. //https://obs-cs-1.obs.cn-north-4.myhuaweicloud.com/D1.jpg
  2868. //https://obs-cs-1.obs.cn-north-4.myhuaweicloud.com/2341881486/
  2869. url_head = "https://" + m_bucketHuawei + "." + m_hostHuawei + "/" + paper->yun_header + "/";
  2870. }
  2871. Json::FastWriter writer;
  2872. Json::Value json;
  2873. json["online_card"] = 1;
  2874. json["exam_id"] = m_exam_id;
  2875. json["task_id"] = m_task_id;
  2876. json["student_code"] = paper->student_code;
  2877. json["pages"] = url_head + "page0.jpg" + "," + url_head + "page1.jpg";;
  2878. json["school_id"] = atoi(g_SchoolId.c_str());
  2879. json["batch_code"] = m_batch_code.c_str();
  2880. json["absent"] = paper->result[0]->quekaoFlag == false ? 0 : 1;
  2881. vector<KEGUANTI_RESULT> keguan_result = paper->result[0]->group_result;
  2882. for (int i = 0; i < paper->result[1]->group_result.size(); i++)
  2883. {
  2884. keguan_result.push_back(paper->result[1]->group_result[i]);
  2885. }
  2886. vector<TIANKONGTI_RESULT> tiankong_result = paper->result[0]->tiankongti_result;
  2887. for (int i = 0; i < paper->result[1]->tiankongti_result.size(); i++)
  2888. {
  2889. tiankong_result.push_back(paper->result[1]->tiankongti_result[i]);
  2890. }
  2891. vector<ZHUGUANTI_RESULT> zhuguan_result = paper->result[0]->zhutuanti_result;
  2892. for (int i = 0; i < paper->result[1]->zhutuanti_result.size(); i++)
  2893. {
  2894. bool pingjie = false;
  2895. for (int j = 0; j < zhuguan_result.size(); j++)
  2896. {
  2897. if (paper->result[1]->zhutuanti_result[i].question_code == zhuguan_result[j].question_code)
  2898. {
  2899. pingjie = true;
  2900. break;
  2901. }
  2902. }
  2903. if (pingjie == false)
  2904. {
  2905. zhuguan_result.push_back(paper->result[1]->zhutuanti_result[i]);
  2906. }
  2907. }
  2908. Json::Value json_array(Json::arrayValue);
  2909. if (paper->result[0]->quekaoFlag != true)
  2910. {
  2911. for (auto& it : keguan_result)
  2912. {
  2913. Json::Value item;
  2914. item["id"] = it.question_code;
  2915. item["answer"] = it.answer;
  2916. item["name"] = qid_name[it.question_code];
  2917. item["url"] = "";
  2918. item["score"] = "";
  2919. json_array.append(item);
  2920. }
  2921. for (auto& it : tiankong_result)
  2922. {
  2923. Json::Value item;
  2924. item["id"] = it.question_code;
  2925. item["answer"] = "";
  2926. item["name"] = qid_name[it.question_code];
  2927. item["url"] = url_head + it.question_code + ".jpg";
  2928. item["score"] = it.question_score;
  2929. if (it.question_score>-0.1 && it.question_score<0.1)
  2930. {
  2931. item["score"] = 0.0;
  2932. }
  2933. json_array.append(item);
  2934. }
  2935. for (auto& it : zhuguan_result)
  2936. {
  2937. Json::Value item;
  2938. item["id"] = it.question_code;
  2939. item["answer"] = "";
  2940. string url = url_head + it.question_code + ".jpg";
  2941. item["name"] = qid_name[it.question_code];
  2942. /* if (paper->qid_cut_map[it.question_code]>1)
  2943. {
  2944. char buf[256] = { 0 };
  2945. for (int i = 0; i < paper->qid_cut_map[it.question_code];i++)
  2946. {
  2947. sprintf_s(buf, "%s%s_%d.jpg", url_head.c_str(), it.question_code.c_str(), i);
  2948. url += ",";
  2949. url += buf;
  2950. }
  2951. }*/
  2952. item["url"] = url;
  2953. item["score"] = it.question_score;
  2954. if (it.question_score > -0.1 && it.question_score < 0.1)
  2955. {
  2956. item["score"] = 0.0;
  2957. }
  2958. json_array.append(item);
  2959. }
  2960. }
  2961. json["questionList"] = json_array;
  2962. string res_json = writer.write(json);
  2963. string json_file = paper->result_dir + "/" + "json.txt";
  2964. FILE* pf = fopen(json_file.c_str(), "wb");
  2965. fwrite(res_json.c_str(), 1, res_json.length(), pf);
  2966. fclose(pf);
  2967. UploadResult(paper);
  2968. return res_json;
  2969. }
  2970. int CBatch_Server::UploadResult(Paper_Page* paper)
  2971. {
  2972. paper->exc_code = paper_exc_upload;
  2973. string jpgname = paper->result_dir + "/" + "jpgname.txt";
  2974. string json_file = paper->result_dir + "/" + "json.txt";
  2975. char* jpgbuf = new char[10240];
  2976. memset(jpgbuf, 0, 10240);
  2977. char* json_buf = new char[20480];
  2978. memset(json_buf, 0, 10240);
  2979. auto act1 = finally([&]
  2980. {
  2981. delete[] json_buf;
  2982. delete[] jpgbuf;
  2983. UpdatePaper(paper);
  2984. //重传完成通知上层界面
  2985. if (paper->exc_code == paper_exc_success)
  2986. ::PostMessage(g_MsgWnd, UM_REUPLOAD_FINISHED, atoi(m_batch_id.c_str()), paper->id);
  2987. else
  2988. ::PostMessage(g_MsgWnd, UM_REUPLOAD_FAILED, atoi(m_batch_id.c_str()), paper->id);
  2989. });
  2990. FILE* pf = fopen(jpgname.c_str(), "rb");
  2991. if (!pf)
  2992. {
  2993. g_log.PutMsg(LogLvlFailed, "打开上传文件失败 %s", jpgname.c_str());
  2994. paper->exc_code = paper_exc_upload;
  2995. return 0;
  2996. }
  2997. fread(jpgbuf, 1, 10240, pf);
  2998. fclose(pf);
  2999. vector<string> jpgs = splitEx(jpgbuf, ",");
  3000. /*FILE* pf2 = fopen(json_file.c_str(), "rb");
  3001. if (!pf2)
  3002. {
  3003. g_log.PutMsg(LogLvlFailed, "打开上传文件失败 %s", json_file.c_str());
  3004. paper->exc_code = paper_exc_upload;
  3005. return 0;
  3006. }
  3007. fread(json_buf, 1, 20480, pf2);
  3008. fclose(pf2);*/
  3009. string strContent;
  3010. string strTemp;
  3011. ifstream in;
  3012. ofstream out;
  3013. in.open(json_file);
  3014. while (getline(in, strTemp))
  3015. {
  3016. strContent += strTemp;
  3017. }
  3018. in.close();
  3019. //Json::Features features;
  3020. //Json::Reader re(features);
  3021. //Json::Value root;
  3022. //re.parse(json_buf, root);
  3023. //Json::Value json_array= root["questionList"];
  3024. {
  3025. char key[512] = { 0 };
  3026. sprintf_s(key, "%s/page0.jpg", paper->yun_header.c_str());
  3027. char url[512] = { 0 };
  3028. bool ret = CloudPutFile(key, (char*)paper->path_jiaozheng[0].c_str(), url);
  3029. if (!ret)
  3030. {
  3031. g_log.PutMsg(LogLvlError, "上传云失败 批次id=%s 试卷id=%d", m_batch_id.c_str(), paper->id);
  3032. return 0;
  3033. }
  3034. memset(key, 0, 512);
  3035. sprintf_s(key, "%s/page1.jpg", paper->yun_header.c_str());
  3036. ret = CloudPutFile(key, (char*)paper->path_jiaozheng[1].c_str(), url);
  3037. if (!ret)
  3038. {
  3039. g_log.PutMsg(LogLvlError, "上传云失败 批次id=%s 试卷id=%d", m_batch_id.c_str(), paper->id);
  3040. return 0;
  3041. }
  3042. }
  3043. for (auto& it : jpgs)
  3044. {
  3045. string id = it;
  3046. string jpgpath = paper->result_dir + "/" + id + ".jpg";
  3047. char key[512] = { 0 };
  3048. sprintf_s(key, "%s/%s.jpg", paper->yun_header.c_str(), id.c_str());
  3049. char url[512] = { 0 };
  3050. bool ret = CloudPutFile(key, (char*)jpgpath.c_str(), url);
  3051. if (!ret)
  3052. {
  3053. g_log.PutMsg(LogLvlError, "上传云失败 批次id=%s 试卷id=%d", m_batch_id.c_str(), paper->id);
  3054. return 0;
  3055. }
  3056. }
  3057. {
  3058. CHttpClient httpClient;
  3059. string response;
  3060. CString url;
  3061. url.Format(_T("%s/teacher/third/student/upload"), strA2W(g_ServerUrl).c_str());
  3062. string strJsonContent = UtfToGbk(strContent);
  3063. CString strJson = CString(_T("json=")) + strA2W(strJsonContent).c_str();
  3064. httpClient.HttpPost(url, strJson, response);
  3065. if (response.find("\"code\":200") != string::npos)
  3066. {
  3067. paper->exc_code = paper_exc_success;
  3068. //上传成功
  3069. }
  3070. else
  3071. {
  3072. Json::Features features;
  3073. Json::Reader re(features);
  3074. Json::Value root;
  3075. re.parse(response, root);
  3076. paper->err_msg = root["msg"].asString();
  3077. }
  3078. }
  3079. return 0;
  3080. }
  3081. void CBatch_Server::StatisticsBatchInfo(string batch_id)
  3082. {
  3083. //return;
  3084. int suc_count = m_batch_db.execScalar("SELECT count(0) FROM papers where state = '-1'");
  3085. if (suc_count == m_total_cnt)
  3086. {
  3087. UpdateIndexDb(m_batch_id, batch_exc_success, suc_count);
  3088. return;
  3089. }
  3090. if (g_IsPagesMissed == true)
  3091. {
  3092. UpdateIndexDb(m_batch_id, batch_exc_pages_missed, suc_count);
  3093. return;
  3094. }
  3095. int exc_count = m_batch_db.execScalar("SELECT count(0) FROM papers where state > 0");
  3096. if (exc_count > 0)
  3097. {
  3098. UpdateIndexDb(m_batch_id, batch_exc_scan_excption);
  3099. return;
  3100. }
  3101. }
  3102. void CBatch_Server::Reset(int batch_id)
  3103. {
  3104. CppSQLite3DB index_db;
  3105. try
  3106. {
  3107. index_db.open(ToUtf8(m_indexDbPath).c_str());
  3108. }
  3109. catch (CException* e)
  3110. {
  3111. g_log.PutMsg(LogLvlFailed, "UpdateIndexDb 开启index.db3失败 ");
  3112. ReleaseMutex(m_hMutexIndex);
  3113. return;
  3114. }
  3115. char sql[1024] = { 0 };
  3116. sprintf_s(sql, 1024, "update batchs set state = 0 ");
  3117. index_db.execDML(sql);
  3118. index_db.close();
  3119. batch_info info = GetBatchInfo(batch_id);
  3120. if (info.id == -1)
  3121. {
  3122. g_log.PutMsg(LogLvlFailed, "StartScan 未查到批次=%d", batch_id);
  3123. return;
  3124. }
  3125. m_batch_id = to_string(batch_id);
  3126. m_batchDbPath = info.batchdb_path;
  3127. m_total_cnt = info.total_cnt;
  3128. m_work_dir = UtfToGbk(info.work_dir);
  3129. m_batch_code = getBatchCode(info.work_dir);
  3130. if (!OpenBatchDb())
  3131. {
  3132. return;
  3133. }
  3134. sprintf_s(sql, "update papers set state = 0,scan_cnt=0");
  3135. m_batch_db.execDML("begin transaction");
  3136. m_batch_db.execDML(sql);
  3137. m_batch_db.execDML("commit transaction");
  3138. }
  3139. void CBatch_Server::UpdatePaper(Paper_Page* paper)
  3140. {
  3141. //return;
  3142. char sql[1024] = { 0 };
  3143. string strErrMsg = handleApostrophe(paper->err_msg);
  3144. string strRestultDir = handleApostrophe(paper->result_dir);
  3145. string strJiaoZheng0 = handleApostrophe(paper->path_jiaozheng[0]);
  3146. string strJiaoZheng1 = handleApostrophe(paper->path_jiaozheng[1]);
  3147. sprintf_s(sql, "update papers set student_id ='%s', student_name ='%s', result_dir ='%s',state = %d,err_msg='%s',scan_time=%lld,qr_code='%s',yun_header='%s',jiaozheng0='%s',jiaozheng1='%s',scan_cnt=%d where id='%d'",
  3148. paper->student_code.c_str(), paper->student_name.c_str(), strRestultDir.c_str(), paper->exc_code, strErrMsg.c_str(), std::time(0), paper->qr_code.c_str(), paper->yun_header.c_str(), strJiaoZheng0.c_str(), strJiaoZheng1.c_str(), paper->scan_cnt, paper->id);
  3149. m_batch_db.execDML("begin transaction");
  3150. m_batch_db.execDML(sql);
  3151. m_batch_db.execDML("commit transaction");
  3152. }
  3153. void CBatch_Server::UpdateIndexDb(string batch_id, long long state, int success_cnt)
  3154. {
  3155. /*DWORD dw = WaitForSingleObject(m_hMutexIndex, 10000);
  3156. if (WAIT_TIMEOUT == dw)
  3157. {
  3158. g_log.PutMsg(LogLvlFailed, "UpdateIndexDb 访问 index_db3 超时");
  3159. return ;
  3160. }*/
  3161. CppSQLite3DB index_db;
  3162. try
  3163. {
  3164. index_db.open(ToUtf8(m_indexDbPath).c_str());
  3165. }
  3166. catch (CException* e)
  3167. {
  3168. g_log.PutMsg(LogLvlFailed, "UpdateIndexDb 开启index.db3失败 ");
  3169. ReleaseMutex(m_hMutexIndex);
  3170. return;
  3171. }
  3172. char sql[1024] = { 0 };
  3173. if (success_cnt<0)
  3174. {
  3175. sprintf_s(sql, 1024, "update batchs set state = %lld where id = '%s'", state, batch_id.c_str());
  3176. }
  3177. else
  3178. {
  3179. sprintf_s(sql, 1024, "update batchs set state = %lld,success_cnt= %d where id = '%s'",
  3180. state, success_cnt, batch_id.c_str());
  3181. }
  3182. index_db.execDML(sql);
  3183. index_db.close();
  3184. ReleaseMutex(m_hMutexIndex);
  3185. }
  3186. void CBatch_Server::ReUploadAllFailed()
  3187. {
  3188. if (!OpenBatchDb())
  3189. return;
  3190. CppSQLite3Query query0;
  3191. char sql[256];
  3192. sprintf_s(sql, "select * from papers where state in(%d)", paper_exc_upload);
  3193. query0 = m_batch_db.execQuery(sql);
  3194. while (!query0.eof())
  3195. {
  3196. Paper_Page* paper = new Paper_Page;
  3197. paper->id = query0.getIntField("id");
  3198. paper->scan_cnt = query0.getIntField("scan_cnt");
  3199. paper->path[0] = UtfToGbk(query0.getStringField("page0"));
  3200. paper->path[1] = UtfToGbk(query0.getStringField("page1"));
  3201. paper->path_jiaozheng[0] = query0.getStringField("jiaozheng0");
  3202. paper->path_jiaozheng[1] = query0.getStringField("jiaozheng1");
  3203. paper->result_dir = UtfToGbk(m_work_dir) + "result/" + to_string(paper->id) + "/";
  3204. paper->result_json = paper->result_dir + "result.json";
  3205. paper->yun_header = query0.getStringField("yun_header");
  3206. paper->student_code = query0.getStringField("student_id");
  3207. paper->qr_code = query0.getStringField("qr_code");
  3208. m_PageVec.push_back(paper);
  3209. query0.nextRow();
  3210. }
  3211. query0.finalize();
  3212. while (true)
  3213. {
  3214. Paper_Page* paper = ReadNextPaper();
  3215. if (paper == NULL)
  3216. {
  3217. break;
  3218. }
  3219. auto act1 = finally([&]
  3220. {
  3221. delete paper; paper = NULL;
  3222. });
  3223. UploadResult(paper);
  3224. }
  3225. StatisticsBatchInfo(m_batch_id);
  3226. }
  3227. void CBatch_Server::DrawSchema(IplImage*dst_img, SchemaPage* pageSchema, OMR_RESULT *result)
  3228. {
  3229. CvFont font;
  3230. float scale = (float)40 * 20 / pageSchema->locatePoints[0].width / pageSchema->locatePoints[0].height;
  3231. scale = sqrt(scale);
  3232. cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 2.0 / scale, 2.0 / scale, 0, 2);
  3233. if (m_bDrawSchema)
  3234. {
  3235. // 绘制定位点
  3236. for (std::size_t i = 0; i < pageSchema->questionLocatePoints.size(); i++){
  3237. cvDrawRect(dst_img,
  3238. cvPoint(pageSchema->questionLocatePoints[i].centerx - pageSchema->questionLocatePoints[i].width / 2.0, pageSchema->questionLocatePoints[i].centery - pageSchema->questionLocatePoints[i].height / 2.0),
  3239. cvPoint(pageSchema->questionLocatePoints[i].centerx + pageSchema->questionLocatePoints[i].width / 2.0, pageSchema->questionLocatePoints[i].centery + pageSchema->questionLocatePoints[i].height / 2.0),
  3240. cvScalar(0, 255, 0));
  3241. }
  3242. // 绘制二维码 条形码
  3243. for (std::size_t i = 0; i < pageSchema->codes.size(); i++){
  3244. cvDrawRect(dst_img,
  3245. cvPoint(pageSchema->codes[i].centerx - pageSchema->codes[i].width / 2.0, pageSchema->codes[i].centery - pageSchema->codes[i].height / 2.0),
  3246. cvPoint(pageSchema->codes[i].centerx + pageSchema->codes[i].width / 2.0, pageSchema->codes[i].centery + pageSchema->codes[i].height / 2.0),
  3247. cvScalar(0, 255, 0));
  3248. cvPutText(dst_img, pageSchema->codes[i].strContent.c_str(), cvPoint(pageSchema->codes[i].centerx - pageSchema->codes[i].width / 2.0, pageSchema->codes[i].centery - pageSchema->codes[i].height / 2.0),
  3249. &font, CV_RGB(255, 0, 0));
  3250. }
  3251. // 客观题
  3252. for (std::size_t i = 0; i < pageSchema->items.size(); i++){
  3253. cvDrawRect(dst_img,
  3254. cvPoint(pageSchema->items[i].centerx - pageSchema->items[i].width / 2.0, pageSchema->items[i].centery - pageSchema->items[i].height / 2.0),
  3255. cvPoint(pageSchema->items[i].centerx + pageSchema->items[i].width / 2.0, pageSchema->items[i].centery + pageSchema->items[i].height / 2.0),
  3256. cvScalar(0, 255, 0));
  3257. }
  3258. // 主观题
  3259. for (std::size_t i = 0; i < pageSchema->question_score.size(); i++){
  3260. if (pageSchema->question_score[i].scoreBox.bXuanZuoTi){
  3261. for (int j = 0; j < pageSchema->question_score[i].countNum; j++){
  3262. cvDrawRect(dst_img,
  3263. cvPoint(pageSchema->question_score[i].item[j].centerx - pageSchema->question_score[i].item[j].width / 2.0, pageSchema->question_score[i].item[j].centery - pageSchema->question_score[i].item[j].height / 2.0),
  3264. cvPoint(pageSchema->question_score[i].item[j].centerx + pageSchema->question_score[i].item[j].width / 2.0, pageSchema->question_score[i].item[j].centery + pageSchema->question_score[i].item[j].height / 2.0),
  3265. cvScalar(0, 255, 0));
  3266. }
  3267. }
  3268. // 绘制打分区域
  3269. int x = pageSchema->question_score[i].scoreBox.pos.x,
  3270. y = pageSchema->question_score[i].scoreBox.pos.y,
  3271. w = pageSchema->question_score[i].scoreBox.pos.w,
  3272. h = pageSchema->question_score[i].scoreBox.pos.h;
  3273. cvDrawRect(dst_img,
  3274. cvPoint(x, y),
  3275. cvPoint(x + w, y + h),
  3276. cvScalar(255, 0, 255));
  3277. }
  3278. // 剪裁区域
  3279. for (std::size_t i = 0; i < pageSchema->cutAreas.size(); ++i)
  3280. {
  3281. cvDrawRect(dst_img,
  3282. cvPoint(pageSchema->cutAreas[i].centerx - pageSchema->cutAreas[i].width / 2.0, pageSchema->cutAreas[i].centery - pageSchema->cutAreas[i].height / 2.0),
  3283. cvPoint(pageSchema->cutAreas[i].centerx + pageSchema->cutAreas[i].width / 2.0, pageSchema->cutAreas[i].centery + pageSchema->cutAreas[i].height / 2.0),
  3284. cvScalar(0, 255, 0));
  3285. }
  3286. // 学号
  3287. for (std::size_t i = 0; i < pageSchema->stuItems.size(); i++){
  3288. cvDrawRect(dst_img,
  3289. cvPoint(pageSchema->stuItems[i].centerx - pageSchema->stuItems[i].width / 2.0, pageSchema->stuItems[i].centery - pageSchema->stuItems[i].height / 2.0),
  3290. cvPoint(pageSchema->stuItems[i].centerx + pageSchema->stuItems[i].width / 2.0, pageSchema->stuItems[i].centery + pageSchema->stuItems[i].height / 2.0),
  3291. cvScalar(0, 255, 0));
  3292. }
  3293. //缺考标识
  3294. if (pageSchema->quekaoLocatePointIndex.size() > 0){
  3295. cvDrawRect(dst_img,
  3296. cvPoint(pageSchema->quekao.centerx - pageSchema->quekao.width / 2.0, pageSchema->quekao.centery - pageSchema->quekao.height / 2.0),
  3297. cvPoint(pageSchema->quekao.centerx + pageSchema->quekao.width / 2.0, pageSchema->quekao.centery + pageSchema->quekao.height / 2.0),
  3298. cvScalar(0, 0, 255));
  3299. }
  3300. }
  3301. if (m_bDrawResult)
  3302. {
  3303. // 绘制二维码 条形码
  3304. for (std::size_t i = 0; i < pageSchema->codes.size(); i++)
  3305. {
  3306. cvPutText(dst_img, pageSchema->codes[i].strContent.c_str(), cvPoint(pageSchema->codes[i].centerx - pageSchema->codes[i].width / 2.0, pageSchema->codes[i].centery - pageSchema->codes[i].height / 2.0),
  3307. &font, CV_RGB(255, 0, 0));
  3308. }
  3309. // 学号
  3310. if (result->qr_result.size()>0 && pageSchema->stuItems.size()>0)
  3311. {
  3312. cvPutText(dst_img, result->qr_result[0].qr_str.c_str(), cvPoint(pageSchema->stuItems[0].centerx - pageSchema->stuItems[0].width / 2.0, pageSchema->stuItems[0].centery - pageSchema->stuItems[0].height / 2.0),
  3313. &font, CV_RGB(255, 0, 0));
  3314. }
  3315. // 客观题
  3316. for (std::size_t i = 0; i < pageSchema->items.size(); i++){
  3317. cvDrawRect(dst_img,
  3318. cvPoint(pageSchema->items[i].centerx - pageSchema->items[i].width / 2.0, pageSchema->items[i].centery - pageSchema->items[i].height / 2.0),
  3319. cvPoint(pageSchema->items[i].centerx + pageSchema->items[i].width / 2.0, pageSchema->items[i].centery + pageSchema->items[i].height / 2.0),
  3320. cvScalar(0, 255, 0));
  3321. if (result->group_result[pageSchema->items[i].keguanti_question_locate_point_index].answer.find(pageSchema->items[i].OutChar) != string::npos)
  3322. {
  3323. cvDrawRect(dst_img,
  3324. cvPoint(pageSchema->items[i].centerx - pageSchema->items[i].width / 2.0, pageSchema->items[i].centery - pageSchema->items[i].height / 2.0),
  3325. cvPoint(pageSchema->items[i].centerx + pageSchema->items[i].width / 2.0, pageSchema->items[i].centery + pageSchema->items[i].height / 2.0),
  3326. cvScalar(0, 0, 255));
  3327. cvPutText(dst_img, tostring(pageSchema->items[i].OutChar).c_str(), cvPoint(pageSchema->items[i].centerx - pageSchema->items[i].width / 2.0, pageSchema->items[i].centery + pageSchema->items[i].height / 2.0),
  3328. &font, CV_RGB(255, 0, 0));
  3329. }
  3330. }
  3331. // 主观题
  3332. for (std::size_t i = 0; i < pageSchema->question_score.size(); i++){
  3333. if (pageSchema->question_score[i].scoreBox.bXuanZuoTi)
  3334. {
  3335. for (int j = 0; j < pageSchema->question_score[i].countNum; j++){
  3336. cvDrawRect(dst_img,
  3337. cvPoint(pageSchema->question_score[i].item[j].centerx - pageSchema->question_score[i].item[j].width / 2.0, pageSchema->question_score[i].item[j].centery - pageSchema->question_score[i].item[j].height / 2.0),
  3338. cvPoint(pageSchema->question_score[i].item[j].centerx + pageSchema->question_score[i].item[j].width / 2.0, pageSchema->question_score[i].item[j].centery + pageSchema->question_score[i].item[j].height / 2.0),
  3339. cvScalar(0, 255, 0));
  3340. }
  3341. }
  3342. // 绘制打分区域
  3343. int x = pageSchema->question_score[i].scoreBox.pos.x,
  3344. y = pageSchema->question_score[i].scoreBox.pos.y,
  3345. w = pageSchema->question_score[i].scoreBox.pos.w,
  3346. h = pageSchema->question_score[i].scoreBox.pos.h;
  3347. cvDrawRect(dst_img,
  3348. cvPoint(x, y),
  3349. cvPoint(x + w, y + h),
  3350. cvScalar(255, 0, 255));
  3351. for (int j = 0; j < result->tiankongti_result.size(); j++)
  3352. {
  3353. if (pageSchema->question_score[i].question_code == result->tiankongti_result[j].question_code)
  3354. {
  3355. double sss = result->tiankongti_result[j].question_score;
  3356. if (sss<0.1 && sss>-0.1)
  3357. {
  3358. sss = 0;
  3359. }
  3360. cvPutText(dst_img, tostring(sss).c_str(), cvPoint(x + w, y + h),
  3361. &font, CV_RGB(255, 0, 0));
  3362. }
  3363. }
  3364. for (int j = 0; j < result->zhutuanti_result.size(); j++)
  3365. {
  3366. if (pageSchema->question_score[i].question_code == result->zhutuanti_result[j].question_code)
  3367. {
  3368. double sss = result->zhutuanti_result[j].question_score;
  3369. if (sss<0.1 && sss>-0.1)
  3370. {
  3371. sss = 0;
  3372. }
  3373. cvPutText(dst_img, tostring(sss).c_str(), cvPoint(x + w, y + h),
  3374. &font, CV_RGB(255, 0, 0));
  3375. }
  3376. }
  3377. }
  3378. }
  3379. }