------=_Part_8118_7473268.1200248517958 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline Well I feel save enough to answer ;). The attached solution does not seem to work on Windows (Timeout::timeout does not timeout) and as I have no Mac I cannot tell. On Linux it seems to work fine though, sorry for the revolutionary user interface but I tried to separate the dealing mechanism from the UI quite ok so if someone wants to write a plugin ;). Ok here we go file: human-interface.rb ============== require 'timeout' class << HumanInterface = Object.new attr_reader :errors def read_int_within_delay delay Timeout::timeout( delay ){ $stdin.readline.chomp } rescue Timeout::Error nil end def show_cards cards, delay, count @errors ||= 0 puts cards.join(",") print "> " $stdout.flush read_value = read_int_within_delay delay case read_value when nil @errors += 1 puts "Sorry timeout, current count is #{count}" else if read_value.to_i == count puts "ok" else @errors += 1 puts "Sorry this is incorrect, current count is #{count}" end end end end file:robert-dober-152.rb ============== require 'human-interface' class Array def random_element self[ rand( size ) ] end def shift_some n=1 (1..[n,size].min).map{ shift } end def zip_with zip_value zip [ zip_value ] * size end end class Shoe ShoeParameters = %w{ decks delay cards } HonorCards = %w{ 10 J Q K A } MediumCards = %w{ 8 9 } SmallCards = %w{ 2 3 4 5 6 7 } CardValues = Hash[ *( HonorCards.zip_with( -1 ) + MediumCards.zip_with( 0 ) + SmallCards.zip_with( 1 ) ).flatten ] FaceValues = SmallCards + MediumCards + HonorCards private def draw_cards cards = @deck.shift_some @cards.random_element @count += cards.inject(0){|s, c| s + CardValues[c[1..-1]]} cards end def initialize params = {} set_ivars_default params.each do | name, value | instance_variable_set "@#{name}", value raise RuntimeError, "No such parameter #{name}" unless ShoeParameters.include? name.to_s end set_computed_ivars end def set_computed_ivars @count = 4 * ( 1 - @decks ) @deck = %w{S H D C}.inject([]){ |deck, suit| deck + FaceValues.map{ |c| suit + c } } * @decks @deck = @deck.sort_by{ rand } end def set_ivars_default @decks = 2 @delay = 3 @cards = 2 end public def training human_interface loop do return if @deck.empty? cards = draw_cards human_interface.show_cards cards, @delay, @count end end end def usage puts <<-EOS usage: #{$0} <number of decks> <delay in seconds> <cards drawn> [<cards max drawn>] Trains you in counting cards. The trainer uses the number of decks you indicate as first parameter, shows you the drawn cards for a delay in seconds indicated as the second parameter. The number of cards drawn at each draw is either constant, as indicated by the third parameter or random in a range bound by the third and fourth parameter. EOS exit -1 end usage if ARGV.size < 3 || /^-h|^--help/ === ARGV.first training_shoe = Shoe.new :decks => ARGV[0].to_i, :delay => ARGV[1].to_i, :cards => [*ARGV[2].to_i .. (ARGV[3]||ARGV[2]).to_i] puts "Starting training with #{ARGV.first} decks of cards:" sleep 1 training_shoe.training HumanInterface puts "Total errors made: #{HumanInterface.errors}" ------=_Part_8118_7473268.1200248517958 Content-Type: application/x-ruby; name=robert-dober-152.rb Content-Transfer-Encoding: base64 X-Attachment-Id: f_fbdwttp90 Content-Disposition: attachment; filename=robert-dober-152.rb IyB2aW06IHN3PTIgdHM9MiBmdD1ydWJ5IGV4cGFuZHRhYiB0dz0wIG51OgpyZXF1aXJlICdodW1h bi1pbnRlcmZhY2UnCgpjbGFzcyBBcnJheQogIGRlZiByYW5kb21fZWxlbWVudAogICAgc2VsZlsg cmFuZCggc2l6ZSApIF0KICBlbmQKICBkZWYgc2hpZnRfc29tZSBuPTEKICAgICgxLi5bbixzaXpl XS5taW4pLm1hcHsgc2hpZnQgfQogIGVuZAogIGRlZiB6aXBfd2l0aCB6aXBfdmFsdWUKICAgIHpp cCBbIHppcF92YWx1ZSBdICogc2l6ZQogIGVuZAoKZW5kCgpjbGFzcyBTaG9lCiAgU2hvZVBhcmFt ZXRlcnMgPSAld3sgZGVja3MgZGVsYXkgY2FyZHMgfQoKICBIb25vckNhcmRzID0gJXd7IDEwIEog USBLIEEgfQogIE1lZGl1bUNhcmRzID0gJXd7IDggOSB9CiAgU21hbGxDYXJkcyA9ICV3eyAyIDMg NCA1IDYgNyB9CgogIENhcmRWYWx1ZXMgPSBIYXNoWyAqKCAKICAgICAgICAgICAgICAgICAgICAg IEhvbm9yQ2FyZHMuemlwX3dpdGgoIC0xICkgKyAKICAgICAgICAgICAgICAgICAgICAgIE1lZGl1 bUNhcmRzLnppcF93aXRoKCAwICkgKwogICAgICAgICAgICAgICAgICAgICAgU21hbGxDYXJkcy56 aXBfd2l0aCggMSApIAogICAgICAgICAgICAgICAgICAgICAgKS5mbGF0dGVuIF0KCiAgRmFjZVZh bHVlcyA9IFNtYWxsQ2FyZHMgKyBNZWRpdW1DYXJkcyArIEhvbm9yQ2FyZHMKCiAgcHJpdmF0ZQog IGRlZiBkcmF3X2NhcmRzCiAgICBjYXJkcyA9IEBkZWNrLnNoaWZ0X3NvbWUgQGNhcmRzLnJhbmRv bV9lbGVtZW50CiAgICBAY291bnQgKz0gY2FyZHMuaW5qZWN0KDApe3xzLCBjfCBzICsgQ2FyZFZh bHVlc1tjWzEuLi0xXV19CiAgICBjYXJkcwogIGVuZAoKICBkZWYgaW5pdGlhbGl6ZSBwYXJhbXMg PSB7fQogICAgc2V0X2l2YXJzX2RlZmF1bHQKCiAgICBwYXJhbXMuZWFjaCBkbyAgfCBuYW1lLCB2 YWx1ZSB8CiAgICAgIGluc3RhbmNlX3ZhcmlhYmxlX3NldCAiQCN7bmFtZX0iLCB2YWx1ZQogICAg ICByYWlzZSBSdW50aW1lRXJyb3IsICJObyBzdWNoIHBhcmFtZXRlciAje25hbWV9IiB1bmxlc3MK ICAgICAgICBTaG9lUGFyYW1ldGVycy5pbmNsdWRlPyBuYW1lLnRvX3MKICAgIGVuZAoKICAgIHNl dF9jb21wdXRlZF9pdmFycwogIGVuZAoKICBkZWYgc2V0X2NvbXB1dGVkX2l2YXJzCiAgICBAY291 bnQgPSA0ICogKCAxIC0gQGRlY2tzICkKICAgIEBkZWNrID0gJXd7UyBIIEQgQ30uaW5qZWN0KFtd KXsgfGRlY2ssIHN1aXR8CiAgICAgIGRlY2sgKyBGYWNlVmFsdWVzLm1hcHsgfGN8IHN1aXQgKyBj IH0KICAgIH0gKiBAZGVja3MKICAgIEBkZWNrID0gQGRlY2suc29ydF9ieXsgcmFuZCB9CiAgZW5k CgogIGRlZiBzZXRfaXZhcnNfZGVmYXVsdAogICAgQGRlY2tzID0gMgogICAgQGRlbGF5ID0gMwog ICAgQGNhcmRzID0gMgogIGVuZAoKICBwdWJsaWMKICBkZWYgdHJhaW5pbmcgaHVtYW5faW50ZXJm YWNlCiAgICBsb29wIGRvCiAgICAgIHJldHVybiBpZiBAZGVjay5lbXB0eT8KICAgICAgY2FyZHMg PSBkcmF3X2NhcmRzCiAgICAgIGh1bWFuX2ludGVyZmFjZS5zaG93X2NhcmRzIGNhcmRzLCBAZGVs YXksIEBjb3VudAogICAgZW5kCiAgZW5kCmVuZAoKZGVmIHVzYWdlCiAgcHV0cyA8PC1FT1MKICB1 c2FnZToKICAgICN7JDB9IDxudW1iZXIgb2YgZGVja3M+IDxkZWxheSBpbiBzZWNvbmRzPiA8Y2Fy ZHMgZHJhd24+IFs8Y2FyZHMgbWF4IGRyYXduPl0KCiAgVHJhaW5zIHlvdSBpbiBjb3VudGluZyBj YXJkcy4gVGhlIHRyYWluZXIgdXNlcyB0aGUgbnVtYmVyIG9mIGRlY2tzIHlvdSBpbmRpY2F0ZQog IGFzIGZpcnN0IHBhcmFtZXRlciwgc2hvd3MgeW91IHRoZSBkcmF3biBjYXJkcyBmb3IgYSBkZWxh eSBpbiBzZWNvbmRzIGluZGljYXRlZAogIGFzIHRoZSBzZWNvbmQgcGFyYW1ldGVyLgogIFRoZSBu dW1iZXIgb2YgY2FyZHMgZHJhd24gYXQgZWFjaCBkcmF3IGlzIGVpdGhlciBjb25zdGFudCwgYXMg aW5kaWNhdGVkIGJ5IHRoZQogIHRoaXJkIHBhcmFtZXRlciBvciByYW5kb20gaW4gYSByYW5nZSBi b3VuZCBieSB0aGUgdGhpcmQgYW5kIGZvdXJ0aCBwYXJhbWV0ZXIuCiAgRU9TCiAgZXhpdCAtMQpl bmQKCnVzYWdlIGlmIEFSR1Yuc2l6ZSA8IDMgfHwgL14taHxeLS1oZWxwLyA9PT0gQVJHVi5maXJz dCAKdHJhaW5pbmdfc2hvZSA9IFNob2UubmV3IDpkZWNrcyA9PiBBUkdWWzBdLnRvX2ksCiAgICAg ICAgIDpkZWxheSA9PiBBUkdWWzFdLnRvX2ksCiAgICAgICAgIDpjYXJkcyA9PiBbKkFSR1ZbMl0u dG9faSAuLiAoQVJHVlszXXx8QVJHVlsyXSkudG9faV0KCnB1dHMgIlN0YXJ0aW5nIHRyYWluaW5n IHdpdGggI3tBUkdWLmZpcnN0fSBkZWNrcyBvZiBjYXJkczoiCnNsZWVwIDEKdHJhaW5pbmdfc2hv ZS50cmFpbmluZyBIdW1hbkludGVyZmFjZQoKcHV0cyAiVG90YWwgZXJyb3JzIG1hZGU6ICN7SHVt YW5JbnRlcmZhY2UuZXJyb3JzfSIK ------=_Part_8118_7473268.1200248517958 Content-Type: application/x-ruby; name=human-interface.rb Content-Transfer-Encoding: base64 X-Attachment-Id: f_fbdwu8aj1 Content-Disposition: attachment; filename=human-interface.rb DQpyZXF1aXJlICd0aW1lb3V0Jw0KDQpjbGFzcyA8PCBIdW1hbkludGVyZmFjZSA9IE9iamVjdC5u ZXcNCiAgYXR0cl9yZWFkZXIgOmVycm9ycw0KICBkZWYgcmVhZF9pbnRfd2l0aGluX2RlbGF5IGRl bGF5DQogICAgVGltZW91dDo6dGltZW91dCggZGVsYXkgKXsgJHN0ZGluLnJlYWRsaW5lLmNob21w IH0NCiAgcmVzY3VlIFRpbWVvdXQ6OkVycm9yDQogICAgbmlsDQogIGVuZA0KDQogIGRlZiBzaG93 X2NhcmRzIGNhcmRzLCBkZWxheSwgY291bnQNCiAgICBAZXJyb3JzIHx8PSAwDQogICAgcHV0cyBj YXJkcy5qb2luKCIsIikNCiAgICBwcmludCAiPiAiDQogICAgJHN0ZG91dC5mbHVzaA0KICAgIHJl YWRfdmFsdWUgPSByZWFkX2ludF93aXRoaW5fZGVsYXkgZGVsYXkNCiAgICBjYXNlIHJlYWRfdmFs dWUNCiAgICB3aGVuIG5pbA0KICAgICAgQGVycm9ycyArPSAxDQogICAgICBwdXRzICJTb3JyeSB0 aW1lb3V0LCBjdXJyZW50IGNvdW50IGlzICN7Y291bnR9Ig0KICAgIGVsc2UNCiAgICAgIGlmIHJl YWRfdmFsdWUudG9faSA9PSBjb3VudA0KICAgICAgICBwdXRzICJvayINCiAgICAgIGVsc2UNCiAg ICAgICAgQGVycm9ycyArPSAxDQogICAgICAgIHB1dHMgIlNvcnJ5IHRoaXMgaXMgaW5jb3JyZWN0 LCBjdXJyZW50IGNvdW50IGlzICN7Y291bnR9Ig0KICAgICAgZW5kDQogICAgZW5kDQogIGVuZCAN CmVuZA0K ------=_Part_8118_7473268.1200248517958--