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,73 @@
CLASS {{p}}oil_settlement DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_restaurant TYPE c LENGTH 10.
TYPES:
BEGIN OF ty_collection,
restaurant TYPE ty_restaurant,
collected_on TYPE d,
litres TYPE i,
END OF ty_collection.
TYPES tt_collections TYPE STANDARD TABLE OF ty_collection WITH EMPTY KEY.
TYPES:
BEGIN OF ty_settlement,
restaurant TYPE ty_restaurant,
total_litres TYPE i,
round_count TYPE i,
last_collection TYPE d,
END OF ty_settlement.
TYPES tt_settlements TYPE SORTED TABLE OF ty_settlement WITH UNIQUE KEY restaurant.
METHODS settle
IMPORTING it_collections TYPE tt_collections
RETURNING VALUE(rt_settlements) TYPE tt_settlements.
PRIVATE SECTION.
TYPES:
BEGIN OF ty_buffer,
restaurant TYPE ty_restaurant,
total_litres TYPE i,
round_count TYPE i,
last_collection TYPE d,
END OF ty_buffer.
TYPES tt_buffer TYPE HASHED TABLE OF ty_buffer WITH UNIQUE KEY restaurant.
METHODS normalize
IMPORTING iv_restaurant TYPE ty_restaurant
RETURNING VALUE(rv_restaurant) TYPE ty_restaurant.
ENDCLASS.
CLASS {{p}}oil_settlement IMPLEMENTATION.
METHOD settle.
DATA lt_buffer TYPE tt_buffer.
LOOP AT it_collections INTO DATA(ls_collection).
DATA(lv_restaurant) = normalize( ls_collection-restaurant ).
IF lv_restaurant IS INITIAL OR ls_collection-litres <= 0.
CONTINUE.
ENDIF.
ASSIGN lt_buffer[ restaurant = lv_restaurant ] TO FIELD-SYMBOL(<ls_buffer>).
IF sy-subrc <> 0.
INSERT VALUE #( restaurant = lv_restaurant ) INTO TABLE lt_buffer ASSIGNING <ls_buffer>.
ENDIF.
<ls_buffer>-total_litres = <ls_buffer>-total_litres + ls_collection-litres.
<ls_buffer>-round_count = <ls_buffer>-round_count + 1.
IF ls_collection-collected_on > <ls_buffer>-last_collection.
<ls_buffer>-last_collection = ls_collection-collected_on.
ENDIF.
ENDLOOP.
rt_settlements = CORRESPONDING #( lt_buffer ).
ENDMETHOD.
METHOD normalize.
rv_restaurant = to_upper( replace( val = iv_restaurant sub = ` ` with = `` occ = 0 ) ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,86 @@
CLASS ltc_oil_settlement DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
DATA mo_cut TYPE REF TO {{p}}oil_settlement.
METHODS setup.
METHODS sums_same_restaurant FOR TESTING.
METHODS ignores_invalid_records FOR TESTING.
METHODS normalises_restaurant FOR TESTING.
METHODS keeps_latest_date FOR TESTING.
METHODS sorts_result FOR TESTING.
METHODS find_row
IMPORTING it_result TYPE {{p}}oil_settlement=>tt_settlements
iv_restaurant TYPE {{p}}oil_settlement=>ty_restaurant
RETURNING VALUE(rs_row) TYPE {{p}}oil_settlement=>ty_settlement.
ENDCLASS.
CLASS ltc_oil_settlement IMPLEMENTATION.
METHOD setup.
mo_cut = NEW {{p}}oil_settlement( ).
ENDMETHOD.
METHOD sums_same_restaurant.
DATA(lt_result) = mo_cut->settle( VALUE #(
( restaurant = 'R001' collected_on = '20240110' litres = 100 )
( restaurant = 'R001' collected_on = '20240115' litres = 50 ) ) ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_result ) ).
DATA(ls_row) = find_row( it_result = lt_result iv_restaurant = 'R001' ).
cl_abap_unit_assert=>assert_equals( exp = 150 act = ls_row-total_litres ).
cl_abap_unit_assert=>assert_equals( exp = 2 act = ls_row-round_count ).
ENDMETHOD.
METHOD ignores_invalid_records.
DATA(lt_result) = mo_cut->settle( VALUE #(
( restaurant = 'R001' collected_on = '20240110' litres = 0 )
( restaurant = space collected_on = '20240110' litres = 20 )
( restaurant = 'R002' collected_on = '20240110' litres = 30 ) ) ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_result ) ).
DATA(ls_row) = find_row( it_result = lt_result iv_restaurant = 'R002' ).
cl_abap_unit_assert=>assert_equals( exp = 30 act = ls_row-total_litres ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = ls_row-round_count ).
ENDMETHOD.
METHOD normalises_restaurant.
DATA(lt_result) = mo_cut->settle( VALUE #(
( restaurant = 'r001' collected_on = '20240110' litres = 10 )
( restaurant = ' R001 ' collected_on = '20240111' litres = 20 ) ) ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_result ) ).
DATA(ls_row) = find_row( it_result = lt_result iv_restaurant = 'R001' ).
cl_abap_unit_assert=>assert_equals( exp = 30 act = ls_row-total_litres ).
cl_abap_unit_assert=>assert_equals( exp = 'R001' act = ls_row-restaurant ).
ENDMETHOD.
METHOD keeps_latest_date.
DATA(lt_result) = mo_cut->settle( VALUE #(
( restaurant = 'R001' collected_on = '20240110' litres = 10 )
( restaurant = 'R001' collected_on = '20240305' litres = 10 ) ) ).
DATA lv_expected TYPE d.
lv_expected = '20240305'.
DATA(ls_row) = find_row( it_result = lt_result iv_restaurant = 'R001' ).
cl_abap_unit_assert=>assert_equals( exp = lv_expected act = ls_row-last_collection ).
ENDMETHOD.
METHOD sorts_result.
DATA(lt_result) = mo_cut->settle( VALUE #(
( restaurant = 'R003' collected_on = '20240110' litres = 10 )
( restaurant = 'R001' collected_on = '20240110' litres = 10 )
( restaurant = 'R002' collected_on = '20240110' litres = 10 ) ) ).
DATA lv_order TYPE string.
LOOP AT lt_result INTO DATA(ls_row).
lv_order = lv_order && ls_row-restaurant+0(4).
ENDLOOP.
cl_abap_unit_assert=>assert_equals( exp = 'R001R002R003' act = lv_order ).
ENDMETHOD.
METHOD find_row.
DATA ls_row TYPE {{p}}oil_settlement=>ty_settlement.
DATA lv_found TYPE abap_bool.
LOOP AT it_result INTO ls_row WHERE restaurant = iv_restaurant.
rs_row = ls_row.
lv_found = abap_true.
EXIT.
ENDLOOP.
cl_abap_unit_assert=>assert_equals( exp = abap_true act = lv_found ).
ENDMETHOD.
ENDCLASS.