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, ...
随机推荐
- hadoop-0.23.9安装以及第一个mapreduce测试程序
hadoop是一个能够对大量数据进行分布式处理的软件框架.它实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS.HDFS有着高容错性的特点,并且设计 ...
- cmd打开git
一旦你的git安装成功,而且在安装是没有选择可以使用cmd黑窗口来打开,那么你再来设置会很麻烦,我表示不会. 今天分享下同事分享给我的一个不错的方法. 这个方法依赖一个 Dos 文件(.bat文件), ...
- centos6.5安装mongodb
搜索正面五个文件,由于MongoDB的redhat国外镜像访问非常慢,下载安装suse版本并安装: mongodb-org-2.6.6-1.i686.rpm mongodb-org-mongos-2. ...
- Android自动化测试之Monkeyrunner从零开始(三)
转自http://www.51testing.com/html/81/22381-854342.html 时光过得太快了,一晃离上一篇monkeyrunner系列的博客已经一年多了.这一年多时间经历了 ...
- hdu 4920 Matrix multiplication (矩阵计算)
题目链接 题意:给两个矩阵a, b, 计算矩阵a*b的结果对3取余. 分析:直接计算时间复杂度是O(n^3),会超时,但是下面第一个代码勉强可以水过,数据的原因. #include <iostr ...
- 计算几何基础——矢量和叉积 && 叉积、线段相交判断、凸包(转载)
转载自 http://blog.csdn.net/william001zs/article/details/6213485 矢量 如果一条线段的端点是有次序之分的话,那么这种线段就称为 有向线段,如果 ...
- 结构体key
http://www.cnblogs.com/xpchild/p/3770823.html http://blog.sae.sina.com.cn/archives/3968 实例 http://bl ...
- Jqgrid入门-Jqgrid设置二级表头(六)
上一章已经说明了Jqgrid结合Struts2+json展示数据,这一章主要探讨Jqgrid如何设置二级表头,类似这样的效果.如: 要实现这个功能,其实也不难.通过Jqgrid的s ...
- 手动配置gradle
最近从github倒入项目,运行的特别慢gradle配置有问题,解决方法: 1.C:\android\demo\hellocharts-android-master\gradle\wrapper 目录 ...
- WDF模型驱动程序开发
WDF驱动程序开发 1. 引言 设备驱动程序是硬件设备连接到计算机系统的软件接口,任何设备都必须有相应的驱动程序才能在计算机系统上正常工作.设备驱动程序的优劣直接关系到整个系统的性能和稳定性,因此,设 ...