eclipse,maven,jdbc
一:流程說明,
1、以word文檔形式的的試卷,格式要求第一行爲試卷名,以非word自動生成的數字爲題號 開頭,以題型或固定格式文字爲結尾,這裏使用'[單選題]'。上傳word,解析word文檔內容,詳細解析出試卷名,題號,問題,選項,題型等插入數據庫。注,同試卷不能重複錄入。
2、插入對應的答案和分值。
3、考試計分。
二:pom,有部分依賴沒有用到,可刪除
<dependencies>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.8.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-examples</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-excelant</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.41</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
一:word文檔錄入;
@Test
public void didposeTestFinal() {
ArrayList<Question> list = new ArrayList<>();
XWPFDocument doc = null;
try{
doc = new XWPFDocument(POIXMLDocument.openPackage("E:/test.docx"));
List<XWPFParagraph> paragraphs = doc.getParagraphs();
System.out.println(paragraphs.size());
/**
* 處理paragraphs
* 每個paragraphs是一行文本內容
*/
String rule = "^[\\d]{1,3}$"; //正則表達式,^表示起始,$表示結束
// String ruleA = "^[A-E]";
Pattern pTitle = Pattern.compile(rule);
//首先確定第一行爲試卷標題。title
for (int i = 1;i < paragraphs.size();i++) {
String text = paragraphs.get(i).getParagraphText().trim(); //獲取選中行的內容 去空格
//匹配題目,先整行一題
Matcher pTm = pTitle.matcher(text.substring(0, text.indexOf("、") == -1 ? 0 : text.indexOf("、"))); //正則匹配是否有題號
boolean matcher = pTm.find(); //注意,pTm.find()第一次使用時爲正常匹配,連續使用會無效,所以需要把這個提取出來
if(matcher && text.contains("[單選題]")){ //如果題號匹配上且以題型結尾,說明是一行的題
//單選,整行一題
Question q = new Question();
q.setTitle(paragraphs.get(0).getParagraphText()); //設置問題的試卷名,所有問題都是以第一行的試卷名
q.setNumber(Integer.parseInt(pTm.group(0))); //獲取匹配的項。
q.setQuestion(text); //設置問題內容
i = matchingAnswer(paragraphs, pTitle, i, q); //匹配答案
q.setQuestionType(QuestionType.SINGLE_SELECT); //設置題型,這裏使用了枚舉,不好用,可以直接使用String
q.setRightAnswer(null); //錄入的時候沒有正確答案和得分
q.setGetScore(null);
list.add(q); //加入list
}else if(matcher&&!text.contains("[單選題]")){
//多行一題,題號開頭。非題型結尾
i++; //先跳下一行
while(!paragraphs.get(i).getParagraphText().contains("[單選題]")){ //如果當前行不是以題型結尾
text = text + paragraphs.get(i).getParagraphText(); //題目內容拼接
i++; //跳轉下一行
}
text = text + paragraphs.get(i).getParagraphText(); //如果是以題型爲結尾,則跳出循環,拼接題目內容爲最終內容
Question q = new Question();
q.setTitle(paragraphs.get(0).getParagraphText());
q.setNumber(Integer.parseInt(pTm.group(0)));
q.setQuestion(text);
i = matchingAnswer(paragraphs, pTitle, i, q);
q.setQuestionType(QuestionType.SINGLE_SELECT);
q.setRightAnswer(null);
q.setGetScore(null);
list.add(q);
}else if(matcher && text.contains("[多選題]")){
//多選,整行一題
Question q = new Question();
q.setTitle(paragraphs.get(0).getParagraphText());
q.setNumber(Integer.parseInt(pTm.group(0)));
q.setQuestion(text);
i = matchingAnswer(paragraphs, pTitle, i, q);
q.setQuestionType(QuestionType.MULTI_SELECT);
q.setRightAnswer(null);
q.setGetScore(null);
list.add(q);
}else if(matcher && !text.contains("[多選題]")){
i++; //先跳下一行
while(!paragraphs.get(i).getParagraphText().contains("[多選題]")){ //如果當前行不是以題型結尾
text = text + paragraphs.get(i).getParagraphText(); //題目內容拼接
i++; //跳轉下一行
}
text = text + paragraphs.get(i).getParagraphText(); //如果是以題型爲結尾,則跳出循環,拼接題目內容爲最終內容
Question q = new Question();
q.setTitle(paragraphs.get(0).getParagraphText());
q.setNumber(Integer.parseInt(pTm.group(0)));
q.setQuestion(text);
i = matchingAnswer(paragraphs, pTitle, i, q);
q.setQuestionType(QuestionType.MULTI_SELECT);
q.setRightAnswer(null);
q.setGetScore(null);
list.add(q);
}
}
for(int i=0;i<list.size();i++){
System.out.println(list.get(i).toString());
}
if(list.size()<100){
System.out.println("試卷錄入異常,題數不足100");
System.exit(0);
// throw new Exception("試卷錄入異常,題數不足100");
}
Examination e = new Examination();
e.insertExamination(list);
}catch(Exception e){
e.printStackTrace();
}
}
private int matchingAnswer(List<XWPFParagraph> paragraphs, Pattern pTitle, int i, Question q) {
String text;
//匹配答案
while(true){ //多行答案處理!!!!!!!!!!
i++; //先加一行
text = paragraphs.get(i).getParagraphText().trim();
if( text != null && text != "" ){
//如果4個答案在一行,或者5個答案在一行
if(text.contains("A")&& text.contains("B")&&text.contains("C")&&text.contains("D")){
q.setAnswerA(text.substring(0,text.indexOf("B")));
q.setAnswerB(text.substring(text.indexOf("B"),text.indexOf("C")));
q.setAnswerC(text.substring(text.indexOf("C"),text.indexOf("D")));
if(text.contains("E")){
q.setAnswerD(text.substring(text.indexOf("D"),text.indexOf("E")));
q.setAnswerE(text.substring(text.indexOf("E")));
}else{
q.setAnswerD(text.substring(text.indexOf("D")));
}
break;
}
if( text.startsWith("A") ){
while(!paragraphs.get(i+1).getParagraphText().trim().startsWith("B")){
i++;
text = text + paragraphs.get(i).getParagraphText();
}
q.setAnswerA(text);
}else if( text.startsWith("B") ){
while(!paragraphs.get(i+1).getParagraphText().trim().startsWith("C")){
i++;
text = text + paragraphs.get(i).getParagraphText();
}
q.setAnswerB(text);
}else if( text.startsWith("C") ){
while(!paragraphs.get(i+1).getParagraphText().trim().startsWith("D")){
i++;
text = text + paragraphs.get(i).getParagraphText();
}
q.setAnswerC(text);
}else if( text.startsWith("D") ){
if(paragraphs.size() == i+1){ //防止已經到最後一行了,防止索引越界
q.setAnswerD(text);
break;
}
String textD = paragraphs.get(i+1).getParagraphText().trim();
System.out.println(textD);
System.out.println(pTitle.matcher(textD.substring(0, textD.indexOf("、") == -1 ? 0 : textD.indexOf("、"))).find());
while( textD != null && //如果選項中有4項時,這一行有內容,且不是題號開頭,
!pTitle.matcher(textD.substring(0, textD.indexOf("、") == -1 ? 0 : textD.indexOf("、"))).find()
&& !textD.equals("")){
if( textD.startsWith("E")){ //如果是E開頭,說明有答案E,
q.setAnswerD(text);
break;
}
i++;
text = text + paragraphs.get(i).getParagraphText();
}
q.setAnswerD(text);
break;
}else if( text.startsWith("E")){
if(paragraphs.size() == i+1){
q.setAnswerD(text);
break;
}
String textE = paragraphs.get(i+1).getParagraphText().trim();
System.out.println(pTitle.matcher(textE.substring(0, textE.indexOf("、") == -1 ? 0 : textE.indexOf("、"))).find());
while( textE != null &&
!pTitle.matcher(textE.substring(0, textE.indexOf("、") == -1 ? 0 : textE.indexOf("、"))).find() && !textE.equals("")){
i++;
text = text + paragraphs.get(i).getParagraphText();
}
q.setAnswerE(text);
break;
}
}
}
return i;
}
jdbc----------------
public Boolean insertExamination(List<Question> list) throws SQLException, ClassNotFoundException{
Class.forName("com.mysql.jdbc.Driver");
java.sql.Connection conn = DriverManager.getConnection(
"jdbc:mysql://***************************?characterEncoding=UTF-8","root","123456");
java.sql.PreparedStatement ps = conn.prepareStatement("insert into yucs_exam "
+ "(title,number,answerA,answerB,answerC,answerD,answerE,questionType,rightAnswer,getScore,question)"
+ " values (?,?,?,?,?,?,?,?,?,?,?)");
for(int i =0; i<list.size(); i++){
Question question = list.get(i);
ps.setString(1, question.getTitle() ==null ? "":question.getTitle());
ps.setInt(2, question.getNumber()==null?0:question.getNumber());
ps.setString(3, question.getAnswerA()==null?"":question.getAnswerA());
ps.setString(4, question.getAnswerB()==null?"":question.getAnswerB());
ps.setString(5, question.getAnswerC()==null?"":question.getAnswerC());
ps.setString(6, question.getAnswerD()==null?"":question.getAnswerD());
ps.setString(7, question.getAnswerE()==null?"":question.getAnswerE());
ps.setString(8, question.getQuestionType()==null ? QuestionType.SINGLE_SELECT +"":question.getQuestionType()+"");
ps.setString(9, question.getRightAnswer()==null?"":question.getRightAnswer());
ps.setInt(10, question.getGetScore()==null?0:question.getGetScore());
ps.setString(11, question.getQuestion());
ps.addBatch();
}
ps.executeBatch();
conn.close();
return false;
}
二:答案及分值錄入,使用測試手段
@Test
public void insertAnswer() throws Exception{
String[] ss = {"A","B","C","D"};
Random r = new Random();
ArrayList<Question> list = new ArrayList<>();
for(int i = 1 ; i<=100;i++){
int nextInt = r.nextInt(4);
Question q = new Question();
q.setRightAnswer(ss[nextInt]);
q.setGetScore(1);
q.setTitle("test");
q.setNumber(i);
list.add(q);
}
Examination e = new Examination();
e.insertAnswerAndScore(list);
}
jdbc--------------
public Boolean insertAnswerAndScore(List<Question> list) throws Exception{
Class.forName("com.mysql.jdbc.Driver");
java.sql.Connection conn = DriverManager.getConnection(
"jdbc:mysql://****************************?characterEncoding=UTF-8","root","123456");
java.sql.PreparedStatement ps = conn.prepareStatement("update yucs_exam set rightAnswer=?,getScore=? where title =? and number=?");
for(int i =0; i<list.size(); i++){
Question question = list.get(i);
ps.setString(1, question.getRightAnswer()==null?"":question.getRightAnswer());
ps.setInt(2, question.getGetScore()==null?0:question.getGetScore());
ps.setString(3, question.getTitle());
ps.setInt(4, question.getNumber());
ps.addBatch();
}
ps.executeBatch();
conn.close();
return true;
}
三:計分
/**
* 打分系統
* 獲取考生答題項:包括試卷title或編號、考生id、答題答案
*
* 1,匹配數據庫,獲取表中當前卷的正確答案
* 1、單選,直接匹配
* 2、多選,----------
* @throws Exception
*/
@Test
public void checkAnswer() throws Exception{
Examination e = new Examination();
Map<Integer,Question> m = e.checkAnswer();
String[] ss = {"A","B","C","D"};
Random r = new Random();
ArrayList<Question> list = new ArrayList<>();
for(int i = 1 ; i<=100;i++){
int nextInt = r.nextInt(4);
Question q = new Question();
q.setRightAnswer(ss[nextInt]);
q.setTitle("testOne");
q.setNumber(i);
list.add(q);
}
int totalScore = 0;
for(int j =0; j<list.size();j++){
String rightAnswer = m.get(j+1).getRightAnswer();
String rightAnswer2 = list.get(j).getRightAnswer();
if(m.get(j+1).getQuestionType().equals(QuestionType.SINGLE_SELECT)){
//單選
if(rightAnswer.equals(rightAnswer2)){
totalScore += m.get(j).getGetScore(); //如果答案匹配正確,得分
}
}else if(m.get(j+1).getQuestionType().equals(QuestionType.MULTI_SELECT)){
//多選
m.get(j+1).getRightAnswer();
String[] answers = rightAnswer.split(","); //截取答案
String[] answers2 = rightAnswer2.split(",");
if(Arrays.equals(answers, answers2)){ //如果答案完全匹配,得全分
totalScore += m.get(j).getGetScore();
}else { //否則說明答案不完全正確,需要詳細匹配。
for(int i=0; i<answers2.length;i++){
if(!Arrays.asList(answers).contains(answers2[i])){ //否則,具體匹配,如果有一個選項不在正確答案選項中,則不得分,整題不正確
continue; //跳過當前題的
}
}
totalScore += (m.get(j).getGetScore()/2); //如果選項沒有錯誤的,說明答案不完全,給一半分。
}
}
}
System.out.println(totalScore);
}
jdbc---------------
public Map<Integer,Question> checkAnswer() throws Exception{
Class.forName("com.mysql.jdbc.Driver");
java.sql.Connection conn = DriverManager.getConnection(
"jdbc:mysql://**********************************?characterEncoding=UTF-8","root","123456");
java.sql.PreparedStatement ps = conn.prepareStatement("select rightAnswer,number,questionType,getScore from yucs_exam "
+ "where title=?");
ps.setString(1, "test");
ResultSet executeQuery = ps.executeQuery();
Map<Integer, Question> m = new HashMap<>();
while(executeQuery.next()){
Question q = new Question();
q.setRightAnswer(executeQuery.getString(1));
int int1 = executeQuery.getInt(2);
q.setNumber(int1); //以題號做map,方便匹配
q.setQuestionType(QuestionType.SINGLE_SELECT);
q.setGetScore(executeQuery.getInt(4));
m.put(int1, q);
}
System.out.println(m.size());
conn.close();
return m;
}