homework-05

接口声明

/reg

GET:

    输出一个注册表单,其中

    id:用户名

    pd:密码

POST:

    接收一个表单{id="",pd=""},返回:

    0:注册成功

    -1:注册失败

/attend

GET:

    输出一个游戏参与表单,其中

    id:用户名

    pd:密码

    num:1-100之间的实数,表示所要提交的数字

POST:

    接受一个表单(id="",pd="",num=""),返回:

    -1:用户名不存在

    -2:密码错误

    -3:数字范围出错(必须在1-100之间)

    -4:游戏结束 
   left_time+","+now_turn+","+success?: left_time:表示下一轮多少秒后开始 now_turn:当前轮数 success?:1表示提交成功,0表示提交失败(服务器锁中,正在计算)

/result

GET:

    返回n行,倒序的golden_number

/

GET:

    返回综合信息榜

游戏流程和设计简述

游戏一开始(第0轮)有20s的注册时间,这段时间内必须注册好用户,注册的用户提交{用户名,密码}到/reg,服务器返回0表示提交成功,返回-1表示用户名重复了。这保证了一个用户名只能存在一个。

每次用户往/attend提交自己的 {用户名、密码、数}时,服务器返回三个信息:下一轮比赛开始时间time,当前提交的轮数turn,当前提交是否成功succ。通过后两个信息可以得知自己的提交结果。而time预示了下一轮比赛的开始时间,客户端可以sleep(time)再继续提交,所以说这样客户端很容易实现自动游戏。

这就意味着,客户端和服务端之间不“等待”,服务端不等待所有用户提交后才进行游戏。所以游戏时间是均匀的(我设定为1.2s一次),为了保证能计算出游戏结果,在游戏的最后0.2s里不允许用户再进行提交了。

为了让客户端程序能得到更多可供AI调用的信息,我们在/result里返回了历史的Golden number,来让客户端“学习”golden number分布的模式。

程序主体采用Python编写,http请求处理使用webpy框架实现,主要对每个url实现了GET/POST相应。

在综合信息榜(/)上,为了实现更好的信息展示效果,我们用了canvas元素来绘制折线图,加上Ajax通信手段,来实现异步刷新golden number 变化曲线。

主程序分两类线程,一类线程用来处理http请求,这方面的线程调度由webpy自动处理。另一个线程是游戏结果处理线程。两类线程之间通过全局变量来通信。

Peer用ruby写了个随机提交数字的程序,测试时使用1.2s进行一次游戏,一共40个客户端,能在规定时间内跑完100轮游戏,并输出结果。

回答问题

  1. 你对于这个系统的服务器和接口是如何设计的?  应该采取哪些设计让游戏能顺利完成? 写出具体的接口。

   接口上边已经说了。

  1. 你和你的同伴分工负责, 设计出服务器应该有几个功能模块,  这些功能模块之间的关系 (用 UML 或其它图例来表示)。

   功能模块主要分http请求处理线程和游戏处理线程。 模块之间通过全局变量来通信。uml不会。

  1. 写出每个模块功能的伪代码,要能做到让另一个同学能看到这些伪代码,就能明确实现的要求并马上开始实现。

      ??

  1. 我们的课程有 60 名学生 (60 个客户程序),如何能设计服务器程序和交互的接口让它能在 1 秒钟之内就完成一轮比赛?  

   可以,只需要加个随机随机化让用户分散在0.5秒里均匀访问就行了。当然我们不能假设用户的行为,   但可以规定。

 

主程序

  1 import web
  2 import string
  3 import time
  4 import thread
  5 from web import form
  6 import data
  7 
  8 urls = (
  9     '/reg','reg',
 10     '/attend','attend',
 11     '/','board',
 12     '/result','result',
 13     '/resulthtml','resulthtml',
 14     '/scorehtml','scorehtml',
 15     '/infohtml','infohtml',
 16     '/turnhtml','turnhtml',
 17     '/totalboard','totalboard'
 18 )
 19 
 20 render = web.template.render('templates/')
 21 app = web.application(urls, globals())
 22 
 23 regform = form.Form(
 24     form.Textbox("id",
 25         form.notnull),
 26     form.Password("pd",
 27         form.notnull)
 28 )
 29 
 30 attendform = form.Form(
 31     form.Textbox("id",
 32         form.notnull),
 33     form.Password("pd",
 34         form.notnull),
 35     form.Textbox("num",
 36         form.regexp('\d+', 'Must be a digit')),    
 37 )
 38 
 39 
 40 class turnhtml:
 41     def GET(self):
 42         return data.nowturn
 43 
 44 class infohtml:
 45     def GET(self):
 46         if data.gameover==1:
 47             return "<b>Game is over!</b> the winner is  <b>" + data.winner + "</b>  score is  <b>" + str(data.users[data.winner]) +"</b>"
 48         else:
 49             return "LEFT "+ str(data.TURNTIME-(time.time()-data.nowstart)) + "s TO SUBMIT YOUR NUMBER"
 50 
 51 class result:
 52     def GET(self):
 53         s = ""
 54         for i in range(len(data.alluped)-1,-1,-1):
 55             s += str(data.alluped[i]['result']) + '\n'
 56         return s
 57 
 58 class resulthtml:
 59     def GET(self):
 60         s = "<table ><tr><td>Round:</td>"
 61         l = len(data.alluped)
 62         for i in range(l-1,max(l-12,-1),-1):
 63             s += "<td>"+str(i)+"</td>"
 64         s +="</tr><td></td>"
 65         for i in range(l-1,max(l-12,-1),-1):
 66             s += "<td>"+str(data.alluped[i]['result'])+"</td>"
 67         s += "</tr></table>"
 68         return s
 69 
 70 class scorehtml:
 71     def GET(self):
 72         b = sorted(data.users.iteritems(),key=lambda a:a[1],reverse = True)
 73         return render.scorehtml(b,data.alluped)
 74 
 75 class totalboard:
 76     def GET(self):
 77         return render.totalboard(data.users,data.alluped)
 78 
 79 class reg:
 80     def GET(self):
 81         form = regform()
 82         return render.reg(form)        
 83     def POST(self):
 84         form = regform()
 85         if not form.validates():
 86             return render.reg(form)
 87         else:
 88             i = web.input()
 89             myvar = dict(id = i.id)
 90             result = list(data.db.select('users',myvar,where = "id = $id"))
 91             if result==[]:
 92                 data.db.insert('users',id = i.id,pd = i.pd)
 93                 data.users[i.id]=0.0    
 94                 return 0
 95             else:
 96                 return -1
 97 
 98 class attend:
 99     def GET(self):
100         form = attendform()
101         return render.attend(form)
102     def POST(self):
103         form = attendform()
104         if not form.validates():
105             return render.attend(form)
106         else:
107             i = web.input()
108             i.num = string.atof(i.num)
109             result = list(data.db.select('users',where = 'id = "%s"'%(i.id)))
110             if result==[]:
111                 return -1
112             if result[0]['pd']!=i.pd:
113                 return -2
114             if 100<i.num or i.num<1:
115                 return -3
116             if data.gameover == 1:
117                 return -4
118             a = data.nowuped.get(i.id)
119             t = data.TURNTIME-(time.time()-data.nowstart)
120             if a==None and t>=data.DEAD:
121                 data.nown += 1
122                 data.nowtot += i.num
123                 data.nowuped[i.id] = dict(num = i.num,deltscore = 0)
124             return "%f,%d,%d"%(data.TURNTIME-(time.time()-data.nowstart),data.nowturn,a==None and t>=data.DEAD)
125 
126 class board:
127     def GET(self):
128         t = data.TURNTIME-(time.time()-data.nowstart)
129         a = render.board(data.DEAD,data.TURNTIME,t>=data.DEAD,data.nowturn,t,data.alluped,data.users,data.TURNTIME)
130         return a
131 def dealwinlost(uped,users,avgn,nowturn):
132     minv = 101
133     maxv = 0
134     winner = 0
135     for i in uped:
136         delt = abs(uped[i]['num']-avgn)
137         if delt>maxv:
138             maxv = delt
139         if delt<minv:
140             minv = delt
141             winner = i
142     uped[winner]['deltscore'] = 10
143     for i in uped:
144         if i==winner:
145             continue
146         delt = abs(uped[i]['num']-avgn)
147         if delt==maxv:
148             uped[i]['deltscore'] = -1
149     a = list(data.db.select('users'))
150     for i in a:
151         if i['id'] not in uped and i['id']!=winner:
152             uped[i['id']] = dict(num = 0.0,deltscore = -5)
153     for i in a:
154         users[i['id']] += uped[i['id']]['deltscore']
155     return winner
156 
157 def gameinit():
158     a = list(data.db.select('users'))
159     for i in a:
160         data.users[i['id']]=0.0    
161 
162 def roundinit():
163     data.nowuped = {}
164     data.nown = 0
165     data.nowtot = 0
166 
167 def round():
168     data.nowstart = time.time()
169     time.sleep(data.TURNTIME-data.DEAD)
170     if (data.nown!=0):
171         avgn = data.nowtot/data.nown * 0.618
172         data.nowuped['winner'] = dealwinlost(data.nowuped,data.users,avgn,data.nowturn)
173         data.nowuped['result'] = avgn
174         data.nowuped['turn'] = data.nowturn
175         data.alluped.append(data.nowuped)
176         data.nowturn += 1
177         if data.nowturn >= data.MAXTURN:
178             data.gameover = 1
179         t =data.TURNTIME-(time.time()-data.nowstart)
180         if t>0:
181             time.sleep(t)
182 
183 def game():
184     gameinit()
185     temp = data.TURNTIME
186     data.TURNTIME = 20
187     round()
188     data.TURNTIME = temp
189     while True:
190         roundinit()
191         round()
192         if data.gameover ==1:
193             break
194     maxscore = -100000
195     for i in data.users:
196         if data.users[i]>maxscore:
197             maxscore = data.users[i]
198             data.winner = i
199     thread.exit_thread() 
200 
201 if __name__ == "__main__":
202     thread.start_new_thread(game,())
203     app.run()
View Code

 

演示效果

posted @ 2013-11-03 01:01  Forwil  阅读(249)  评论(0编辑  收藏  举报