gxgenerator.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. """
  2. 高校整卷数据生成器
  3. """
  4. from generator import generator
  5. import config
  6. import pandas as pd
  7. import numpy as np
  8. import random
  9. import json
  10. import openpyxl
  11. import commonhandle
  12. import os
  13. from gxmarkingcloudInf import gxmarkingcloudInf
  14. from imagebuilder import imageBuilder
  15. import logger
  16. class gxgenerator(generator):
  17. def __init__(self):
  18. self.courseLst = []
  19. course_content = config.course.split(",")
  20. self.questionLst = []
  21. self.dataoutputpath = str(config.examId)
  22. if not os.path.exists(self.dataoutputpath):
  23. os.makedirs(self.dataoutputpath)
  24. for courses in course_content:
  25. if len(courses.split("#")) < 3:
  26. raise Exception("课程参数未配置齐全,请检查")
  27. self.courseLst.append(
  28. {"code": courses.split("#")[0], "name": courses.split("#")[1], "imagenum": int(courses.split("#")[2])})
  29. object_num = config.singlechoice_num + config.multichoice_num + config.trueorfalse_num
  30. if object_num == 0 and config.subjective_num == 0:
  31. raise Exception("总题目数量为0,请保证至少含有一道客观题或者一道主观题")
  32. self.choice = []
  33. for i in range(int(config.choice_len)):
  34. self.choice.append(chr(65 + i))
  35. self.single_choice_order = []
  36. self.multi_choice_order = []
  37. self.trueorfalse_order = []
  38. order = 1
  39. for idx in range(int(config.singlechoice_num)):
  40. self.single_choice_order.append(order)
  41. order = order + 1
  42. for idx in range(int(config.multichoice_num)):
  43. self.multi_choice_order.append(order)
  44. order = order + 1
  45. for idx in range(int(config.trueorfalse_num)):
  46. self.trueorfalse_order.append(order)
  47. order = order + 1
  48. self.inf=gxmarkingcloudInf()
  49. self.inf.selectExam()
  50. def studentgenerator(self):
  51. student_temp_path = self.dataoutputpath + os.sep + "temp"
  52. if os.path.exists(student_temp_path + os.sep + "student_temp.xlsx"):
  53. os.remove(student_temp_path + os.sep + "student_temp.xlsx")
  54. if os.path.exists(student_temp_path + os.sep + "upload.json"):
  55. os.remove(student_temp_path + os.sep + "upload.json")
  56. self.student_name_prefix = "张大_"
  57. self.org_name_prefix = "数据中心_"
  58. self.signtable_prefix = 19000000
  59. self.student_code_prefix = 19000000
  60. self.identity_num_prefix = 19000000
  61. self.batch_prefix="A"
  62. student_template_file = openpyxl.load_workbook("template/gx/考生数据导入模板.xlsx")
  63. student_sheet = student_template_file.active
  64. start_row = 3
  65. for idx in range(1,int(config.studentnum)+1):
  66. # 随机获取课程
  67. courses = random.choice(self.courseLst)
  68. if config.signtable_num != 0:
  69. signtable = self.signtable_prefix + random.choice(range(1, config.signtable_num + 1))
  70. else:
  71. signtable = ""
  72. student_sheet.cell(start_row, 1, self.org_name_prefix + self.org_name_prefix +str(random.choice(range(1,int(config.org_num)))))
  73. student_sheet.cell(start_row, 2, courses["code"])
  74. student_sheet.cell(start_row, 3, courses["name"])
  75. student_sheet.cell(start_row, 4, self.identity_num_prefix + idx)
  76. student_sheet.cell(start_row, 5, self.student_code_prefix + idx)
  77. student_sheet.cell(start_row, 6, self.student_name_prefix + str(idx))
  78. student_sheet.cell(start_row, 7, signtable)
  79. student_sheet.cell(start_row, 8, "")
  80. student_sheet.cell(start_row, 9, "")
  81. student_sheet.cell(start_row, 10, "")
  82. student_sheet.cell(start_row, 11, "")
  83. student_sheet.cell(start_row, 12, "")
  84. student_sheet.cell(start_row, 13, "")
  85. student_sheet.cell(start_row, 14, "")
  86. student_sheet.cell(start_row, 15, "")
  87. student_sheet.cell(start_row, 16, self.batch_prefix+str(idx//int(config.batch_num)+1))
  88. start_row=start_row+1
  89. student_template_file.save(self.dataoutputpath+os.sep+"student.xlsx")
  90. def papergenerator(self):
  91. #生成object导入文件
  92. object_template_file=openpyxl.load_workbook("template/gx/客观题导入模板.xlsx")
  93. object_sheet=object_template_file.active
  94. start_row = 3
  95. for course in self.courseLst:
  96. main_number=1
  97. sub_number=1
  98. for i in range(1,int(config.subjective_num)+1):
  99. object_sheet.cell(start_row, 1, course["code"])
  100. object_sheet.cell(start_row, 2, course["name"])
  101. object_sheet.cell(start_row, 3, main_number)
  102. object_sheet.cell(start_row, 4, sub_number)
  103. object_sheet.cell(start_row, 5, "第%d大题"%(main_number))
  104. object_sheet.cell(start_row, 6, random.choice(self.choice))
  105. object_sheet.cell(start_row, 7, config.question_point)
  106. sub_number=sub_number+1
  107. start_row=start_row+1
  108. main_number = main_number + 1
  109. sub_number=1
  110. for i in range(1,int(config.multichoice_num)+1):
  111. object_sheet.cell(start_row, 1, course["code"])
  112. object_sheet.cell(start_row, 2, course["name"])
  113. object_sheet.cell(start_row, 3, main_number)
  114. object_sheet.cell(start_row, 4, sub_number)
  115. object_sheet.cell(start_row, 5, "第%d大题"%(main_number))
  116. #生成随机答案数量
  117. question_num=random.choice(range(1,len(self.choice)+1))
  118. righanswer=random.sample(self.choice,question_num)
  119. righanswer.sort()
  120. object_sheet.cell(start_row, 6, "".join(righanswer))
  121. object_sheet.cell(start_row, 7, config.question_point)
  122. sub_number = sub_number + 1
  123. start_row=start_row+1
  124. main_number=main_number+1
  125. sub_number = 1
  126. for i in range(1, int(config.trueorfalse_num) + 1):
  127. object_sheet.cell(start_row, 1, course["code"])
  128. object_sheet.cell(start_row, 2, course["name"])
  129. object_sheet.cell(start_row, 3, main_number)
  130. object_sheet.cell(start_row, 4, sub_number)
  131. object_sheet.cell(start_row, 5, "第%d大题" % (main_number))
  132. # 生成随机答案数量
  133. object_sheet.cell(start_row, 6, random.choice(["A","B"]))
  134. object_sheet.cell(start_row, 7, config.question_point)
  135. sub_number = sub_number + 1
  136. start_row = start_row + 1
  137. object_template_file.save(self.dataoutputpath+os.sep+"object.xlsx")
  138. #生成主观题数据
  139. subject_template_file = openpyxl.load_workbook("template/gx/主观题导入模板.xlsx")
  140. subject_sheet = subject_template_file.active
  141. start_row = 3
  142. for course in self.courseLst:
  143. main_number = 1
  144. sub_number = 1
  145. for i in range(1, int(config.subjective_num) + 1):
  146. subject_sheet.cell(start_row, 1, course["code"])
  147. subject_sheet.cell(start_row, 2, course["name"])
  148. subject_sheet.cell(start_row, 3, main_number)
  149. subject_sheet.cell(start_row, 4, "第%d大题" % (main_number))
  150. subject_sheet.cell(start_row, 5, sub_number)
  151. subject_sheet.cell(start_row, 6, config.question_point)
  152. subject_sheet.cell(start_row, 7, config.interval_score)
  153. sub_number = sub_number + 1
  154. start_row = start_row + 1
  155. subject_template_file.save(self.dataoutputpath+os.sep+"subjective.xlsx")
  156. def importData(self):
  157. """
  158. 导入数据
  159. """
  160. self.inf.importStudent()
  161. self.inf.importSubjectivePaper()
  162. self.inf.importObjectivePaper()
  163. def filterManual(self,line):
  164. if line["准考证号"] in list(self.mauallst.values):
  165. line["maual"]=True
  166. else:
  167. line["maual"]=False
  168. return line
  169. def filterabsent(self,line):
  170. if line["准考证号"] in list(self.noabsentLst.values):
  171. line["absent"] = False
  172. else:
  173. line["absent"] = True
  174. return line
  175. def imagegenerator(self):
  176. """
  177. 生成签到表图片和学生作答图片及裁切图
  178. 签到表路径{examId}/{签到表编号}/1
  179. .jpg
  180. """
  181. # 读取临时文件数据
  182. student_temp_path = self.dataoutputpath + os.sep + "temp"
  183. student_data_frame = pd.read_excel(student_temp_path + os.sep + "student_temp.xlsx")
  184. student_data_frame["课程代码"] = student_data_frame["课程代码"].astype('str')
  185. student_data_frame["准考证号"] = student_data_frame["准考证号"].astype('str')
  186. student_data_frame["学号"] = student_data_frame["学号"].astype('str')
  187. student_data_frame["签到表编号"] = student_data_frame["签到表编号"].astype('str')
  188. student_data_signtable_group = student_data_frame.groupby("签到表编号")
  189. commonhandle.generateSignTable(student_data_frame, student_data_signtable_group)
  190. with open(student_temp_path + os.sep + "upload.json", 'r', encoding='utf8')as fp:
  191. json_data = json.load(fp)
  192. for key, student_data in student_data_frame.iterrows():
  193. if not student_data["absent"]:
  194. # 开始生成文件
  195. course_code = student_data["课程代码"]
  196. for course in self.courseLst:
  197. if str(course_code) == str(course["code"]):
  198. sheet_num = course["imagenum"]
  199. break
  200. # checkstudent获取学生的信息
  201. student_check_data = self.inf.queryStudent(student_data["准考证号"])
  202. sheet_path = str(config.examId) + os.sep + "image" + os.sep + "ft-sheet" + os.sep + str(
  203. config.examId) + "-" + str(
  204. student_check_data["campusCode"]) + os.sep + course_code
  205. slice_path = str(config.examId) + os.sep + "image" + os.sep + "ft-slice" + os.sep + str(
  206. config.examId) + "-" + str(
  207. student_check_data["campusCode"]) + os.sep + course_code
  208. if not os.path.exists(sheet_path):
  209. os.makedirs(sheet_path)
  210. if not os.path.exists(slice_path):
  211. os.makedirs(slice_path)
  212. used_num = 1
  213. object_answerdata = json_data[student_data["准考证号"]]["objectanswer"]
  214. subject_answer_List = json_data[student_data["准考证号"]]["subject_answer"]
  215. if object_answerdata:
  216. first_image = imageBuilder(int(config.image_width), int(config.image_length),
  217. color=(255, 255, 255, 255))
  218. first_image.draw_text(200, 500, object_answerdata)
  219. image_path = sheet_path + os.sep + student_check_data["examNumber"] + "-" + str(used_num) + ".jpg"
  220. first_image.saveimage(image_path)
  221. used_num = used_num + 1
  222. unused_num = sheet_num - used_num + 1
  223. sheet_list = []
  224. sheet_list_path = []
  225. for i in range(1, unused_num + 1):
  226. image = imageBuilder(int(config.image_width), int(config.image_length),
  227. color=(255, 255, 255, 255))
  228. image_path = sheet_path + os.sep + student_check_data["examNumber"] + "-" + str(
  229. used_num) + ".jpg"
  230. sheet_list_path.append(image_path)
  231. used_num = used_num + 1
  232. sheet_list.append(image)
  233. if len(subject_answer_List) != 0:
  234. # 裁切图数量
  235. slice_num = len(subject_answer_List)
  236. slice_index = 1
  237. data_group = np.array_split(range(slice_num), unused_num)
  238. image_index = 0
  239. for split_data in data_group:
  240. index_data = 0
  241. image = sheet_list[image_index]
  242. if len(split_data)>0:
  243. for split_single in split_data:
  244. # print("font pos:",config.image_length//len(split_data)*index_data+50,subject_answer_List[split_single])
  245. #
  246. image.draw_text(200, int(config.image_length) // len(split_data) * index_data + 50,
  247. subject_answer_List[split_single])
  248. # 生成slice截图
  249. split_image = image.splitImage(
  250. (0, int(config.image_length) // len(split_data) * index_data,
  251. 2200, int(config.image_length) // len(split_data) * (
  252. index_data + 1) - 50))
  253. split_image_path = slice_path + os.sep + student_check_data["examNumber"] + "-" + str(
  254. slice_index) + ".jpg"
  255. split_image.save(split_image_path)
  256. slice_index = slice_index + 1
  257. index_data = index_data + 1
  258. else:
  259. image.draw_text(200, 50,
  260. "补充")
  261. split_image = image.splitImage(
  262. (0, 0,
  263. 2200, int(config.image_length)))
  264. split_image_path = slice_path + os.sep + student_check_data["examNumber"] + "-" + str(
  265. slice_index) + ".jpg"
  266. split_image.save(split_image_path)
  267. slice_index = slice_index + 1
  268. index_data = index_data + 1
  269. image.saveimage(sheet_list_path[image_index])
  270. image_index = image_index + 1
  271. def addMaker(self):
  272. for course in self.courseLst:
  273. count = input("请输入要创建的评卷员数量:")
  274. self.inf.batchcreateMarker(count, course["code"])
  275. def uploadstudent(self):
  276. student_temp_path = self.dataoutputpath + os.sep + "temp"
  277. if not os.path.exists(student_temp_path):
  278. os.makedirs(student_temp_path)
  279. if os.path.exists(student_temp_path + os.sep + "student_temp.xlsx"):
  280. student_data_frame = pd.read_excel(student_temp_path + os.sep + "student_temp.xlsx")
  281. else:
  282. student_data_frame = pd.read_excel(self.dataoutputpath + os.sep + "student.xlsx", header=1)
  283. student_data_frame["课程代码"] = student_data_frame["课程代码"].astype('str')
  284. student_data_frame["准考证号"] = student_data_frame["准考证号"].astype('str')
  285. student_data_frame["学号"] = student_data_frame["学号"].astype('str')
  286. student_data_frame["签到表编号"] = student_data_frame["签到表编号"].astype('str')
  287. # 根据
  288. student_absent_frame = student_data_frame.sample(
  289. int(len(student_data_frame) * (100 - int(config.absentper)) / 100))
  290. self.noabsentLst = student_absent_frame["准考证号"]
  291. student_data_frame = student_data_frame.apply(self.filterabsent, axis=1)
  292. # 从中随机出manual
  293. student_maual_frame = student_absent_frame.sample(
  294. int(len(student_absent_frame) * (100 - int(config.manualper)) / 100))
  295. self.nomauallst = student_maual_frame["准考证号"]
  296. student_data_frame = student_data_frame.apply(self.filterManual, axis=1)
  297. # 存储到temp文件夹下
  298. student_data_frame.to_excel(student_temp_path + os.sep + "student_temp.xlsx", index=False)
  299. # 取出题目信息
  300. object_data_frame = pd.read_excel(self.dataoutputpath + os.sep + "object.xlsx", header=1)
  301. object_data_frame["科目代码"] = object_data_frame["科目代码"].astype('str')
  302. object_group = object_data_frame.groupby("科目代码")
  303. subject_data_frame = pd.read_excel(self.dataoutputpath + os.sep + "subjective.xlsx", header=1)
  304. subject_data_frame["科目代码"] = subject_data_frame["科目代码"].astype('str')
  305. subbject_group = subject_data_frame.groupby("科目代码")
  306. uploadList = {}
  307. for key, student_data in student_data_frame.iterrows():
  308. if not student_data["absent"]:
  309. rightper = random.choice(range(101))
  310. course_code = student_data["课程代码"]
  311. for course in self.courseLst:
  312. if str(course_code) == str(course["code"]):
  313. sheet_num = course["imagenum"]
  314. break
  315. # 生成客观题作答信息
  316. object_course_data = object_group.get_group(str(course_code))
  317. object_answerdata = commonhandle.generateObjectAnswer(rightper, student_data, object_course_data,
  318. self.single_choice_order, self.multi_choice_order,
  319. self.choice)
  320. subject_course_data = subbject_group.get_group(str(course_code))
  321. subject_answer_List = commonhandle.generategxSubjectAnswer(student_data, subject_course_data)
  322. uploadList[student_data["准考证号"]] = {"objectanswer": object_answerdata,
  323. "subject_answer": subject_answer_List}
  324. student_upload_data = {
  325. "examNumber": student_data["准考证号"],
  326. "sliceCount": config.subjective_num,
  327. "sheetCount": sheet_num,
  328. "answers": object_answerdata,
  329. "batchCode": "",
  330. "absent": False,
  331. "manual": student_data["maual"]
  332. }
  333. logger.info(student_upload_data)
  334. self.inf.scanstudent(student_upload_data)
  335. else:
  336. student_upload_data = {
  337. "examNumber": student_data["准考证号"],
  338. "sliceCount": 0,
  339. "sheetCount": 0,
  340. "answers": "",
  341. "batchCode": "",
  342. "absent": True,
  343. "manual": False
  344. }
  345. logger.info(student_upload_data)
  346. self.inf.scanstudent(student_upload_data)
  347. with open(student_temp_path + os.sep + "upload.json", "w", encoding="utf-8") as file:
  348. json_str = json.dumps(uploadList, indent=4, ensure_ascii=False)
  349. file.write(json_str)
  350. # builder=gxgenerator()
  351. # #builder.studentgenerator()
  352. # # builder.papergenerator()
  353. # builder.imagegenerator()