Stage 2 summary at 50 accepted trajectories

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Kral
2026-10-05 18:02:52 +02:00
parent 332fb4601d
commit 5bcd1bf9cd
1230 changed files with 77563 additions and 33 deletions

View File

@@ -0,0 +1,123 @@
CLASS {{p}}league_table DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_team TYPE c LENGTH 10.
TYPES:
BEGIN OF ty_match,
home_team TYPE ty_team,
away_team TYPE ty_team,
home_goals TYPE i,
away_goals TYPE i,
END OF ty_match.
TYPES tt_match TYPE STANDARD TABLE OF ty_match WITH EMPTY KEY.
TYPES:
BEGIN OF ty_row,
rank TYPE i,
team TYPE ty_team,
played TYPE i,
won TYPE i,
drawn TYPE i,
lost TYPE i,
goals_for TYPE i,
goals_against TYPE i,
goal_diff TYPE i,
points TYPE i,
END OF ty_row.
TYPES tt_row TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY.
METHODS evaluate
IMPORTING it_matches TYPE tt_match
RETURNING VALUE(rt_table) TYPE tt_row.
PRIVATE SECTION.
TYPES tt_work TYPE HASHED TABLE OF ty_row WITH UNIQUE KEY team.
METHODS is_invalid
IMPORTING is_match TYPE ty_match
RETURNING VALUE(rv_bad) TYPE abap_bool.
METHODS add_result
IMPORTING iv_team TYPE ty_team
iv_goals_for TYPE i
iv_goals_against TYPE i
CHANGING ct_work TYPE tt_work.
METHODS assign_rank
CHANGING ct_table TYPE tt_row.
ENDCLASS.
CLASS {{p}}league_table IMPLEMENTATION.
METHOD evaluate.
DATA lt_work TYPE tt_work.
LOOP AT it_matches INTO DATA(ls_match).
IF is_invalid( ls_match ) = abap_true.
add_result( EXPORTING iv_team = ls_match-home_team
iv_goals_for = ls_match-home_goals
iv_goals_against = ls_match-away_goals
CHANGING ct_work = lt_work ).
add_result( EXPORTING iv_team = ls_match-away_team
iv_goals_for = ls_match-away_goals
iv_goals_against = ls_match-home_goals
CHANGING ct_work = lt_work ).
ENDIF.
ENDLOOP.
rt_table = lt_work.
SORT rt_table BY points DESCENDING
goal_diff DESCENDING
goals_for DESCENDING
team ASCENDING.
assign_rank( CHANGING ct_table = rt_table ).
ENDMETHOD.
METHOD is_invalid.
rv_bad = xsdbool( is_match-home_team IS INITIAL
OR is_match-away_team IS INITIAL
OR is_match-home_team = is_match-away_team
OR is_match-home_goals < 0
OR is_match-away_goals < 0 ).
ENDMETHOD.
METHOD add_result.
ASSIGN ct_work[ team = iv_team ] TO FIELD-SYMBOL(<ls_row>).
IF sy-subrc <> 0.
INSERT VALUE ty_row( team = iv_team ) INTO TABLE ct_work ASSIGNING <ls_row>.
ENDIF.
<ls_row>-played = <ls_row>-played + 1.
<ls_row>-goals_for = <ls_row>-goals_for + iv_goals_for.
<ls_row>-goals_against = <ls_row>-goals_against + iv_goals_against.
<ls_row>-goal_diff = <ls_row>-goals_for - <ls_row>-goals_against.
IF iv_goals_for > iv_goals_against.
<ls_row>-won = <ls_row>-won + 1.
<ls_row>-points = <ls_row>-points + 3.
ELSEIF iv_goals_for = iv_goals_against.
<ls_row>-drawn = <ls_row>-drawn + 1.
<ls_row>-points = <ls_row>-points + 1.
ELSE.
<ls_row>-lost = <ls_row>-lost + 1.
ENDIF.
ENDMETHOD.
METHOD assign_rank.
DATA lv_rank TYPE i.
DATA lv_position TYPE i.
DATA ls_previous TYPE ty_row.
LOOP AT ct_table ASSIGNING FIELD-SYMBOL(<ls_row>).
lv_position = lv_position + 1.
IF lv_position = 1
OR <ls_row>-points <> ls_previous-points
OR <ls_row>-goal_diff <> ls_previous-goal_diff
OR <ls_row>-goals_for <> ls_previous-goals_for.
lv_rank = lv_position.
ENDIF.
<ls_row>-rank = lv_rank.
ls_previous = <ls_row>.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,123 @@
CLASS {{p}}league_table DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_team TYPE c LENGTH 10.
TYPES:
BEGIN OF ty_match,
home_team TYPE ty_team,
away_team TYPE ty_team,
home_goals TYPE i,
away_goals TYPE i,
END OF ty_match.
TYPES tt_match TYPE STANDARD TABLE OF ty_match WITH EMPTY KEY.
TYPES:
BEGIN OF ty_row,
rank TYPE i,
team TYPE ty_team,
played TYPE i,
won TYPE i,
drawn TYPE i,
lost TYPE i,
goals_for TYPE i,
goals_against TYPE i,
goal_diff TYPE i,
points TYPE i,
END OF ty_row.
TYPES tt_row TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY.
METHODS evaluate
IMPORTING it_matches TYPE tt_match
RETURNING VALUE(rt_table) TYPE tt_row.
PRIVATE SECTION.
TYPES tt_work TYPE HASHED TABLE OF ty_row WITH UNIQUE KEY team.
METHODS is_invalid
IMPORTING is_match TYPE ty_match
RETURNING VALUE(rv_bad) TYPE abap_bool.
METHODS add_result
IMPORTING iv_team TYPE ty_team
iv_goals_for TYPE i
iv_goals_against TYPE i
CHANGING ct_work TYPE tt_work.
METHODS assign_rank
CHANGING ct_table TYPE tt_row.
ENDCLASS.
CLASS {{p}}league_table IMPLEMENTATION.
METHOD evaluate.
DATA lt_work TYPE tt_work.
LOOP AT it_matches INTO DATA(ls_match).
IF is_invalid( ls_match ) = abap_false.
add_result( EXPORTING iv_team = ls_match-home_team
iv_goals_for = ls_match-home_goals
iv_goals_against = ls_match-away_goals
CHANGING ct_work = lt_work ).
add_result( EXPORTING iv_team = ls_match-away_team
iv_goals_for = ls_match-away_goals
iv_goals_against = ls_match-home_goals
CHANGING ct_work = lt_work ).
ENDIF.
ENDLOOP.
rt_table = lt_work.
SORT rt_table BY points DESCENDING
goal_diff DESCENDING
goals_for DESCENDING
team ASCENDING.
assign_rank( CHANGING ct_table = rt_table ).
ENDMETHOD.
METHOD is_invalid.
rv_bad = xsdbool( is_match-home_team IS INITIAL
OR is_match-away_team IS INITIAL
AND is_match-home_team = is_match-away_team
OR is_match-home_goals < 0
OR is_match-away_goals < 0 ).
ENDMETHOD.
METHOD add_result.
ASSIGN ct_work[ team = iv_team ] TO FIELD-SYMBOL(<ls_row>).
IF sy-subrc <> 0.
INSERT VALUE ty_row( team = iv_team ) INTO TABLE ct_work ASSIGNING <ls_row>.
ENDIF.
<ls_row>-played = <ls_row>-played + 1.
<ls_row>-goals_for = <ls_row>-goals_for + iv_goals_for.
<ls_row>-goals_against = <ls_row>-goals_against + iv_goals_against.
<ls_row>-goal_diff = <ls_row>-goals_for - <ls_row>-goals_against.
IF iv_goals_for > iv_goals_against.
<ls_row>-won = <ls_row>-won + 1.
<ls_row>-points = <ls_row>-points + 3.
ELSEIF iv_goals_for = iv_goals_against.
<ls_row>-drawn = <ls_row>-drawn + 1.
<ls_row>-points = <ls_row>-points + 1.
ELSE.
<ls_row>-lost = <ls_row>-lost + 1.
ENDIF.
ENDMETHOD.
METHOD assign_rank.
DATA lv_rank TYPE i.
DATA lv_position TYPE i.
DATA ls_previous TYPE ty_row.
LOOP AT ct_table ASSIGNING FIELD-SYMBOL(<ls_row>).
lv_position = lv_position + 1.
IF lv_position = 1
OR <ls_row>-points <> ls_previous-points
OR <ls_row>-goal_diff <> ls_previous-goal_diff
OR <ls_row>-goals_for <> ls_previous-goals_for.
lv_rank = lv_position.
ENDIF.
<ls_row>-rank = lv_rank.
ls_previous = <ls_row>.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,123 @@
CLASS {{p}}league_table DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_team TYPE c LENGTH 10.
TYPES:
BEGIN OF ty_match,
home_team TYPE ty_team,
away_team TYPE ty_team,
home_goals TYPE i,
away_goals TYPE i,
END OF ty_match.
TYPES tt_match TYPE STANDARD TABLE OF ty_match WITH EMPTY KEY.
TYPES:
BEGIN OF ty_row,
rank TYPE i,
team TYPE ty_team,
played TYPE i,
won TYPE i,
drawn TYPE i,
lost TYPE i,
goals_for TYPE i,
goals_against TYPE i,
goal_diff TYPE i,
points TYPE i,
END OF ty_row.
TYPES tt_row TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY.
METHODS evaluate
IMPORTING it_matches TYPE tt_match
RETURNING VALUE(rt_table) TYPE tt_row.
PRIVATE SECTION.
TYPES tt_work TYPE HASHED TABLE OF ty_row WITH UNIQUE KEY team.
METHODS is_invalid
IMPORTING is_match TYPE ty_match
RETURNING VALUE(rv_bad) TYPE abap_bool.
METHODS add_result
IMPORTING iv_team TYPE ty_team
iv_goals_for TYPE i
iv_goals_against TYPE i
CHANGING ct_work TYPE tt_work.
METHODS assign_rank
CHANGING ct_table TYPE tt_row.
ENDCLASS.
CLASS {{p}}league_table IMPLEMENTATION.
METHOD evaluate.
DATA lt_work TYPE tt_work.
LOOP AT it_matches INTO DATA(ls_match).
IF is_invalid( ls_match ) = abap_false.
add_result( EXPORTING iv_team = ls_match-home_team
iv_goals_for = ls_match-home_goals
iv_goals_against = ls_match-away_goals
CHANGING ct_work = lt_work ).
add_result( EXPORTING iv_team = ls_match-away_team
iv_goals_for = ls_match-away_goals
iv_goals_against = ls_match-home_goals
CHANGING ct_work = lt_work ).
ENDIF.
ENDLOOP.
rt_table = lt_work.
SORT rt_table BY points DESCENDING
goal_diff DESCENDING
goals_for DESCENDING
team ASCENDING.
assign_rank( CHANGING ct_table = rt_table ).
ENDMETHOD.
METHOD is_invalid.
rv_bad = xsdbool( is_match-home_team IS INITIAL
OR is_match-away_team IS INITIAL
OR is_match-home_team = is_match-away_team
OR is_match-home_goals < 0
OR is_match-away_goals < 0 ).
ENDMETHOD.
METHOD add_result.
ASSIGN ct_work[ team = iv_team ] TO FIELD-SYMBOL(<ls_row>).
IF sy-subrc <> 0.
INSERT VALUE ty_row( team = iv_team ) INTO TABLE ct_work ASSIGNING <ls_row>.
ENDIF.
<ls_row>-played = <ls_row>-played - 1.
<ls_row>-goals_for = <ls_row>-goals_for + iv_goals_for.
<ls_row>-goals_against = <ls_row>-goals_against + iv_goals_against.
<ls_row>-goal_diff = <ls_row>-goals_for - <ls_row>-goals_against.
IF iv_goals_for > iv_goals_against.
<ls_row>-won = <ls_row>-won + 1.
<ls_row>-points = <ls_row>-points + 3.
ELSEIF iv_goals_for = iv_goals_against.
<ls_row>-drawn = <ls_row>-drawn + 1.
<ls_row>-points = <ls_row>-points + 1.
ELSE.
<ls_row>-lost = <ls_row>-lost + 1.
ENDIF.
ENDMETHOD.
METHOD assign_rank.
DATA lv_rank TYPE i.
DATA lv_position TYPE i.
DATA ls_previous TYPE ty_row.
LOOP AT ct_table ASSIGNING FIELD-SYMBOL(<ls_row>).
lv_position = lv_position + 1.
IF lv_position = 1
OR <ls_row>-points <> ls_previous-points
OR <ls_row>-goal_diff <> ls_previous-goal_diff
OR <ls_row>-goals_for <> ls_previous-goals_for.
lv_rank = lv_position.
ENDIF.
<ls_row>-rank = lv_rank.
ls_previous = <ls_row>.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,123 @@
CLASS {{p}}league_table DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_team TYPE c LENGTH 10.
TYPES:
BEGIN OF ty_match,
home_team TYPE ty_team,
away_team TYPE ty_team,
home_goals TYPE i,
away_goals TYPE i,
END OF ty_match.
TYPES tt_match TYPE STANDARD TABLE OF ty_match WITH EMPTY KEY.
TYPES:
BEGIN OF ty_row,
rank TYPE i,
team TYPE ty_team,
played TYPE i,
won TYPE i,
drawn TYPE i,
lost TYPE i,
goals_for TYPE i,
goals_against TYPE i,
goal_diff TYPE i,
points TYPE i,
END OF ty_row.
TYPES tt_row TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY.
METHODS evaluate
IMPORTING it_matches TYPE tt_match
RETURNING VALUE(rt_table) TYPE tt_row.
PRIVATE SECTION.
TYPES tt_work TYPE HASHED TABLE OF ty_row WITH UNIQUE KEY team.
METHODS is_invalid
IMPORTING is_match TYPE ty_match
RETURNING VALUE(rv_bad) TYPE abap_bool.
METHODS add_result
IMPORTING iv_team TYPE ty_team
iv_goals_for TYPE i
iv_goals_against TYPE i
CHANGING ct_work TYPE tt_work.
METHODS assign_rank
CHANGING ct_table TYPE tt_row.
ENDCLASS.
CLASS {{p}}league_table IMPLEMENTATION.
METHOD evaluate.
DATA lt_work TYPE tt_work.
LOOP AT it_matches INTO DATA(ls_match).
IF is_invalid( ls_match ) = abap_false.
add_result( EXPORTING iv_team = ls_match-home_team
iv_goals_for = ls_match-home_goals
iv_goals_against = ls_match-away_goals
CHANGING ct_work = lt_work ).
add_result( EXPORTING iv_team = ls_match-away_team
iv_goals_for = ls_match-away_goals
iv_goals_against = ls_match-home_goals
CHANGING ct_work = lt_work ).
ENDIF.
ENDLOOP.
rt_table = lt_work.
SORT rt_table BY points DESCENDING
goal_diff DESCENDING
goals_for DESCENDING
team ASCENDING.
assign_rank( CHANGING ct_table = rt_table ).
ENDMETHOD.
METHOD is_invalid.
rv_bad = xsdbool( is_match-home_team IS INITIAL
OR is_match-away_team IS INITIAL
OR is_match-home_team = is_match-away_team
OR is_match-home_goals < 0
OR is_match-away_goals < 0 ).
ENDMETHOD.
METHOD add_result.
ASSIGN ct_work[ team = iv_team ] TO FIELD-SYMBOL(<ls_row>).
IF sy-subrc <> 0.
INSERT VALUE ty_row( team = iv_team ) INTO TABLE ct_work ASSIGNING <ls_row>.
ENDIF.
<ls_row>-played = <ls_row>-played + 1.
<ls_row>-goals_for = <ls_row>-goals_for + iv_goals_for.
<ls_row>-goals_against = <ls_row>-goals_against + iv_goals_against.
<ls_row>-goal_diff = <ls_row>-goals_for - <ls_row>-goals_against.
IF iv_goals_for > iv_goals_against.
<ls_row>-won = <ls_row>-won + 1.
<ls_row>-points = <ls_row>-points + 3.
ELSEIF iv_goals_for <> iv_goals_against.
<ls_row>-drawn = <ls_row>-drawn + 1.
<ls_row>-points = <ls_row>-points + 1.
ELSE.
<ls_row>-lost = <ls_row>-lost + 1.
ENDIF.
ENDMETHOD.
METHOD assign_rank.
DATA lv_rank TYPE i.
DATA lv_position TYPE i.
DATA ls_previous TYPE ty_row.
LOOP AT ct_table ASSIGNING FIELD-SYMBOL(<ls_row>).
lv_position = lv_position + 1.
IF lv_position = 1
OR <ls_row>-points <> ls_previous-points
OR <ls_row>-goal_diff <> ls_previous-goal_diff
OR <ls_row>-goals_for <> ls_previous-goals_for.
lv_rank = lv_position.
ENDIF.
<ls_row>-rank = lv_rank.
ls_previous = <ls_row>.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,123 @@
CLASS {{p}}league_table DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_team TYPE c LENGTH 10.
TYPES:
BEGIN OF ty_match,
home_team TYPE ty_team,
away_team TYPE ty_team,
home_goals TYPE i,
away_goals TYPE i,
END OF ty_match.
TYPES tt_match TYPE STANDARD TABLE OF ty_match WITH EMPTY KEY.
TYPES:
BEGIN OF ty_row,
rank TYPE i,
team TYPE ty_team,
played TYPE i,
won TYPE i,
drawn TYPE i,
lost TYPE i,
goals_for TYPE i,
goals_against TYPE i,
goal_diff TYPE i,
points TYPE i,
END OF ty_row.
TYPES tt_row TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY.
METHODS evaluate
IMPORTING it_matches TYPE tt_match
RETURNING VALUE(rt_table) TYPE tt_row.
PRIVATE SECTION.
TYPES tt_work TYPE HASHED TABLE OF ty_row WITH UNIQUE KEY team.
METHODS is_invalid
IMPORTING is_match TYPE ty_match
RETURNING VALUE(rv_bad) TYPE abap_bool.
METHODS add_result
IMPORTING iv_team TYPE ty_team
iv_goals_for TYPE i
iv_goals_against TYPE i
CHANGING ct_work TYPE tt_work.
METHODS assign_rank
CHANGING ct_table TYPE tt_row.
ENDCLASS.
CLASS {{p}}league_table IMPLEMENTATION.
METHOD evaluate.
DATA lt_work TYPE tt_work.
LOOP AT it_matches INTO DATA(ls_match).
IF is_invalid( ls_match ) = abap_false.
add_result( EXPORTING iv_team = ls_match-home_team
iv_goals_for = ls_match-home_goals
iv_goals_against = ls_match-away_goals
CHANGING ct_work = lt_work ).
add_result( EXPORTING iv_team = ls_match-away_team
iv_goals_for = ls_match-away_goals
iv_goals_against = ls_match-home_goals
CHANGING ct_work = lt_work ).
ENDIF.
ENDLOOP.
rt_table = lt_work.
SORT rt_table BY points DESCENDING
goal_diff DESCENDING
goals_for DESCENDING
team ASCENDING.
assign_rank( CHANGING ct_table = rt_table ).
ENDMETHOD.
METHOD is_invalid.
rv_bad = xsdbool( is_match-home_team IS INITIAL
OR is_match-away_team IS INITIAL
OR is_match-home_team = is_match-away_team
OR is_match-home_goals < 0
OR is_match-away_goals < 0 ).
ENDMETHOD.
METHOD add_result.
ASSIGN ct_work[ team = iv_team ] TO FIELD-SYMBOL(<ls_row>).
IF sy-subrc <> 0.
INSERT VALUE ty_row( team = iv_team ) INTO TABLE ct_work ASSIGNING <ls_row>.
ENDIF.
<ls_row>-played = <ls_row>-played + 1.
<ls_row>-goals_for = <ls_row>-goals_for + iv_goals_for.
<ls_row>-goals_against = <ls_row>-goals_against + iv_goals_against.
<ls_row>-goal_diff = <ls_row>-goals_for - <ls_row>-goals_against.
IF iv_goals_for > iv_goals_against.
<ls_row>-won = <ls_row>-won + 1.
<ls_row>-points = <ls_row>-points + 3.
ELSEIF iv_goals_for = iv_goals_against.
<ls_row>-drawn = <ls_row>-drawn + 1.
<ls_row>-points = <ls_row>-points + 1.
ELSE.
<ls_row>-lost = <ls_row>-lost + 1.
ENDIF.
ENDMETHOD.
METHOD assign_rank.
DATA lv_rank TYPE i.
DATA lv_position TYPE i.
DATA ls_previous TYPE ty_row.
LOOP AT ct_table ASSIGNING FIELD-SYMBOL(<ls_row>).
lv_position = lv_position + 1.
IF lv_position = 1
OR <ls_row>-points <> ls_previous-points
OR <ls_row>-goal_diff <> ls_previous-goal_diff
OR <ls_row>-goals_for = ls_previous-goals_for.
lv_rank = lv_position.
ENDIF.
<ls_row>-rank = lv_rank.
ls_previous = <ls_row>.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,19 @@
{
"id": "G1069",
"pool": "train",
"object_type": "CLAS",
"category": "C",
"attempts": [
{
"stage": "validate",
"oracle": 100.0,
"null": 0,
"mutation": {
"valid": 5,
"killed": 5,
"ok": true
}
}
],
"accepted": true
}

View File

@@ -0,0 +1,142 @@
CLASS {{p}}t31_hidden DEFINITION PUBLIC FINAL CREATE PUBLIC
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
DATA mo_cut TYPE REF TO {{p}}league_table.
METHODS setup.
METHODS basic_league
RETURNING VALUE(rt_matches) TYPE {{p}}league_table=>tt_match.
METHODS empty_input_is_empty FOR TESTING.
METHODS ignores_invalid_matches FOR TESTING.
METHODS counts_played_and_points FOR TESTING.
METHODS accumulates_goals FOR TESTING.
METHODS sorts_by_points FOR TESTING.
METHODS sorts_by_goal_diff FOR TESTING.
METHODS sorts_by_goals_for FOR TESTING.
METHODS sorts_by_team_name FOR TESTING.
METHODS ties_share_rank FOR TESTING.
METHODS rank_jumps_after_tie FOR TESTING.
ENDCLASS.
CLASS {{p}}t31_hidden IMPLEMENTATION.
METHOD setup.
mo_cut = NEW {{p}}league_table( ).
ENDMETHOD.
METHOD basic_league.
rt_matches = VALUE #(
( home_team = 'A' away_team = 'B' home_goals = 2 away_goals = 0 )
( home_team = 'A' away_team = 'C' home_goals = 1 away_goals = 1 )
( home_team = 'B' away_team = 'C' home_goals = 3 away_goals = 1 )
( home_team = 'C' away_team = 'D' home_goals = 2 away_goals = 2 )
( home_team = 'D' away_team = 'A' home_goals = 0 away_goals = 3 ) ).
ENDMETHOD.
METHOD empty_input_is_empty.
DATA(lt_table) = mo_cut->evaluate( VALUE {{p}}league_table=>tt_match( ) ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lines( lt_table ) ).
ENDMETHOD.
METHOD ignores_invalid_matches.
DATA(lt_matches) = VALUE {{p}}league_table=>tt_match(
( home_team = '' away_team = 'B' home_goals = 1 away_goals = 0 )
( home_team = 'A' away_team = '' home_goals = 1 away_goals = 0 )
( home_team = 'A' away_team = 'A' home_goals = 1 away_goals = 0 )
( home_team = 'A' away_team = 'B' home_goals = -1 away_goals = 0 )
( home_team = 'A' away_team = 'B' home_goals = 0 away_goals = -2 ) ).
DATA(lt_table) = mo_cut->evaluate( lt_matches ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lines( lt_table ) ).
ENDMETHOD.
METHOD counts_played_and_points.
DATA(lt_table) = mo_cut->evaluate( basic_league( ) ).
cl_abap_unit_assert=>assert_equals( exp = 4 act = lines( lt_table ) ).
cl_abap_unit_assert=>assert_equals( exp = 'A' act = lt_table[ 1 ]-team ).
cl_abap_unit_assert=>assert_equals( exp = 3 act = lt_table[ 1 ]-played ).
cl_abap_unit_assert=>assert_equals( exp = 2 act = lt_table[ 1 ]-won ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lt_table[ 1 ]-drawn ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lt_table[ 1 ]-lost ).
cl_abap_unit_assert=>assert_equals( exp = 7 act = lt_table[ 1 ]-points ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lt_table[ 1 ]-rank ).
ENDMETHOD.
METHOD accumulates_goals.
DATA(lt_table) = mo_cut->evaluate( basic_league( ) ).
cl_abap_unit_assert=>assert_equals( exp = 6 act = lt_table[ 1 ]-goals_for ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lt_table[ 1 ]-goals_against ).
cl_abap_unit_assert=>assert_equals( exp = 5 act = lt_table[ 1 ]-goal_diff ).
cl_abap_unit_assert=>assert_equals( exp = 2 act = lt_table[ 4 ]-goals_for ).
cl_abap_unit_assert=>assert_equals( exp = 5 act = lt_table[ 4 ]-goals_against ).
cl_abap_unit_assert=>assert_equals( exp = -3 act = lt_table[ 4 ]-goal_diff ).
ENDMETHOD.
METHOD sorts_by_points.
DATA(lt_table) = mo_cut->evaluate( basic_league( ) ).
cl_abap_unit_assert=>assert_equals( exp = 'A' act = lt_table[ 1 ]-team ).
cl_abap_unit_assert=>assert_equals( exp = 'B' act = lt_table[ 2 ]-team ).
cl_abap_unit_assert=>assert_equals( exp = 'C' act = lt_table[ 3 ]-team ).
cl_abap_unit_assert=>assert_equals( exp = 'D' act = lt_table[ 4 ]-team ).
ENDMETHOD.
METHOD sorts_by_goal_diff.
DATA(lt_matches) = VALUE {{p}}league_table=>tt_match(
( home_team = 'P' away_team = 'R' home_goals = 3 away_goals = 0 )
( home_team = 'Q' away_team = 'S' home_goals = 1 away_goals = 0 ) ).
DATA(lt_table) = mo_cut->evaluate( lt_matches ).
cl_abap_unit_assert=>assert_equals( exp = 'P' act = lt_table[ 1 ]-team ).
cl_abap_unit_assert=>assert_equals( exp = 'Q' act = lt_table[ 2 ]-team ).
cl_abap_unit_assert=>assert_equals( exp = 'S' act = lt_table[ 3 ]-team ).
cl_abap_unit_assert=>assert_equals( exp = 'R' act = lt_table[ 4 ]-team ).
ENDMETHOD.
METHOD sorts_by_goals_for.
DATA(lt_matches) = VALUE {{p}}league_table=>tt_match(
( home_team = 'P' away_team = 'R' home_goals = 2 away_goals = 0 )
( home_team = 'Q' away_team = 'S' home_goals = 3 away_goals = 1 ) ).
DATA(lt_table) = mo_cut->evaluate( lt_matches ).
cl_abap_unit_assert=>assert_equals( exp = 'Q' act = lt_table[ 1 ]-team ).
cl_abap_unit_assert=>assert_equals( exp = 'P' act = lt_table[ 2 ]-team ).
cl_abap_unit_assert=>assert_equals( exp = 'S' act = lt_table[ 3 ]-team ).
cl_abap_unit_assert=>assert_equals( exp = 'R' act = lt_table[ 4 ]-team ).
ENDMETHOD.
METHOD sorts_by_team_name.
DATA(lt_matches) = VALUE {{p}}league_table=>tt_match(
( home_team = 'ZEBRA' away_team = 'Y' home_goals = 1 away_goals = 0 )
( home_team = 'ALPHA' away_team = 'X' home_goals = 1 away_goals = 0 ) ).
DATA(lt_table) = mo_cut->evaluate( lt_matches ).
cl_abap_unit_assert=>assert_equals( exp = 'ALPHA' act = lt_table[ 1 ]-team ).
cl_abap_unit_assert=>assert_equals( exp = 'ZEBRA' act = lt_table[ 2 ]-team ).
cl_abap_unit_assert=>assert_equals( exp = 'X' act = lt_table[ 3 ]-team ).
cl_abap_unit_assert=>assert_equals( exp = 'Y' act = lt_table[ 4 ]-team ).
ENDMETHOD.
METHOD ties_share_rank.
DATA(lt_matches) = VALUE {{p}}league_table=>tt_match(
( home_team = 'E' away_team = 'F' home_goals = 1 away_goals = 1 )
( home_team = 'G' away_team = 'H' home_goals = 1 away_goals = 1 ) ).
DATA(lt_table) = mo_cut->evaluate( lt_matches ).
cl_abap_unit_assert=>assert_equals( exp = 4 act = lines( lt_table ) ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lt_table[ 1 ]-rank ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lt_table[ 2 ]-rank ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lt_table[ 3 ]-rank ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lt_table[ 4 ]-rank ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lt_table[ 1 ]-points ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lt_table[ 1 ]-drawn ).
ENDMETHOD.
METHOD rank_jumps_after_tie.
DATA(lt_matches) = VALUE {{p}}league_table=>tt_match(
( home_team = 'A' away_team = 'B' home_goals = 1 away_goals = 0 )
( home_team = 'C' away_team = 'D' home_goals = 1 away_goals = 1 ) ).
DATA(lt_table) = mo_cut->evaluate( lt_matches ).
cl_abap_unit_assert=>assert_equals( exp = 'A' act = lt_table[ 1 ]-team ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lt_table[ 1 ]-rank ).
cl_abap_unit_assert=>assert_equals( exp = 2 act = lt_table[ 2 ]-rank ).
cl_abap_unit_assert=>assert_equals( exp = 2 act = lt_table[ 3 ]-rank ).
cl_abap_unit_assert=>assert_equals( exp = 4 act = lt_table[ 4 ]-rank ).
cl_abap_unit_assert=>assert_equals( exp = 'B' act = lt_table[ 4 ]-team ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,65 @@
{
"task": "G1069",
"mutants": [
{
"object": "{{P}}LEAGUE_TABLE",
"mutant": "line 56: abap_false -> abap_true (bool)",
"status": "killed",
"hidden": "1/10",
"failed_tests": [
"ACCUMULATES_GOALS",
"COUNTS_PLAYED_AND_POINTS",
"IGNORES_INVALID_MATCHES",
"RANK_JUMPS_AFTER_TIE",
"SORTS_BY_GOALS_FOR",
"SORTS_BY_GOAL_DIFF",
"SORTS_BY_POINTS",
"SORTS_BY_TEAM_NAME",
"TIES_SHARE_RANK"
]
},
{
"object": "{{P}}LEAGUE_TABLE",
"mutant": "line 79: OR -> AND (logic)",
"status": "killed",
"hidden": "9/10",
"failed_tests": [
"IGNORES_INVALID_MATCHES"
]
},
{
"object": "{{P}}LEAGUE_TABLE",
"mutant": "line 90: + -> - (arith)",
"status": "killed",
"hidden": "9/10",
"failed_tests": [
"COUNTS_PLAYED_AND_POINTS"
]
},
{
"object": "{{P}}LEAGUE_TABLE",
"mutant": "line 98: = -> <> (eq)",
"status": "killed",
"hidden": "7/10",
"failed_tests": [
"COUNTS_PLAYED_AND_POINTS",
"RANK_JUMPS_AFTER_TIE",
"TIES_SHARE_RANK"
]
},
{
"object": "{{P}}LEAGUE_TABLE",
"mutant": "line 116: <> -> = (rel)",
"status": "killed",
"hidden": "8/10",
"failed_tests": [
"RANK_JUMPS_AFTER_TIE",
"TIES_SHARE_RANK"
]
}
],
"valid": 5,
"killed": 5,
"kill_rate": 1.0,
"ok": true
}

View File

@@ -0,0 +1,123 @@
CLASS {{p}}league_table DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_team TYPE c LENGTH 10.
TYPES:
BEGIN OF ty_match,
home_team TYPE ty_team,
away_team TYPE ty_team,
home_goals TYPE i,
away_goals TYPE i,
END OF ty_match.
TYPES tt_match TYPE STANDARD TABLE OF ty_match WITH EMPTY KEY.
TYPES:
BEGIN OF ty_row,
rank TYPE i,
team TYPE ty_team,
played TYPE i,
won TYPE i,
drawn TYPE i,
lost TYPE i,
goals_for TYPE i,
goals_against TYPE i,
goal_diff TYPE i,
points TYPE i,
END OF ty_row.
TYPES tt_row TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY.
METHODS evaluate
IMPORTING it_matches TYPE tt_match
RETURNING VALUE(rt_table) TYPE tt_row.
PRIVATE SECTION.
TYPES tt_work TYPE HASHED TABLE OF ty_row WITH UNIQUE KEY team.
METHODS is_invalid
IMPORTING is_match TYPE ty_match
RETURNING VALUE(rv_bad) TYPE abap_bool.
METHODS add_result
IMPORTING iv_team TYPE ty_team
iv_goals_for TYPE i
iv_goals_against TYPE i
CHANGING ct_work TYPE tt_work.
METHODS assign_rank
CHANGING ct_table TYPE tt_row.
ENDCLASS.
CLASS {{p}}league_table IMPLEMENTATION.
METHOD evaluate.
DATA lt_work TYPE tt_work.
LOOP AT it_matches INTO DATA(ls_match).
IF is_invalid( ls_match ) = abap_false.
add_result( EXPORTING iv_team = ls_match-home_team
iv_goals_for = ls_match-home_goals
iv_goals_against = ls_match-away_goals
CHANGING ct_work = lt_work ).
add_result( EXPORTING iv_team = ls_match-away_team
iv_goals_for = ls_match-away_goals
iv_goals_against = ls_match-home_goals
CHANGING ct_work = lt_work ).
ENDIF.
ENDLOOP.
rt_table = lt_work.
SORT rt_table BY points DESCENDING
goal_diff DESCENDING
goals_for DESCENDING
team ASCENDING.
assign_rank( CHANGING ct_table = rt_table ).
ENDMETHOD.
METHOD is_invalid.
rv_bad = xsdbool( is_match-home_team IS INITIAL
OR is_match-away_team IS INITIAL
OR is_match-home_team = is_match-away_team
OR is_match-home_goals < 0
OR is_match-away_goals < 0 ).
ENDMETHOD.
METHOD add_result.
ASSIGN ct_work[ team = iv_team ] TO FIELD-SYMBOL(<ls_row>).
IF sy-subrc <> 0.
INSERT VALUE ty_row( team = iv_team ) INTO TABLE ct_work ASSIGNING <ls_row>.
ENDIF.
<ls_row>-played = <ls_row>-played + 1.
<ls_row>-goals_for = <ls_row>-goals_for + iv_goals_for.
<ls_row>-goals_against = <ls_row>-goals_against + iv_goals_against.
<ls_row>-goal_diff = <ls_row>-goals_for - <ls_row>-goals_against.
IF iv_goals_for > iv_goals_against.
<ls_row>-won = <ls_row>-won + 1.
<ls_row>-points = <ls_row>-points + 3.
ELSEIF iv_goals_for = iv_goals_against.
<ls_row>-drawn = <ls_row>-drawn + 1.
<ls_row>-points = <ls_row>-points + 1.
ELSE.
<ls_row>-lost = <ls_row>-lost + 1.
ENDIF.
ENDMETHOD.
METHOD assign_rank.
DATA lv_rank TYPE i.
DATA lv_position TYPE i.
DATA ls_previous TYPE ty_row.
LOOP AT ct_table ASSIGNING FIELD-SYMBOL(<ls_row>).
lv_position = lv_position + 1.
IF lv_position = 1
OR <ls_row>-points <> ls_previous-points
OR <ls_row>-goal_diff <> ls_previous-goal_diff
OR <ls_row>-goals_for <> ls_previous-goals_for.
lv_rank = lv_position.
ENDIF.
<ls_row>-rank = lv_rank.
ls_previous = <ls_row>.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,47 @@
CLASS ltc_league_table DEFINITION FINAL FOR TESTING
DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
DATA mo_cut TYPE REF TO {{p}}league_table.
METHODS setup.
METHODS empty_input_is_empty FOR TESTING.
METHODS counts_points FOR TESTING.
METHODS ignores_invalid_match FOR TESTING.
METHODS ranks_ties_equal FOR TESTING.
ENDCLASS.
CLASS ltc_league_table IMPLEMENTATION.
METHOD setup.
mo_cut = NEW {{p}}league_table( ).
ENDMETHOD.
METHOD empty_input_is_empty.
DATA(lt_table) = mo_cut->evaluate( VALUE {{p}}league_table=>tt_match( ) ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lines( lt_table ) ).
ENDMETHOD.
METHOD counts_points.
DATA(lt_table) = mo_cut->evaluate( VALUE {{p}}league_table=>tt_match(
( home_team = 'A' away_team = 'B' home_goals = 2 away_goals = 0 )
( home_team = 'B' away_team = 'A' home_goals = 2 away_goals = 2 ) ) ).
cl_abap_unit_assert=>assert_equals( exp = 2 act = lines( lt_table ) ).
cl_abap_unit_assert=>assert_equals( exp = 'A' act = lt_table[ 1 ]-team ).
cl_abap_unit_assert=>assert_equals( exp = 4 act = lt_table[ 1 ]-points ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lt_table[ 2 ]-points ).
ENDMETHOD.
METHOD ignores_invalid_match.
DATA(lt_table) = mo_cut->evaluate( VALUE {{p}}league_table=>tt_match(
( home_team = 'A' away_team = 'A' home_goals = 1 away_goals = 0 ) ) ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lines( lt_table ) ).
ENDMETHOD.
METHOD ranks_ties_equal.
DATA(lt_table) = mo_cut->evaluate( VALUE {{p}}league_table=>tt_match(
( home_team = 'A' away_team = 'B' home_goals = 1 away_goals = 1 ) ) ).
cl_abap_unit_assert=>assert_equals( exp = 2 act = lines( lt_table ) ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lt_table[ 1 ]-rank ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lt_table[ 2 ]-rank ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,67 @@
# 1. Goal
A regional football league collects the results of one season. The league office
needs the league table. The table shows one row for each team with the matches,
the points, the goals and the rank. A league program calls the evaluation once
for the whole season.
# 2. Open questions
None.
# 3. Context
- Work in package $TMP. No other object is necessary.
- The caller collects all match results of the season in one internal table.
The caller passes this table to the evaluation.
- The evaluation works only on this table. It does not read the database.
# 4. Contract
- Create the class {{P}}LEAGUE_TABLE in package $TMP.
- The class is public, final, and has a public constructor without parameters.
- The class has these public types:
- TY_TEAM: type c length 10. The name of a team.
- TY_MATCH: structure with HOME_TEAM (TY_TEAM), AWAY_TEAM (TY_TEAM),
HOME_GOALS (type i), AWAY_GOALS (type i).
- TT_MATCH: standard table of TY_MATCH.
- TY_ROW: structure with RANK (type i), TEAM (TY_TEAM), PLAYED (type i),
WON (type i), DRAWN (type i), LOST (type i), GOALS_FOR (type i),
GOALS_AGAINST (type i), GOAL_DIFF (type i), POINTS (type i).
- TT_ROW: standard table of TY_ROW.
- The class has this public method:
EVALUATE
IMPORTING it_matches TYPE tt_match
RETURNING VALUE(rt_table) TYPE tt_row.
- Do not add other public methods.
# 5. Business rules
1. A match is valid when HOME_TEAM is not initial, AWAY_TEAM is not initial,
HOME_TEAM and AWAY_TEAM are different, HOME_GOALS is not negative and
AWAY_GOALS is not negative. Ignore every match that is not valid.
2. Each team that appears in at least one valid match gets exactly one row in
the result. A team that appears in several matches keeps this one row.
3. For each valid match the home team gets HOME_GOALS as goals for and
AWAY_GOALS as goals against. The away team gets AWAY_GOALS as goals for and
HOME_GOALS as goals against.
4. The team with more goals wins the match. If both teams have the same number
of goals, both teams draw the match.
5. A win gives 3 points. A draw gives 1 point. A loss gives 0 points.
6. PLAYED is the number of valid matches of the team. WON, DRAWN and LOST count
the wins, the draws and the losses. GOALS_FOR and GOALS_AGAINST are the sums
of the goals. GOAL_DIFF is GOALS_FOR minus GOALS_AGAINST. POINTS is the sum
of the points.
7. Sort the result: POINTS descending, then GOAL_DIFF descending, then
GOALS_FOR descending, then TEAM ascending.
8. RANK of a row is 1 plus the number of rows in the result that have more
POINTS, or that have the same POINTS and a higher GOAL_DIFF, or that have
the same POINTS, the same GOAL_DIFF and more GOALS_FOR. Rows with equal
POINTS, equal GOAL_DIFF and equal GOALS_FOR have the same rank.
9. If IT_MATCHES is empty or has no valid match, return an empty table.
# 6. Constraints
- Release target: ABAP Platform 2025 (SAP_BASIS 816).
- Coding standards: Clean ABAP. Method length below 40 statements. No global
variables. No comment that restates the code.
- Out of scope: no database access. Do not create other objects in package $TMP.
# 7. Acceptance
- The class is active and has no syntax error.
- The hidden tests pass.
- Write your own ABAP Unit tests for the class.

View File

@@ -0,0 +1,44 @@
{
"id": "G1069",
"category": "C",
"object_type": "CLAS",
"difficulty": 2,
"release_target": "v816",
"expected_outcome": "implement",
"budget": {
"max_tool_calls": 60,
"max_activations": 15
},
"seed": [],
"contract": [
{
"type": "CLAS",
"name": "{{P}}LEAGUE_TABLE"
}
],
"out_of_scope": [
"No database access.",
"No other object in package $TMP."
],
"hidden_tests": [
{
"type": "CLAS",
"name": "{{P}}T31_HIDDEN",
"file": "hidden/t31_hidden.clas.abap",
"description": "T31 hidden tests for the league table"
}
],
"reference": [
{
"type": "CLAS",
"name": "{{P}}LEAGUE_TABLE",
"file": "reference/league_table.clas.abap",
"description": "League table builder",
"testclasses_file": "reference/league_table.testclasses.abap"
}
],
"craft_checks": [
"method_length",
"db_operation_in_loop"
]
}