The players can code agents, which then will be uploaded to participate to the tournaments.
I hope to release a first beta version still this month, until then I leave you with a first screenshot showing the ranking page:
rvm install 1.9 rvm use ruby 1.9Darauf installiert RVM automatisch die aktuelle 1.9 Version.
undefined method `^' for "c":String (NoMethodError)Deshalb muss auf 2.3.3 zurückgegriffen werden:
gem install -v='2.3.3' railsMein Projekt nutzt Cucumber und RSpec als Testframeworks. Hier können zwar die neusten Versionen installiert werden, jedoch muss auch Test-Unit mit der Version 1.2.3 und zwar exakt diese mitinstalliert werden:
gem install cucumber rspec rspec-rails webrat gem install -v="1.2.3" test-unitAls nächstes meldete Nokogiri, das von Webrat genutzt wird, einen Konflikt:
dyld: lazy symbol binding failed: Symbol not found: _rb_intern2 Referenced from: /Users/adm/.rvm/gems/ruby/1.9.1/gems/nokogiri-1.3.3/lib/nokogiri/nokogiri.bundle Expected in: flat namespace dyld: Symbol not found: _rb_intern2 Referenced from: /Users/adm/.rvm/gems/ruby/1.9.1/gems/nokogiri-1.3.3/lib/nokogiri/nokogiri.bundle Expected in: flat namespace Trace/BPT trapUm diesen Konflikt zu lösen musste ich über Ports meine libxml Bibliothek aktualisieren und Nokogiri nochmals installieren:
sudo port install libxml2 sudo port install libxslt gem install nokogiriDanach startete mein Projekt endlich unter Ruby 1.9 auf. Meine eignen Konflikte mit 1.9 konnte ich dank meinen Testsuits innerhalb einer halben Stunde lösen. Gute Tests sind wirklich Gold wert.
class SyncObject
def initialize
@semaphore = Mutex.new
end
def synchronize &block
@semaphore.synchronize &block
end
end
Before changing something in the sim objects, I synchronize them :
object.synchronize do
# change the state of the object
end
But as things were growing, I suddently got some deadlocks. After some research I found out, that a thread was invoking synchronize on the same object multiple times. The semaphore object doesn't care which thread is locking it. As long it's locked it will block all threads until the block is finished. Even if it's the same thread, that locked the semaphore just before.
it "should not block the same thread when synchronizing" do
object = SyncObject.new
object.synchronize do
object.synchronize do
object.synchronize do
true.should be_true
end
end
end
end
it "should block two different threads when synchronizing" do
object = SyncObject.new
wait_for_me = true
object.synchronize do
Thread.fork do
object.synchronize do
wait_for_me = false
end
end
sleep 1
wait_for_me.should be_true
end
wait_for_me.should be_false
end
The first test's pretty straight forward, we want to allow nested synchronize blocks for the same thread.
class SyncObject
def initialize
@semaphore = Mutex.new
end
def synchronize
unless @current_thread == Thread.current
@semaphore.synchronize do
@current_thread = Thread.current
yield
@current_thread = nil
end
else
yield
end
end
end
The first time synchronize is accessed, @current_thread is set to the current running thread. The semaphore is locked and the blocked yield. If in the meantime a different thread invokes synchronize, it will be blocked until the first one finishes the block. Else if the same thread access the method in the meantime, it will not try to lock the semaphore again, but can yield its new block immediately.
require File.expand_path(File.dirname(__FILE__)+'/../../init') # Comment out the next line if you don't want Cucumber Unicode support require 'cucumber/formatter/unicode'To run the stories I need to execute cucumber features/ in the corresponding direcotries. Running the rake features doesn't work for me as env.rb is not loaded.
require 'drb'
class SimpleServer
def initialize
DRb.start_service('druby://localhost:9000', self)
end
def server_time
Time.now
end
end
SimpleServer.new
DRb.thread.join
In the constructor we start the drb service and register the server to localhost on port 9000. Then we have a very simple method, which just returns the time on the server, that we now want to call from our client. The last line prevents the programm to exit and keeps the server thread waiting for incoming requests.
require 'drb'
class SimpleClient
def initialize
@remote = DRbObject.new(nil, 'druby://localhost:9000')
end
def time_on_server
puts "Time on server #{@remote.server_time}"
end
end
client = SimpleClient.new
client.time_on_server
In the client's constructor we get the remote object of the previous registered server. After that we can call the "time_on_server" method to print it on the client side.
def time_on_client
puts "Time on client #{yield}"
end
and in the client:
def client_time
@remote.time_on_client { Time.now }
end
Calling now "client_time" from the client, will raise a DRb::DRbServerNotFound error. The client fails to provide a drb proxy object for the server, which would need it to call the block on the client again. Blocks are bind to the environment, where they have been defined, in our case on the client.
def initialize
DRb.start_service
@remote = DRbObject.new(nil, 'druby://localhost:9000')
end
So in Ruby we often have symetric roles, both sides need to act as client and server.
Zlib::GzipReader.open(filename) do |gz|
x = 0
# read one line (16-Bit-Integer = 2 bytes)
while line = gz.read(2 * @size)
@data[x] = line.unpack('s' * @size)
x += 1
end
end
If you need more, have a look at BitStruct. It provides a nice DSL for handling binaries.