Welcome to Yumao′s Blog.
T-ELTS Project Day03
, 2012年03月26日 , Java Language , 评论 在〈T-ELTS Project Day03〉中留言功能已關閉 ,

T-ELTS Project Day03

====================
1. 三層架構, 整體架構
2. 開始考試功能實現
3. 上/下一題功能實現 和 交卷
4 查看考分功能實現
5 關閉窗口 問題 與窗口事件監聽

1. 三層架構, 整體架構

 1) 表現層(數據呈現/用戶交互)
   在ui包中 的 "用戶界面"和"控制器(ClientContext)"
  如: 接受登錄請求

 2) 業務層(業務模型), 是軟件的核心功能
  在service包中, 核心接口ExamService
  如: 登錄系統

 3) 數據管理層(數據持久化層), 是提供數據的CRUD管理,增刪改查
  C: 創建, R: 尋回, 查找, U:更新, D:刪除.
  數據管理層: 只關心數據操作, 不涉及業務功能
  如: 查找用戶
  在entity包中, 核心類: EntityContext, 管理User 和
  Question

2. 開始考試功能實現
 1) 視圖 MenuFrame 中增加事件監聽
  private ClientContext clientContext;
  public void setClientContext(ClientContext clientContext) {
    this.clientContext = clientContext;
  }
  //...增加事件監聽
    start.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e) {
        clientContext.start();
      }
    });
  更新ExamFrame, 增加: updateView()
  private JLabel info;//引用到界面控件實例
  private JLabel questionCount;//引用到界面控件實例
  private JTextArea question;//引用到界面控件實例
  public void updateView(
      ExamInfo examInfo, QuestionInfo questionInfo){
    info.setText(examInfo.toString());
    //"題目:20 的 1題"
    questionCount.setText("題目:"+
        examInfo.getQuestionCount()+" 的 "+
        (questionInfo.getQuestionIndex()+1)+"題");
    question.setText(questionInfo.toString());
  }


 2) 控制器, 增加事件響應方法start()
  /** 開始考試 */
  public void start(){
    try {
      //考試信息
      ExamInfo examInfo = examService.startExam();
      //第一道考題
      QuestionInfo questionInfo =
        examService.getQuestion(0);
      examFrame.updateView(examInfo, questionInfo);
      menuFrame.setVisible(false);
      examFrame.setVisible(true);
    } catch (Exception e) {
      e.printStackTrace();
      JOptionPane.showMessageDialog(
          menuFrame, e.getMessage());
    }
  }


 3) 業務層: 增加: startExam() getQuestion()
 開始考試業務描述: 開始考試時候, 抽取考卷試題, 每個level抽取2題
 返回考試描述信息:ExamInfo
 考卷是: 有抽取的題目組成的線性表集合
 獲取試題: 根據題目序號獲取指定試題

  private List paper =
    new ArrayList();

  public QuestionInfo getQuestion(int index) {
    return paper.get(index);
  }

  private User loginUser;

  private void createPaper(){
    Random r = new Random();
    int idx = 0;
    for(int i=Question.LEVEL1; i<=Question.LEVEL10; i++){
      List list =
        entityContext.findQuestions(i);
      //抽出2道題
      Question q1 = list.remove(r.nextInt(list.size()));
      Question q2 = list.remove(r.nextInt(list.size()));
      paper.add(new QuestionInfo(idx++, q1));
      paper.add(new QuestionInfo(idx++, q2));
    }
  }

  public ExamInfo startExam() {
    createPaper();
    ExamInfo info = new ExamInfo();
    //初始化info ...
    info.setQuestionCount(paper.size());
    info.setTimeLimit(entityContext.getTimeLimit());
    info.setTitle(entityContext.getTitle());
    info.setUser(loginUser);
    return info;
  }

 4) 持久層
  public int getTimeLimit() {
    return config.getInt("TimeLimit");
  }

  public String getTitle() {
    return config.getString("PaperTitle");
  }

 5) 更新Main.class
     menuFrame.setClientContext(clientContext);
3. 上/下一題功能實現 和 交卷

 1) 視圖 (增加界面事件監聽)
  A 增加對控制器的引用
  private ClientContext clientContext;
  public void setClientContext(ClientContext clientContext) {
    this.clientContext = clientContext;
  }
  B 增加界面事件監聽
    prev.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e) {
        clientContext.prev();
      }
    });
    next.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e) {
        clientContext.next();
      }
    });
    send.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e) {
        clientContext.send();
      }
    });

  C 更新視圖為下/上一題(更新 用戶的答案)
  private JLabel info;
  private JLabel questionCount;
  private JTextArea question;
  public void updateView(
      ExamInfo examInfo, QuestionInfo questionInfo){
    info.setText(examInfo.toString());
    //"題目:20 的 1題"
    questionCount.setText("題目:"+
        examInfo.getQuestionCount()+" 的 "+
        (questionInfo.getQuestionIndex()+1)+"題");
    question.setText(questionInfo.toString());
    updateOptions(questionInfo.getUserAnswers());
  }

  private void updateOptions(List userAnswers) {
    for (Option o : options) {
      o.setSelected(false);
      if(userAnswers.contains(o.val)){
        o.setSelected(true);
      }
    }
  }
  public List getUserAnswers() {
    List ans = new ArrayList();
    for (Option o : options) {
      if(o.isSelected()){
        ans.add(o.val);
      }
    }
    return ans;
  }

 2) 控制器(增加界面功能實現方法 next() prev(), send())
   /** 當前正在答對題目, 開始考試時候, 初始化為第一題
   * 每次翻頁, 更新為新的當前題目 */
  private QuestionInfo currentQuestion;
  /** 當前考試的狀態信息, 在開始考試時候初始化為 考試信息
   * 重構開始開始start()代碼!
   */
  private ExamInfo examInfo;
  public void next() {
    try {
      int idx = currentQuestion.getQuestionIndex();
      List userAnswers =
          examFrame.getUserAnswers();
      examService.saveUserAnswers(idx, userAnswers);
      currentQuestion = examService.getQuestion(idx+1);
      examFrame.updateView(examInfo, currentQuestion);
    } catch (Exception e) {
      e.printStackTrace();
      JOptionPane.showMessageDialog(
          examFrame, e.getMessage());
    }
  }
  public void prev() {
    try {
      int idx = currentQuestion.getQuestionIndex();
      List userAnswers =
          examFrame.getUserAnswers();
      examService.saveUserAnswers(idx, userAnswers);
      currentQuestion = examService.getQuestion(idx-1);
      examFrame.updateView(examInfo, currentQuestion);
    } catch (Exception e) {
      e.printStackTrace();
      JOptionPane.showMessageDialog(
          examFrame, e.getMessage());
    }
  }

  public void send() {

    try {
      int val = JOptionPane
        .showConfirmDialog(examFrame, "交嗎?");

      if(val != JOptionPane.YES_OPTION){
        return;
      }

      int idx = currentQuestion.getQuestionIndex();
      List userAnswers =
          examFrame.getUserAnswers();
      examService.saveUserAnswers(idx, userAnswers);

      int score = examService.examOver();
      JOptionPane.showMessageDialog(
          examFrame, "你的分數:"+score);
      examFrame.setVisible(false);
      menuFrame.setVisible(true);

    } catch (Exception e) {
      e.printStackTrace();
      JOptionPane.showMessageDialog(
          examFrame, e.getMessage());
    }

  }


 3) 業務層(保存用戶答案 saveUserAnswers())

  public void saveUserAnswers(int idx, List userAnswers) {
    //保存用戶答案到考卷中的考題上
    paper.get(idx).setUserAnswers(userAnswers);
  }
  private int score = 0;
  public int examOver() {
    //判分
    for (QuestionInfo qInfo : paper) {
      Question q = qInfo.getQuestion();
      if(qInfo.getUserAnswers().equals(q.getAnswer())){
        score+=q.getScore();
      }
    }
    return score;
  }

4 查看考分功能實現
 1) 界面
    result.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e) {
        clientContext.result();
      }
    });
 2) 控制器
  public void result() {
    try {
      int score = examService.getScore();
      JOptionPane.showMessageDialog(
          menuFrame, "考試分數:"+score);

    } catch (Exception e) {
      e.printStackTrace();
      JOptionPane.showMessageDialog(
          menuFrame, e.getMessage());
    }
  }

 3) 業務層
  public int getScore() {
    if(!finish)
      throw new RuntimeException("還沒有考試呀!");
    return score;
  }

5 關閉窗口 問題 與窗口事件監聽
 1) 設置默認的窗口關閉操作
    setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
 2) 綁定窗口關閉事件
    addWindowListener(new WindowAdapter(){
      public void windowClosing(WindowEvent e) {
         clientContext.send();
      }
    });
 

Download==>OnlineExamSystem

关键字:, , ,

评论已关闭