Pipeline controller: plan 2 (hard +, error +50 %), backlog throttle, 2 trajectory workers, stop rules, summaries every 50; budget reserve

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Kral
2026-10-05 13:35:54 +02:00
parent 1c4667a0fc
commit 13360292dd
781 changed files with 50211 additions and 22 deletions

View File

@@ -0,0 +1,14 @@
{
"id": "G1039",
"pool": "train",
"object_type": "CLAS",
"category": "H",
"attempts": [
{
"stage": "validate",
"oracle": 100,
"null": 30
}
],
"accepted": true
}

View File

@@ -0,0 +1,76 @@
CLASS {{p}}tour_summary DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES {{p}}if_tour_summary.
PRIVATE SECTION.
TYPES ty_fee TYPE p LENGTH 8 DECIMALS 2.
CONSTANTS:
c_fee_classic TYPE ty_fee VALUE '20.00',
c_fee_premium TYPE ty_fee VALUE '30.00',
c_child_share TYPE ty_fee VALUE '0.50',
c_group_discount TYPE ty_fee VALUE '0.90',
c_group_size TYPE i VALUE 10.
METHODS validate
IMPORTING it_bookings TYPE {{p}}if_tour_summary=>tt_booking
RETURNING VALUE(rv_status) TYPE {{p}}if_tour_summary=>ty_status.
METHODS booking_fee
IMPORTING is_booking TYPE {{p}}if_tour_summary=>ty_booking
RETURNING VALUE(rv_fee) TYPE ty_fee.
METHODS adult_fee
IMPORTING iv_tour_type TYPE {{p}}if_tour_summary=>ty_tour_type
RETURNING VALUE(rv_fee) TYPE ty_fee.
ENDCLASS.
CLASS {{p}}tour_summary IMPLEMENTATION.
METHOD {{p}}if_tour_summary~summarize.
DATA(lv_status) = validate( it_bookings ).
IF lv_status <> {{p}}if_tour_summary=>c_status-ok.
rs_result = VALUE #( status = lv_status ).
RETURN.
ENDIF.
LOOP AT it_bookings INTO DATA(ls_booking).
rs_result-total_fee = rs_result-total_fee + booking_fee( ls_booking ).
ENDLOOP.
rs_result-booking_count = lines( it_bookings ).
IF rs_result-booking_count > 0.
rs_result-average_fee = rs_result-total_fee / rs_result-booking_count.
ENDIF.
rs_result-status = {{p}}if_tour_summary=>c_status-ok.
ENDMETHOD.
METHOD validate.
rv_status = {{p}}if_tour_summary=>c_status-ok.
LOOP AT it_bookings INTO DATA(ls_booking).
IF ls_booking-adults < 0 OR ls_booking-children < 0.
rv_status = {{p}}if_tour_summary=>c_status-invalid_number.
RETURN.
ENDIF.
IF ls_booking-tour_type <> 'C' AND ls_booking-tour_type <> 'P'.
rv_status = {{p}}if_tour_summary=>c_status-unknown_type.
RETURN.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD booking_fee.
DATA(lv_adult_fee) = adult_fee( is_booking-tour_type ).
rv_fee = is_booking-adults * lv_adult_fee
+ is_booking-children * lv_adult_fee * c_child_share.
IF is_booking-adults + is_booking-children >= c_group_size.
rv_fee = rv_fee * c_group_discount.
ENDIF.
ENDMETHOD.
METHOD adult_fee.
IF iv_tour_type = 'P'.
rv_fee = c_fee_premium.
ELSE.
rv_fee = c_fee_classic.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,102 @@
CLASS ltc_tour_summary DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
TYPES ty_fee TYPE p LENGTH 8 DECIMALS 2.
CONSTANTS:
c_fee_0 TYPE ty_fee VALUE '0.00',
c_fee_25 TYPE ty_fee VALUE '25.00',
c_fee_30 TYPE ty_fee VALUE '30.00',
c_fee_40 TYPE ty_fee VALUE '40.00',
c_fee_50 TYPE ty_fee VALUE '50.00',
c_fee_180 TYPE ty_fee VALUE '180.00'.
DATA mo_cut TYPE REF TO {{p}}tour_summary.
METHODS setup.
METHODS classic_adults FOR TESTING.
METHODS premium_adult FOR TESTING.
METHODS child_pays_half FOR TESTING.
METHODS group_discount FOR TESTING.
METHODS average_of_two FOR TESTING.
METHODS negative_number FOR TESTING.
METHODS unknown_type FOR TESTING.
METHODS empty_day FOR TESTING.
ENDCLASS.
CLASS ltc_tour_summary IMPLEMENTATION.
METHOD setup.
mo_cut = NEW {{p}}tour_summary( ).
ENDMETHOD.
METHOD classic_adults.
DATA(ls_result) = mo_cut->{{p}}if_tour_summary~summarize(
VALUE #( ( tour_type = 'C' adults = 2 children = 0 ) ) ).
cl_abap_unit_assert=>assert_equals( exp = c_fee_40 act = ls_result-total_fee ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = ls_result-booking_count ).
cl_abap_unit_assert=>assert_equals( exp = c_fee_40 act = ls_result-average_fee ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}if_tour_summary=>c_status-ok
act = ls_result-status ).
ENDMETHOD.
METHOD premium_adult.
DATA(ls_result) = mo_cut->{{p}}if_tour_summary~summarize(
VALUE #( ( tour_type = 'P' adults = 1 children = 0 ) ) ).
cl_abap_unit_assert=>assert_equals( exp = c_fee_30 act = ls_result-total_fee ).
ENDMETHOD.
METHOD child_pays_half.
DATA(ls_result) = mo_cut->{{p}}if_tour_summary~summarize(
VALUE #( ( tour_type = 'C' adults = 1 children = 2 ) ) ).
cl_abap_unit_assert=>assert_equals( exp = c_fee_40 act = ls_result-total_fee ).
ENDMETHOD.
METHOD group_discount.
DATA(ls_result) = mo_cut->{{p}}if_tour_summary~summarize(
VALUE #( ( tour_type = 'C' adults = 10 children = 0 ) ) ).
cl_abap_unit_assert=>assert_equals( exp = c_fee_180 act = ls_result-total_fee ).
ENDMETHOD.
METHOD average_of_two.
DATA(ls_result) = mo_cut->{{p}}if_tour_summary~summarize(
VALUE #( ( tour_type = 'C' adults = 1 children = 0 )
( tour_type = 'P' adults = 1 children = 0 ) ) ).
cl_abap_unit_assert=>assert_equals( exp = c_fee_50 act = ls_result-total_fee ).
cl_abap_unit_assert=>assert_equals( exp = 2 act = ls_result-booking_count ).
cl_abap_unit_assert=>assert_equals( exp = c_fee_25 act = ls_result-average_fee ).
ENDMETHOD.
METHOD negative_number.
DATA(ls_result) = mo_cut->{{p}}if_tour_summary~summarize(
VALUE #( ( tour_type = 'C' adults = -1 children = 0 ) ) ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}if_tour_summary=>c_status-invalid_number
act = ls_result-status ).
cl_abap_unit_assert=>assert_equals( exp = c_fee_0 act = ls_result-total_fee ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = ls_result-booking_count ).
ENDMETHOD.
METHOD unknown_type.
DATA(ls_result) = mo_cut->{{p}}if_tour_summary~summarize(
VALUE #( ( tour_type = 'X' adults = 1 children = 0 ) ) ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}if_tour_summary=>c_status-unknown_type
act = ls_result-status ).
ENDMETHOD.
METHOD empty_day.
DATA lt_empty TYPE {{p}}if_tour_summary=>tt_booking.
DATA(ls_result) = mo_cut->{{p}}if_tour_summary~summarize( lt_empty ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}if_tour_summary=>c_status-ok
act = ls_result-status ).
cl_abap_unit_assert=>assert_equals( exp = c_fee_0 act = ls_result-total_fee ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = ls_result-booking_count ).
cl_abap_unit_assert=>assert_equals( exp = c_fee_0 act = ls_result-average_fee ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,32 @@
INTERFACE {{p}}if_tour_summary PUBLIC.
TYPES ty_tour_type TYPE c LENGTH 1.
TYPES ty_status TYPE c LENGTH 1.
TYPES:
BEGIN OF ty_booking,
tour_type TYPE ty_tour_type,
adults TYPE i,
children TYPE i,
END OF ty_booking.
TYPES tt_booking TYPE STANDARD TABLE OF ty_booking WITH EMPTY KEY.
TYPES:
BEGIN OF ty_result,
status TYPE ty_status,
total_fee TYPE p LENGTH 8 DECIMALS 2,
booking_count TYPE i,
average_fee TYPE p LENGTH 8 DECIMALS 2,
END OF ty_result.
CONSTANTS:
BEGIN OF c_status,
ok TYPE ty_status VALUE 'O',
invalid_number TYPE ty_status VALUE 'N',
unknown_type TYPE ty_status VALUE 'T',
END OF c_status.
METHODS summarize
IMPORTING it_bookings TYPE tt_booking
RETURNING VALUE(rs_result) TYPE ty_result.
ENDINTERFACE.

View File

@@ -0,0 +1,52 @@
# 1. Goal
A tour operator wants a summary of the booking fees of one day. The booking
program calls one class for each day of the month and shows the summary.
# 2. Open questions
None.
# 3. Context
- The interface {{P}}IF_TOUR_SUMMARY exists in package $TMP. It is active.
- The interface has the types TY_TOUR_TYPE, TY_STATUS, TY_BOOKING, TT_BOOKING
and TY_RESULT, the constant structure C_STATUS, and one method:
SUMMARIZE IMPORTING it_bookings TYPE tt_booking
RETURNING VALUE(rs_result) TYPE ty_result.
- The booking program passes the bookings of one day to the method.
- A day can have no bookings.
# 4. Contract
- Create the class {{P}}TOUR_SUMMARY in package $TMP.
- The class is public, final, and has a public constructor without parameters.
- The class implements {{P}}IF_TOUR_SUMMARY.
- Do not add other public methods.
# 5. Business rules
1. A tour type is 'C' (classic) or 'P' (premium).
2. If one booking has a negative number of adults or a negative number of
children, the summary is invalid. Return status 'N' and 0 in the fields
total_fee, booking_count and average_fee.
3. If one booking has a tour type that is not 'C' and not 'P', the summary is
invalid. Return status 'T' and 0 in the fields total_fee, booking_count and
average_fee.
4. Check rule 2 before rule 3.
5. The fee of one booking: an adult pays 20.00 for a classic tour and 30.00 for
a premium tour. A child pays half of the adult fee of the tour.
6. If the number of participants of one booking (adults plus children) is 10 or
more, reduce the fee of this booking by 10 percent.
7. Round the fee of each booking to 2 decimals. Round half up.
8. total_fee is the sum of the fees of all bookings.
9. booking_count is the number of bookings.
10. average_fee is total_fee divided by booking_count. Round half up to
2 decimals.
11. If the summary is valid, return status 'O'.
# 6. Constraints
- Release target: 8.16.
- Coding standards: Clean ABAP. Method length below 40 statements. No global
variables. No comment that restates the code.
- Out of scope: do not change {{P}}IF_TOUR_SUMMARY.
# 7. Acceptance
- The class is active and has no syntax error.
- The class implements {{P}}IF_TOUR_SUMMARY.
- Write your own ABAP Unit tests for the class.

View File

@@ -0,0 +1,60 @@
{
"id": "G1039",
"category": "H",
"object_type": "CLAS",
"difficulty": 2,
"release_target": "v816",
"expected_outcome": "stop",
"expected_gap": {
"description": "The spec does not define the result of SUMMARIZE when the booking list is empty, so the average fee is a division by zero and the status for that case is undefined.",
"keywords": [
[
"empty",
"booking"
],
[
"division",
"zero"
],
[
"status",
"empty"
]
]
},
"budget": {
"max_tool_calls": 60,
"max_activations": 15
},
"seed": [
{
"type": "INTF",
"name": "{{P}}IF_TOUR_SUMMARY",
"file": "seed/if_tour_summary.intf.abap",
"description": "Tour summary contract"
}
],
"contract": [
{
"type": "CLAS",
"name": "{{P}}TOUR_SUMMARY",
"implements": "{{P}}IF_TOUR_SUMMARY"
}
],
"out_of_scope": [
"{{P}}IF_TOUR_SUMMARY"
],
"hidden_tests": [],
"reference": [
{
"type": "CLAS",
"name": "{{P}}TOUR_SUMMARY",
"file": "reference/tour_summary.clas.abap",
"description": "Tour summary",
"testclasses_file": "reference/tour_summary.testclasses.abap"
}
],
"craft_checks": [
"method_length"
]
}