work5
这一次写的内容是黄金豆小游戏,由于现在偏重写服务器端。对于算法层面其实涉及不多,更多偏于工程上的架构。
总而言之本次作业的服务器核心是用web.py所写,而且为了方便其他用户写客户端,架构非常简单。
具体而言,首先从接口上来说,服务器只涉及到两个表单操作,注册表单和提交表单,注册也同样可以在网页上进行。
由于是测试服务器通讯的,为了方便客户端调试很多细节与题设有所不同,但修改起来非常简单。
注册模块:
注册需要提交用户名和密码{[username],[password]}
1.只有在游戏开始前可以进行注册。
2.注册失败,会返回-1.
3.注册成功,会返回0.
4.注册信息会录入注册表中。
提交模块:
提交模式需要提交用户名和密码以及给的数字{[username],[password],[nut]}
1.如果下一轮还未开始用户已经提交,便会等待。
2.如果用户提交后,本轮还未结束,依然等待直到,结束,返回G值
3.若登录失败,则返回-1(测试完毕后,若为按时提交也返回-1)
游戏模块:
1.会等待本轮用户提交完毕才会给出G值(测试完毕后改为,若1秒之后仍未提交,直接失败)。
2.分数策略如提所述。
即服务器与客户端同步,以免发生一开始客户端设计的缺陷引发客户端一次都无法返回有意义的结果。
正式发布时,服务器将不等待客户端的同步。
画图由一个monitor实时返回此时AVG的值。值得一提的是,由于web.py对于线程数有限制(10),我们修改了web.py source里的代码,把THREAD数目放宽才使得该项目成为可能。
测试程序:
开了30个线程测了50组数据,图像反应正常。
#coding=utf-8
import wx
from matplotlib.figure import Figure
import matplotlib.font_manager as font_manager
import numpy as np
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
import web
import datetime
import time
from web import form
import matplotlib.pyplot as plt
import thread
web.config.debug = False
import sys
succ = '0'
fail = '1'
PLAYERNUM = 30
reload(sys)
sys.setdefaultencoding("utf-8")
class Game():
nowtime = 0
paticipate_num = 0
active_num = 0
total =0.0
avg = 0.0
score = {}
times = {}
number = {}
def __init__(self):
pass
G = Game()
x = []
y = []
urls=('/','Index',
'/reg','Reg',
'/login','Login',
'/logout','Logout',
'/showusers','Showusers',
)
app=web.application(urls,globals())
render = web.template.render('templates',base='base')
session = web.session.Session(app, web.session.DiskStore('sessions'),initializer={'login':0,'id':'0'})
db1=web.database(dbn='mysql',
db='golden',
user='root',
pw='199089455',
port=3306,)
###首页
class Index:
def GET(self):
#return web.ctx.ip
return datetime.datetime.now().strftime('%Y%m%d%H%M%S%S')
###注册页
class Reg:
vusername= form.regexp(r".{3,20}$", '用户名长度为3-20位')
vpass = form.regexp(r".{6,20}$", '密码长度为6-20位')
vemail = form.regexp(r".*@.*", "must be a valid email address")
regForm=web.form.Form(
form.Textbox('username',vusername,description=u'用户名'),
form.Password("password",vpass,description=u"密码"),
form.Password("password2", description=u"确认密码"),
form.Button(u"马上注册", type="submit", description="submit"),
validators = [
form.Validator("两次输入的密码不一致", lambda i: i.password == i.password2)]
)
def GET(self):
return render.reg(self.regForm,u'注册成功后自动跳往登陆界面')
def POST(self):
formdata=web.input();
username=web.net.websafe(formdata.username)
password=web.net.websafe(formdata.password)
regdate=datetime.datetime.now().strftime('%Y%m%d%H%M%S')
if not self.regForm.validates() and G.paticipate_num>=PLAYERNUM:
return fail
#判断用户名是否存在:
else:
if len(getUserByUserName(username))>0:
#return render.reg(self.regForm,u'用户名已存在')
return fail
else:
ret=addUser(username,password,regdate)
if ret==0:
#return u'注册成功'
G.paticipate_num+=1
G.score [username]= 0
G.times [username]= 0
G.number[username]= 0
return succ
else:
return fail
###登陆页面
class Login:
loginForm=form.Form(form.Textbox('username',description=u'用户名'),
form.Password("password",description=u"密码"),
form.Button(u"马上登陆", type="submit", description="submit"),)
def GET(self):
if logged():
return 'you are logged '+session.id
else:
return render.login(self.loginForm)
def POST(self):
postdata=web.input()
username=web.net.websafe(postdata.username)
password=web.net.websafe(postdata.password)
nut=float(web.net.websafe(postdata.nut))
rslist=getUserByUserName(username)
if len(rslist)==0:
#return render.login(self.loginForm,'用户名不存在')
return
else:
if password==rslist[0].password:
while G.times[username]>=G.nowtime:
time.sleep(0.001)
G.times[username]+=1
G.number[username]=nut
G.active_num+=1
G.total+=nut
while G.times[username]==G.nowtime:
time.sleep(0.001)
return G.avg*0.618
else:
#return render.login(self.loginForm,'用户名及密码不匹配')
return fail
###注销登陆页面
class Logout:
def GET(self):
session.login=0
session.kill()
return 'you have logged out!'
###显示用户列表
class Showusers:
def GET(self):
if logged():
usersList=getUsers()
return render.users(usersList)
else:
return 'please log in first!'
###判断用户是否登陆
def logged():
if session.login==1:
return True
else:
return False
################################################ 数据库操作部分 begin ############################################################
#增加用户
def addUser(username,password,regdate):
ret=db1.insert('t_user',username=username ,password=password,regdate=regdate)
return ret
#获取用户列表
def getUsers(orderby='regdate'):
rs=db1.select('t_user',order=orderby)
rslist=[]
for r in rs:
rslist.append(r)
return rslist
#根据用户名查询用户信息
def getUserByUserName(username):
rs=db1.select('t_user',where='username="'+username+'"')
rslist=[]
for r in rs:
rslist.append(r)
return rslist
################################################ 数据库操作部分 end ############################################################
################################################ 游戏线程 begin ############################################################
def Gamestart():
while (G.paticipate_num!= PLAYERNUM):
time.sleep(0.1)
if G.paticipate_num== PLAYERNUM:
for G.nowtime in range(1,51):
G.total = 0.0
G.active_num = 0
while G.active_num<G.paticipate_num:
time.sleep(0.1)
print G.nowtime
G.avg = G.total/PLAYERNUM
winner = ""
minsqr = 10000.0
loser = ""
maxsqr = -10000.0
for each in G.number:
if (G.number[each]-G.avg*0.618)*(G.number[each]-G.avg*0.618)<minsqr:
minsqr = (G.number[each]-G.avg*0.618)*(G.number[each]-G.avg*0.618)
winner = each
if (G.number[each]-G.avg*0.618)*(G.number[each]-G.avg*0.618)>maxsqr:
maxsqr = (G.number[each]-G.avg*0.618)*(G.number[each]-G.avg*0.618)
loser = each
G.score[winner] += PLAYERNUM
G.score[loser] -= 2
x.append(G.nowtime)
y.append(G.avg)
G.nowtime=51
################################################ 游戏线程 end ############################################################
POINTS = 300
################################################ 绘图部分 begin ############################################################
class PlotFigure(wx.Frame):
"""Matplotlib wxFrame with animation effect"""
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, title="Monitor", size=(600, 400))
# Matplotlib Figure
self.fig = Figure((6, 4), 100)
# bind the Figure to the backend specific canvas
self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
# add a subplot
self.ax = self.fig.add_subplot(111)
# limit the X and Y axes dimensions
self.ax.set_ylim([0, 100])
self.ax.set_xlim([0, POINTS])
self.ax.set_autoscale_on(False)
self.ax.set_xticks([])
# we want a tick every 10 point on Y (101 is to have 10
self.ax.set_yticks(range(0, 101, 10))
# disable autoscale, since we don't want the Axes to ad
# draw a grid (it will be only for Y)
self.ax.grid(True)
# generates first "empty" plots
self.user = [None] * POINTS
self.l_user,=self.ax.plot(range(POINTS),self.user,label='AVG')
# add the legend
self.ax.legend(loc='upper center',
ncol=4,
prop=font_manager.FontProperties(size=10))
# force a draw on the canvas()
# trick to show the grid and the legend
self.canvas.draw()
# save the clean background - everything but the line
# is drawn and saved in the pixel buffer background
self.bg = self.canvas.copy_from_bbox(self.ax.bbox)
# bind events coming from timer with id = TIMER_ID
# to the onTimer callback function
wx.EVT_TIMER(self, TIMER_ID, self.onTimer)
def onTimer(self, evt):
"""callback function for timer events"""
# restore the clean background, saved at the beginning
self.canvas.restore_region(self.bg)
# update the data
temp = G.avg
self.user = self.user[1:] + [temp]
# update the plot
self.l_user.set_ydata(self.user)
# just draw the "animated" objects
self.ax.draw_artist(self.l_user)# It is used to efficiently update Axes data (axis ticks, labels, etc are not updated)
self.canvas.blit(self.ax.bbox)
def __del__( self ):
t.Stop()
########################################################################################################################
TIMER_ID = wx.NewId()
if __name__=="__main__":
thread.start_new_thread(Gamestart,())
thread.start_new_thread(app.run,())
app1 = wx.PySimpleApp()
frame = PlotFigure()
t = wx.Timer(frame, TIMER_ID)
t.Start(50)
frame.Show()
app1.MainLoop()
work5的更多相关文章
- python - work5 - 类与对象 - 拓展题
''' 5:购物车类,包含的功能如下,请自行设计这个类以及类里面的方法:1)用户输入工资后,打印商品列表(商品列表自行设计展示模式)2)允许用户根据商品编号去选择商品3)用户选择商品后,检查余额是否足 ...
- python - work5 - 类与对象
# -*- coding:utf-8 -*- '''@project: jiaxy@author: Jimmy@file: work_20181119.py@ide: PyCharm Communit ...
- Node.js显示页面
首先我们先要下载并安装Nodejs,然后进入Node.js中安装supervisor, npm -g install supervisor -g表示全局模式 (无论windows哪一个用户登陆都可以使 ...
- 4月10日java上机任务
1. 一维数组的创建和遍历. 声明并创建存放4个人考试成绩的一维数组,并使用for循环遍历数组并打印分数.要求: (1) 首先按“顺序”遍历,即打印顺序为:从第一个人到第四个人: (2) ...
- BM算法学习笔记
一种nb算法,可以求出数列的递推式. 具体过程是这样的. 我们先假设它有一个递推式,然后按位去算他的值. ;j<now.size();++j)(delta[i]+=1ll*now[j]*f[i- ...
- 团体程序设计天梯赛(CCCC) L3019 代码排版 方法与编译原理密切相关,只有一个测试点段错误
团体程序设计天梯赛代码.体现代码技巧,比赛技巧. https://github.com/congmingyige/cccc_code
- Java第一次实训
package com.wsy.work; public class JudgeNumber { public static void main(String[] args) { int a = 5; ...
- c++ 条件变量
.条件变量创建 静态创建:pthread_cond_t cond=PTHREAD_COND_INITIALIZER; 动态创建:pthread_cond _t cond; pthread_cond_i ...
- 2018 ACM 网络选拔赛 北京赛区
A Saving Tang Monk II #include <bits/stdc++.h> using namespace std; ; struct node { int x,y,z, ...
随机推荐
- 【原创】Sliding Window Maximum 解法分析
这道题是lintcode上的一道题,当然leetcode上同样有. 本题需要寻找O(N)复杂度的算法. 解体思路比较有特点,所以容易想到参考 最小栈 的解题办法. 但是最小栈用栈维护最小值很直观,这道 ...
- 《Linux/Unix系统编程手册》读书笔记2
<Linux/Unix系统编程手册>读书笔记 目录 第5章: 主要介绍了文件I/O更深入的一些内容. 原子操作,将一个系统调用所要完成的所有动作作为一个不可中断的操作,一次性执行:这样可以 ...
- NDK(15)在ndk代码中注册和注销native函数
转自: http://www.cnblogs.com/canphp/archive/2012/11/13/2768937.html C和C++注册native函数的方式大致上相同,下面给出具体的代码 ...
- struts1,struts2,springMVC终极对比
最近做项目用到了struts2,之前一直是用struts1和springMVC.感觉到了struts2从很大程度上和这两个还是有很大区别的,所以今天搜集了些资料,给他们做一下对比. Struts1官方 ...
- Android Studio修改包名和applicationId的方法
背景: 如果新做的项目跟以前做的某一个项目十分相似,那么一个简单的方法就是把原来项目拷贝一份,然后修改代码,但是这样包名还是原来项目的包名,还有如果想在同一台手机上同时安装新做的app和原来的app会 ...
- Codeforces Round #254 (Div. 2) B. DZY Loves Chemistry (并查集)
题目链接 昨天晚上没有做出来,刚看题目的时候还把题意理解错了,当时想着以什么样的顺序倒,想着就饶进去了, 也被题目下面的示例分析给误导了. 题意: 有1-n种化学药剂 总共有m对试剂能反应,按不同的 ...
- uva12034Race
递推,组合. 考虑第一名有i个人,则f[n]=sum(C(n,i)*f[n-i]),递推即可.. #include<cstdio> #include<algorithm> #i ...
- ASP.NET缓存OutputCache和Response.Cache之C#后台设置
一.ASPX页面缓存页面缓存的使用方法非常的简单,只需要在aspx页的顶部加一句声明<%@ OutputCache Duration="60" VaryByParam=&qu ...
- 浅析Java中HashMap的实现
概述 HashMap是一个散列表,是基于拉链法实现的.这个类继承了Map接口,Map接口提供了所有的哈希操作,比如set().put().remove()等,并且允许操作的键值对为null.HashM ...
- zend studio安装xdebug调试工具
1. 软件准备 登录xdebug 版本检测地址 http://xdebug.org/wizard.php :将phpinfo产生的数据页面复制到其文本框内,显示类似如下内容: 二.将下载的xdebu ...