结对项目

温吞:

结对项目

这个作业属于哪个课程 软件工程4班
这个给作业要求在哪里 结对项目
这个作业的目标 实现一个自动生成小学四则运算题目的命令行程序

合作人员

学号 姓名
3122004557 蔡昱鹏
3122004567 韩逸朗

Github链接

结对项目

PSS表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 10 15
Estimate 估计这个任务要多少时间 5 5
Development 开发 200 300
Analysis 需求分析(包括学习新技术) 200 200
Design Spec 生成设计文档 10 20
Design Review 设计复审 10 20
Coding Standard 代码规范 20 20
Design 具体设计 30 30
Coding 具体编码 300 350
Code Review 代码复审 30 30
Test 测试 50 50
Reporting 报告 60 60
Test Repor 测试报告 60 60
Size Measurement 计算工作量 10 10
Postmortem & Process Improvement Plan 事后总结 改进计划 30 30
All 总计 1025 1200

效能分析


设计实现过程

一、函数部分

generate_expression(r)生成表达式
generate_exercises(exercises, answers, n, r)生成表达式以及答案列表
save_exercises_and_answers(exercises, answers, script_dir)保存表达式以及答案到文件中
is_valid(expression)表达式的合法性判断
grade_answers(exercise_file, answer_file)比对答案正确性
save_grade(correct_answers, wrong_answers, script_dir)保存得分文件

二、命令行参数解析

使用 argparse 解析命令行参数,包括生成题目数量 -n、数值范围 -r、题目文件路径 -e 和答案文件路径 -a。

三、主程序逻辑:

根据命令行参数判断是否提供了题目文件和答案文件,若提供了则执行评分逻辑,否则执行生成题目和答案的逻辑。

四、文件操作:

使用文件读写操作来保存题目、答案和评分结果。

五、异常处理:

在生成题目时进行合法性检查,避免出现负数或除零错误。
注:本次没有使用类,而是采用了函数式编程的方式来组织逻辑。不同函数之间通过参数传递数据,实现了不同功能的模块化。

代码说明

生成题目

def generate_expression(r):
# 由于运算符数量不定,需要特殊处理
num_operators = random.randint(1, 3)
num_operand = num_operators + 1

operators = ['+', '-', '*', '/']
operands = [random.randint(0, r) for _ in range(num_operand)]

select_operator = random.sample(operators, num_operators)

expression = ""  # 初始化一个空表达式
expression += str(operands[0]) + " "

for i in range(num_operators):
    expression += str(select_operator[i]) + " " + str(operands[i + 1]) + " "

return expression

生成题目以及答案列表

def generate_exercises(exercises, answers, n, r):
while len(exercises) < n:
    expression = generate_expression(r)
    if is_valid(expression):
        exercises.append(expression)
        answer = eval(expression)
        fraction = Fraction(answer).limit_denominator()  # 将答案转换为真分数
        whole_part = fraction.numerator // fraction.denominator  # 获取整数部分
        numerator = abs(fraction.numerator) % fraction.denominator  # 获取真分数的分子(取绝对值)
        denominator = fraction.denominator  # 获取真分数的分母
        if numerator == 0:  # 如果分子为0
            if whole_part == 0:  # 如果整数部分也为0
                answers.append("0")  # 答案为0
            else:  # 如果整数部分不为0
                answers.append(f"{whole_part}")  # 只输出整数部分
        else:  # 如果分子不为0
            if whole_part == 0:  # 如果整数部分为0
                answers.append(f"{numerator}/{denominator}")  # 答案直接为真分数
            else:  # 如果整数部分不为0
                answers.append(f"{whole_part}'{numerator}/{denominator}")

保存题目和答案到文件中

def save_exercises_and_answers(exercises, answers, script_dir):
exercise_file = os.path.join(script_dir, "exercises.txt")
answer_file = os.path.join(script_dir, "answers.txt")

with open(exercise_file, "w") as exercises_file:
    for i, exercise in enumerate(exercises, start=1):
        exercises_file.write(f"{i}. {exercise}\n")

with open(answer_file, "w") as answers_file:
    for i, answer in enumerate(answers, start=1):
        answers_file.write(f"{i}. {answer}\n")

合法性判断

def is_valid(expression):
	try:
		if eval(expression) < 0:
			return False
	except ZeroDivisionError:
		return False
	return True

正确率计数

def grade_answers(exercise_file, answer_file):
	exercises = load_file(exercise_file)
	answers = load_file(answer_file)
	correct_answers = []
	wrong_answers = []
for i in range(len(answers)):
		if exercises[i].strip() == answers[i].strip():
			wrong_answers.append(i + 1)
		else:
			correct_answers.append(i + 1)
	return correct_answers, wrong_answers

计数保存到文件中

def save_grade(correct_answers, wrong_answers, script_dir):
total_correct = len(correct_answers)
total_wrong = len(wrong_answers)

grade_file_path = os.path.join(script_dir, "grade.txt")

with open(grade_file_path, "w") as grade_file:
    grade_file.write(f"Correct: {total_correct}\n")

    if total_correct > 0:
        grade_file.write("(")
        for idx, correct in enumerate(correct_answers, start=1):
            grade_file.write(f"{correct},")
        grade_file.write(")\n")

    grade_file.write(f"Wrong: {total_wrong}\n")

    if total_wrong > 0:
        grade_file.write("(")
        for idx, wrong in enumerate(wrong_answers, start=1):
            grade_file.write(f"{wrong},")
        grade_file.write(")\n")

主函数调用parser模块部分

if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('-n', type=int, help='Number of exercises to generate', default=10)
parser.add_argument('-r', type=int, help='Range of numbers in exercises', default=10)
parser.add_argument('-e', '--exercisefile', type=str, help='Exercise file path')
parser.add_argument('-a', '--answerfile', type=str, help='Answer file path')
args = parser.parse_args()

script_dir = os.path.dirname(os.path.realpath(__file__))

exercises = []
answers = []

if args.exercisefile and args.answerfile:
    correct_answers, wrong_answers = grade_answers(args.exercisefile, args.answerfile)
    save_grade(correct_answers, wrong_answers, script_dir)
else:
    generate_exercises(exercises, answers, args.n, args.r)
    save_exercises_and_answers(exercises, answers, script_dir)

测试运行




项目小结

在本次项目中,两人合作共同完成了一个关于小学四则运算的生成项目,因为是与舍友合作,所以在项目的进展中合作较为顺利,遇到难题可以共同即使讨论出解决方法。也积累了很多的经验,相信在下次合作中可以更加顺利合作。

posted @ 2024-03-26 13:56  千夫所指里、  阅读(25)  评论(0编辑  收藏  举报