|
@@ -0,0 +1,316 @@
|
|
|
+package com.qmth.test.image;
|
|
|
+
|
|
|
+import com.qmth.test.image.model.*;
|
|
|
+import com.qmth.test.image.model.Image;
|
|
|
+import org.apache.commons.dbcp.BasicDataSource;
|
|
|
+import org.apache.commons.lang.StringUtils;
|
|
|
+import org.springframework.jdbc.core.JdbcTemplate;
|
|
|
+import org.springframework.jdbc.support.rowset.SqlRowSet;
|
|
|
+
|
|
|
+import javax.imageio.ImageIO;
|
|
|
+import java.awt.*;
|
|
|
+import java.awt.image.BufferedImage;
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileInputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStream;
|
|
|
+import java.text.DecimalFormat;
|
|
|
+import java.util.*;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+public class SheetTrack {
|
|
|
+
|
|
|
+ private static Properties p = new Properties();
|
|
|
+
|
|
|
+ private static JdbcTemplate template;
|
|
|
+
|
|
|
+ private static DecimalFormat format = new DecimalFormat("###.#");
|
|
|
+
|
|
|
+ private static Map<String, List<Coordinate>> sliceConfigMap = new HashMap<>();
|
|
|
+
|
|
|
+ private static int fontSize = 60;
|
|
|
+
|
|
|
+ public static void main(String[] args) throws IOException {
|
|
|
+ init(new FileInputStream(args[0]));
|
|
|
+ // init(SheetTrack.class.getClassLoader().getResourceAsStream("track.properties"));
|
|
|
+
|
|
|
+ int examId = Integer.parseInt(p.getProperty("examId"));
|
|
|
+ Set<String> subjects = findSubjectCode(examId);
|
|
|
+ System.out.println("examId=" + examId + ", subject count=" + subjects.size());
|
|
|
+ for (String subjectCode : subjects) {
|
|
|
+ process(examId, subjectCode);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void process(int examId, String subjectCode) throws IOException {
|
|
|
+ List<Integer> groups = new ArrayList<>();
|
|
|
+ List<Question> questions = new ArrayList<>();
|
|
|
+ buildGroupQuestion(examId, subjectCode, groups, questions);
|
|
|
+
|
|
|
+ int totalCount = 0;
|
|
|
+ SqlRowSet crs = template
|
|
|
+ .queryForRowSet(
|
|
|
+ "select count(*) as count from eb_exam_student where exam_id=? and subject_code=? and is_upload=1 and is_absent=0 and is_breach=0",
|
|
|
+ examId, subjectCode);
|
|
|
+ while (crs.next()) {
|
|
|
+ totalCount = crs.getInt("count");
|
|
|
+ }
|
|
|
+
|
|
|
+ int count = 0;
|
|
|
+ SqlRowSet rs = template
|
|
|
+ .queryForRowSet(
|
|
|
+ "select s.id,b.id as campus_id,s.exam_number,s.sheet_count,s.slice_count,s.subjective_score,s.subjective_score_list "
|
|
|
+ + "from eb_exam_student s,b_campus b where s.school_id=b.school_id and s.campus_name=b.name and s.exam_id=? "
|
|
|
+ + "and s.subject_code=? and s.is_upload=1 and s.is_absent=0 and s.is_breach=0 "
|
|
|
+ // + "and s.exam_number='402414432'"
|
|
|
+ , examId, subjectCode);
|
|
|
+ while (rs.next()) {
|
|
|
+ Student s = new Student();
|
|
|
+ s.examId = examId;
|
|
|
+ s.subjectCode = subjectCode;
|
|
|
+ s.id = rs.getInt("id");
|
|
|
+ s.campusId = rs.getInt("campus_id");
|
|
|
+ s.examNumber = rs.getString("exam_number");
|
|
|
+ s.sheetCount = rs.getInt("sheet_count");
|
|
|
+ s.sliceCount = rs.getInt("slice_count");
|
|
|
+ s.score = rs.getDouble("subjective_score");
|
|
|
+ s.scoreDetail = rs.getString("subjective_score_list");
|
|
|
+ s.scoreList = s.getScoreList();
|
|
|
+ s.groups = groups;
|
|
|
+ s.questions = questions;
|
|
|
+
|
|
|
+ List<Tag> tags = new LinkedList<>();
|
|
|
+ for (Integer groupNumber : groups) {
|
|
|
+ tags.addAll(buildGroupTag(s, groupNumber, questions));
|
|
|
+ }
|
|
|
+ processSheet(p.getProperty("output.path"), s, transform(s, tags));
|
|
|
+
|
|
|
+ count++;
|
|
|
+ // if (count % 10 == 0) {
|
|
|
+ System.out.print("\r" + "examId=" + examId + ", subjectCode=" + subjectCode + ": " + count + "/"
|
|
|
+ + totalCount);
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ System.out.print("\r" + "examId=" + examId + ", subjectCode=" + subjectCode + ": " + count + "/" + totalCount);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void processSheet(String outputPath, Student s, List<Track> tracks) throws IOException {
|
|
|
+ List<Image> sheets = buildImage(p.getProperty("sheet.path"), s, s.sheetCount);
|
|
|
+ for (int i = 1; i <= s.sheetCount; i++) {
|
|
|
+ Image sheet = sheets.get(i - 1);
|
|
|
+ BufferedImage newImg = new BufferedImage(sheet.data.getWidth(), sheet.data.getHeight(),
|
|
|
+ BufferedImage.TYPE_INT_RGB);
|
|
|
+ Graphics2D g = newImg.createGraphics();
|
|
|
+ g.drawImage(sheet.data, 0, 0, sheet.data.getWidth(), sheet.data.getHeight(), null);
|
|
|
+ g.setColor(Color.RED);
|
|
|
+ g.setFont(new Font("simsun", Font.PLAIN, fontSize));
|
|
|
+ if (i == 1) {
|
|
|
+ buildScoreSummary(g, newImg, s);
|
|
|
+ }
|
|
|
+ for (Track t : tracks) {
|
|
|
+ if (t.index != i || StringUtils.isBlank(t.content)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ int left = Math.max(fontSize, t.left);
|
|
|
+ int top = Math.max(fontSize, t.top);
|
|
|
+ g.drawString(t.content, left, top);
|
|
|
+ }
|
|
|
+ g.dispose();
|
|
|
+
|
|
|
+ File output = new File(new File(new File(outputPath, s.examId + ""), s.subjectCode), s.examNumber + "-" + i
|
|
|
+ + ".jpg");
|
|
|
+ output.getParentFile().mkdirs();
|
|
|
+ ImageIO.write(newImg, "jpg", output);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void buildScoreSummary(Graphics2D g, BufferedImage image, Student s) {
|
|
|
+ int top = fontSize;
|
|
|
+ int left = fontSize;
|
|
|
+ String total = "总分:" + format.format(s.score) + "=" + s.buildGroupScoreDetail();
|
|
|
+ g.drawString(total, left, top);
|
|
|
+
|
|
|
+ int startTop = 0;
|
|
|
+ int maxWidth = 0;
|
|
|
+ for (int i = 0; i < s.questions.size(); i++) {
|
|
|
+ if (s.scoreList.size() > i) {
|
|
|
+ top += (fontSize + 10);
|
|
|
+ if (startTop == 0) {
|
|
|
+ startTop = top;
|
|
|
+ } else if (top > (image.getHeight() - 100)) {
|
|
|
+ left += maxWidth + fontSize;
|
|
|
+ top = startTop;
|
|
|
+ }
|
|
|
+ Question q = s.questions.get(i);
|
|
|
+ double score = s.scoreList.get(i);
|
|
|
+ String content = q.mainNumber + "-" + q.subNumber + ":" + format.format(score);
|
|
|
+ maxWidth = Math.max(maxWidth, content.length() * fontSize);
|
|
|
+ g.drawString(content, left, top);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static List<Track> transform(Student s, List<Tag> tags) throws IOException {
|
|
|
+ List<Track> result = new ArrayList<>();
|
|
|
+ List<Image> slices = buildImage(p.getProperty("slice.path"), s, s.sliceCount);
|
|
|
+ List<Coordinate> sliceConfig = findSliceConfig(s);
|
|
|
+
|
|
|
+ int maxWidth = 0;
|
|
|
+ int totalHeight = 0;
|
|
|
+ for (Image image : slices) {
|
|
|
+ image.top = totalHeight;
|
|
|
+ maxWidth = Math.max(maxWidth, image.data.getWidth());
|
|
|
+ totalHeight += image.data.getHeight();
|
|
|
+ }
|
|
|
+
|
|
|
+ for (Tag tag : tags) {
|
|
|
+ int left = (int) (maxWidth * tag.left);
|
|
|
+ int top = (int) (totalHeight * tag.top);
|
|
|
+ int index = 0;
|
|
|
+ for (int i = 0; i < slices.size(); i++) {
|
|
|
+ Image slice = slices.get(i);
|
|
|
+ if (top > slice.top && top < (slice.top + slice.data.getHeight())) {
|
|
|
+ index = i + 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (index > 0) {
|
|
|
+ Coordinate c = sliceConfig.get(index - 1);
|
|
|
+ Image slice = slices.get(index - 1);
|
|
|
+
|
|
|
+ Track t = new Track();
|
|
|
+ t.index = c.index;
|
|
|
+ t.content = tag.content;
|
|
|
+ t.left = c.left + left;
|
|
|
+ t.top = c.top + (top - slice.top);
|
|
|
+ result.add(t);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static List<Coordinate> findSliceConfig(Student s) {
|
|
|
+ String key = String.valueOf(s.examId);
|
|
|
+ return sliceConfigMap.computeIfAbsent(
|
|
|
+ key,
|
|
|
+ code -> {
|
|
|
+ String config = p.getProperty("slice.config");
|
|
|
+ if (StringUtils.isBlank(config)) {
|
|
|
+ config = template.queryForObject("select slice_config from eb_exam where id=" + s.examId,
|
|
|
+ String.class);
|
|
|
+ }
|
|
|
+ return Coordinate.build(config);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private static List<Image> buildImage(String path, Student s, int count) throws IOException {
|
|
|
+ List<Image> list = new ArrayList<>(count);
|
|
|
+ for (int i = 1; i <= count; i++) {
|
|
|
+ File file = new File(new File(new File(path, s.examId + "-" + s.campusId), s.subjectCode), s.examNumber
|
|
|
+ + "-" + i + ".jpg");
|
|
|
+ Image image = new Image();
|
|
|
+ image.file = file;
|
|
|
+ image.data = ImageIO.read(file);
|
|
|
+ list.add(image);
|
|
|
+ }
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static List<Tag> buildGroupTag(Student s, int groupNumber, List<Question> questions) {
|
|
|
+ double totalScore = 0d;
|
|
|
+ for (int i = 0; i < questions.size(); i++) {
|
|
|
+ if (questions.get(i).groupNumber == groupNumber && s.scoreList.size() > i) {
|
|
|
+ totalScore += s.scoreList.get(i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return findTags(findLibrary(s, groupNumber, totalScore));
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Library findLibrary(Student s, int groupNumber, double totalScore) {
|
|
|
+ SqlRowSet rs = template.queryForRowSet(
|
|
|
+ "select id,marker_score from m_library where student_id=? and group_number=?", s.id, groupNumber);
|
|
|
+ while (rs.next()) {
|
|
|
+ double score = rs.getDouble("marker_score");
|
|
|
+ if (score == totalScore) {
|
|
|
+ Library library = new Library();
|
|
|
+ library.id = rs.getInt("id");
|
|
|
+ library.markerScore = score;
|
|
|
+ return library;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static List<Tag> findTags(Library library) {
|
|
|
+ List<Tag> tags = new ArrayList<>();
|
|
|
+ if (library != null) {
|
|
|
+ SqlRowSet trs = template.queryForRowSet(
|
|
|
+ "select score, position_x, position_y from m_track where library_id=?", library.id);
|
|
|
+ while (trs.next()) {
|
|
|
+ Tag t = new Tag();
|
|
|
+ t.content = format.format(trs.getDouble("score"));
|
|
|
+ t.left = trs.getDouble("position_x");
|
|
|
+ t.top = trs.getDouble("position_y");
|
|
|
+ tags.add(t);
|
|
|
+ }
|
|
|
+ SqlRowSet srs = template.queryForRowSet(
|
|
|
+ "select tag_name, position_x, position_y from m_special_tag where library_id=?", library.id);
|
|
|
+ while (srs.next()) {
|
|
|
+ Tag t = new Tag();
|
|
|
+ t.content = srs.getString("tag_name");
|
|
|
+ t.left = srs.getDouble("position_x");
|
|
|
+ t.top = srs.getDouble("position_y");
|
|
|
+ tags.add(t);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return tags;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void buildGroupQuestion(int examId, String subjectCode, List<Integer> groups,
|
|
|
+ List<Question> questions) {
|
|
|
+ Set<Integer> set = new HashSet<>();
|
|
|
+ SqlRowSet rs = template.queryForRowSet(
|
|
|
+ "select group_number,main_number,sub_number,total_score from eb_exam_question "
|
|
|
+ + "where exam_id=? and subject_code=? and is_objective=0 order by main_number, sub_number",
|
|
|
+ examId, subjectCode);
|
|
|
+ while (rs.next()) {
|
|
|
+ Question q = new Question();
|
|
|
+ q.groupNumber = rs.getInt("group_number");
|
|
|
+ q.mainNumber = rs.getInt("main_number");
|
|
|
+ q.subNumber = rs.getInt("sub_number");
|
|
|
+ q.totalScore = rs.getDouble("total_score");
|
|
|
+ questions.add(q);
|
|
|
+ set.add(q.groupNumber);
|
|
|
+ }
|
|
|
+ groups.addAll(set);
|
|
|
+ groups.sort(Comparator.comparingInt(c -> c));
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Set<String> findSubjectCode(int examId) {
|
|
|
+ String config = p.getProperty("subjects");
|
|
|
+ Set<String> subjects = new HashSet<>();
|
|
|
+ if (StringUtils.isBlank(config)) {
|
|
|
+ SqlRowSet rs = template.queryForRowSet("select exam_id,code from eb_exam_subject where exam_id=?", examId);
|
|
|
+ while (rs.next()) {
|
|
|
+ subjects.add(rs.getString("code"));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Collections.addAll(subjects, p.getProperty("subjects").split(","));
|
|
|
+ }
|
|
|
+ return subjects;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void init(InputStream ins) throws IOException {
|
|
|
+ p.load(ins);
|
|
|
+
|
|
|
+ BasicDataSource ds = new BasicDataSource();
|
|
|
+ ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
|
|
|
+ ds.setUrl(p.getProperty("mysql.url"));
|
|
|
+ ds.setUsername(p.getProperty("mysql.username"));
|
|
|
+ ds.setPassword(p.getProperty("mysql.password"));
|
|
|
+
|
|
|
+ Student.format = format;
|
|
|
+
|
|
|
+ template = new JdbcTemplate(ds);
|
|
|
+ }
|
|
|
+}
|