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,29 @@
{
"id": "G1113",
"pool": "train",
"object_type": "FUNC",
"category": "C",
"attempts": [
{
"stage": "validate",
"oracle": 0,
"null": 0
},
{
"stage": "validate",
"oracle": 0,
"null": 0
},
{
"stage": "validate",
"oracle": 49.4,
"null": 0
},
{
"stage": "validate",
"oracle": 98.5,
"null": 0
}
],
"accepted": false
}

View File

@@ -0,0 +1,248 @@
CLASS {{P}}T14_HIDDEN DEFINITION PUBLIC FINAL CREATE PUBLIC
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS line_for
IMPORTING iv_donor TYPE string
iv_group TYPE string
iv_units TYPE i
RETURNING VALUE(rv_line) TYPE string.
METHODS sum_for
IMPORTING iv_donations TYPE string
iv_start TYPE string OPTIONAL
EXPORTING ev_totals TYPE string
ev_count TYPE i
ev_subrc TYPE sysubrc.
METHODS sums_per_group FOR TESTING.
METHODS counts_donors FOR TESTING.
METHODS sorted_result FOR TESTING.
METHODS upper_case_group FOR TESTING.
METHODS replaces_content FOR TESTING.
METHODS empty_input FOR TESTING.
METHODS invalid_units_raises FOR TESTING.
METHODS invalid_keeps_totals FOR TESTING.
METHODS donor_two_groups FOR TESTING.
ENDCLASS.
CLASS {{P}}T14_HIDDEN IMPLEMENTATION.
METHOD line_for.
rv_line = iv_donor && ';' && iv_group && ';' && |{ iv_units }|.
ENDMETHOD.
METHOD sum_for.
DATA lv_totals TYPE string.
lv_totals = iv_start.
CALL FUNCTION '{{P}}DON_SUM'
EXPORTING
iv_donations = iv_donations
IMPORTING
ev_donor_count = ev_count
CHANGING
cv_totals = lv_totals
EXCEPTIONS
invalid_units = 1
OTHERS = 2.
ev_subrc = sy-subrc.
ev_totals = lv_totals.
ENDMETHOD.
METHOD sums_per_group.
DATA lv_actual TYPE string.
DATA lv_count TYPE i.
DATA lv_subrc TYPE sysubrc.
DATA(lv_input) = line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 2 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 3 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D2' iv_group = 'O-' iv_units = 1 ).
sum_for( EXPORTING iv_donations = lv_input
IMPORTING ev_totals = lv_actual
ev_count = lv_count
ev_subrc = lv_subrc ).
DATA(lv_expected) = line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 5 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D2' iv_group = 'O-' iv_units = 1 ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lv_subrc ).
cl_abap_unit_assert=>assert_equals( exp = 2 act = lv_count ).
cl_abap_unit_assert=>assert_equals( exp = lv_expected act = lv_actual ).
ENDMETHOD.
METHOD counts_donors.
DATA lv_actual TYPE string.
DATA lv_count TYPE i.
DATA lv_subrc TYPE sysubrc.
DATA(lv_input) = line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 1 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D1' iv_group = 'O-' iv_units = 1 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D2' iv_group = 'A+' iv_units = 1 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D3' iv_group = 'B' iv_units = 1 ).
sum_for( EXPORTING iv_donations = lv_input
IMPORTING ev_totals = lv_actual
ev_count = lv_count
ev_subrc = lv_subrc ).
DATA(lv_expected) = line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 1 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D1' iv_group = 'O-' iv_units = 1 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D2' iv_group = 'A+' iv_units = 1 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D3' iv_group = 'B' iv_units = 1 ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lv_subrc ).
cl_abap_unit_assert=>assert_equals( exp = 3 act = lv_count ).
cl_abap_unit_assert=>assert_equals( exp = lv_expected act = lv_actual ).
ENDMETHOD.
METHOD sorted_result.
DATA lv_actual TYPE string.
DATA lv_count TYPE i.
DATA lv_subrc TYPE sysubrc.
DATA(lv_input) = line_for( iv_donor = 'D2' iv_group = 'A+' iv_units = 1 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D1' iv_group = 'O-' iv_units = 1 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 1 ).
sum_for( EXPORTING iv_donations = lv_input
IMPORTING ev_totals = lv_actual
ev_count = lv_count
ev_subrc = lv_subrc ).
DATA(lv_expected) = line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 1 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D1' iv_group = 'O-' iv_units = 1 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D2' iv_group = 'A+' iv_units = 1 ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lv_subrc ).
cl_abap_unit_assert=>assert_equals( exp = lv_expected act = lv_actual ).
ENDMETHOD.
METHOD upper_case_group.
DATA lv_actual TYPE string.
DATA lv_count TYPE i.
DATA lv_subrc TYPE sysubrc.
DATA(lv_input) = line_for( iv_donor = 'D1' iv_group = 'a+' iv_units = 2 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 3 ).
sum_for( EXPORTING iv_donations = lv_input
IMPORTING ev_totals = lv_actual
ev_count = lv_count
ev_subrc = lv_subrc ).
DATA(lv_expected) = line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 5 ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lv_subrc ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lv_count ).
cl_abap_unit_assert=>assert_equals( exp = lv_expected act = lv_actual ).
ENDMETHOD.
METHOD replaces_content.
DATA lv_actual TYPE string.
DATA lv_count TYPE i.
DATA lv_subrc TYPE sysubrc.
DATA(lv_input) = line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 2 ).
sum_for( EXPORTING iv_donations = lv_input
iv_start = 'OLD TOTALS'
IMPORTING ev_totals = lv_actual
ev_count = lv_count
ev_subrc = lv_subrc ).
DATA(lv_expected) = line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 2 ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lv_subrc ).
cl_abap_unit_assert=>assert_equals( exp = lv_expected act = lv_actual ).
ENDMETHOD.
METHOD empty_input.
DATA lv_actual TYPE string.
DATA lv_count TYPE i.
DATA lv_subrc TYPE sysubrc.
sum_for( EXPORTING iv_donations = ''
IMPORTING ev_totals = lv_actual
ev_count = lv_count
ev_subrc = lv_subrc ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lv_subrc ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lv_count ).
cl_abap_unit_assert=>assert_equals( exp = '' act = lv_actual ).
ENDMETHOD.
METHOD invalid_units_raises.
DATA lv_actual TYPE string.
DATA lv_count TYPE i.
DATA lv_subrc TYPE sysubrc.
DATA(lv_input) = line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 0 ).
sum_for( EXPORTING iv_donations = lv_input
IMPORTING ev_totals = lv_actual
ev_count = lv_count
ev_subrc = lv_subrc ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lv_subrc ).
ENDMETHOD.
METHOD invalid_keeps_totals.
DATA lv_actual TYPE string.
DATA lv_count TYPE i.
DATA lv_subrc TYPE sysubrc.
DATA(lv_input) = line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 2 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D2' iv_group = 'A+' iv_units = 0 ).
sum_for( EXPORTING iv_donations = lv_input
iv_start = 'KEEP'
IMPORTING ev_totals = lv_actual
ev_count = lv_count
ev_subrc = lv_subrc ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lv_subrc ).
cl_abap_unit_assert=>assert_equals( exp = 'KEEP' act = lv_actual ).
ENDMETHOD.
METHOD donor_two_groups.
DATA lv_actual TYPE string.
DATA lv_count TYPE i.
DATA lv_subrc TYPE sysubrc.
DATA(lv_input) = line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 2 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D1' iv_group = 'O-' iv_units = 3 ).
sum_for( EXPORTING iv_donations = lv_input
IMPORTING ev_totals = lv_actual
ev_count = lv_count
ev_subrc = lv_subrc ).
DATA(lv_expected) = line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 2 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D1' iv_group = 'O-' iv_units = 3 ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lv_subrc ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lv_count ).
cl_abap_unit_assert=>assert_equals( exp = lv_expected act = lv_actual ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,70 @@
FUNCTION {{P}}DON_SUM
IMPORTING
iv_donations TYPE string
EXPORTING
ev_donor_count TYPE i
CHANGING
cv_totals TYPE string
EXCEPTIONS
invalid_units.
TYPES:
BEGIN OF ty_total,
donor_id TYPE string,
group_code TYPE string,
total_units TYPE i,
END OF ty_total.
DATA lt_lines TYPE STANDARD TABLE OF string WITH EMPTY KEY.
DATA lt_totals TYPE SORTED TABLE OF ty_total
WITH UNIQUE KEY donor_id group_code.
DATA lv_line TYPE string.
DATA lv_donor TYPE string.
DATA lv_group TYPE string.
DATA lv_units TYPE string.
DATA lv_units_int TYPE i.
DATA lv_result TYPE string.
DATA lv_prev TYPE string.
IF iv_donations IS NOT INITIAL.
SPLIT iv_donations AT cl_abap_char_utilities=>newline INTO TABLE lt_lines.
ENDIF.
LOOP AT lt_lines INTO lv_line.
SPLIT lv_line AT ';' INTO lv_donor lv_group lv_units.
lv_units_int = lv_units.
IF lv_units_int < 1.
RAISE invalid_units.
ENDIF.
lv_group = to_upper( lv_group ).
READ TABLE lt_totals ASSIGNING FIELD-SYMBOL(<ls_total>)
WITH TABLE KEY donor_id = lv_donor group_code = lv_group.
IF sy-subrc <> 0.
INSERT VALUE #( donor_id = lv_donor
group_code = lv_group
total_units = 0 )
INTO TABLE lt_totals ASSIGNING <ls_total>.
ENDIF.
<ls_total>-total_units = <ls_total>-total_units + lv_units_int.
ENDLOOP.
LOOP AT lt_totals INTO DATA(ls_total).
IF ls_total-donor_id <> lv_prev.
ev_donor_count = ev_donor_count + 1.
lv_prev = ls_total-donor_id.
ENDIF.
DATA(lv_out) = |{ ls_total-donor_id };{ ls_total-group_code };{ ls_total-total_units }|.
IF lv_result IS INITIAL.
lv_result = lv_out.
ELSE.
lv_result = lv_result && cl_abap_char_utilities=>newline && lv_out.
ENDIF.
ENDLOOP.
cv_totals = lv_result.
ENDFUNCTION.

View File

@@ -0,0 +1,120 @@
CLASS {{P}}T14_TEST DEFINITION PUBLIC FINAL CREATE PUBLIC
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS line_for
IMPORTING iv_donor TYPE string
iv_group TYPE string
iv_units TYPE i
RETURNING VALUE(rv_line) TYPE string.
METHODS totals_for
IMPORTING iv_donations TYPE string
EXPORTING ev_totals TYPE string
ev_count TYPE i.
METHODS groups_donations FOR TESTING.
METHODS counts_donors FOR TESTING.
METHODS rejects_zero_units FOR TESTING.
METHODS empty_input FOR TESTING.
ENDCLASS.
CLASS {{P}}T14_TEST IMPLEMENTATION.
METHOD line_for.
rv_line = iv_donor && ';' && iv_group && ';' && |{ iv_units }|.
ENDMETHOD.
METHOD totals_for.
DATA lv_totals TYPE string.
CALL FUNCTION '{{P}}DON_SUM'
EXPORTING
iv_donations = iv_donations
IMPORTING
ev_donor_count = ev_count
CHANGING
cv_totals = lv_totals
EXCEPTIONS
invalid_units = 1
OTHERS = 2.
cl_abap_unit_assert=>assert_subrc( exp = 0 ).
ev_totals = lv_totals.
ENDMETHOD.
METHOD groups_donations.
DATA lv_totals TYPE string.
DATA lv_count TYPE i.
DATA(lv_input) = line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 2 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D1' iv_group = 'a+' iv_units = 3 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D2' iv_group = 'O-' iv_units = 1 ).
totals_for( EXPORTING iv_donations = lv_input
IMPORTING ev_totals = lv_totals
ev_count = lv_count ).
DATA(lv_expected) = line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 5 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D2' iv_group = 'O-' iv_units = 1 ).
cl_abap_unit_assert=>assert_equals( exp = lv_expected act = lv_totals ).
cl_abap_unit_assert=>assert_equals( exp = 2 act = lv_count ).
ENDMETHOD.
METHOD counts_donors.
DATA lv_totals TYPE string.
DATA lv_count TYPE i.
DATA(lv_input) = line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 1 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D1' iv_group = 'O-' iv_units = 1 )
&& cl_abap_char_utilities=>newline
&& line_for( iv_donor = 'D2' iv_group = 'A+' iv_units = 1 ).
totals_for( EXPORTING iv_donations = lv_input
IMPORTING ev_totals = lv_totals
ev_count = lv_count ).
cl_abap_unit_assert=>assert_equals( exp = 2 act = lv_count ).
cl_abap_unit_assert=>assert_equals(
exp = 3
act = strlen( lv_totals ) - strlen( replace( val = lv_totals sub = cl_abap_char_utilities=>newline with = '' occ = 0 ) ) + 1 ).
ENDMETHOD.
METHOD rejects_zero_units.
DATA lv_totals TYPE string.
DATA lv_count TYPE i.
DATA(lv_input) = line_for( iv_donor = 'D1' iv_group = 'A+' iv_units = 0 ).
CALL FUNCTION '{{P}}DON_SUM'
EXPORTING
iv_donations = lv_input
IMPORTING
ev_donor_count = lv_count
CHANGING
cv_totals = lv_totals
EXCEPTIONS
invalid_units = 1
OTHERS = 2.
cl_abap_unit_assert=>assert_equals( exp = 1 act = sy-subrc ).
ENDMETHOD.
METHOD empty_input.
DATA lv_totals TYPE string.
DATA lv_count TYPE i.
totals_for( EXPORTING iv_donations = ''
IMPORTING ev_totals = lv_totals
ev_count = lv_count ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lv_count ).
cl_abap_unit_assert=>assert_equals( exp = '' act = lv_totals ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,18 @@
FUNCTION {{P}}DON_SAMPLE
IMPORTING
iv_donations TYPE string
EXPORTING
ev_line_count TYPE i
ev_first_line TYPE string.
DATA lt_lines TYPE STANDARD TABLE OF string WITH EMPTY KEY.
IF iv_donations IS NOT INITIAL.
SPLIT iv_donations AT cl_abap_char_utilities=>newline INTO TABLE lt_lines.
ENDIF.
ev_line_count = lines( lt_lines ).
READ TABLE lt_lines INTO ev_first_line INDEX 1.
ENDFUNCTION.

View File

@@ -0,0 +1,58 @@
# 1. Goal
A blood donation centre summarises the donations of one collection day. The
centre calls one function module for each collection day. The function module
groups the donations by donor and blood group and gives the total units of each
group.
# 2. Open questions
None.
# 3. Context
- Function group {{P}}FG_DON exists in package $TMP.
- The collection team records the donations of one day on a handheld device.
The device sends the donations of the day as one text.
- Each donation is one line of the text. A line has three fields that are
separated by a semicolon (;):
- field 1: the donor id, without blanks
- field 2: the blood group code, without blanks
- field 3: the units, a decimal number without leading zeros
- The lines of the text are separated by the newline character
(cl_abap_char_utilities=>newline). The text does not end with a newline.
- Function module {{P}}DON_SAMPLE exists in the group. It shows how the text of
one day is split into lines.
# 4. Contract
- Create the function module {{P}}DON_SUM in function group {{P}}FG_DON.
- Use this interface:
- IMPORTING iv_donations TYPE string
- EXPORTING ev_donor_count TYPE i
- CHANGING cv_totals TYPE string
- EXCEPTIONS invalid_units
# 5. Business rules
1. A donation is not valid if its units are less than 1. If the text contains a
donation that is not valid, raise the exception INVALID_UNITS. In this case,
do not change cv_totals.
2. Group the donations by donor id and blood group code. The total units of a
group is the sum of the units of all donations of the group.
3. Compare blood group codes without regard to case. Write the blood group code
in the result in upper case.
4. cv_totals has exactly one line for each group. Replace the content of
cv_totals. Do not append to the old content.
5. A line of cv_totals has the same layout as a line of the input text: donor
id, semicolon, blood group code, semicolon, total units. The total units have
no leading zeros. The lines are sorted by donor id in ascending order and
then by blood group code in ascending order. The lines are separated by the
newline character. The text does not end with a newline.
6. ev_donor_count is the number of different donor id values in the text.
7. If the text is empty, cv_totals is empty and ev_donor_count is 0.
# 6. Constraints
- Release target: 8.16.
- Coding standard: Clean ABAP. Methods have less than 40 statements.
- Out of scope: do not change {{P}}DON_SAMPLE.
# 7. Acceptance
- The function module is active and has no syntax error.
- The hidden tests pass.
- Write ABAP Unit tests for the function module in a global test class.

View File

@@ -0,0 +1,77 @@
{
"id": "G1113",
"category": "C",
"object_type": "FUNC",
"difficulty": 2,
"release_target": "v816",
"expected_outcome": "implement",
"budget": {
"max_tool_calls": 60,
"max_activations": 15
},
"seed": [
{
"type": "FUGR",
"name": "{{P}}FG_DON",
"description": "Function group for blood donation summaries"
},
{
"type": "FUNC",
"name": "{{P}}DON_SAMPLE",
"functionGroup": "{{P}}FG_DON",
"file": "seed/don_sample.func.abap",
"description": "Sample module that splits a donation text into lines"
}
],
"contract": [
{
"type": "FUNC",
"name": "{{P}}DON_SUM",
"functionGroup": "{{P}}FG_DON",
"params": [
{
"name": "iv_donations",
"type": "string"
},
{
"name": "ev_donor_count",
"type": "i"
},
{
"name": "cv_totals",
"type": "string"
}
]
}
],
"out_of_scope": [
"{{P}}DON_SAMPLE"
],
"hidden_tests": [
{
"type": "CLAS",
"name": "{{P}}T14_HIDDEN",
"file": "hidden/t14_hidden.clas.abap",
"description": "T14 hidden tests"
}
],
"reference": [
{
"type": "FUNC",
"name": "{{P}}DON_SUM",
"functionGroup": "{{P}}FG_DON",
"file": "reference/don_sum.func.abap",
"description": "Donation summary module"
},
{
"type": "CLAS",
"name": "{{P}}T14_TEST",
"file": "reference/t14_test.clas.abap",
"description": "T14 own tests"
}
],
"craft_checks": [
"method_length",
"no_nested_loops"
]
}