doing something a bit more marco-polo-ish (and more interesting, too)

This commit is contained in:
Dan Buch 2012-06-16 23:29:57 -04:00
parent 5927b05f6c
commit 190bdbee9f
2 changed files with 123 additions and 39 deletions

View File

@ -1,25 +1,40 @@
require 'socket' require 'socket'
successes = 0 def main
backoff = 0.5 client_type = %w(read write).include?(ARGV.first) ? ARGV.first : 'read'
loop do sleep_interval = (ARGV[1] || 0).to_f
begin puts "Starting #{client_type} client"
TCPSocket.open('127.0.0.1', 22000) do |sock|
sock.send("sally #{rand(101)} #{rand(101)}\n", 0) successes = 0
sock.recv(100) backoff = 0.5
sock.close nextloc = [rand(0..99), rand(0..99)]
STDOUT.write('.') loop do
STDOUT.flush begin
TCPSocket.open('127.0.0.1', 22000) do |sock|
case client_type
when 'read'
sock.send("marco sally\n", 0)
location = sock.recv(100).to_s.split[2,4].map(&:to_i)
puts "#{location.first} #{location.last}"
when 'write'
sock.send("polo sally #{nextloc.first} #{nextloc.last}\n", 0)
nextloc = sock.recv(100).to_s.split.map(&:to_i)
puts "sent location '#{nextloc.first} #{nextloc.last}'"
end
sock.close
end
successes += 1
backoff = 0.5
sleep sleep_interval
rescue
puts "made it #{successes} times. sleeping #{backoff} secs"
successes = 0
sleep backoff
backoff *= 2
end end
successes += 1
backoff = 0.5
sleep 0.01 if ENV['SLEEP']
rescue
STDOUT.write('E')
STDOUT.flush
STDERR.write("\nmade it #{successes} times. sleeping #{backoff} secs\n")
successes = 0
sleep backoff
backoff *= 2
end end
end end
if $0 == __FILE__
main
end

View File

@ -1,33 +1,102 @@
require 'logger'
require 'eventmachine' require 'eventmachine'
require 'sequel' require 'sequel'
DB = Sequel.connect("postgres://#{ENV['USER']}@localhost/marco_polo", class MarcoPolo
:max_connections => 10) attr_reader :locations, :db
DB.create_table! :locations do
primary_key :id def initialize
String :client @pool_range = 0..99
Integer :x # I'm not using this (yet?) ... but don't want to forget how I did it
Integer :y # @pool = [].tap do |board|
# @pool_range.each do |y|
# board << [].tap do |row|
# @pool_range.each do |x|
# row << "#{y}-#{x}"
# end
# end
# end
# end
@db = Sequel.connect("postgres://#{ENV['USER']}@localhost/marco_polo",
:max_connections => 10)
unless @db.table_exists?(:locations)
@db.create_table :locations do
primary_key :id
String :client
DateTime :timestamp
Integer :x
Integer :y
constraint(:in_the_pool, 'x > -1 and x < 100 and y > -1 and y < 100')
end
end
@locations = @db[:locations]
puts "LET GAME BEGIN NOW"
end
def polo(client, x, y)
@locations.insert(:client => client, :x => x, :y => y,
:timestamp => Time.now)
nextloc(x, y)
end
def marco(client = nil)
if client
@locations.where(:client => client).order_by(:timestamp.desc).first
else
@locations.order_by(:timestamp.desc).first
end
end
private
def nextloc(x, y)
# we allow exiting the pool as long as you get back in on the opposite side
# a la pac man
move_x, move_y = rand(-2..2), rand(-2..2)
new_x = x + move_x
new_x = 100 + new_x if new_x <= -1
new_y = y + move_y
new_y = 100 + new_y if new_y <= -1
[
new_x > 99 ? new_x % 100 : new_x,
new_y > 99 ? new_y % 100 : new_y
]
end
end end
module MarcoPoloServer class MarcoPoloServer < EventMachine::Connection
def post_init class << self
@locations = DB[:locations] attr_accessor :game
end end
def receive_data(data) def receive_data(data)
client, x, y = data.split parts = data.to_s.split
@locations.insert(:client => client, :x => x.to_i, :y => y.to_i) case parts.first
send_data("thanks\n") when 'polo'
client, x, y = parts[1,4]
newloc = self.class.game.polo(client, x.to_i, y.to_i)
send_data("#{newloc.first} #{newloc.last}\n")
when 'marco'
if loc = self.class.game.marco(parts[1])
send_data("polo #{loc[:client]} #{loc[:x]} #{loc[:y]}\n")
else
send_data("polo NULL 0 0\n")
end
else
send_data("#{parts.first}???\n")
end
rescue => e rescue => e
STDERR.puts("#{e.class.name} #{e.message}: #{e.backtrace.join("\n")}") STDERR.puts("#{e.class.name} #{e.message}: #{e.backtrace.join("\n")}")
end end
end end
EventMachine.run do def main
host, port = '0.0.0.0', 22000 MarcoPoloServer.game = MarcoPolo.new
EventMachine.start_server(host, port, MarcoPoloServer) EventMachine.run do
puts "Listening on #{host}:#{port}" host, port = '0.0.0.0', 22000
EventMachine.start_server(host, port, MarcoPoloServer)
puts "Listening on #{host}:#{port}"
end
end
if $0 == __FILE__
main
end end