iFurySt

导航

 

程序设计

应用代码见此 / web应用地址 / 合作伙伴jahowz博文连接

实现功能

  1. 难度分级和题数选择
  2. 错题计数(本次和总次数)和错题集
  3. 做题计时功能
  4. 多语言选择(用户没选择会根据HTTP头来自动选择)
  5. 支持小数计算
  6. 限定用户输入(不允许非数字、/和.)

原本的控制台版本是用python实现的,本次使用Flask开发web端应用。整个应用的树状图如下:

pair_work
├── data
│   └── calc.db
├── func.py
├── README.md
├── static
│   └── timer.js
├── templates
│   ├── error_question.html
│   ├── index.html
│   ├── layout.html
│   ├── question_paper.html
│   └── result.html
└── views.py

3 directories, 10 files
  • data目录下是数据库文件
  • func.py是功能模块的代码
  • static目录下是用于计时功能的js代码
  • templates目录下是页面的html文件
  • views.py是视图模块的代码

视图模块

views.py里面存放视图函数,用在用户端和服务端中间处理。
比如会判断用户端使用的语言,自动选择语言并写到session中,选择相应的模板渲染返回给用户;根据用户的操作选择相应的功能函数进行处理。

主要代码如下(请到coding.net上查看最新的代码):

@app.route('/', methods=['GET', 'POST'])
def index():
    session['lang'] = request.form.get("lang",0)
    s = session['lang']
    if s == '1': # zh-cn
        return render_template("index.html",selnum="0",lang=zh_cn)
    elif s == '2': # zh-tw,zh-hk
        return render_template("index.html",selnum="1",lang=zh_hk)
    elif s == '3': # en
        return render_template("index.html",selnum="2",lang=en)
    else:
        al = request.headers['ACCEPT_LANGUAGE']
        if al.startswith("zh-TW") or al.startswith("zh-HK"):
            return render_template("index.html",selnum="1",lang=zh_hk)
        elif al.startswith("en"):
            return render_template("index.html",selnum="2",lang=en)
        else:
            return render_template("index.html",selnum="0",lang=zh_cn)

@app.route('/question_paper/', methods=['GET', 'POST'])
def question_paper():
    if request.method == 'POST':
        sel = request.form.get('easy','0') + request.form.get('medium','0') + request.form.get('hard','0')
        num = request.form.get('num',0)
        return render_template('question_paper.html', questions=main(sel, num),lang=all_lang[language_choice()])
    return redirect(url_for('index'))

@app.route('/result/', methods=['GET', 'POST'])
def result():
    if request.method == 'POST':
        user_answer = []
        num = get_num()
        for i in range(1,num+1):
            # 'x' stands for the user has not input answer
            user_answer.append(request.form.get('t'+str(i),'x'))
        # format of results is  [{'question':'1+3*2','user_answer':'6','real_answer':'7','flag':0},{'question':'1+3*2','user_answer':'7','real_answer':'7','flag':1}]
        t = compare(user_answer) # 0->results , 1->current_error
        return render_template('result.html', results=t[0], timer=request.form.get('timer','0'), current_error=t[1], total_error=len(error_reader()),lang=all_lang[language_choice()])
    return redirect(url_for('index'))

@app.route('/error_question/', methods=['GET'])
def error_question():
    e = error_reader()
    return render_template('error_question.html', total_error=len(e), error_questions=e,lang=all_lang[language_choice()])

功能模块和数据模块

数据模块主要是存储在data/文件夹下的数据,最初是文本存储,改版后变成了数据库,这一块主要是让功能模块取用的。

功能模块主要存在func.py里面,功能模块的实现是有jahowz基于他上一次做的控制台版本的程序改写并新增功能而来,期间会根据我这边的需求去改动。

内部具体实现细节完全由他来完成,我只会和他交流需要对接的地方,比如我需要一个功能,能传递给他什么参数,他需要给我返回什么结果。

模板

templates目录下主要存放了html模板,视图在接受用户传来的信息,并调用功能模块处理完后,会渲染里面相应的html模板,把结果返回给用户端。

html文件主要使用模板继承,layout.html为基文件,其他页面都是基于这个页面继承而来,相应的模块可以根据相应的页面更改,其他的注入头部和尾部基本一致就都通过继承而来。

程序运行展示

首先运行程序,访问主页可以看到,有语言选择,难度选择和题量:

之后出现相应题量的题目,并开始计时:

用户答完题提交后,显示本次答题结果,可以选择再做,也可以看看以前错的题目:

错题集里收录了以前做错的题目。

总结

分模块是一个很好的设计思想,本次我们主要把整个项目分了四大模块:视图功能数据模板。相应的模块主要完成对应的功能,这样的好处在于,不同的模块进行改动甚至大改版也不会影响到别的模块。比如jahowz负责的功能模块内部算法改变,对于我负责的视图模块没有半点影响,数据模块由文本改成数据库,也依然毫无影响。这为整个应用系统的升级带来集大的便利。

最后很感谢jahowz的大力支持,给他需求,就能很快得到方案和成果。

posted on 2017-03-10 11:06  iFurySt  阅读(468)  评论(3编辑  收藏  举报