# encoding: UTF-8 require File.expand_path(File.dirname(__FILE__) + '/spec_helper') module ICU class Tournament describe Krause do def check_player(num, first, last, other={}) p = @t.player(num) expect(p.first_name).to eq(first) expect(p.last_name).to eq(last) [:gender, :title, :rating, :fide_rating, :fed, :id, :fide_id, :dob, :rank].each do |key| expect(p.send(key)).to eq(other[key]) if other.has_key?(key) end end def check_results(num, results, points) p = @t.player(num) expect(p.results.size).to eq(results) expect(p.points).to eq(points) end context "a typical tournament" do before(:all) do krause = < true) end it "should have a name, city and federation" do expect(@t.name).to eq('Las Vegas National Open') expect(@t.city).to eq('Las Vegas') expect(@t.fed).to eq('USA') end it "should have start and end dates" do expect(@t.start).to eq('2008-06-07') expect(@t.finish).to eq('2008-06-09') end it "should have a number of rounds, a type and a time control" do expect(@t.rounds).to eq(3) expect(@t.last_round).to eq(3) expect(@t.type).to eq('All-Play-All') expect(@t.time_control).to eq('60 in 2hr, 30 in 1hr, rest in 1hr') end it "should have an arbiter and deputies" do expect(@t.arbiter).to eq('Hans Scmidt') expect(@t.deputy).to eq('Gerry Graham, Herbert Scarry') end it "should have players and their details" do expect(@t.players.size).to eq(3) check_player(1, 'Gearoidin', 'Ui Laighleis', :gender => 'F', :fide_rating => 1985, :fed => 'IRL', :fide_id => 2501171, :dob => '1964-06-10', :rank => 2) check_player(2, 'Mark', 'Orr', :gender => 'M', :fide_rating => 2258, :fed => 'IRL', :fide_id => 2500035, :dob => '1955-11-09', :rank => 1, :title => 'IM') check_player(3, 'Viktor', 'Bologan', :gender => 'M', :fide_rating => 2663, :fed => 'MDA', :fide_id => 13900048, :dob => '1971-01-01', :rank => 3, :title => 'GM') end it "should have correct results for each player" do check_results(1, 2, 1.0) check_results(2, 2, 2.0) check_results(3, 2, 0.0) end it "should have correct round dates" do expect(@t.round_dates.join('|')).to eq('2008-06-07|2008-06-08|2008-06-09') end it "the parser should retain comment lines" do comments = < 'F', :rating => 1900, :fed => 'USA', :fide_id => 1234567, :dob => '1928-05-15', :rank => 2) check_player(2, 'Daffy', 'Duck', :gender => 'M', :rating => 2200, :fed => 'IRL', :fide_id => 7654321, :dob => '1937-04-17', :rank => 1, :title => 'IM') check_player(3, 'Mickey', 'Mouse', :gender => 'M', :rating => 2600, :fed => 'USA', :fide_id => 1726354, :dob => '1928-05-15', :rank => 3, :title => 'GM') end it "should have correct results for each player" do check_results(1, 2, 1.0) check_results(2, 2, 2.0) check_results(3, 2, 0.0) end it "the parser should retain comment lines" do expect(@p.comments).to eq("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n") end end context "the README serialisation example" do before(:all) do @t = ICU::Tournament.new('World Championship', '1972-07-11') @t.add_player(ICU::Player.new('Robert J.', 'Fischer', 1)) @t.add_player(ICU::Player.new('Boris V.', 'Spassky', 2)) @t.add_result(ICU::Result.new(1, 1, 'L', :opponent => 2, :colour => 'B')) @t.add_result(ICU::Result.new(2, 1, 'L', :opponent => 2, :colour => 'W', :rateable => false)) @t.add_result(ICU::Result.new(3, 1, 'W', :opponent => 2, :colour => 'B')) @t.add_result(ICU::Result.new(4, 1, 'D', :opponent => 2, :colour => 'W')) serializer = ICU::Tournament::Krause.new @k = serializer.serialize(@t) end it "should produce a valid tournament" do expect(@t.invalid).to be_falsey end it "should produce output that looks reasonable" do expect(@k).to match(/Fischer,Robert J\./) end end context "serialisation" do before(:each) do @krause = < true) expect(ICU::Tournament::Krause.new.serialize(t, :fide => true)).to eq(@krause) end it "should serialize using the convenience method of the tournament object" do t = @p.parse!(@krause, :fide => true) expect(t.serialize('Krause', :fide => true)).to eq(@krause) end it "should serialize only if :fide option is used correctly" do t = @p.parse!(@krause, :fide => true) expect(t.serialize('Krause', :fide => true)).to eq(@krause) expect(t.serialize('Krause')).not_to eq(@krause) end it "should not serialize correctly if mixed rating types are used" do t = @p.parse!(@krause, :fide => true) expect(t.serialize('Krause')).not_to eq(@krause) end end context "auto-ranking" do before(:all) do @krause = < 1985, :fide_rating => nil) check_player(2, 'Mark', 'Orr', :rating => 2258, :fide_rating => nil) check_player(3, 'Viktor', 'Bologan', :rating => 2663, :fide_rating => nil) end it "should have FIDE ratings if option is specified" do @t = @p.parse(@krause, :fide => true) check_player(1, 'Gearoidin', 'Ui Laighleis', :rating => nil, :fide_rating => 1985) check_player(2, 'Mark', 'Orr', :rating => nil, :fide_rating => 2258) check_player(3, 'Viktor', 'Bologan', :rating => nil, :fide_rating => 2663) end it "should auto-detect FIDE or ICU IDs based on size, the option has no effect" do @t = @p.parse(@krause) check_player(1, 'Gearoidin', 'Ui Laighleis', :id => nil, :fide_id => 2501171) check_player(2, 'Mark', 'Orr', :id => 1350, :fide_id => nil) @t = @p.parse(@krause, :fide => true) check_player(1, 'Gearoidin', 'Ui Laighleis', :id => nil, :fide_id => 2501171) check_player(2, 'Mark', 'Orr', :id => 1350, :fide_id => nil) end end context "renumbering" do before(:all) do @krause = < 1985, :id => 2501171, :dob => '1964-06-10', :fed => 'IRL', :gender => 'f')) @t.add_player(ICU::Player.new('Mark', 'Orr', 2, :rating => 2258, :id => 2500035, :dob => '1955-11-09', :fed => 'IRL', :title => 'm')) @t.add_player(ICU::Player.new('Viktor', 'Bologan', 3, :rating => 2663, :id => 13900048, :dob => '1971-01-01', :fed => 'MDA', :title => 'g')) @t.add_result(ICU::Result.new(1, 1, 'L', :opponent => 2, :colour => 'B')) @t.add_result(ICU::Result.new(2, 1, 'W', :opponent => 3, :colour => 'W')) @t.add_result(ICU::Result.new(3, 2, 'W', :opponent => 3, :colour => 'B')) @output = @p.serialize(@t) end it "should serialise" do expect(@output).to eq(@krause) end end context "customised serialisation with ICU IDs" do before(:all) do @k = < true) expect(text).to match(/001 1 w Ui Laighleis,Gearoidin IRL 1964-06-10 1.0 2/) expect(text).to match(/001 2 m Orr,Mark IRL 1955-11-09 2.0 1/) expect(text).to match(/001 3 g Svidler,Peter RUS 1971-01-01 0.0 3/) end it "should omitt all optional data if the :only option is an empty hash" do text = @t.serialize('Krause', :only => []) expect(text).to match(/001 1 Ui Laighleis,Gearoidin 1.0 /) expect(text).to match(/001 2 Orr,Mark 2.0 /) expect(text).to match(/001 3 Svidler,Peter 0.0 /) end it "should should be able to include a subset of attributes, test 1" do text = @t.serialize('Krause', :only => [:gender, "dob", :id, "rubbish"]) expect(text).to match(/001 1 w Ui Laighleis,Gearoidin 3364 1964-06-10 1.0 /) expect(text).to match(/001 2 Orr,Mark 1350 1955-11-09 2.0 /) expect(text).to match(/001 3 Svidler,Peter 16790 1971-01-01 0.0 /) end it "should should be able to include a subset of attributes, test 2" do text = @t.serialize('Krause', :only => [:rank, "title", :fed, "rating"]) expect(text).to match(/001 1 Ui Laighleis,Gearoidin 1985 IRL 1.0 2/) expect(text).to match(/001 2 m Orr,Mark 2258 IRL 2.0 1/) expect(text).to match(/001 3 g Svidler,Peter 2663 RUS 0.0 3/) end it "should should be able to include all attributes" do text = @t.serialize('Krause', :only => [:gender, :title, :rating, :fed, :id, :dob, :rank]) expect(text).to match(/001 1 w Ui Laighleis,Gearoidin 1985 IRL 3364 1964-06-10 1.0 2/) expect(text).to match(/001 2 m Orr,Mark 2258 IRL 1350 1955-11-09 2.0 1/) expect(text).to match(/001 3 g Svidler,Peter 2663 RUS 16790 1971-01-01 0.0 3/) end it "the :only and :except options are logical opposites" do expect(@t.serialize('Krause', :only => [:gender, :title, :rating])).to eq(@t.serialize('Krause', :except => [:fed, :id, "dob", :rank])) expect(@t.serialize('Krause', :only => [:gender])).to eq(@t.serialize('Krause', :except => [:fed, :id, :dob, :rank, :title, :rating])) expect(@t.serialize('Krause', :only => [:gender, :title, "rating", :fed, :id, :dob])).to eq(@t.serialize('Krause', :except => [:rank])) expect(@t.serialize('Krause', :only => [:gender, :title, :rating, :fed, "id", :dob, :rank])).to eq(@t.serialize('Krause', :except => [])) expect(@t.serialize('Krause', :only => [])).to eq(@t.serialize('Krause', :except => [:gender, :title, :rating, :fed, :id, :dob, :rank])) end end context "customised serialisation with FIDE IDs" do before(:all) do @k = < true) end it "should include all data without any explict cusromisation" do text = @t.serialize('Krause', :fide => true) expect(text).to match(/001 1 w Ui Laighleis,Gearoidin 1985 IRL 2501171 1964-06-10 1.0 2/) expect(text).to match(/001 2 m Orr,Mark 2258 IRL 2500035 1955-11-09 2.0 1/) expect(text).to match(/001 3 g Svidler,Peter 2663 RUS 4102142 1971-01-01 0.0 3/) end it "should omitt ratings and IDs if FIDE option is not chosen" do text = @t.serialize('Krause') expect(text).to match(/001 1 w Ui Laighleis,Gearoidin IRL 1964-06-10 1.0 2/) expect(text).to match(/001 2 m Orr,Mark IRL 1955-11-09 2.0 1/) expect(text).to match(/001 3 g Svidler,Peter RUS 1971-01-01 0.0 3/) end it "should omitt all optional data if the :only option is an empty hash" do text = @t.serialize('Krause', :only => []) expect(text).to match(/001 1 Ui Laighleis,Gearoidin 1.0 /) expect(text).to match(/001 2 Orr,Mark 2.0 /) expect(text).to match(/001 3 Svidler,Peter 0.0 /) end it "should should be able to include a subset of attributes, test 1" do text = @t.serialize('Krause', :only => [:gender, "dob", :id], :fide => true) expect(text).to match(/001 1 w Ui Laighleis,Gearoidin 2501171 1964-06-10 1.0 /) expect(text).to match(/001 2 Orr,Mark 2500035 1955-11-09 2.0 /) expect(text).to match(/001 3 Svidler,Peter 4102142 1971-01-01 0.0 /) end it "should should be able to include a subset of attributes, test 2" do text = @t.serialize('Krause', :only => [:rank, "title", :fed, "rating", :rubbish], :fide => true) expect(text).to match(/001 1 Ui Laighleis,Gearoidin 1985 IRL 1.0 2/) expect(text).to match(/001 2 m Orr,Mark 2258 IRL 2.0 1/) expect(text).to match(/001 3 g Svidler,Peter 2663 RUS 0.0 3/) end it "should should be able to include all attributes" do text = @t.serialize('Krause', :only => [:gender, :title, :rating, :fed, :id, :dob, :rank], :fide => true) expect(text).to match(/001 1 w Ui Laighleis,Gearoidin 1985 IRL 2501171 1964-06-10 1.0 2/) expect(text).to match(/001 2 m Orr,Mark 2258 IRL 2500035 1955-11-09 2.0 1/) expect(text).to match(/001 3 g Svidler,Peter 2663 RUS 4102142 1971-01-01 0.0 3/) end end context "errors" do before(:each) do @k = < "ignore") }.not_to raise_error expect { @p.parse!(@k.sub('08.02.24', '08.02.22'), :round_dates => "ignore") }.not_to raise_error end it "creating a duplicate player number should cause an error" do expect { @p.parse!(@k.sub(' 2 ', ' 1 ')) }.to raise_error(/player number/) end it "creating a duplicate rank number should not cause an error becuse the tournament will be reranked" do t = @p.parse!(@k.sub('4.0 1', '4.0 2')) expect(t.player(1).rank).to eq(1) end it "referring to a non-existant player number should cause an error" do expect { @p.parse!(@k.sub(' 3 b 1', '33 b 1')) }.to raise_error(/opponent number/) end it "inconsistent colours should cause an error" do expect { @p.parse!(@k.sub('3 b 1', '3 w 1')) }.to raise_error(/result/) end it "inconsistent scores should cause an error" do expect { @p.parse!(@k.sub('3 b 1', '3 b =')) }.to raise_error(/result/) end it "inconsistent totals should cause an error" do expect { @p.parse!(@k.sub('3.5', '4.0')) }.to raise_error(/total/) end it "invalid federations should cause an error unless an option is used" do @k.sub!('SCO', 'XYZ') expect { @p.parse!(@k) }.to raise_error(/federation/) expect { @t = @p.parse!(@k, :fed => "skip") }.not_to raise_error expect(@t.player(5).fed).to be_nil expect(@t.player(1).fed).to eq("IRL") expect { @t = @p.parse!(@k, :fed => "ignore") }.not_to raise_error expect(@t.player(5).fed).to be_nil expect(@t.player(1).fed).to be_nil end it "an invalid DOB is silently ignored" do expect { @t = @p.parse!(@k.sub(/1993-12-20/, '1993 ')) }.not_to raise_error expect(@t.player(1).dob).to be_nil end it "removing any player that somebody else has played should cause an error" do expect { @p.parse!(@k.sub(/^001 12.*$/, '')) }.to raise_error(/opponent/) end end context "encoding" do before(:all) do @utf8 = < :skip, :fide => true) expect(@t).not_to be_nil expect(@t.start).to eq("2011-02-25") expect(@t.finish).to eq("2011-02-27") check_player(1, 'Nigel', 'Short', :gender => 'M', :fide_rating => 2658, :fed => 'ENG', :rating => nil, :rank => 5, :title => 'GM') check_results(1, 6, 4.0) check_player(16, 'Jonathan', "O'Connor", :gender => 'M', :fide_rating => 2111, :fed => nil, :rating => nil, :rank => 25, :title => nil) check_results(16, 6, 2.5) expect(@t.player(16).results.map(&:score).join('')).to eq('DWLDDL') check_player(24, 'David', 'Murray', :gender => 'M', :fide_rating => 2023, :fed => nil, :rating => nil, :rank => 34, :title => nil) check_results(24, 2, 0.5) expect(@t.player(24).results.map(&:score).join('')).to eq('LD') check_player(26, 'Alexandra', 'Wilson', :gender => 'F', :fide_rating => 2020, :fed => 'ENG', :rating => nil, :rank => 29, :title => 'WFM') check_results(26, 6, 2.0) end it "should handle Bunratty Major 2011" do file = "#{@s}/bunratty_major_2011.tab" @t = @p.parse_file(file, :fed => :ignore) expect(@t).not_to be_nil expect(@t.start).to eq("2011-02-25") expect(@t.finish).to eq("2011-02-27") check_player(1, 'Dan', 'Clancy', :gender => 'M', :fide_rating => nil, :fed => nil, :id => 204, :rating => nil, :rank => 12) check_results(1, 6, 4) check_player(10, 'Phillip', 'Foenander', :gender => 'M', :fide_rating => nil, :fed => nil, :id => 7168, :rating => nil, :rank => 18) check_results(10, 6, 3.5) check_player(40, 'Ron', 'Cummins', :gender => 'M', :fide_rating => nil, :fed => nil, :id => 4610, :rating => nil, :rank => 56) check_results(40, 1, 0.0) end it "should handle bunratty_minor_2011.tab" do file = "#{@s}/bunratty_minor_2011.tab" expect { @p.parse_file!(file, :fed => :ignore) }.not_to raise_error end it "should handle Bunratty Challengers 2011" do file = "#{@s}/bunratty_challengers_2011.tab" expect { @p.parse_file!(file, :fed => :ignore) }.not_to raise_error end it "should handle Irish Intermediate Championships 2011" do file = "#{@s}/irish_intermediate_champs_2011.tab" expect { @p.parse_file!(file) }.not_to raise_error end it "should handle Irish Junior Championships 2011" do file = "#{@s}/irish_junior_champs_2011.tab" expect { @p.parse_file!(file) }.not_to raise_error end it "should handle a file with a BOM" do file = "#{@s}/armstrong_2012_with_bom.tab" expect { @p.parse_file!(file) }.not_to raise_error end end end end end