The Elo has landed

Foosball chat / key issues and discussion
User avatar
Shovo
Posts: 2774
Joined: Sat Feb 22, 2003 9:59 pm
Real Name: John Shovelton
Location: Oxford
Contact:

Re: The Elo has landed

Post by Shovo » Fri Sep 20, 2013 10:26 am

It's Pinday.

User avatar
robmoss2k
Posts: 1682
Joined: Mon Feb 10, 2003 3:36 pm
Real Name: Robert Moss
Location: Bolton
Contact:

Re: The Elo has landed

Post by robmoss2k » Fri Sep 20, 2013 11:05 am

Shovo wrote:It's Pinday.
Bugger. Now I have to write something to merge players... :?
Image

User avatar
davez
Posts: 4072
Joined: Sun Jan 19, 2003 11:17 pm
Real Name: Dave Ziemann
Location: London, UK

Re: The Elo has landed

Post by davez » Fri Sep 20, 2013 11:47 am

No you don't!
Apostrophes never make plurals.Incorrect:Table's,Garlando's,DVD's,1900's.Correct:Tables,Garlandos,DVDs,1900s.

User avatar
robmoss2k
Posts: 1682
Joined: Mon Feb 10, 2003 3:36 pm
Real Name: Robert Moss
Location: Bolton
Contact:

Re: The Elo has landed

Post by robmoss2k » Fri Sep 20, 2013 12:33 pm

davez wrote:No you don't!
Oh. Too late, I already did...
Image

The Doctor
BFA Chairman
Posts: 1698
Joined: Mon Apr 14, 2003 5:41 pm
Real Name: Andrei Russell-Gebbett
Location: London

Re: The Elo has landed

Post by The Doctor » Fri Sep 20, 2013 12:46 pm

I've made a spreadsheet that simulates tournaments using the ELO singles ratings probabilistically to decide the winners of every head-to-head.

Now we don't even have to run any events in the first place, let alone worry about match scheduling.

Here are the top placings for the next three events:

UK Champs:
1st Robert Atha
2nd Joe Bundy
3rd-4th Andrew Nubbert
3rd-4th Tich Degun

Isha Tornado Series:
1st Richard Marsh
2nd Christopher Lyall
3rd-4th Blonky Bains
3rd-4th Tom Willetts

Leonhart Open:
1st Christopher Lyall
2nd Alex Shovelton
3rd-4th Stephen Edwards
3rd-4th Fung Kiu Franky Chau

Congratulations to all of our winners.

Link: http://www.filedropper.com/simsingles

Press F9 to run the simulation.

The less busy among you may wish to unhide some columns to pick at the inefficiencies and flaws in the spreadsheet's design.

User avatar
Bundy Volume 1
BFA Regional Rep - London
Posts: 3258
Joined: Thu Jul 27, 2006 6:13 pm
Real Name: Joe Bundy
Location: Liverpool

Re: The Elo has landed

Post by Bundy Volume 1 » Fri Sep 20, 2013 1:12 pm

Excellent. I wasn't planning to go to the UKC, but it's ideal that I now don't have to as I've already qualified in OS.

I'll see the rest of the guys going in Nantes.

User avatar
robmoss2k
Posts: 1682
Joined: Mon Feb 10, 2003 3:36 pm
Real Name: Robert Moss
Location: Bolton
Contact:

Re: The Elo has landed

Post by robmoss2k » Thu Sep 26, 2013 5:04 pm

http://www.robmoss2k.co.uk:8000/sap/bc/ ... efault.htm

Well, there it is. You can drill down on individual players to see what they're rated at in various different events and/or categories, and when you're looking at a player, you can drill down further to see their results that correspond to that ranking. That last bit is slightly unfinished in terms of applicability of men/women and GB/non-GB stuff but I'll get to that at some point. For now, have fun clicking around, and send me SPORT files...!
Image

User avatar
davez
Posts: 4072
Joined: Sun Jan 19, 2003 11:17 pm
Real Name: Dave Ziemann
Location: London, UK

Re: The Elo has landed

Post by davez » Thu Sep 26, 2013 6:04 pm

I'm a Novice at Master's Singles!
Apostrophes never make plurals.Incorrect:Table's,Garlando's,DVD's,1900's.Correct:Tables,Garlandos,DVDs,1900s.

User avatar
robmoss2k
Posts: 1682
Joined: Mon Feb 10, 2003 3:36 pm
Real Name: Robert Moss
Location: Bolton
Contact:

Re: The Elo has landed

Post by robmoss2k » Fri Sep 27, 2013 7:00 am

davez wrote:I'm a Novice at Master's Singles!
Yes, Dave. Yes you are. :-)
Image

User avatar
robmoss2k
Posts: 1682
Joined: Mon Feb 10, 2003 3:36 pm
Real Name: Robert Moss
Location: Bolton
Contact:

Re: The Elo has landed

Post by robmoss2k » Mon Oct 07, 2013 10:23 pm

New features
Added a graph to show progression of a player's Elo rating over time in each category and event (on player-specific pages)
Added a list of all event results (on player-specific pages). Please note that many will be groups - see the column "System" - elimination means knock-outs and round-robin means groups

Fixes
Some Goalie Wars events were being treated as 2BRB - this is fixed

Hopefully some more SPORT files should be headed my way soon so things should start reflecting reality a little more closely.
Image

User avatar
Shovo
Posts: 2774
Joined: Sat Feb 22, 2003 9:59 pm
Real Name: John Shovelton
Location: Oxford
Contact:

Re: The Elo has landed

Post by Shovo » Tue Oct 08, 2013 8:23 am

Amazing. If only the top 9 were all available for Nantes...
1	Robert Atha		GBR	2410.983782	Giga-Pro Master
2	Jonathan May		GBR	2070.793042	Kilo-Pro Master
3	Alex Shovelton		GBR	2037.410850	Kilo-Pro Master
4	Tom Burdett		GBR	2025.788475	Kilo-Pro Master
5	Joe Hamilton		GBR	2017.157121	Kilo-Pro Master
6	Mike Amsden		GBR	1989.191990	Pro-Master
7	Jujhar Singh Sohi	GBR	1969.542271	Pro-Master
8	Patrick Grover		GBR	1894.245608	Pro-Master
9	Dave Bareham		GBR	1891.401567	Pro-Master

User avatar
robmoss2k
Posts: 1682
Joined: Mon Feb 10, 2003 3:36 pm
Real Name: Robert Moss
Location: Bolton
Contact:

Re: The Elo has landed

Post by robmoss2k » Tue Oct 08, 2013 9:45 am

The ITSF turned down my initial informal request for someone to send me a database dump of all their results. Does anyone know who we put pressure on them to change their mind to the correct decision?
Image

User avatar
robmoss2k
Posts: 1682
Joined: Mon Feb 10, 2003 3:36 pm
Real Name: Robert Moss
Location: Bolton
Contact:

Re: The Elo has landed

Post by robmoss2k » Tue Oct 08, 2013 12:06 pm

New features
Added some rudimentary styling to make things look a bit less ugly (suggestions more than welcome)
Added an event results page to show who placed where in each event - you can drill down to these from the player pages

Fixes
Hopefully fixed the page titles to make them actually make sense
Image

User avatar
Matt Price
Site Administrator
Posts: 540
Joined: Sat Dec 20, 2008 2:08 am
Real Name: Matt Price
Location: Yeovil

Re: The Elo has landed

Post by Matt Price » Tue Oct 08, 2013 6:47 pm

This is insanulous. And incrazing - both (all four?) at the same time

User avatar
robmoss2k
Posts: 1682
Joined: Mon Feb 10, 2003 3:36 pm
Real Name: Robert Moss
Location: Bolton
Contact:

Re: The Elo has landed

Post by robmoss2k » Tue Oct 08, 2013 8:06 pm

Chris Lyall has very kindly supplied me with the SPORT files for all the Capital Venue events. I've added them in and the rankings have been updated. Unsurprisingly, Rob's rating has increased. Again. There's a shock. He's now a Tera-Pro Master. That's a four star PM in old money, with no international events involved and only a few tournaments. In other news, Callum Oakes has gone Pro Master, pretty much off results since late 2012. Anyway, have a peruse at your leisure...
Image

User avatar
Sampson
Posts: 368
Joined: Tue Sep 09, 2008 8:55 pm
Real Name: Luke Sampson
Location: Coventry

Re: The Elo has landed

Post by Sampson » Wed Oct 09, 2013 11:10 am

Bobby, I know this is a personal question and something that should be saved for later in our relationship, but can I see your algorithm? :oops:

What language is it written in?


Also, I don't know much about Elo but I know that its goal is to predict the result of a match between two players using the statistical analysis of previous matches. So, how does it, for example, handle this scenario?

Player A consistently beats Player B

Player B consistently beats Player C

Player C consistently beats Player A

Who would be ranked higher?

I know this is an unlikely scenario but [geek] I'm genuinely interested by this kind of thing [/geek].

Thanks again for all your work/time that's gone into this.

User avatar
Shovo
Posts: 2774
Joined: Sat Feb 22, 2003 9:59 pm
Real Name: John Shovelton
Location: Oxford
Contact:

Re: The Elo has landed

Post by Shovo » Wed Oct 09, 2013 11:27 am

It's all here, Luke! I guess Rob will just be making some decisions on the K-factor.

User avatar
robmoss2k
Posts: 1682
Joined: Mon Feb 10, 2003 3:36 pm
Real Name: Robert Moss
Location: Bolton
Contact:

Re: The Elo has landed

Post by robmoss2k » Thu Oct 10, 2013 9:34 am

Sampson wrote:Bobby, I know this is a personal question and something that should be saved for later in our relationship, but can I see your algorithm? :oops:
Well, you did ask... this is just the bit that calculates and saves Elo ratings from the results saved in the database tables. Happy reading...

Code: Select all

class ZCL_BFA_ELO_RATING definition
  public
  create public .

public section.

  methods GET_ELO_PROGRESSION
    returning
      value(ELO_PROGRESSION) type ZBFA_ELO_PROGRES_TAB
    raising
      ZCX_NO_ELO_RATINGS_FOUND .
  methods CONSTRUCTOR
    importing
      !START_DATE type DATUM
      !END_DATE type DATUM default SY-DATUM
      !EVENT_TYPE type ZBFA_EVENT_KEY optional
      !RANK_CAT type ZBFA_RANK_CAT optional
      !ENABLE_MATCH_RESULTS type FLAG default SPACE
      !FILTER_NON_GB type FLAG default SPACE .
  methods GET_ELO_RATINGS
    importing
      !PLAYER_ID type ZBFA_PLAYER_ID optional
    returning
      value(ELO_RATINGS) type ZBFA_ELO_RATING_TABLE
    raising
      ZCX_NO_ELO_RATINGS_FOUND .
  methods GET_MATCH_RESULTS
    importing
      !PLAYER_ID type ZBFA_PLAYER_ID
    returning
      value(LT_MATCH_RESULTS) type ZBFA_MATCH_RESULTS_TABLE
    raising
      ZCX_NO_MATCH_RESULTS_FOUND .
protected section.
private section.

  data LT_ELO_PROGRESSION type ZBFA_ELO_PROGRES_TAB .
  constants LC_AWAY_WIN type CHAR1 value 'A'. "#EC NOTEXT
  constants LC_GUEST type CHAR1 value 'A'. "#EC NOTEXT
  constants LC_HOME type CHAR1 value 'H'. "#EC NOTEXT
  constants LC_HOME_WIN type CHAR1 value 'H'. "#EC NOTEXT
  constants LV_ELO_SEED_RATING type INT4 value 1500. "#EC NOTEXT
  data LT_CAT_MEMBERS type T_CAT_MEMBERS .
  data LT_CAT_WEIGHT type T_CAT_WEIGHT .
  data LT_CLUB type T_BFA_CLUB .
  data LT_ELO_RATING type ZBFA_ELO_RATING_TABLE .
  data LT_ENTRY_PLYRS type T_BFA_ENTRY_PLYRS .
  data LT_EVENT type T_BFA_EVENT .
  data LT_EVENT_ENTRY type T_BFA_EVENT_ENTRY .
  data LT_EVENT_ROUND type T_BFA_EVENT_ROUND .
  data LT_EVENT_SYS type T_BFA_EVENT_SYS .
  data LT_EVENT_TYPES type T_EVENT_TYPES .
  data LT_MATCH_GAMES type T_BFA_MATCH_GAMES .
  data LT_MATCH_RESULTS type ZBFA_MATCH_RESULTS_TABLE .
  data LT_PLAYER_DATA type T_BFA_PLAYER_DATA .
  data LT_RANKS type TAB_RANKS .
  data LT_ROUND_MATCH type T_BFA_ROUND_MATCH .
  data LT_TOURNAMENT type T_BFA_TOURNAMENT .
  data LV_EVENT_TYPE type ZBFA_EVENT_KEY .

  methods SAVE_RATING_PROGRESSION
    importing
      !YEAR type NUMC4 .
  methods ADD_MATCH_RESULT
    importing
      !TOURNAMENT_KEY type ZTOURNAMENT_KEY
      !EVENT_KEY type ZEVENT_KEY
      !HOME_ENTRY type ZENTRY_KEY
      !GUEST_ENTRY type ZENTRY_KEY
      !K_VALUE type ZBFA_ELO_RATING
      !ROUND_KEY type ZROUND_KEY
      !MATCH_KEY type ZMATCH_KEY
    raising
      ZCX_GUEST_ENTRY_NOT_FOUND
      ZCX_HOME_ENTRY_NOT_FOUND
      ZCX_ROUND_MATCH_NOT_FOUND
      ZCX_EVENT_TYPE_NOT_FOUND
      ZCX_EVENT_SYSTEM_NOT_FOUND
      ZCX_EVENT_NOT_FOUND
      ZCX_TOURNAMENT_NOT_FOUND .
  methods CALCULATE_EVENT_RATINGS
    importing
      !TOURNAMENT_KEY type ZTOURNAMENT_KEY
      !EVENT_KEY type ZBFA_EVENT_KEY
      !ENABLE_MATCH_RESULTS type FLAG
    raising
      ZCX_TOURNAMENT_NOT_FOUND
      ZCX_EVENT_NOT_FOUND
      ZCX_EVENT_SYSTEM_NOT_FOUND
      ZCX_NO_ROUNDS_IN_EVENT
      ZCX_PLAYER_ELO_NOT_FOUND
      ZCX_NEGATIVE_ELO_RATING
      ZCX_EVENT_ENTRY_NOT_FOUND
      ZCX_EVENT_TYPE_NOT_FOUND
      ZCX_INVALID_SCORE
      ZCX_ROUND_MATCH_NOT_FOUND
      ZCX_HOME_ENTRY_NOT_FOUND
      ZCX_GUEST_ENTRY_NOT_FOUND
      ZCX_CAT_WEIGHT_NOT_FOUND .
  methods CALCULATE_TOURN_CAT
    importing
      !PLAYERS type INT4
    returning
      value(TOURN_CAT) type ZBFA_TOURN_CAT .
  methods GET_ELO_DIFF
    importing
      !HOME type ZBFA_ELO_RATING
      !GUEST type ZBFA_ELO_RATING
      !RESULT type CHAR1
      !K_VALUE type ZBFA_ELO_RATING
      !PLAYER type CHAR1
    returning
      value(ELO_DIFF) type ZBFA_ELO_RATING
    raising
      ZCX_INVALID_SCORE .
  methods GET_ELO_RATING
    importing
      !TOURNAMENT_KEY type ZTOURNAMENT_KEY
      !EVENT_KEY type ZBFA_EVENT_KEY
      !ENTRY_KEY type ZENTRY_KEY
    returning
      value(ELO_RATING) type ZBFA_ELO_RATING
    raising
      ZCX_WRONG_NUMBER_OF_PLAYERS
      ZCX_EVENT_TYPE_NOT_FOUND
      ZCX_EVENT_NOT_FOUND
      ZCX_EVENT_ENTRY_NOT_FOUND
      ZCX_NEGATIVE_ELO_RATING
      ZCX_PLAYER_ELO_NOT_FOUND .
  methods GET_MATCH_RESULT
    importing
      !TOURNAMENT_KEY type ZTOURNAMENT_KEY
      !EVENT_KEY type ZEVENT_KEY
      !ROUND_KEY type ZROUND_KEY
      !MATCH_KEY type ZMATCH_KEY
    returning
      value(RESULT) type CHAR1
    raising
      ZCX_MATCH_DRAWN
      ZCX_MATCH_GAMES_NOT_FOUND .
  methods GET_TOURNAMENT_DATA
    importing
      !START_DATE type DATUM
      !END_DATE type DATUM default SY-DATUM
      !EVENT_TYPE type ZBFA_EVENT_KEY optional
      !RANK_CAT type ZBFA_RANK_CAT optional .
  methods GET_TOURNAMENT_PLAYERS
    importing
      !TOURNAMENT_KEY type ZTOURNAMENT_KEY
    returning
      value(PLAYERS) type INT4 .
  methods POPULATE_ELO_SEED_DATA .
  methods SET_RANK_BOUNDARIES .
  methods UPDATE_ELO_RATING
    importing
      !TOURNAMENT_KEY type ZTOURNAMENT_KEY
      !EVENT_KEY type ZEVENT_KEY
      !ENTRY_KEY type ZENTRY_KEY
      !ELO_DIFF type ZBFA_ELO_RATING .
ENDCLASS.



CLASS ZCL_BFA_ELO_RATING IMPLEMENTATION.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_BFA_ELO_RATING->ADD_MATCH_RESULT
* +-------------------------------------------------------------------------------------------------+
* | [--->] TOURNAMENT_KEY                 TYPE        ZTOURNAMENT_KEY
* | [--->] EVENT_KEY                      TYPE        ZEVENT_KEY
* | [--->] HOME_ENTRY                     TYPE        ZENTRY_KEY
* | [--->] GUEST_ENTRY                    TYPE        ZENTRY_KEY
* | [--->] K_VALUE                        TYPE        ZBFA_ELO_RATING
* | [--->] ROUND_KEY                      TYPE        ZROUND_KEY
* | [--->] MATCH_KEY                      TYPE        ZMATCH_KEY
* | [!CX!] ZCX_GUEST_ENTRY_NOT_FOUND
* | [!CX!] ZCX_HOME_ENTRY_NOT_FOUND
* | [!CX!] ZCX_ROUND_MATCH_NOT_FOUND
* | [!CX!] ZCX_EVENT_TYPE_NOT_FOUND
* | [!CX!] ZCX_EVENT_SYSTEM_NOT_FOUND
* | [!CX!] ZCX_EVENT_NOT_FOUND
* | [!CX!] ZCX_TOURNAMENT_NOT_FOUND
* +--------------------------------------------------------------------------------------</SIGNATURE>
method add_match_result.
  field-symbols: <ls_match_results> like line of me->lt_match_results,
                 <ls_tournament> like line of me->lt_tournament,
                 <ls_event> like line of me->lt_event,
                 <ls_event_sys> like line of me->lt_event_sys,
                 <ls_event_types> like line of me->lt_event_types,
                 <ls_round_match> like line of me->lt_round_match,
                 <ls_event_home_entry> like line of me->lt_event_entry,
                 <ls_event_guest_entry> like line of me->lt_event_entry,
                 <ls_entry_plyrs> like line of me->lt_entry_plyrs,
                 <ls_match_games> like line of me->lt_match_games.
  read table me->lt_tournament
    assigning <ls_tournament>
    with table key tournament_key = tournament_key.
  if sy-subrc eq 0.
    read table me->lt_event
      assigning <ls_event>
      with table key tournament_key = tournament_key
                     event_key      = event_key.
    if sy-subrc eq 0.
      read table me->lt_event_sys
        assigning <ls_event_sys>
        with table key event_system = <ls_event>-event_system.
      if sy-subrc eq 0.
        read table me->lt_event_types
          assigning <ls_event_types>
          with table key event_key = <ls_event>-event_type.
        if sy-subrc eq 0.
          read table me->lt_round_match
            assigning <ls_round_match>
            with table key tournament_key = tournament_key
                           event_key      = event_key
                           round_key      = round_key
                           match_key      = match_key.
          if sy-subrc eq 0.
            read table me->lt_event_entry
              assigning <ls_event_home_entry>
              with table key tournament_key = tournament_key
                             event_key      = event_key
                             entry_key      = home_entry.
            if sy-subrc eq 0.
              read table me->lt_event_entry
                assigning <ls_event_guest_entry>
                with table key tournament_key = tournament_key
                               event_key      = event_key
                               entry_key      = guest_entry.
              if sy-subrc eq 0.
                append initial line to me->lt_match_results assigning <ls_match_results>.
                move: tournament_key to <ls_match_results>-tournament_key,
                      event_key to <ls_match_results>-event_key,
                      <ls_tournament>-tournament_desc to <ls_match_results>-tournament_desc,
                      <ls_tournament>-tournament_date to <ls_match_results>-tournament_date,
                      <ls_event_sys>-system_desc to <ls_match_results>-system_desc,
                      <ls_event_types>-event_desc to <ls_match_results>-event_type_desc,
                      k_value to <ls_match_results>-weighting,
                      <ls_round_match>-round_key to <ls_match_results>-round_key,
                      <ls_event_home_entry>-entry_seed to <ls_match_results>-home_entry_seed,
                      <ls_event_home_entry>-entry_rank to <ls_match_results>-home_entry_rank,
                      <ls_event_guest_entry>-entry_seed to <ls_match_results>-guest_entry_seed,
                      <ls_event_guest_entry>-entry_rank to <ls_match_results>-guest_entry_rank.
                loop at me->lt_entry_plyrs assigning <ls_entry_plyrs>
                  where tournament_key eq <ls_event_home_entry>-tournament_key and
                        event_key eq <ls_event_home_entry>-event_key and
                        entry_key eq <ls_event_home_entry>-entry_key.
                  insert <ls_entry_plyrs> into table <ls_match_results>-home_player.
                endloop.
                loop at me->lt_entry_plyrs assigning <ls_entry_plyrs>
                  where tournament_key eq <ls_event_guest_entry>-tournament_key and
                        event_key eq <ls_event_guest_entry>-event_key and
                        entry_key eq <ls_event_guest_entry>-entry_key.
                  insert <ls_entry_plyrs> into table <ls_match_results>-guest_player.
                endloop.
                loop at me->lt_match_games assigning <ls_match_games>
                  where tournament_key eq <ls_round_match>-tournament_key and
                        event_key eq <ls_round_match>-event_key and
                        round_key eq <ls_round_match>-round_key and
                        match_key eq <ls_round_match>-match_key.
                  append <ls_match_games> to <ls_match_results>-game.
                endloop.
              else.
                raise exception type zcx_guest_entry_not_found.
              endif.
            else.
              raise exception type zcx_home_entry_not_found.
            endif.
          else.
            raise exception type zcx_round_match_not_found.
          endif.
        else.
          raise exception type zcx_event_type_not_found.
        endif.
      else.
        raise exception type zcx_event_system_not_found.
      endif.
    else.
      raise exception type zcx_event_not_found.
    endif.
  else.
    raise exception type zcx_tournament_not_found.
  endif.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_BFA_ELO_RATING->CALCULATE_EVENT_RATINGS
* +-------------------------------------------------------------------------------------------------+
* | [--->] TOURNAMENT_KEY                 TYPE        ZTOURNAMENT_KEY
* | [--->] EVENT_KEY                      TYPE        ZBFA_EVENT_KEY
* | [--->] ENABLE_MATCH_RESULTS           TYPE        FLAG
* | [!CX!] ZCX_TOURNAMENT_NOT_FOUND
* | [!CX!] ZCX_EVENT_NOT_FOUND
* | [!CX!] ZCX_EVENT_SYSTEM_NOT_FOUND
* | [!CX!] ZCX_NO_ROUNDS_IN_EVENT
* | [!CX!] ZCX_PLAYER_ELO_NOT_FOUND
* | [!CX!] ZCX_NEGATIVE_ELO_RATING
* | [!CX!] ZCX_EVENT_ENTRY_NOT_FOUND
* | [!CX!] ZCX_EVENT_TYPE_NOT_FOUND
* | [!CX!] ZCX_INVALID_SCORE
* | [!CX!] ZCX_ROUND_MATCH_NOT_FOUND
* | [!CX!] ZCX_HOME_ENTRY_NOT_FOUND
* | [!CX!] ZCX_GUEST_ENTRY_NOT_FOUND
* | [!CX!] ZCX_CAT_WEIGHT_NOT_FOUND
* +--------------------------------------------------------------------------------------</SIGNATURE>
method calculate_event_ratings.
  data: lv_k_value type zbfa_elo_rating,
        lv_home_elo type zbfa_elo_rating,
        lv_guest_elo type zbfa_elo_rating,
        lv_home_elo_diff type zbfa_elo_rating,
        lv_guest_elo_diff type zbfa_elo_rating,
        lv_result type c length 1.
  field-symbols: <ls_tournament> like line of me->lt_tournament,
                 <ls_event> like line of me->lt_event,
                 <ls_event_sys> like line of me->lt_event_sys,
                 <ls_event_types> like line of me->lt_event_types,
                 <ls_cat_weight> like line of me->lt_cat_weight,
                 <ls_event_round> like line of me->lt_event_round,
                 <ls_round_match> like line of me->lt_round_match.
  read table me->lt_tournament
    assigning <ls_tournament>
    with table key tournament_key = tournament_key.
  if sy-subrc eq 0.
    read table me->lt_event
      assigning <ls_event>
      with table key tournament_key = tournament_key
                     event_key      = event_key.
    if sy-subrc eq 0.
      read table me->lt_event_sys assigning <ls_event_sys>
        with table key event_system = <ls_event>-event_system.
      if sy-subrc eq 0.
        read table me->lt_event_types assigning <ls_event_types>
          with table key event_key = <ls_event>-event_type.
        if me->lv_event_type is not initial.
          lv_k_value = 32.
        else.
          read table me->lt_cat_weight
            assigning <ls_cat_weight>
            with table key tourn_cat = <ls_tournament>-tourn_cat
                           event_key = <ls_event>-event_type.
          if sy-subrc eq 0.
            lv_k_value = <ls_cat_weight>-weighting * 32.
          else.
            raise exception type zcx_cat_weight_not_found.
          endif.
        endif.
        case <ls_event>-event_system.
          when 1 or 4.
            lv_k_value = lv_k_value / 2.
          when others.
        endcase.
        loop at me->lt_event_round assigning <ls_event_round>
          where tournament_key eq <ls_event>-tournament_key and
                event_key eq <ls_event>-event_key.
          loop at me->lt_round_match assigning <ls_round_match>
            where tournament_key eq <ls_event_round>-tournament_key and
                  event_key eq <ls_event_round>-event_key and
                  round_key eq <ls_event_round>-round_key.
            try.
                lv_home_elo = me->get_elo_rating( tournament_key = <ls_round_match>-tournament_key
                                                  event_key      = <ls_round_match>-event_key
                                                  entry_key      = <ls_round_match>-home_player ).
                lv_guest_elo = me->get_elo_rating( tournament_key = <ls_round_match>-tournament_key
                                                   event_key      = <ls_round_match>-event_key
                                                   entry_key      = <ls_round_match>-guest_player ).
                lv_result = me->get_match_result( tournament_key = <ls_round_match>-tournament_key
                                                  event_key      = <ls_round_match>-event_key
                                                  round_key      = <ls_round_match>-round_key
                                                  match_key      = <ls_round_match>-match_key ).
                lv_home_elo_diff = me->get_elo_diff( home    = lv_home_elo
                                                     guest   = lv_guest_elo
                                                     k_value = lv_k_value
                                                     result  = lv_result
                                                     player  = me->lc_home ).
                lv_guest_elo_diff = me->get_elo_diff( home    = lv_guest_elo
                                                      guest   = lv_home_elo
                                                      k_value = lv_k_value
                                                      result  = lv_result
                                                      player  = me->lc_guest ).
                me->update_elo_rating( tournament_key = <ls_round_match>-tournament_key
                                       event_key      = <ls_round_match>-event_key
                                       entry_key      = <ls_round_match>-home_player
                                       elo_diff       = lv_home_elo_diff ).
                me->update_elo_rating( tournament_key = <ls_round_match>-tournament_key
                                       event_key      = <ls_round_match>-event_key
                                       entry_key      = <ls_round_match>-guest_player
                                       elo_diff       = lv_guest_elo_diff ).
                if enable_match_results eq abap_true.
                  me->add_match_result( tournament_key = <ls_round_match>-tournament_key
                                        event_key      = <ls_round_match>-event_key
                                        home_entry     = <ls_round_match>-home_player
                                        guest_entry    = <ls_round_match>-guest_player
                                        k_value        = lv_k_value
                                        round_key      = <ls_round_match>-round_key
                                        match_key      = <ls_round_match>-match_key ).
                endif.
              catch zcx_wrong_number_of_players.
* Skip to next match - don't rate
                continue.
              catch zcx_event_type_not_found.
* Skip to next match - don't rate
                continue.
              catch zcx_event_not_found.
* Skip to next match - don't rate
                continue.
              catch zcx_event_entry_not_found.
* Skip to next match - don't rate
                continue.
              catch zcx_negative_elo_rating.
* Skip to next match - don't rate
                continue.
              catch zcx_player_elo_not_found.
* Skip to next match - don't rate
                continue.
              catch zcx_match_games_not_found.
* Skip to next match - don't rate
                continue.
              catch zcx_match_drawn.
* Skip to next match - don't rate
                continue.
            endtry.
          endloop.
*          if sy-subrc ne 0.
*            raise exception type zcx_no_matches_in_round.
*          endif.
        endloop.
        if sy-subrc ne 0.
          raise exception type zcx_no_rounds_in_event.
        endif.
      else.
        raise exception type zcx_event_system_not_found.
      endif.
    else.
      raise exception type zcx_event_not_found.
    endif.
  else.
    raise exception type zcx_tournament_not_found.
  endif.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_BFA_ELO_RATING->CALCULATE_TOURN_CAT
* +-------------------------------------------------------------------------------------------------+
* | [--->] PLAYERS                        TYPE        INT4
* | [<-()] TOURN_CAT                      TYPE        ZBFA_TOURN_CAT
* +--------------------------------------------------------------------------------------</SIGNATURE>
method calculate_tourn_cat.
  if players lt 8.
    tourn_cat = 7.
  elseif players lt 16.
    tourn_cat = 6.
  elseif players lt 32.
    tourn_cat = 5.
  elseif players lt 64.
    tourn_cat = 4.
  elseif players lt 128.
    tourn_cat = 3.
  elseif players lt 256.
    tourn_cat = 2.
  else.
    tourn_cat = 1.
  endif.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_BFA_ELO_RATING->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] START_DATE                     TYPE        DATUM
* | [--->] END_DATE                       TYPE        DATUM (default =SY-DATUM)
* | [--->] EVENT_TYPE                     TYPE        ZBFA_EVENT_KEY(optional)
* | [--->] RANK_CAT                       TYPE        ZBFA_RANK_CAT(optional)
* | [--->] ENABLE_MATCH_RESULTS           TYPE        FLAG (default =SPACE)
* | [--->] FILTER_NON_GB                  TYPE        FLAG (default =SPACE)
* +--------------------------------------------------------------------------------------</SIGNATURE>
method constructor.
  data: lv_players type i,
        lv_index type i,
        lv_year type n length 4.
  field-symbols: <ls_event> like line of me->lt_event,
                 <ls_player_data> like line of me->lt_player_data,
                 <ls_tournament> like line of me->lt_tournament,
                 <ls_elo_rating> like line of me->lt_elo_rating,
                 <ls_elo_progression> like line of me->lt_elo_progression,
                 <ls_ranks> like line of me->lt_ranks.
  move event_type to me->lv_event_type.
  me->get_tournament_data( start_date        = start_date
                           end_date          = end_date
                           event_type        = event_type
                           rank_cat          = rank_cat ).
  me->populate_elo_seed_data( ).
  sort me->lt_tournament by tournament_date tournament_desc.
  loop at me->lt_tournament assigning <ls_tournament>.
    lv_players = me->get_tournament_players( <ls_tournament>-tournament_key ).
    if <ls_tournament>-tourn_cat is initial.
      <ls_tournament>-tourn_cat = me->calculate_tourn_cat( players = lv_players ).
    endif.
    if lv_year is initial.
      move <ls_tournament>-tournament_date(4) to lv_year.
    endif.
    if start_date eq '00010101'
      and end_date eq '99991231'
      and lv_year ne <ls_tournament>-tournament_date(4).
      me->save_rating_progression( year = lv_year ).
      move <ls_tournament>-tournament_date(4) to lv_year.
    endif.
    loop at me->lt_event assigning <ls_event>
      where tournament_key eq <ls_tournament>-tournament_key.
      try.
          me->calculate_event_ratings( tournament_key       = <ls_event>-tournament_key
                                       event_key            = <ls_event>-event_key
                                       enable_match_results = enable_match_results ).
        catch zcx_tournament_not_found.
        catch zcx_cat_weight_not_found.
        catch zcx_guest_entry_not_found.
        catch zcx_home_entry_not_found.
        catch zcx_round_match_not_found.
        catch zcx_invalid_score.
        catch zcx_event_type_not_found.
        catch zcx_event_entry_not_found.
        catch zcx_negative_elo_rating.
        catch zcx_player_elo_not_found.
        catch zcx_no_matches_in_round.
        catch zcx_no_rounds_in_event.
        catch zcx_event_system_not_found.
        catch zcx_event_not_found.
      endtry.
    endloop.
  endloop.
  if start_date eq '00010101'
    and end_date eq '99991231'
    and lv_year is not initial.
    if <ls_tournament> is assigned.
      move <ls_tournament>-tournament_date(4) to lv_year.
      me->save_rating_progression( year = lv_year ).
    endif.
  endif.
  sort me->lt_elo_rating by elo_rating descending.
  delete me->lt_elo_rating where elo_rating eq zcl_bfa_elo_rating=>lv_elo_seed_rating.
  loop at me->lt_elo_rating assigning <ls_elo_rating>.
    read table me->lt_player_data assigning <ls_player_data>
      with table key player_id = <ls_elo_rating>-player_id.
    if sy-subrc eq 0.
      concatenate <ls_player_data>-prefix <ls_player_data>-name into <ls_elo_rating>-name separated by space.
      condense <ls_elo_rating>-name.
      move <ls_player_data>-city_state_zip to <ls_elo_rating>-city_state_zip.
    endif.
  endloop.
  if filter_non_gb ne space.
    delete me->lt_elo_rating where city_state_zip ne 'GBR'.
  endif.
  clear lv_index.
  loop at me->lt_elo_rating assigning <ls_elo_rating>.
    add 1 to lv_index.
    move lv_index to <ls_elo_rating>-elo_position.
  endloop.
  me->set_rank_boundaries( ).
  loop at me->lt_elo_rating assigning <ls_elo_rating>.
    loop at me->lt_ranks assigning <ls_ranks>
      where low_boundary le <ls_elo_rating>-elo_rating and
            high_boundary ge <ls_elo_rating>-elo_rating.
      move <ls_ranks>-rank to <ls_elo_rating>-ranking.
    endloop.
  endloop.
  if lines( me->lt_elo_progression ) ne 0.
    sort me->lt_elo_progression by elo_rating descending.
    delete me->lt_elo_progression where elo_rating eq zcl_bfa_elo_rating=>lv_elo_seed_rating.
    loop at me->lt_elo_progression assigning <ls_elo_progression>.
      move: start_date to <ls_elo_progression>-start_date,
            end_date to <ls_elo_progression>-end_date,
            event_type to <ls_elo_progression>-event_type,
            rank_cat to <ls_elo_progression>-rank_cat,
            filter_non_gb to <ls_elo_progression>-filter_non_gb.
      read table me->lt_player_data assigning <ls_player_data>
        with table key player_id = <ls_elo_progression>-player_id.
      if sy-subrc eq 0.
        concatenate <ls_player_data>-prefix <ls_player_data>-name into <ls_elo_progression>-name separated by space.
        condense <ls_elo_progression>-name.
        move <ls_player_data>-city_state_zip to <ls_elo_progression>-city_state_zip.
      endif.
    endloop.
    if filter_non_gb ne space.
      delete me->lt_elo_progression where city_state_zip ne 'GBR'.
    endif.
    clear lv_index.
    loop at me->lt_elo_progression assigning <ls_elo_progression>.
      add 1 to lv_index.
      move lv_index to <ls_elo_progression>-elo_position.
    endloop.
    loop at me->lt_elo_progression assigning <ls_elo_progression>.
      loop at me->lt_ranks assigning <ls_ranks>
        where low_boundary le <ls_elo_progression>-elo_rating and
              high_boundary ge <ls_elo_progression>-elo_rating.
        move <ls_ranks>-rank to <ls_elo_progression>-ranking.
      endloop.
    endloop.
  endif.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_BFA_ELO_RATING->GET_ELO_DIFF
* +-------------------------------------------------------------------------------------------------+
* | [--->] HOME                           TYPE        ZBFA_ELO_RATING
* | [--->] GUEST                          TYPE        ZBFA_ELO_RATING
* | [--->] RESULT                         TYPE        CHAR1
* | [--->] K_VALUE                        TYPE        ZBFA_ELO_RATING
* | [--->] PLAYER                         TYPE        CHAR1
* | [<-()] ELO_DIFF                       TYPE        ZBFA_ELO_RATING
* | [!CX!] ZCX_INVALID_SCORE
* +--------------------------------------------------------------------------------------</SIGNATURE>
method get_elo_diff.
  data: lv_home_q_score type zbfa_elo_rating,
        lv_guest_q_score type zbfa_elo_rating,
        lv_exp_home_score type zbfa_elo_rating,
        lv_score type zbfa_elo_rating,
        lv_new_home_elo type zbfa_elo_rating.
  lv_home_q_score = 10 ** ( home / 400 ).
  lv_guest_q_score = 10 ** ( guest / 400 ).
  if result eq player.
    lv_score = 1.
  else.
    lv_score = 0.
  endif.
  lv_exp_home_score = lv_home_q_score / ( lv_home_q_score + lv_guest_q_score ).
  lv_new_home_elo = home + k_value * ( lv_score - lv_exp_home_score ).
  elo_diff = lv_new_home_elo - home.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_BFA_ELO_RATING->GET_ELO_PROGRESSION
* +-------------------------------------------------------------------------------------------------+
* | [<-()] ELO_PROGRESSION                TYPE        ZBFA_ELO_PROGRES_TAB
* | [!CX!] ZCX_NO_ELO_RATINGS_FOUND
* +--------------------------------------------------------------------------------------</SIGNATURE>
method get_elo_progression.
  move me->lt_elo_progression to elo_progression.
  if lines( elo_progression ) eq 0.
    raise exception type zcx_no_elo_ratings_found.
  endif.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_BFA_ELO_RATING->GET_ELO_RATING
* +-------------------------------------------------------------------------------------------------+
* | [--->] TOURNAMENT_KEY                 TYPE        ZTOURNAMENT_KEY
* | [--->] EVENT_KEY                      TYPE        ZBFA_EVENT_KEY
* | [--->] ENTRY_KEY                      TYPE        ZENTRY_KEY
* | [<-()] ELO_RATING                     TYPE        ZBFA_ELO_RATING
* | [!CX!] ZCX_WRONG_NUMBER_OF_PLAYERS
* | [!CX!] ZCX_EVENT_TYPE_NOT_FOUND
* | [!CX!] ZCX_EVENT_NOT_FOUND
* | [!CX!] ZCX_EVENT_ENTRY_NOT_FOUND
* | [!CX!] ZCX_NEGATIVE_ELO_RATING
* | [!CX!] ZCX_PLAYER_ELO_NOT_FOUND
* +--------------------------------------------------------------------------------------</SIGNATURE>
method get_elo_rating.
  data: lv_player_count type i.
  field-symbols: <ls_event_entry> like line of me->lt_event_entry,
                 <ls_entry_plyrs> like line of me->lt_entry_plyrs,
                 <ls_elo_rating> like line of me->lt_elo_rating,
                 <ls_event> like line of me->lt_event,
                 <ls_event_types> like line of me->lt_event_types.
  read table me->lt_event_entry
    assigning <ls_event_entry>
    with table key tournament_key = tournament_key
                   event_key = event_key
                   entry_key = entry_key.
  if sy-subrc ne 0.
    raise exception type zcx_event_entry_not_found.
  endif.
  clear: lv_player_count,
         elo_rating.
  loop at me->lt_entry_plyrs assigning <ls_entry_plyrs>
    where tournament_key eq <ls_event_entry>-tournament_key and
          event_key eq <ls_event_entry>-event_key and
          entry_key eq <ls_event_entry>-entry_key.
    read table me->lt_elo_rating assigning <ls_elo_rating>
      with table key player_id = <ls_entry_plyrs>-player_id.
    if sy-subrc eq 0.
      if <ls_elo_rating>-elo_rating gt 0.
        add 1 to lv_player_count.
        try.
            elo_rating = elo_rating + ( <ls_elo_rating>-elo_rating * <ls_elo_rating>-elo_rating ).
          catch cx_sy_arithmetic_overflow.
            check 1 = 1.
        endtry.
      else.
        raise exception type zcx_negative_elo_rating.
      endif.
    else.
      raise exception type zcx_player_elo_not_found.
    endif.
  endloop.
  read table lt_event
    assigning <ls_event>
    with table key tournament_key = tournament_key
                   event_key      = event_key.
  if sy-subrc eq 0.
    read table lt_event_types
      assigning <ls_event_types>
      with table key event_key = <ls_event>-event_type.
    if sy-subrc eq 0.
      if lv_player_count eq <ls_event_types>-players.
        elo_rating = elo_rating / lv_player_count.
        elo_rating = sqrt( elo_rating ).
      else.
        raise exception type zcx_wrong_number_of_players.
      endif.
    else.
      raise exception type zcx_event_type_not_found.
    endif.
  else.
    raise exception type zcx_event_not_found.
  endif.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_BFA_ELO_RATING->GET_ELO_RATINGS
* +-------------------------------------------------------------------------------------------------+
* | [--->] PLAYER_ID                      TYPE        ZBFA_PLAYER_ID(optional)
* | [<-()] ELO_RATINGS                    TYPE        ZBFA_ELO_RATING_TABLE
* | [!CX!] ZCX_NO_ELO_RATINGS_FOUND
* +--------------------------------------------------------------------------------------</SIGNATURE>
method get_elo_ratings.
  move me->lt_elo_rating to elo_ratings.
  if player_id is not initial.
    delete elo_ratings where player_id ne player_id.
  endif.
  if lines( elo_ratings ) eq 0.
    raise exception type zcx_no_elo_ratings_found.
  endif.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_BFA_ELO_RATING->GET_MATCH_RESULT
* +-------------------------------------------------------------------------------------------------+
* | [--->] TOURNAMENT_KEY                 TYPE        ZTOURNAMENT_KEY
* | [--->] EVENT_KEY                      TYPE        ZEVENT_KEY
* | [--->] ROUND_KEY                      TYPE        ZROUND_KEY
* | [--->] MATCH_KEY                      TYPE        ZMATCH_KEY
* | [<-()] RESULT                         TYPE        CHAR1
* | [!CX!] ZCX_MATCH_DRAWN
* | [!CX!] ZCX_MATCH_GAMES_NOT_FOUND
* +--------------------------------------------------------------------------------------</SIGNATURE>
method get_match_result.
  field-symbols: <ls_match_games> like line of me->lt_match_games.
  data: lv_home_score type i,
        lv_guest_score type i.
  clear: lv_home_score,
         lv_guest_score.
  loop at me->lt_match_games assigning <ls_match_games>
    where tournament_key eq tournament_key and
          event_key eq event_key and
          round_key eq round_key and
          match_key eq match_key.
    if <ls_match_games>-home_score gt <ls_match_games>-guest_score.
      add 1 to lv_home_score.
    elseif <ls_match_games>-home_score lt <ls_match_games>-guest_score.
      add 1 to lv_guest_score.
    endif.
  endloop.
  if sy-subrc ne 0.
    raise exception type zcx_match_games_not_found.
  endif.
  if lv_home_score gt lv_guest_score.
    result = me->lc_home_win.
  elseif lv_guest_score gt lv_home_score.
    result = me->lc_away_win.
  else.
    raise exception type zcx_match_drawn.
  endif.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_BFA_ELO_RATING->GET_MATCH_RESULTS
* +-------------------------------------------------------------------------------------------------+
* | [--->] PLAYER_ID                      TYPE        ZBFA_PLAYER_ID
* | [<-()] LT_MATCH_RESULTS               TYPE        ZBFA_MATCH_RESULTS_TABLE
* | [!CX!] ZCX_NO_MATCH_RESULTS_FOUND
* +--------------------------------------------------------------------------------------</SIGNATURE>
method get_match_results.
  field-symbols: <ls_match_results> like line of me->lt_match_results.
  lt_match_results = me->lt_match_results.
  loop at lt_match_results assigning <ls_match_results>.
    read table <ls_match_results>-home_player
      transporting no fields
      with key player_id = player_id.
    if sy-subrc ne 0.
      read table <ls_match_results>-guest_player
        transporting no fields
        with key player_id = player_id.
      if sy-subrc ne 0.
        clear <ls_match_results>.
      endif.
    endif.
  endloop.
  delete lt_match_results where table_line is initial.
  if lines( lt_match_results ) ne 0.
    sort lt_match_results by tournament_key event_key weighting round_key.
  else.
    raise exception type zcx_no_match_results_found.
  endif.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_BFA_ELO_RATING->GET_TOURNAMENT_DATA
* +-------------------------------------------------------------------------------------------------+
* | [--->] START_DATE                     TYPE        DATUM
* | [--->] END_DATE                       TYPE        DATUM (default =SY-DATUM)
* | [--->] EVENT_TYPE                     TYPE        ZBFA_EVENT_KEY(optional)
* | [--->] RANK_CAT                       TYPE        ZBFA_RANK_CAT(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
method get_tournament_data.
  data: ls_rank_cat type zbfa_rank_cats.
  data: lv_start_date type datum,
        lv_end_date type datum.
  field-symbols: <ls_event> like line of me->lt_event,
                 <ls_event_entry> like line of me->lt_event_entry,
                 <ls_entry_plyrs> like line of me->lt_entry_plyrs,
                 <ls_player_data> like line of me->lt_player_data.
  select * from zbfa_event_sys
    into table me->lt_event_sys.
  select * from zbfa_player_data
    into table me->lt_player_data.
  select * from zbfa_cat_weight
    into table me->lt_cat_weight.
  if event_type is initial.
    select * from zbfa_event_types
      into table me->lt_event_types.
  else.
    select * from zbfa_event_types
      into table me->lt_event_types
      where event_key eq event_type.
  endif.
  if rank_cat is not initial.
    select single * from zbfa_rank_cats
      into ls_rank_cat
      where rank_cat eq rank_cat.
    if sy-subrc eq 0.
      select * from zbfa_cat_members
        into table me->lt_cat_members
        where rank_cat eq ls_rank_cat-rank_cat.
    endif.
  endif.
  select * from zbfa_club
    into table me->lt_club.
  lv_start_date = start_date.
  if lv_start_date is initial.
    lv_start_date = '00010101'.
  endif.
  lv_end_date = end_date.
  if lv_end_date is initial.
    lv_end_date = sy-datum.
  endif.
  select * from zbfa_tournament
    into table me->lt_tournament
    where tournament_date ge lv_start_date and
          tournament_date le lv_end_date.
  if sy-subrc eq 0.
    select * from zbfa_event
      into table me->lt_event
      for all entries in me->lt_tournament
      where tournament_key eq me->lt_tournament-tournament_key.
    loop at me->lt_event assigning <ls_event>.
      read table me->lt_event_types
        transporting no fields
        with table key event_key = <ls_event>-event_type.
      if sy-subrc ne 0.
        clear: <ls_event>-event_desc,
               <ls_event>-event_system,
               <ls_event>-event_type.
      endif.
      if me->lt_cat_members is not initial.
        read table me->lt_cat_members
          transporting no fields
          with table key rank_cat  = rank_cat
                         event_key = <ls_event>-event_type.
        if sy-subrc ne 0.
          clear: <ls_event>-event_desc,
                 <ls_event>-event_system,
                 <ls_event>-event_type.
        endif.
      endif.
    endloop.
    delete me->lt_event where event_desc is initial and
                                  event_system is initial and
                                  event_type is initial.
    if lines( me->lt_event ) ne 0.
      select * from zbfa_event_entry
        into table me->lt_event_entry
        for all entries in me->lt_event
        where tournament_key eq me->lt_event-tournament_key and
              event_key eq me->lt_event-event_key.
      if sy-subrc eq 0.
        select * from zbfa_entry_plyrs
          into table me->lt_entry_plyrs
          for all entries in me->lt_event_entry
          where tournament_key eq me->lt_event_entry-tournament_key and
                event_key eq me->lt_event_entry-event_key and
                entry_key eq me->lt_event_entry-entry_key.
      endif.
      case rank_cat.
        when 4.
          loop at me->lt_event_entry
            assigning <ls_event_entry>.
            loop at me->lt_entry_plyrs
              assigning <ls_entry_plyrs>
              where tournament_key eq <ls_event_entry>-tournament_key and
                    event_key eq <ls_event_entry>-event_key and
                    entry_key eq <ls_event_entry>-entry_key.
              read table me->lt_player_data
                assigning <ls_player_data>
                with table key player_id = <ls_entry_plyrs>-player_id.
              if sy-subrc eq 0.
                if <ls_player_data>-gender eq 'F'.
                  clear: <ls_event_entry>-entry_name,
                         <ls_event_entry>-entry_seed,
                         <ls_event_entry>-entry_rank.
                endif.
              endif.
            endloop.
          endloop.
          delete me->lt_event_entry where entry_name is initial and
                                          entry_seed is initial and
                                          entry_rank is initial.
        when 5.
          loop at me->lt_event_entry
            assigning <ls_event_entry>.
            loop at me->lt_entry_plyrs
              assigning <ls_entry_plyrs>
              where tournament_key eq <ls_event_entry>-tournament_key and
                    event_key eq <ls_event_entry>-event_key and
                    entry_key eq <ls_event_entry>-entry_key.
              read table me->lt_player_data
                assigning <ls_player_data>
                with table key player_id = <ls_entry_plyrs>-player_id.
              if sy-subrc eq 0.
                if <ls_player_data>-gender eq 'M'.
                  clear: <ls_event_entry>-entry_name,
                         <ls_event_entry>-entry_seed,
                         <ls_event_entry>-entry_rank.
                endif.
              endif.
            endloop.
          endloop.
          delete me->lt_event_entry where entry_name is initial and
                                          entry_seed is initial and
                                          entry_rank is initial.
      endcase.
      if rank_cat eq 4 or rank_cat eq 5 or rank_cat eq 6 or rank_cat eq 7.
        loop at me->lt_event_entry
          assigning <ls_event_entry>.
          loop at me->lt_entry_plyrs
            assigning <ls_entry_plyrs>
            where tournament_key eq <ls_event_entry>-tournament_key and
                  event_key eq <ls_event_entry>-event_key and
                  entry_key eq <ls_event_entry>-entry_key.
            loop at me->lt_player_data
              assigning <ls_player_data>
              where player_id = <ls_entry_plyrs>-player_id.
              find first occurrence of 'GBR' in <ls_player_data>-city_state_zip.
              if sy-subrc ne 0.
                clear: <ls_event_entry>-entry_name,
                       <ls_event_entry>-entry_seed,
                       <ls_event_entry>-entry_rank.
              endif.
            endloop.
          endloop.
        endloop.
        delete me->lt_event_entry where entry_name is initial and
                                        entry_seed is initial and
                                        entry_rank is initial.
      endif.
      select * from zbfa_event_round
        into table me->lt_event_round
        for all entries in me->lt_event
        where tournament_key eq me->lt_event-tournament_key and
              event_key eq me->lt_event-event_key.
      if sy-subrc eq 0.
        select * from zbfa_round_match
          into table me->lt_round_match
          for all entries in me->lt_event_round
          where tournament_key eq me->lt_event_round-tournament_key and
                event_key eq me->lt_event_round-event_key and
                round_key eq me->lt_event_round-round_key.
        if sy-subrc eq 0.
          select * from zbfa_match_games
            into table me->lt_match_games
            for all entries in me->lt_round_match
            where tournament_key eq me->lt_round_match-tournament_key and
                  event_key eq me->lt_round_match-event_key and
                  round_key eq me->lt_round_match-round_key and
                  match_key eq me->lt_round_match-match_key.
        endif.
      endif.
    endif.
  endif.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_BFA_ELO_RATING->GET_TOURNAMENT_PLAYERS
* +-------------------------------------------------------------------------------------------------+
* | [--->] TOURNAMENT_KEY                 TYPE        ZTOURNAMENT_KEY
* | [<-()] PLAYERS                        TYPE        INT4
* +--------------------------------------------------------------------------------------</SIGNATURE>
method get_tournament_players.
  types: begin of t_tournament_plyrs,
           player_id type zbfa_player_id,
         end of t_tournament_plyrs.
  data: lt_tournament_plyrs type standard table of t_tournament_plyrs.
  field-symbols: <ls_entry_plyrs> like line of me->lt_entry_plyrs,
                 <ls_tournament_plyrs> like line of lt_tournament_plyrs.
  clear lt_tournament_plyrs.
  loop at me->lt_entry_plyrs
    assigning <ls_entry_plyrs>
    where tournament_key = tournament_key.
    read table lt_tournament_plyrs
      transporting no fields
      with table key player_id = <ls_entry_plyrs>-player_id.
    if sy-subrc ne 0.
      append initial line to lt_tournament_plyrs
        assigning <ls_tournament_plyrs>.
      move <ls_entry_plyrs>-player_id to <ls_tournament_plyrs>-player_id.
    endif.
  endloop.
  players = lines( lt_tournament_plyrs ).
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_BFA_ELO_RATING->POPULATE_ELO_SEED_DATA
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
method populate_elo_seed_data.
  data: ls_elo_rating like line of me->lt_elo_rating.
  field-symbols: <ls_player_data> like line of me->lt_player_data,
                 <ls_elo_rating> like line of me->lt_elo_rating.
  loop at me->lt_player_data assigning <ls_player_data>.
    clear ls_elo_rating.
    move: <ls_player_data>-player_id to ls_elo_rating-player_id,
          zcl_bfa_elo_rating=>lv_elo_seed_rating to ls_elo_rating-elo_rating.
    insert ls_elo_rating into table me->lt_elo_rating.
  endloop.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_BFA_ELO_RATING->SAVE_RATING_PROGRESSION
* +-------------------------------------------------------------------------------------------------+
* | [--->] YEAR                           TYPE        NUMC4
* +--------------------------------------------------------------------------------------</SIGNATURE>
method save_rating_progression.
  field-symbols: <ls_elo_rating> like line of me->lt_elo_rating.
  data: ls_elo_progression like line of me->lt_elo_progression.
  loop at me->lt_elo_rating assigning <ls_elo_rating>.
    clear ls_elo_progression.
    move year to ls_elo_progression-elo_year.
    move-corresponding <ls_elo_rating> to ls_elo_progression.
    insert ls_elo_progression into table me->lt_elo_progression.
  endloop.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_BFA_ELO_RATING->SET_RANK_BOUNDARIES
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
method set_rank_boundaries.
  data: ls_ranks like line of lt_ranks.
  data: lv_high_rating type zbfa_elo_rating,
        lv_low_rating type zbfa_elo_rating,
        lv_margin type zbfa_elo_rating,
        lv_index type i.
  field-symbols: <ls_elo_rating> like line of me->lt_elo_rating,
                 <ls_ranks> like line of me->lt_ranks.
  check lines( me->lt_elo_rating ) gt 0.
  clear me->lt_ranks.
  lv_index = lines( me->lt_elo_rating ) / 100.
  if lv_index lt 1.
    lv_index = 1.
  endif.
  read table me->lt_elo_rating with key elo_position = lv_index assigning <ls_elo_rating>.
  move <ls_elo_rating>-elo_rating to lv_high_rating.
  read table me->lt_elo_rating with key elo_position = lines( me->lt_elo_rating ) assigning <ls_elo_rating>.
  move <ls_elo_rating>-elo_rating to lv_low_rating.
  lv_margin = ( lv_high_rating - lv_low_rating ) / 5.
  move: 1 to ls_ranks-rank,
        lv_low_rating to ls_ranks-low_boundary,
        lv_low_rating to ls_ranks-high_boundary.
  add lv_margin to ls_ranks-high_boundary.
  insert ls_ranks into table lt_ranks assigning <ls_ranks>.
  lv_index = 1.
  do 25 times.
    add 1 to lv_index.
    move: lv_index to ls_ranks-rank,
          <ls_ranks>-high_boundary to ls_ranks-low_boundary,
          <ls_ranks>-high_boundary to ls_ranks-high_boundary.
    add lv_margin to ls_ranks-high_boundary.
    insert ls_ranks into table lt_ranks assigning <ls_ranks>.
  enddo.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_BFA_ELO_RATING->UPDATE_ELO_RATING
* +-------------------------------------------------------------------------------------------------+
* | [--->] TOURNAMENT_KEY                 TYPE        ZTOURNAMENT_KEY
* | [--->] EVENT_KEY                      TYPE        ZEVENT_KEY
* | [--->] ENTRY_KEY                      TYPE        ZENTRY_KEY
* | [--->] ELO_DIFF                       TYPE        ZBFA_ELO_RATING
* +--------------------------------------------------------------------------------------</SIGNATURE>
method update_elo_rating.
  field-symbols: <ls_event_entry> like line of me->lt_event_entry,
                 <ls_entry_plyrs> like line of me->lt_entry_plyrs,
                 <ls_elo_rating> like line of me->lt_elo_rating.
  read table me->lt_event_entry assigning <ls_event_entry>
    with table key tournament_key = tournament_key
                   event_key = event_key
                   entry_key = entry_key.
  loop at me->lt_entry_plyrs assigning <ls_entry_plyrs>
    where tournament_key eq <ls_event_entry>-tournament_key and
          event_key eq <ls_event_entry>-event_key and
          entry_key eq <ls_event_entry>-entry_key.
    read table me->lt_elo_rating assigning <ls_elo_rating>
      with table key player_id = <ls_entry_plyrs>-player_id.
    if sy-subrc eq 0.
      <ls_elo_rating>-elo_rating = <ls_elo_rating>-elo_rating + elo_diff.
    endif.
  endloop.
endmethod.
ENDCLASS.
Sampson wrote:What language is it written in?
It's written in ABAP.

Sampson wrote:Also, I don't know much about Elo but I know that its goal is to predict the result of a match between two players using the statistical analysis of previous matches. So, how does it, for example, handle this scenario?

Player A consistently beats Player B

Player B consistently beats Player C

Player C consistently beats Player A

Who would be ranked higher?

I know this is an unlikely scenario but [geek] I'm genuinely interested by this kind of thing [/geek].
Who would be ranked higher would depend far more on the results against other players than it would on results against each other. In a round-robin bogey-player situation, assuming equal numbers of games played and nobody else played these players, they'd all be ranked about the same.
Sampson wrote:Thanks again for all your work/time that's gone into this.
No worries - but like I say, the goal isn't Elo ratings, it's tournament software, which is still a long way off yet...
Image

User avatar
robmoss2k
Posts: 1682
Joined: Mon Feb 10, 2003 3:36 pm
Real Name: Robert Moss
Location: Bolton
Contact:

Re: The Elo has landed

Post by robmoss2k » Thu Oct 10, 2013 9:37 am

Oh - I should just add - the relevant method you're probably interested in is get_elo_diff( ).
Image

Alex MM
Posts: 771
Joined: Fri Apr 08, 2011 4:21 pm
Real Name: Alex Millington Marston

Re: The Elo has landed

Post by Alex MM » Mon Oct 14, 2013 5:31 pm

Any chance you could move the rank column in the events results pages to before the players names? Nice work Bobby. Probably worth checking for alternative tournament software before you start designing the whole thing. The main reason everyone uses sport seems to be its ok and people can "use" it.

Post Reply