结对对对项目

结对对对项目

这个作业属于哪个课程 软件工程课程
这个作业要求在哪里 个人项目 - 作业 - 计科22级34班 - 班级博客 - 博客园 (cnblogs.com)
这个作业的目标 按照要求写一个四则运算生成器
成员一 3122004883许億驰
成员二 3122004515陈恺麟

任务列表

  Correct: 5 (1, 3, 5, 7, 9)
  Wrong: 5 (2, 4, 6, 8, 10)

作业正文

作业仓库地址

效能分析

性能分析中,代码执行时间最长的是

function generateQuestions() {
    const numQuestions = parseInt(document.getElementById('numQuestions').value, 10);


    questions = [];
    answers = [];
    const questionsDiv = document.getElementById('questions');
    questionsDiv.innerHTML = '';


    for (let i = 0; i < numQuestions; i++) {
      let question, answer;

      // 随机选择是否包含括号
      const hasBrackets = Math.random() > 0.5;

      if (hasBrackets) {
        question = generateExpressionWithBrackets();
      } else {
        question = generateSimpleExpression();
      }

      questions.push(question);

      // 计算答案
      answer = calculateAnswer(question);
      answers.push(answer);



      const questionElement = document.createElement('p');
      questionElement.innerText = `${i + 1}. ${question} =`;
      questionsDiv.appendChild(questionElement);
    }
  }

设计思路

设计思路是通过一个前端网页来生成、下载、上传和校验小学四则运算题目。以下是对你设计思路的详细解释:

  • 用户界面:
    创建一个包含输入框和按钮的网页界面,用户可以通过输入框设置生成题目的数量和数值范围。
    提供文件上传功能,用户可以上传包含答案和题目的文本文件。
    提供按钮用于生成题目、下载题目和答案、以及计算正确率。

  • 生成题目:
    用户输入生成题目的数量和数值范围。
    程序根据用户输入生成指定数量的四则运算题目,并显示在页面上。
    生成的题目可能包含括号和带分数。

  • 下载题目和答案:
    用户可以点击按钮下载生成的题目和答案,分别保存为 questions.txt 和 answers.txt 文件。
    上传答案和题目文件:
    用户可以上传包含答案和题目的文本文件。
    程序解析上传的文件,提取题目和答案,并显示在页面上。
    计算正确率:
    用户上传答案文件后,程序可以计算上传答案的正确率。
    程序将正确率和正确/错误的题目编号输出到 grade.txt 文件中。

  • 具体实现步骤
    生成题目:
    使用 generateQuestions 函数生成题目,根据用户输入的数量和数值范围生成题目。
    使用 generateSimpleExpression 和 generateExpressionWithBrackets 函数生成简单的和带括号的表达式。
    使用 generateNumber 函数生成自然数或带分数。
    计算答案:
    使用 calculateAnswer 函数计算表达式的答案。
    使用 convertToMathExpression 函数将带分数转换为浮点数以便计算。
    下载题目和答案:
    使用 downloadQuestions 和 downloadAnswers 函数将生成的题目和答案下载为文本文件。
    上传答案和题目文件:
    使用 parseAnswersFile 和 parseQuestionsFile 函数解析上传的答案和题目文件。
    提取文件内容并显示在页面上。
    计算正确率:
    使用 calculateAccuracy 函数计算上传答案的正确率。
    将正确率和正确/错误的题目编号输出到 grade.txt 文件中。
    代码结构
    HTML部分:
    包含输入框和按钮,用于设置生成题目的数量和数值范围,以及上传和下载文件。
    包含一个显示题目的容器。
    JavaScript部分:
    包含生成题目、计算答案、下载文件、上传文件和计算正确率的函数。
    使用 document.getElementById 获取页面元素,使用 FileReader 读取上传的文件。

代码说明

let questions = [];
  let answers = [];
  let userAnswers = [];
  function generateQuestions() {
    const numQuestions = parseInt(document.getElementById('numQuestions').value, 10);


    questions = [];
    answers = [];
    const questionsDiv = document.getElementById('questions');
    questionsDiv.innerHTML = '';


    for (let i = 0; i < numQuestions; i++) {
      let question, answer;

      // 随机选择是否包含括号
      const hasBrackets = Math.random() > 0.5;

      if (hasBrackets) {
        question = generateExpressionWithBrackets();
      } else {
        question = generateSimpleExpression();
      }

      questions.push(question);

      // 计算答案
      answer = calculateAnswer(question);
      answers.push(answer);



      const questionElement = document.createElement('p');
      questionElement.innerText = `${i + 1}. ${question} =`;
      questionsDiv.appendChild(questionElement);
    }
  }

  function generateSimpleExpression() {
    const num1 = generateNumber();
    const num2 = generateNumber();
    const operator = ['+', '-', '*', '/'][Math.floor(Math.random() * 4)];
    return `${num1} ${operator} ${num2}`;
  }

  function generateExpressionWithBrackets() {
    const num1 = generateNumber();
    const num2 = generateNumber();
    const num3 = generateNumber();
    const operator1 = ['+', '-', '*', '/'][Math.floor(Math.random() * 4)];
    const operator2 = ['+', '-', '*', '/'][Math.floor(Math.random() * 4)];
    return `(${num1} ${operator1} ${num2}) ${operator2} ${num3}`;
  }

  function generateNumber() {

    const numSetUp = parseInt(document.getElementById('numSetUp').value, 10);

    const isFraction = Math.random() > 0.5;
    if (isFraction) {
      const numerator = Math.floor(Math.random() * 10) + 1;
      const denominator = Math.floor(Math.random() * 10) + 1;
      return convertToMixedNumber(`${numerator}/${denominator}`);
    } else {
      return Math.floor(Math.random() * numSetUp).toString();
    }
  }

  function convertToMixedNumber(fraction) {
    const [numerator, denominator] = fraction.split('/').map(Number);
    const integerPart = Math.floor(numerator / denominator);
    const remainder = numerator % denominator;

    if (integerPart === 0) {
      return fraction;
    }else if (remainder ===0){
      return integerPart;
    } else {
      return `${integerPart}'${remainder}/${denominator}`;
    }
  }

  function calculateAnswer(expression) {
    // 使用 eval 计算表达式,注意 eval 的安全性问题
    try {
      return eval(convertToMathExpression(expression));
    } catch (e) {
      return 'Error';
    }
  }

  function convertToMathExpression(expression) {
    // 将带分数转换为浮点数
    return expression.replace(/(\d+)'(\d+)\/(\d+)/g, (match, p1, p2, p3) => parseFloat(p1) + parseFloat(p2) / parseFloat(p3));
  }

  function downloadQuestions() {
    if (questions.length === 0) {
      alert('请先生成题目!');
      return;
    }

    const questionsText = questions.map((q, i) => `${i + 1}. ${q}`).join('\n');
    const allText = `题目:\n${questionsText}\n`;

    const blob = new Blob([allText], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'questions.txt';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  }

  function downloadAnswers() {
    if (answers.length === 0) {
      alert('请先生成题目!');
      return;
    }

    const answersText = answers.map((a, i) => `${i + 1}. ${a}`).join('\n');
    const allText = `答案:\n${answersText}\n`;

    const blob = new Blob([allText], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'answers.txt';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  }


  function parseAnswersFile(file) {

    userAnswers = [];

    const reader = new FileReader();
    reader.onload = function(event) {
      const content = event.target.result;
      const lines = content.split('\n').map(line => line.trim()).filter(line => line);
      const answersText = lines.join('\n');
      userAnswers = answersText.replace(/^答案:\n/, '').split('\n').map(line => line.trim().split('. ')[1]).filter(line => line);

    };
    reader.readAsText(file);
  }

  function parseQuestionsFile(file) {

    questions = [];

    const reader = new FileReader();
    reader.onload = function(event) {
      const content = event.target.result;
      const lines = content.split('\n').map(line => line.trim()).filter(line => line);
      const answersText = lines.join('\n');
      questions = answersText.replace(/^题目:\n/, '').split('\n').map(line => line.trim().split('. ')[1]).filter(line => line);


      const questionsDiv = document.getElementById('questions');
      questionsDiv.innerHTML = '';

      // 显示题目
      questions.forEach((question) => {
        const questionElement = document.createElement('p');
        questionElement.innerText = `${question}=`;
        questionsDiv.appendChild(questionElement);
      });

      // 计算答案
      questions.forEach((question) => {
        const answer = calculateAnswer(question);
        answers.push(answer);
      });
    };
    reader.readAsText(file);
  }

  function calculateAccuracy(userAnswers) {

    let rightGrade = [];
    let wrongGrade = [];

    if (userAnswers.length === 0) {
      alert('请先上传答案文件!');
      return;
    }
    if (answers.length === 0) {
      alert('请先生成题目!');
      return;
    }
    let correctCount = 0;
    for (let i = 0; i < answers.length; i++) {
      if (parseFloat(userAnswers[i]) === answers[i]) {
        rightGrade.push(i + 1);
        correctCount++;
      }else {
        wrongGrade.push(i + 1);
      }
    }
    const accuracy = (correctCount / answers.length) * 100;
    alert(`正确率: ${accuracy.toFixed(2)}%`);


    grade = `正确题目:${rightGrade.join(', ')}\n错误题目:${wrongGrade.join(', ')}\n正确率: ${accuracy.toFixed(2)}%\n`;

    const blob = new Blob([grade], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'grade.txt';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  }

测试运行

运行效果

PSP表格如下

2.在PSP表格[附录2]记录下你估计在程序开发各个步骤上耗费的时间

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 60 70
· Estimate · 估计这个任务需要多少时间 30 35
Development 开发 240 260
· Analysis · 需求分析(包括学习新技术) 45 50
· Design Spec · 生成设计文档 40 45
· Design Review · 设计复审 30 35
· Coding Standard · 代码规范(为目前的开发制定合适的规范) 20 25
· Design · 具体设计 50 55
· Coding · 具体编码 100 110
· Code Review · 代码复审 25 30
· Test · 测试(自我测试,修改代码,提交修改) 30 40
Reporting 报告 60 65
· Test Report · 测试报告 20 25
· Size Measurement · 计算工作量 20 20
· Postmortem & Process Improvement Plan · 事后总结,并提出过程改进计划 20 30
合计 360 400

项目小结

  • 在本次结对编程项目中,我们共同开发了一个小学四则运算生成器。该程序能够生成指定数量和数值范围的四则运算题目,支持带分数和括号的表达式,并能够下载题目和答案文件,上传答案文件进行校验,计算正确率。

  • 结对编程能够提高代码质量,减少错误。两个人可以互相监督,及时发现和解决问题。

  • 结对编程能够提高开发效率,两个人可以分工合作,共同完成任务。

posted @ 2024-09-17 23:15  iamright  阅读(137)  评论(0编辑  收藏  举报