psp:
psp | 任务内容 | 计划完成需要的时间(min) | 实际完成需要的时间(min) |
---|---|---|---|
Planning | 计划 | 10 | 15 |
Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 6 | 6 |
Development | 开发 | 120 | 120 |
Analysis | 需求分析(包括学习新技术) | 10 | 10 |
Design Spec | 生成设计文档 | 20 | 20 |
Coding Standard | 代码规范 | 5 | 8 |
Design | 具体设计 | 15 | 22 |
Coding | 具体编码 | 40 | 35 |
Code Review | 代码复审 | 5 | 4 |
Test | 测试(自我测试,修改代码,提交修改) | 20 | 15 |
Reporting | 报告 | 10 | 10 |
Test Report | 测试报告 | 2 | 3 |
代码:
sizeyusuan代码:
import wx
from wx.core import CLEAR
from formula import OPT, GeneralFormular, ComputeFormular
class MyApp(wx.App):
def OnInit(self):
frame = wx.Frame(parent=None, title="四则运算生成器") # 新建框架
panel = wx.Panel(frame, -1) # 生成面板
Text = wx.StaticText(panel,-1,"请输入相关需求",pos=(150,2))
label1=wx.StaticText(panel,-1,"生成算式数量(>=1)",pos=(10,30)) #标签
text1=wx.TextCtrl(panel,-1,pos=(200,30),size=(180,20), #输入框
style=wx.TE_MULTILINE)
label2=wx.StaticText(panel,-1,"每个数值的上限(>=10)",pos=(10,60))
text2=wx.TextCtrl(panel,-1,pos=(200,60),size=(180,20),
style=wx.TE_MULTILINE)
label3=wx.StaticText(panel,-1,"操作数个数(>=2)",pos=(10,90))
text3=wx.TextCtrl(panel,-1,pos=(200,90),size=(180,20),
style=wx.TE_MULTILINE)
label4=wx.StaticText(panel,-1,"运算符种数(1~4)",pos=(10,120))
text4=wx.TextCtrl(panel,-1,pos=(200,120),size=(180,20),
style=wx.TE_MULTILINE)
label5=wx.StaticText(panel,-1,"是否要包含分数(0,1)",pos=(10,150))
text5=wx.TextCtrl(panel,-1,pos=(200,150),size=(180,20),
style=wx.TE_MULTILINE)
button = wx.Button(panel,-1, '确定', pos=(150, 180)) # 确定按钮位置
self.text1=text1 #方便跨函数调用
self.text2=text2
self.text3=text3
self.text4=text4
self.text5=text5
self.button1 = button
self.Bind(wx.EVT_BUTTON, # 绑定事件,如果是按钮被点击
self.GetInPut, # 激发的按钮事件
self.button1) # 激发的按钮
frame.Center()
frame.Show() # 显示
return True
def GetInPut(self,event): #事件的激发函数,获得输入
while True:
n = self.text1.GetValue()
try:
n = abs(int(n))
if n < 1:
wx.MessageBox("生成算式数量-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break
except Exception as e:
wx.MessageBox("生成算式数量-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break
up_limit = self.text2.GetValue()
try:
up_limit = abs(int(up_limit))
if up_limit < 10:
wx.MessageBox("每个数值的上限-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break
except Exception as e:
wx.MessageBox("每个数值的上限-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break
oper_num = self.text3.GetValue()
try:
oper_num = abs(int(oper_num))
if oper_num < 2:
wx.MessageBox("操作数个数-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break
except Exception as e:
wx.MessageBox("操作数个数-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break
oper_variety = self.text4.GetValue()
try:
oper_variety = abs(int(oper_variety))
if oper_variety < 1 or oper_variety > 4:
wx.MessageBox("运算符种数-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break
except Exception as e:
wx.MessageBox("运算符种数-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break
has_fraction = self.text5.GetValue()
try:
has_fraction = abs(int(has_fraction))
if has_fraction != 0 and has_fraction != 1:
wx.MessageBox("是否要包含分数-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break
except Exception as e:
wx.MessageBox("是否要包含分数-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break
self.n = int(n)
self.up_limit = int(up_limit)
self.oper_num = int(oper_num)
self.oper_variety = int(oper_variety)
self.has_fraction = int(has_fraction)
self.solveFormular()
break
def solveFormular(self):
opt = OPT(self.up_limit, self.oper_num, self.oper_variety, self.has_fraction)
gf = GeneralFormular(opt)
cf = ComputeFormular()
formulars = []
results = []
for i in range(int(self.n)):
f = gf.solve()
formulars.append(" ".join(i for i in f) + " = ")
results.append(cf.solve(f))
self.formulars=formulars
self.results=results
self.displayFormular()
def displayFormular(self):
frame = wx.Frame(parent=None, title="计算界面", size=(500,500))
self.panel = wx.Panel(frame, -1) # 生成面板
self.Column = 30
self.Row = 10
self.N =len(self.formulars)
self.i = 0
self.GetResult()
frame.Center()
frame.Show() # 显示
return True
def GetResult(self): #显示题目和答题文本框
if self.Column >= 800:
self.Row += 500
self.Column = 30
T_label=wx.StaticText(self.panel,-1,"第{}题:".format(self.i+1) + self.formulars[self.i],pos=(self.Row,self.Column)) #标签
T_text=wx.TextCtrl(self.panel,-1,pos=(self.Row+340,self.Column),size=(100,20), #输入框
style=wx.TE_PROCESS_ENTER)
self.T_text = T_text
self.Bind(wx.EVT_TEXT_ENTER, self.judgeResult, T_text)
def judgeResult(self,event): #判断正误
self.result = self.T_text.GetValue()
self.Column += 30
if self.result == self.results[self.i]:
flag = "正确 √ √ √"
else:
flag = "错误❌❌❌"
T_label=wx.StaticText(self.panel,-1," 正确答案:{} 回答{}"\
.format(self.results[self.i], flag),pos=(self.Row,self.Column))
self.i += 1
try:
if self.i <= self.N-1:
self.Column = self.Column+30
self.GetResult()
else:
End_label=wx.StaticText(self.panel,-1," ---------答题结束--------- ",pos=(self.Row, self.Column+50))
End_label.SetFont(wx.Font(12, wx.SWISS))
except Exception as e:
return True
if __name__ == '__main__':
app = MyApp() # 启动
app.MainLoop() # 进入消息循环
formula代码:
import random
import datetime
import argparse
import re
from fractions import Fraction
def OPT(up_limit=10, oper_num=2, oper_variety=4, has_fraction=True, be_negetive=False):
'''
* 设置参数
* @param up_limit {int} 操作数数值上限
* @param oper_num {int} 操作数个数
* @param oper_variety {int} 运算符种类
* @param has_fraction {bool} 是否带有分数
* @param be_negative {bool} 可否存在负数
'''
parse = argparse.ArgumentParser()
# 操作数数值上限
parse.add_argument('--up_limit', type=int, default=up_limit)
# 操作数个数
parse.add_argument('--oper_num', type=int, default=oper_num)
# 运算符种类
parse.add_argument('--oper_variety', type=int, default=oper_variety)
# 是否带有分数
parse.add_argument('--has_fraction', type=bool, default=has_fraction)
# 可否存在负数
parse.add_argument('--be_negative', type=bool, default=be_negetive)
return parse.parse_args(args=[])
class GeneralFormular:
'''
* 生成算式
* @param opt {OPT} 参数
'''
def __init__(self, opt):
self.opt = opt
# 定义运算符
self.operator = ['+', '-', '×', '÷']
# @profile
def catFormula(self, operand1, operator, operand2):
'''
* 连接算式
* @param operand1 {str} 操作数1
* @param opertor {str} 运算符
* @param operand2 {str} 操作数2
* @return {str}
'''
return "{}#{}#{}".format(operand1, operator, operand2)
# @profile
def getRandomIntOperand(self):
'''
* 返回随机整数操作数
* @return {int}
'''
return random.randint(0, self.opt.up_limit)
# @profile
def getRandomFractionOperand(self):
'''
* 返回随机分数操作数
* @return {str}
'''
# 生成两个整数,一个作为分子,一个作为分母
num01 = self.getRandomIntOperand()
num02 = self.getRandomIntOperand()
while num01 == num02 or num02==0:
num02 = self.getRandomIntOperand()
while num01 == 0:
num01 = self.getRandomIntOperand()
# 保证分数为真分数, 化简
if num01 < num02:
return Fraction(num01, num02).__str__()
else:
return Fraction(num02, num01).__str__()
# @profile
def getRandomOperator(self):
'''
* 返回随机运算符
* @return {str}
'''
index = random.randint(0, self.opt.oper_variety-1)
return self.operator[index]
# @profile
def getOriginFormular(self):
'''
* 生成整数源算式
* @return {list}
'''
# 通过self.opt.oper_num控制操作数个数,循环调用catFormula()方法构造算式
formular = self.getRandomIntOperand()
for i in range(self.opt.oper_num-1):
formular = self.catFormula(formular, self.getRandomOperator(), self.getRandomIntOperand())
# 去掉'÷0'
while(True):
if '÷#0' in formular:
formular = formular.replace('÷#0', '÷#' + str(self.getRandomIntOperand()))
else:
break
# 通过'#'分割生成列表
formular_list = formular.split('#')
return formular_list
# @profile
def insertBracket(self, formular_list):
'''
* 插入括号
* @param formular_list {list} 源算式列表
* @return {list}
'''
# print(formular)
# 若只包含+号 或 只有两个操作数 则不用加括号
if self.opt.oper_variety <= 2 or self.opt.oper_num == 2:
return formular_list
# 若不包含×÷ 则不用加括号
if '×' not in formular_list and '÷' not in formular_list:
return formular_list
# 存储添加括号的算式
new_formular_list = []
# flag表示是否已存在左括号,作用在于构造出一对括号
flag = 0
# 添加括号
while(len(formular_list) > 1):
oper = formular_list.pop(1)
# 若下一个符号为 + or - , 则插入括号
if oper == '-' or oper == '+':
if flag == 0:
new_formular_list.append("(")
flag = 1
new_formular_list.append(formular_list.pop(0))
new_formular_list.append(oper)
else:
new_formular_list.append(formular_list.pop(0))
if flag == 1:
new_formular_list.append(")")
flag = 0
new_formular_list.append(oper)
# print(operand_list, operator_list, new_formular)
new_formular_list.append(formular_list.pop(0))
if flag == 1:
new_formular_list.append(")")
return new_formular_list
# @profile
def replaceFraction(self, formular_list):
'''
* 带入分数
* @param formular_list {list} 源算式列表,可能包含括号
* @return {list}
'''
# 带入分数个数
fraction_num = 1
if self.opt.oper_num > 2:
fraction_num = (self.opt.oper_num - 1) / 2
index = random.randint(0, len(formular_list)-1)
interval = 1
while True:
if formular_list[index].isdigit():
break
elif formular_list[index - interval].isdigit():
index -= interval
break
elif formular_list[index + interval].isdigit():
index += interval
break
else:
interval += 1
formular_list[index] = self.getRandomFractionOperand()
return formular_list
# @profile
def solve(self):
'''
* 整合生成算式的后缀表达式,带括号
* @return {list}
'''
# 生成原生算式
ori_formular = self.getOriginFormular()
# 添加括号
bra_formular = self.insertBracket(ori_formular)
# 带入分数
if self.opt.has_fraction:
bra_formular = self.replaceFraction(bra_formular)
return bra_formular
class ComputeFormular:
'''
* 计算算式的值
'''
def __init__(self):
pass
# @profile
def getPostFormular(self, formular_list):
'''
* 中缀表达式转为后缀表达式
* @param formular_list {list} 中缀表达式
* @return {list}
'''
# 运算符优先级
priority = {'×': 3, '÷': 3, '+': 2, '-': 2, '(': 1}
# 运算符栈
operator_stack = []
# 后缀表达式
post_formular_list = []
# 中缀表达式转为后缀表达式
while formular_list:
char = formular_list.pop(0)
if char == '(':
operator_stack.append(char)
elif char == ')':
oper_char = operator_stack.pop()
while oper_char != '(':
post_formular_list.append(oper_char)
oper_char = operator_stack.pop()
elif char in '+-×÷':
while operator_stack and priority[operator_stack[-1]] >= priority[char]:
post_formular_list.append(operator_stack.pop())
operator_stack.append(char)
else:
post_formular_list.append(char)
# 若符号栈不为空则循环
while operator_stack:
post_formular_list.append(operator_stack.pop())
# print(post_formular)
return post_formular_list
# @profile
def compute(self, char, num01, num02):
'''
* 计算算式的值
* @param char {str} 运算符
* @param num01 {str} 第二个数字,可能为分数
* @param num02 {str} 第二个数字,可能为分数
* @return {str}
'''
if char == '+':
return (Fraction(num02) + Fraction(num01)).__str__()
elif char == '-':
return (Fraction(num02) - Fraction(num01)).__str__()
elif char == '×':
return (Fraction(num02) * Fraction(num01)).__str__()
elif char == '÷':
try:
return (Fraction(num02) / Fraction(num01)).__str__()
except Exception as e:
# print("Error: ", e)
return "NaN"
# @profile
def calcFormular(self, post_formular_list):
'''
* 计算算式的值
* @param post_formular_list {list} 后缀表达式
* @return {str}
'''
# 操作数栈
operand_stack = []
while post_formular_list:
char = post_formular_list.pop(0)
if char in '+-×÷':
result = self.compute(char, operand_stack.pop(), operand_stack.pop())
if result == "NaN":
return result
operand_stack.append(result)
else:
operand_stack.append(char)
return operand_stack.pop()
# @profile
def solve(self, formular):
'''
* 整合计算中缀表达式的值
* @param formular {list} 后缀表达式
* @return {str}
'''
# 转为后缀表达式
post_formular = self.getPostFormular(formular)
# 计算值
value = self.calcFormular(post_formular)
return value
代码截图
本文代码借鉴一名作者(昵称:玩的三立方)的项目代码,