您的位置:首页 > 其它

homework-05

2013-11-04 01:48 267 查看

接口声明

/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:

返回综合信息榜

设计说明

这次服务器是由forwil同学编写的。

游戏一开始(第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自动处理。另一个线程是游戏结果处理线程。两类线程之间通过全局变量来通信。

我主要写了客户端,根据以上接口进行注册和提交,并尝试了40个线程同时提交,效果还可以。但由于ruby的多线程是用户级的 ,调度上可能稍慢,如果分开多个进程效果更好。

提交策略参考了邹欣老师的一篇关于黄金点游戏的文章,根据一般情形下 黄金点游戏的趋势来提交。

为了能让服务器能在一秒内完成比赛,我们在设计接口的时候进行了一些简化。 游戏开始后只有两个请求,并且通过返回距下一次游戏开始的时间来减少请求。 后来forwil同学又简化了数据库操作,使数据先暂存,直到游戏结束再进行存储。这样大大减少 了服务器的负担,基本上能一秒进行一次游戏。

回答问题

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

   接口上边已经说了。

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

   功能模块主要分http请求处理线程和游戏处理线程。 模块之间通过全局变量来通信。简单的说就是客户端请求提交数字,服务端接受并返回下一次游戏开始时间,客户端sleep相应时间避免无意义的提交。

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

   方法很简单,上面一句话就能明白了。

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

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

程序代码

require "net/http"
params = Hash.new
params[:id] = ARGV[0]
params[:pd] = ARGV[1]
addr = "http://192.168.1.3"
uri = URI.parse(addr + "/reg")
res = Net::HTTP.post_form(uri, params)

def gen(last)
if last > 5
temp = last - rand * Math.exp( last / 5 )
return 1 if temp < 1
temp
else
last + rand * Math.exp( last / 2 )
end
end
last = 40

while true
params[:num] = gen(last)
uri = URI.parse(addr + "/attend")
res = Net::HTTP.post_form(uri, params)
str = res.body.split(/,/)

time = str[0].to_f
turn = str[1].to_i
succ = str[2].to_i

puts time
sleep(time)

uri = URI.parse(addr + "/result")
res = Net::HTTP.get(uri)
str = res.split(/\n/)
last = str[0].to_f
end


client

演示效果

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: