zoukankan      html  css  js  c++  java
  • 2017年软件工程团体项目

    小组成员:(组长:刘炜;组员:黄智、何保委、刘少帅、吕智勇)

    源代码链接:https://github.com/superwales/Random_test

    项目功能点:(10个基本功能+1个附件功能)

    1,拥有多个默认标签,用户可以进行交叉选择。例如:操作符标签为:“连乘”、“连加”,数据标签为:“整数”、“真分数”等;

    2,各个标签的交叉选择具有冲突检测功能,提示用户或者自动修正;

    3,用户可以自定义添加或者删除标签;

    4,用户可以自定义题目长度,操作符类型及个数(或比例),数据类型及取值范围等信息来自定义出题;

    5,建立用户的自定义题库,可以查询、统计、删除、清空;

    6,更改错题本为收藏夹,用户可以自由选择题目收藏;

    7,可以判断用户错题的错误类型;

    8,显示错题的解题步骤;

    9,练习模式添加解题提示功能;

    10,能够用折线图、柱状图、饼图等可视化方式显示用户做题记录。

    附件功能:程序界面支持多种语言。

    在确定了功能需求后,我们首先进行了分工,秉持每人都能得到锻炼的原则,组内按照功能点进行了分工:

    功能点1、2、3、4、5、附加功能:刘炜

    功能点7、10:黄智

    功能点9:何保委

    功能点6:刘少帅

    功能点8:吕智勇

    本次项目在刘炜、刘少帅的第二次作业基础上修改展开。

    part1:刘炜

    功能1:拥有多个默认标签,用户可以交叉选择

    首先是设计的工作。一道四则运算的题,题目里面会包含运算符、操作数、有无括号等元素。那么考虑从这三个方面设计标签。运算符的不同体现在类型上,因为数量和顺序是随机生成的。运算符总共有“+”,“-”,“×”,“÷”四种,可以设计一道题拥有一种类型的运算符,有四种情况;两种类型的运算符,情况有6种情况......操作数的不同体现在类型(整数、真分数)和运算范围上,因此可以设计类型标签,让用户手动输入运算范围;括号影响了运算顺序,考虑到小学运算的复杂性,将括号数量的上限设定为1。

    将此功能添加到原程序的随机练习模式中,界面如图:

         

    功能2:各个标签的交叉选择具有冲突检测功能,提示用户或自动修正

    为了避免用户在交叉选择中选择自相矛盾的标签,所有的类型标签都设置为单选。但是在题目工厂中,当指定一个操作符并要求包含括号时,会提示用户。

    功能3:用户可以自定义标签。

    这个功能后来转变成程序自动记忆用户的设置。出题需要选择的标签比较多,如果用户每一次使用都要进行选择,无疑会使使用相当繁琐。因此记忆用户的选择,在下次登录时自动恢复成上次的设置是很有必要的。截图不能展示这个功能,简单介绍一下设计原理。在用户注册的时候,将生成一个设置文件,里面是默认的设置。在用户退出界面的时候,当前选择会修改进入设置文件中。下次登录时,读取设置文件中的设置就行了。

    功能4,:用户可以自定义题目长度,操作符类型及个数,数据类型及取值范围等信息来自定义出题。

    首先是界面设计:

    当点击开始出题时,首先会根据上面的操作符的类型及数量得到一个操作符列表,出题时从这些列表中随机挑操作符就好了。如果有括号的话,将操作符随机分成两部分,一部分在括号内,另一部分在括号外,然后随机选择位置插入括号就好了。

    核心代码:

    def getdiyoperators(list):
        operators = random.choice(list)
        list.remove(operators)
        if operators == '×':
            length = 2
        elif operators == '÷':
            length = 2
        else:
            length = 1
        return operators, length,list
    
    def getdiyquestion(list,numstr,ran,brastr):
        if brastr=="":
            question = ''
            questionstack = []
            ans = 0
            length_ques = 0
    
            for i in range(1, len(list) + 1):
                (op, va, de) = getlabeloperands(numstr, ran)
                operands = op
                value = va
                (operators, length, list1) = getdiyoperators(list)
                list = list1
                question = question + operands + operators
                questionstack.append(value)
                questionstack.append(operators)
                length_ques = length_ques + length + de
            (op, va, de) = getlabeloperands(numstr, ran)
            operands = op
            value = va
            question = question + operands
            questionstack.append(value)
            length_ques = length_ques + de
            # print question
            # print questionstack
            condition = 0
            while len(questionstack) > 1:
                for i in range(0, len(questionstack)):
                    if questionstack[i] == '×':
                        questionstack[i - 1] = questionstack[i - 1] * questionstack[i + 1]
                        del questionstack[i]
                        del questionstack[i]
                        break
                    elif questionstack[i] == '÷':
                        questionstack[i - 1] = questionstack[i - 1] / questionstack[i + 1]
                        del questionstack[i]
                        del questionstack[i]
                        break
                    else:
                        condition = 1
                if condition == 1:
                    if len(questionstack) > 1:
                        questionstack[0] = calculate(questionstack[0], questionstack[2], questionstack[1])
                        del questionstack[1]
                        del questionstack[1]
                        # print question
                        # print questionstack
            else:
                ans = questionstack[0]
        elif brastr=="":
            n1=random.randint(1,len(list)-1)
            n2=len(list)-n1
            n3=random.randint(1,n2)
            list_in=[]
            for i in range(1,n1+1):
                kop=random.choice(list)
                list_in.append(kop)
                list.remove(kop)
    
            question = ''
            questionstack = []
            ans = 0
            length_ques = 0
    
            for i in range(1, n2 + 1):
                if i==n3:
                    (op,va,de)=getdiyquestionbylist(list_in,numstr,ran)
                    operands = op
                    value = va
                    (operators, length, list1) = getdiyoperators(list)
                    list = list1
                    question = question + '('+operands+')' + operators
                    questionstack.append(value)
                    questionstack.append(operators)
                    length_ques = length_ques + length + de
                else:
                    (op, va, de) = getlabeloperands(numstr, ran)
                    operands = op
                    value = va
                    (operators, length, list1) = getdiyoperators(list)
                    list = list1
                    question = question + operands + operators
                    questionstack.append(value)
                    questionstack.append(operators)
                    length_ques = length_ques + length + de
            (op, va, de) = getlabeloperands(numstr, ran)
            operands = op
            value = va
            question = question + operands
            questionstack.append(value)
            length_ques = length_ques + de
            # print question
            # print questionstack
            condition = 0
            while len(questionstack) > 1:
                for i in range(0, len(questionstack)):
                    if questionstack[i] == '×':
                        questionstack[i - 1] = questionstack[i - 1] * questionstack[i + 1]
                        del questionstack[i]
                        del questionstack[i]
                        break
                    elif questionstack[i] == '÷':
                        questionstack[i - 1] = questionstack[i - 1] / questionstack[i + 1]
                        del questionstack[i]
                        del questionstack[i]
                        break
                    else:
                        condition = 1
                if condition == 1:
                    if len(questionstack) > 1:
                        questionstack[0] = calculate(questionstack[0], questionstack[2], questionstack[1])
                        del questionstack[1]
                        del questionstack[1]
                        # print question
                        # print questionstack
            else:
                ans = questionstack[0]
        return question, ans, length_ques

    功能5:建立用户的自定义题库。

    界面就是功能4中的题目工厂,选择添加就能将所选题目添加到收藏夹。

    附加功能:

    支持多语言,显然不能把所有的语言的都写死在程序中,这样不仅麻烦,而且没有任何的可扩展性。参考了其他同学的作业后,发展出了一个思路:把所有的文本写在一个文本文件中,文本文件按照语言类型命名。在登录界面可以添加一个输入框和一个语言设置按钮,当点击按钮时,程序会找到以输入框的文字命名的文件,读取其中的内容,如果读取错误,就调用简体中文包。

    比如:chinese文件:

    english文件:

     当不做选择时,界面是简体中文:

     当设置为英语时:

     当前的程序没有做在登录界面添加输入和按钮,是通过改变全局变量实现的,用户不可控制。

     part2:黄智

    Github链接:https://github.com/hz5612777/Calculator_task3

    1 分配任务

      在这次5人团队任务中,我的任务是可以判断用户的错题类型,并且使软件实现能够用折线图、柱状图、饼状图等可视化方式显示用户做题记录。

    2 解题思路

    我的任务在有用户做题数据的情况下,画出三种类型的图不难,难点在于用户错题类型的分类。用户的错题到底属于哪种类型,单单从答案是很难获得的。我想从用户对该题的答题时间进行判断。

    我们团队根据每题的操作数和运算符设定了一个难度系数,在完成正确的答题后得到每题的做题时间,我将这些难度系数和做题时间作为训练集,采用线性回归的方法训练出模型参数,当系统再次获得一个难度系数的时候,则根据这个难度系数得到相应的预测时间,当用户做错题时,如果用户的做题时间在基于预测时间设定的时间范围以内,则判定为用户会做本题但是做错了,如果在时间范围以外,则认为用户不会计算本题。

    用于训练的线性回归模型可以表示为:

    根据训练集得到的参数值,然后输入难度系数可以得到每题的预测时间。

    3 设计实现

    根据线性回归模型,利用训练集拟合出来的曲线如图所示:

    利用matplotlib包,可以完成柱状图、折线图和饼状图的画图,我设计了三个QT的graphicsview控件,当用户单击显示做题记录的按钮,三个控件分别显示三种作图信息。

      由于当用户做题记录只有一天的时候无法绘制折线图,所以这是提示无法绘制折线图,单击图中的退出按钮完成该界面的退出。

     part3:何保委

    功能:练习模式添加解题提示功能(逐步显示)


    思路:
    求解计算结果用后缀表达式,显示解题过程用中缀表达式。


    方法:
    ①将字符串格式的运算表达式用函数middle_to_after由中缀表达式转换成后缀表达式,存储在列表 expression
    具体转换方法是遇到数字,直接输出;遇到左括号,直接忽略;遇到符号,将符号压入栈,遇到右括号则弹出栈中的符号。
    ②将字符串格式的运算表达式用函数用split函数分解成列表形式存储 存储在列表 expression1
    ③调用求解函数expression_to_value 将后缀表达式expression和中缀表达式expression1作为实参传递
    ④利用函数expression_to_value求解出每一步后缀表达式的结果,
    同时将计算结果赋值给中缀表达式,删除中缀表达式中已经参与运算的数字和字符,用字符串格式打印
    在每一步计算结果后遍历中缀表达式,若括号内有且只有一个数字,则删除()。
    ⑤重复上述步骤①到④,直到求解出结果。

     part4:刘少帅

    一)功能目的

    更改错题本为收藏夹,用户可以自由选择题目收藏。

    (二)解决思路

    原来的“错题本”功能是如果某道题目做错,则该题自动添加到错题本中,比较被动。本功能是在错题本功能基础上添加“收藏夹”功能,用户可以根据自己需要将觉得有收藏价值的题目(不论这道题是做错还是做对)主动添加到收藏夹中。

    (三)实现方法

    1.增加“添加”按钮,并设置好其在界面中的位置;

    2.定义“Add”函数,目的是调用该函数时,会将某道题添加到“收藏夹”中;

    3.将“添加”按钮与“Add”函数绑定。当点击“添加”按钮时,“Add”函数被调用,某道题会添加到“收藏夹”中。

    (四)测试情况

    1.测试内容

    区分四种情况进行测试:

    情况一:题目回答正确,不点击“添加”按钮;

    情况二:题目回答错误,不点击“添加”按钮;

    情况三:题目回答正确,点击“添加”按钮;

    情况四:题目回答错误,点击“添加”按钮。

    2.测试结果

    在情况一、二下,收藏夹中没有收藏相应的题目;在情况三、四下,收藏夹中收藏了相应的题目。

    经测试,能够稳定实现“用户自由选择题目收藏”的功能。

    项目小结:

    本次团体作业可谓是相当敏捷。总结这学期的软件工程课,最大的收获倒不是掌握了软件设计的某些流程方法,反而是了解了一种新的编程语言——python。这是一个有趣的事情,我认为也恰恰反映了软件工程的必要性。很多的东西,比如代码复审、回归测试等,都是编程的新手容易不重视的,然而这学期编程的经验告诉我,最开始不注重代码规范、单元测试等问题,到后面可能得用更多的时间和精力去填自己挖下的坑。团体项目的最后时间,我陷入了一种状态,感觉这个程序,总有可以修改的地方,总有需要改进的地方,总有不尽如人意的地方。现在回头检查,发现确实很多地方做的不好,但是这种感觉很奇妙。

  • 相关阅读:
    requests模块使用
    如何在vue中调用百度地图
    VS Code 改变默认文字编码 为utf-8
    清理电脑C盘的方法
    安装最新版本的angular-cli的命令行代码
    微信小程序发布后查看实时日志
    微信小程序 POST传值跳坑
    App唤起微信小程序和回调
    微信小程序判断进入小程序的入口(场景值)
    微信小程序参数传递获取当前页面的url和参数
  • 原文地址:https://www.cnblogs.com/seven-v13/p/8400599.html
Copyright © 2011-2022 走看看