Why there are too few black goalkeepers in high-level football?

It’s been too long since I have this question first appeared in my mind. Right now I’m watching a football match and a black goalkeeper is guarding one of the goals. And it flashed again.

So I decided to ask here, if anyone knows an explanation for it, maybe a scientific one.

For example, in 100 meters dash, black athletes are one move ahead since their leg muscles are different than white people’s, letting them run faster in short-distances. So, maybe some of you know a similar explanation for this particular situation.

PS: Since I’m not a native speaker of English, I hope I did not write anything wrong, did not compose a racist passage unintentionally and did not offend any of my brothers and sisters. I’m just looking for an answer to a question. Thank you.

Modelling football teams and fixtures in Ruby (as compared to SQL)

I am trying to model information around football teams and fixtures. I am using the Premier League fantasy football API for my data. The fixtures API is here, and the team data (along with a lot of extra data) is here – see the “teams” element.

I want to be able to do things like report on all of Arsenal’s fixtures/results, for example…

ARSENAL
event kickoff      opponent         venue result scoreline
1     12 aug 16:00 Manchester City  H     L      1-2
2     18 Aug 17:30 Chelsea          A     L      2-3
3     25 Aug 15:00 West Ham         H     -

However I may want to access more data items than shown here – it’s just an example.

I’m experienced with database, so if I were writing this to a normalized database I would have two tables, teams and fixtures, and I could write a query like this.

SELECT t.team_name, f.[event], f.kickoff, opp.name,
       CASE WHEN t.team_id = f.home_team_id THEN 'H' ELSE 'A' END AS venue,
       CASE WHEN f.team_h_score IS NULL THEN '-'
            WHEN f.team_h_score = f.team_a_score THEN 'D'
            WHEN f.team_h_score > f.team_a_score AND t.team_id = f.home_team_id THEN 'W'
            WHEN f.team_h_score < f.team_a_score AND t.team_id = f.away_team_id THEN 'W'
            ELSE 'L' END AS result,
       CASE WHEN t.team_id = f.home_team_id THEN f.team_h_score ELSE team_a_score END as own_score,
       CASE WHEN t.team_id = f.home_team_id THEN f.team_a_score ELSE team_h_score END as opp_score       
FROM   team t
INNER JOIN fixture f ON t.team_id IN (f.away_team_id, f.home_team_id)
INNER JOIN team opp ON opp.team_id IN (f.away_team_id, f.home_team_id)
WHERE t.team_id = @input_team_id

I would be happy with this - it "feels" pretty good and I trust my feelings - I know there are rules and principles that I am following but they have been internalised such that I can usually "feel" what is right in database design.

However, when I'm trying to write this in an object-oriented way, I have much less experience so I'm trying to follow guidelines and principles of object-oriented design - SRP, managing dependencies and so on.

I decided that starting from the SQL above is a decent way to start. So, here's my thinking so far. There obviously needs to be a team class and a fixture class. I also thought a TeamFixture class would be good too - and can encapsulate some of the logic in the long case statements above.

class Databank
  def initialize
    #some stuff outside the scope of this review
    #just assume the fixtures and teams methods work
  end

  def fixtures
    #returns array of all Fixtures
  end

  def teams
    #returns array of all Teams
  end

end

class Fixture
  attr_reader :data
  def initialize(data)
    @data = data
  end
end

class Team
  attr_reader :data, :fixtures
  def initialize(data, fixtures)
    @data = data
    @fixtures = fixtures.map { |f| TeamFixture.new(f, @data['id']) }
  end
end

class TeamFixture
  attr_reader :fixture, :venue
  def initialize(fixture,team_id)
    @fixture=fixture
    @venue = fixture.data['team_h']==team_id ? 'H' : 'A'
    @h_score = fixture.data['team_h_score']
    @a_score = fixture.data['team_a_score']
  end

  def result
    return '-' if @h_score=='null'
    return 'D' if @h_score==@a_score
    winner = @h_score==@a_score ? 'H' : 'A'
    return @venue==winner ? 'W' : 'L'
  end

  def own_score
    @venue=='H' ? @h_score : @a_score
  end

  def opp_score
    @venue=='H' ? @a_score : @h_score
  end

  def opponent
    id = @venue=='H' ? @fixture['team_a'] : @fixture['team_h']
    # How to get from this id to the Team object it represents?
  end
end

I'm left asking myself three questions that I'm not sure how to answer. Though feel free to make any other comments.

1) If I want to access information about an opponent, I feel like I'm "reaching through" many objects, for example to print every fixture for every team it would be something like this...

d = Databank.new
d.teams.each |t| do
  puts "#{t.data['name']} are playing these teams..."
  t.fixtures.each |tf| do
    puts "#{tf.fixture.data['kickoff_time_formatted']} - #{tf.opponent.data['name']}"
  end
end

So effectively I'm doing Databank -> teams -> teamFixture -> opponent.data albiet across a few lines.
The Law of Demeter states that this is not usually a good thing, but I'm not experienced enough to know if this is a good violation or not? My database voice in my head says this is fine but the OOP voice isn't so sure.

2) I don't like the Team and Fixture classes, having to write t.data['name'] feels clunky and that it would be easier to just call t['name'], t[:name] or t.name. However looking around I can't seem to find a "good" way to achieve this. I understand that subclassing a Hash is a bad idea. Then there's this Stackoverflow question, which suggests either an OpenStruct (which wouldn't work for the nested nature of some of my data) or some ugly-looking code to achieve this. Am I right in wanting something like t['name'] to work, and if so how should I go about it?

3) The opponent method is not finished. What is the best way to get it to return the appropriate Team object? If I had an Enumerable of the teams I could do teams.find { |t| t["id"]==id} but such an Enumerable is only in the Databank object, so it would be a lot of reaching through objects again and it does not feel right at all to do this.