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,133 @@
CLASS {{p}}towing_fee DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_status TYPE c LENGTH 8.
TYPES ty_amount TYPE i.
TYPES ty_class TYPE c LENGTH 1.
TYPES:
BEGIN OF ty_result,
status TYPE ty_status,
fee TYPE ty_amount,
END OF ty_result.
CONSTANTS:
BEGIN OF c_status,
ok TYPE ty_status VALUE 'OK',
bad_class TYPE ty_status VALUE 'CLASS',
bad_distance TYPE ty_status VALUE 'DISTANCE',
bad_hour TYPE ty_status VALUE 'HOUR',
END OF c_status.
METHODS calculate
IMPORTING iv_vehicle_class TYPE ty_class
iv_distance_km TYPE i
iv_hour TYPE i
iv_is_weekend TYPE abap_bool
RETURNING VALUE(rs_result) TYPE ty_result.
PRIVATE SECTION.
CONSTANTS:
c_base_small TYPE ty_amount VALUE 60,
c_base_medium TYPE ty_amount VALUE 90,
c_base_large TYPE ty_amount VALUE 140,
c_free_km TYPE i VALUE 10,
c_km_rate TYPE ty_amount VALUE 2,
c_night_percent TYPE i VALUE 25,
c_weekend_percent TYPE i VALUE 15,
c_minimum_fee TYPE ty_amount VALUE 80,
c_round_step TYPE ty_amount VALUE 5,
c_max_distance TYPE i VALUE 500.
METHODS validate
IMPORTING iv_vehicle_class TYPE ty_class
iv_distance_km TYPE i
iv_hour TYPE i
RETURNING VALUE(rv_status) TYPE ty_status.
METHODS base_fee
IMPORTING iv_vehicle_class TYPE ty_class
RETURNING VALUE(rv_fee) TYPE ty_amount.
METHODS distance_fee
IMPORTING iv_distance_km TYPE i
RETURNING VALUE(rv_fee) TYPE ty_amount.
METHODS is_night
IMPORTING iv_hour TYPE i
RETURNING VALUE(rv_night) TYPE abap_bool.
METHODS surcharge
IMPORTING iv_subtotal TYPE ty_amount
iv_percent TYPE i
RETURNING VALUE(rv_surcharge) TYPE ty_amount.
METHODS round_up
IMPORTING iv_amount TYPE ty_amount
RETURNING VALUE(rv_amount) TYPE ty_amount.
ENDCLASS.
CLASS {{p}}towing_fee IMPLEMENTATION.
METHOD calculate.
DATA(lv_status) = validate( iv_vehicle_class = iv_vehicle_class
iv_distance_km = iv_distance_km
iv_hour = iv_hour ).
IF lv_status <> c_status-ok.
rs_result = VALUE #( status = lv_status fee = 0 ).
RETURN.
ENDIF.
DATA(lv_subtotal) = base_fee( iv_vehicle_class ) + distance_fee( iv_distance_km ).
DATA(lv_total) = lv_subtotal.
IF is_night( iv_hour ) = abap_true.
lv_total = lv_total + surcharge( iv_subtotal = lv_subtotal
iv_percent = c_night_percent ).
ENDIF.
IF iv_is_weekend <> abap_true.
lv_total = lv_total + surcharge( iv_subtotal = lv_subtotal
iv_percent = c_weekend_percent ).
ENDIF.
IF lv_total < c_minimum_fee.
lv_total = c_minimum_fee.
ENDIF.
rs_result = VALUE #( status = c_status-ok
fee = round_up( lv_total ) ).
ENDMETHOD.
METHOD validate.
IF iv_vehicle_class <> 'S' AND iv_vehicle_class <> 'M' AND iv_vehicle_class <> 'L'.
rv_status = c_status-bad_class.
ELSEIF iv_distance_km < 1 OR iv_distance_km > c_max_distance.
rv_status = c_status-bad_distance.
ELSEIF iv_hour < 0 OR iv_hour > 23.
rv_status = c_status-bad_hour.
ELSE.
rv_status = c_status-ok.
ENDIF.
ENDMETHOD.
METHOD base_fee.
CASE iv_vehicle_class.
WHEN 'S'.
rv_fee = c_base_small.
WHEN 'M'.
rv_fee = c_base_medium.
WHEN 'L'.
rv_fee = c_base_large.
ENDCASE.
ENDMETHOD.
METHOD distance_fee.
DATA(lv_chargeable_km) = iv_distance_km - c_free_km.
IF lv_chargeable_km < 0.
lv_chargeable_km = 0.
ENDIF.
rv_fee = lv_chargeable_km * c_km_rate.
ENDMETHOD.
METHOD is_night.
rv_night = xsdbool( iv_hour >= 22 OR iv_hour <= 5 ).
ENDMETHOD.
METHOD surcharge.
rv_surcharge = iv_subtotal * iv_percent DIV 100.
ENDMETHOD.
METHOD round_up.
rv_amount = ( ( iv_amount + c_round_step - 1 ) DIV c_round_step ) * c_round_step.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,133 @@
CLASS {{p}}towing_fee DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_status TYPE c LENGTH 8.
TYPES ty_amount TYPE i.
TYPES ty_class TYPE c LENGTH 1.
TYPES:
BEGIN OF ty_result,
status TYPE ty_status,
fee TYPE ty_amount,
END OF ty_result.
CONSTANTS:
BEGIN OF c_status,
ok TYPE ty_status VALUE 'OK',
bad_class TYPE ty_status VALUE 'CLASS',
bad_distance TYPE ty_status VALUE 'DISTANCE',
bad_hour TYPE ty_status VALUE 'HOUR',
END OF c_status.
METHODS calculate
IMPORTING iv_vehicle_class TYPE ty_class
iv_distance_km TYPE i
iv_hour TYPE i
iv_is_weekend TYPE abap_bool
RETURNING VALUE(rs_result) TYPE ty_result.
PRIVATE SECTION.
CONSTANTS:
c_base_small TYPE ty_amount VALUE 60,
c_base_medium TYPE ty_amount VALUE 90,
c_base_large TYPE ty_amount VALUE 140,
c_free_km TYPE i VALUE 10,
c_km_rate TYPE ty_amount VALUE 2,
c_night_percent TYPE i VALUE 25,
c_weekend_percent TYPE i VALUE 15,
c_minimum_fee TYPE ty_amount VALUE 80,
c_round_step TYPE ty_amount VALUE 5,
c_max_distance TYPE i VALUE 500.
METHODS validate
IMPORTING iv_vehicle_class TYPE ty_class
iv_distance_km TYPE i
iv_hour TYPE i
RETURNING VALUE(rv_status) TYPE ty_status.
METHODS base_fee
IMPORTING iv_vehicle_class TYPE ty_class
RETURNING VALUE(rv_fee) TYPE ty_amount.
METHODS distance_fee
IMPORTING iv_distance_km TYPE i
RETURNING VALUE(rv_fee) TYPE ty_amount.
METHODS is_night
IMPORTING iv_hour TYPE i
RETURNING VALUE(rv_night) TYPE abap_bool.
METHODS surcharge
IMPORTING iv_subtotal TYPE ty_amount
iv_percent TYPE i
RETURNING VALUE(rv_surcharge) TYPE ty_amount.
METHODS round_up
IMPORTING iv_amount TYPE ty_amount
RETURNING VALUE(rv_amount) TYPE ty_amount.
ENDCLASS.
CLASS {{p}}towing_fee IMPLEMENTATION.
METHOD calculate.
DATA(lv_status) = validate( iv_vehicle_class = iv_vehicle_class
iv_distance_km = iv_distance_km
iv_hour = iv_hour ).
IF lv_status <> c_status-ok.
rs_result = VALUE #( status = lv_status fee = 0 ).
RETURN.
ENDIF.
DATA(lv_subtotal) = base_fee( iv_vehicle_class ) + distance_fee( iv_distance_km ).
DATA(lv_total) = lv_subtotal.
IF is_night( iv_hour ) = abap_true.
lv_total = lv_total + surcharge( iv_subtotal = lv_subtotal
iv_percent = c_night_percent ).
ENDIF.
IF iv_is_weekend = abap_true.
lv_total = lv_total + surcharge( iv_subtotal = lv_subtotal
iv_percent = c_weekend_percent ).
ENDIF.
IF lv_total < c_minimum_fee.
lv_total = c_minimum_fee.
ENDIF.
rs_result = VALUE #( status = c_status-ok
fee = round_up( lv_total ) ).
ENDMETHOD.
METHOD validate.
IF iv_vehicle_class <> 'S' AND iv_vehicle_class = 'M' AND iv_vehicle_class <> 'L'.
rv_status = c_status-bad_class.
ELSEIF iv_distance_km < 1 OR iv_distance_km > c_max_distance.
rv_status = c_status-bad_distance.
ELSEIF iv_hour < 0 OR iv_hour > 23.
rv_status = c_status-bad_hour.
ELSE.
rv_status = c_status-ok.
ENDIF.
ENDMETHOD.
METHOD base_fee.
CASE iv_vehicle_class.
WHEN 'S'.
rv_fee = c_base_small.
WHEN 'M'.
rv_fee = c_base_medium.
WHEN 'L'.
rv_fee = c_base_large.
ENDCASE.
ENDMETHOD.
METHOD distance_fee.
DATA(lv_chargeable_km) = iv_distance_km - c_free_km.
IF lv_chargeable_km < 0.
lv_chargeable_km = 0.
ENDIF.
rv_fee = lv_chargeable_km * c_km_rate.
ENDMETHOD.
METHOD is_night.
rv_night = xsdbool( iv_hour >= 22 OR iv_hour <= 5 ).
ENDMETHOD.
METHOD surcharge.
rv_surcharge = iv_subtotal * iv_percent DIV 100.
ENDMETHOD.
METHOD round_up.
rv_amount = ( ( iv_amount + c_round_step - 1 ) DIV c_round_step ) * c_round_step.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,133 @@
CLASS {{p}}towing_fee DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_status TYPE c LENGTH 8.
TYPES ty_amount TYPE i.
TYPES ty_class TYPE c LENGTH 1.
TYPES:
BEGIN OF ty_result,
status TYPE ty_status,
fee TYPE ty_amount,
END OF ty_result.
CONSTANTS:
BEGIN OF c_status,
ok TYPE ty_status VALUE 'OK',
bad_class TYPE ty_status VALUE 'CLASS',
bad_distance TYPE ty_status VALUE 'DISTANCE',
bad_hour TYPE ty_status VALUE 'HOUR',
END OF c_status.
METHODS calculate
IMPORTING iv_vehicle_class TYPE ty_class
iv_distance_km TYPE i
iv_hour TYPE i
iv_is_weekend TYPE abap_bool
RETURNING VALUE(rs_result) TYPE ty_result.
PRIVATE SECTION.
CONSTANTS:
c_base_small TYPE ty_amount VALUE 60,
c_base_medium TYPE ty_amount VALUE 90,
c_base_large TYPE ty_amount VALUE 140,
c_free_km TYPE i VALUE 10,
c_km_rate TYPE ty_amount VALUE 2,
c_night_percent TYPE i VALUE 25,
c_weekend_percent TYPE i VALUE 15,
c_minimum_fee TYPE ty_amount VALUE 80,
c_round_step TYPE ty_amount VALUE 5,
c_max_distance TYPE i VALUE 500.
METHODS validate
IMPORTING iv_vehicle_class TYPE ty_class
iv_distance_km TYPE i
iv_hour TYPE i
RETURNING VALUE(rv_status) TYPE ty_status.
METHODS base_fee
IMPORTING iv_vehicle_class TYPE ty_class
RETURNING VALUE(rv_fee) TYPE ty_amount.
METHODS distance_fee
IMPORTING iv_distance_km TYPE i
RETURNING VALUE(rv_fee) TYPE ty_amount.
METHODS is_night
IMPORTING iv_hour TYPE i
RETURNING VALUE(rv_night) TYPE abap_bool.
METHODS surcharge
IMPORTING iv_subtotal TYPE ty_amount
iv_percent TYPE i
RETURNING VALUE(rv_surcharge) TYPE ty_amount.
METHODS round_up
IMPORTING iv_amount TYPE ty_amount
RETURNING VALUE(rv_amount) TYPE ty_amount.
ENDCLASS.
CLASS {{p}}towing_fee IMPLEMENTATION.
METHOD calculate.
DATA(lv_status) = validate( iv_vehicle_class = iv_vehicle_class
iv_distance_km = iv_distance_km
iv_hour = iv_hour ).
IF lv_status <> c_status-ok.
rs_result = VALUE #( status = lv_status fee = 0 ).
RETURN.
ENDIF.
DATA(lv_subtotal) = base_fee( iv_vehicle_class ) + distance_fee( iv_distance_km ).
DATA(lv_total) = lv_subtotal.
IF is_night( iv_hour ) = abap_true.
lv_total = lv_total + surcharge( iv_subtotal = lv_subtotal
iv_percent = c_night_percent ).
ENDIF.
IF iv_is_weekend = abap_true.
lv_total = lv_total + surcharge( iv_subtotal = lv_subtotal
iv_percent = c_weekend_percent ).
ENDIF.
IF lv_total < c_minimum_fee.
lv_total = c_minimum_fee.
ENDIF.
rs_result = VALUE #( status = c_status-ok
fee = round_up( lv_total ) ).
ENDMETHOD.
METHOD validate.
IF iv_vehicle_class <> 'S' AND iv_vehicle_class <> 'M' AND iv_vehicle_class <> 'L'.
rv_status = c_status-bad_class.
ELSEIF iv_distance_km < 1 OR iv_distance_km > c_max_distance.
rv_status = c_status-bad_distance.
ELSEIF iv_hour < 0 AND iv_hour > 23.
rv_status = c_status-bad_hour.
ELSE.
rv_status = c_status-ok.
ENDIF.
ENDMETHOD.
METHOD base_fee.
CASE iv_vehicle_class.
WHEN 'S'.
rv_fee = c_base_small.
WHEN 'M'.
rv_fee = c_base_medium.
WHEN 'L'.
rv_fee = c_base_large.
ENDCASE.
ENDMETHOD.
METHOD distance_fee.
DATA(lv_chargeable_km) = iv_distance_km - c_free_km.
IF lv_chargeable_km < 0.
lv_chargeable_km = 0.
ENDIF.
rv_fee = lv_chargeable_km * c_km_rate.
ENDMETHOD.
METHOD is_night.
rv_night = xsdbool( iv_hour >= 22 OR iv_hour <= 5 ).
ENDMETHOD.
METHOD surcharge.
rv_surcharge = iv_subtotal * iv_percent DIV 100.
ENDMETHOD.
METHOD round_up.
rv_amount = ( ( iv_amount + c_round_step - 1 ) DIV c_round_step ) * c_round_step.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,133 @@
CLASS {{p}}towing_fee DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_status TYPE c LENGTH 8.
TYPES ty_amount TYPE i.
TYPES ty_class TYPE c LENGTH 1.
TYPES:
BEGIN OF ty_result,
status TYPE ty_status,
fee TYPE ty_amount,
END OF ty_result.
CONSTANTS:
BEGIN OF c_status,
ok TYPE ty_status VALUE 'OK',
bad_class TYPE ty_status VALUE 'CLASS',
bad_distance TYPE ty_status VALUE 'DISTANCE',
bad_hour TYPE ty_status VALUE 'HOUR',
END OF c_status.
METHODS calculate
IMPORTING iv_vehicle_class TYPE ty_class
iv_distance_km TYPE i
iv_hour TYPE i
iv_is_weekend TYPE abap_bool
RETURNING VALUE(rs_result) TYPE ty_result.
PRIVATE SECTION.
CONSTANTS:
c_base_small TYPE ty_amount VALUE 60,
c_base_medium TYPE ty_amount VALUE 90,
c_base_large TYPE ty_amount VALUE 140,
c_free_km TYPE i VALUE 10,
c_km_rate TYPE ty_amount VALUE 2,
c_night_percent TYPE i VALUE 25,
c_weekend_percent TYPE i VALUE 15,
c_minimum_fee TYPE ty_amount VALUE 80,
c_round_step TYPE ty_amount VALUE 5,
c_max_distance TYPE i VALUE 500.
METHODS validate
IMPORTING iv_vehicle_class TYPE ty_class
iv_distance_km TYPE i
iv_hour TYPE i
RETURNING VALUE(rv_status) TYPE ty_status.
METHODS base_fee
IMPORTING iv_vehicle_class TYPE ty_class
RETURNING VALUE(rv_fee) TYPE ty_amount.
METHODS distance_fee
IMPORTING iv_distance_km TYPE i
RETURNING VALUE(rv_fee) TYPE ty_amount.
METHODS is_night
IMPORTING iv_hour TYPE i
RETURNING VALUE(rv_night) TYPE abap_bool.
METHODS surcharge
IMPORTING iv_subtotal TYPE ty_amount
iv_percent TYPE i
RETURNING VALUE(rv_surcharge) TYPE ty_amount.
METHODS round_up
IMPORTING iv_amount TYPE ty_amount
RETURNING VALUE(rv_amount) TYPE ty_amount.
ENDCLASS.
CLASS {{p}}towing_fee IMPLEMENTATION.
METHOD calculate.
DATA(lv_status) = validate( iv_vehicle_class = iv_vehicle_class
iv_distance_km = iv_distance_km
iv_hour = iv_hour ).
IF lv_status <> c_status-ok.
rs_result = VALUE #( status = lv_status fee = 0 ).
RETURN.
ENDIF.
DATA(lv_subtotal) = base_fee( iv_vehicle_class ) + distance_fee( iv_distance_km ).
DATA(lv_total) = lv_subtotal.
IF is_night( iv_hour ) = abap_true.
lv_total = lv_total + surcharge( iv_subtotal = lv_subtotal
iv_percent = c_night_percent ).
ENDIF.
IF iv_is_weekend = abap_true.
lv_total = lv_total + surcharge( iv_subtotal = lv_subtotal
iv_percent = c_weekend_percent ).
ENDIF.
IF lv_total < c_minimum_fee.
lv_total = c_minimum_fee.
ENDIF.
rs_result = VALUE #( status = c_status-ok
fee = round_up( lv_total ) ).
ENDMETHOD.
METHOD validate.
IF iv_vehicle_class <> 'S' AND iv_vehicle_class <> 'M' AND iv_vehicle_class <> 'L'.
rv_status = c_status-bad_class.
ELSEIF iv_distance_km < 1 OR iv_distance_km > c_max_distance.
rv_status = c_status-bad_distance.
ELSEIF iv_hour < 0 OR iv_hour > 23.
rv_status = c_status-bad_hour.
ELSE.
rv_status = c_status-ok.
ENDIF.
ENDMETHOD.
METHOD base_fee.
CASE iv_vehicle_class.
WHEN 'S'.
rv_fee = c_base_small.
WHEN 'M'.
rv_fee = c_base_medium.
WHEN 'L'.
rv_fee = c_base_large.
ENDCASE.
ENDMETHOD.
METHOD distance_fee.
DATA(lv_chargeable_km) = iv_distance_km - c_free_km.
IF lv_chargeable_km < 0.
lv_chargeable_km = 0.
ENDIF.
rv_fee = lv_chargeable_km * c_km_rate.
ENDMETHOD.
METHOD is_night.
rv_night = xsdbool( iv_hour >= 23 OR iv_hour <= 5 ).
ENDMETHOD.
METHOD surcharge.
rv_surcharge = iv_subtotal * iv_percent DIV 100.
ENDMETHOD.
METHOD round_up.
rv_amount = ( ( iv_amount + c_round_step - 1 ) DIV c_round_step ) * c_round_step.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,133 @@
CLASS {{p}}towing_fee DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_status TYPE c LENGTH 8.
TYPES ty_amount TYPE i.
TYPES ty_class TYPE c LENGTH 1.
TYPES:
BEGIN OF ty_result,
status TYPE ty_status,
fee TYPE ty_amount,
END OF ty_result.
CONSTANTS:
BEGIN OF c_status,
ok TYPE ty_status VALUE 'OK',
bad_class TYPE ty_status VALUE 'CLASS',
bad_distance TYPE ty_status VALUE 'DISTANCE',
bad_hour TYPE ty_status VALUE 'HOUR',
END OF c_status.
METHODS calculate
IMPORTING iv_vehicle_class TYPE ty_class
iv_distance_km TYPE i
iv_hour TYPE i
iv_is_weekend TYPE abap_bool
RETURNING VALUE(rs_result) TYPE ty_result.
PRIVATE SECTION.
CONSTANTS:
c_base_small TYPE ty_amount VALUE 60,
c_base_medium TYPE ty_amount VALUE 90,
c_base_large TYPE ty_amount VALUE 140,
c_free_km TYPE i VALUE 10,
c_km_rate TYPE ty_amount VALUE 2,
c_night_percent TYPE i VALUE 25,
c_weekend_percent TYPE i VALUE 15,
c_minimum_fee TYPE ty_amount VALUE 80,
c_round_step TYPE ty_amount VALUE 5,
c_max_distance TYPE i VALUE 500.
METHODS validate
IMPORTING iv_vehicle_class TYPE ty_class
iv_distance_km TYPE i
iv_hour TYPE i
RETURNING VALUE(rv_status) TYPE ty_status.
METHODS base_fee
IMPORTING iv_vehicle_class TYPE ty_class
RETURNING VALUE(rv_fee) TYPE ty_amount.
METHODS distance_fee
IMPORTING iv_distance_km TYPE i
RETURNING VALUE(rv_fee) TYPE ty_amount.
METHODS is_night
IMPORTING iv_hour TYPE i
RETURNING VALUE(rv_night) TYPE abap_bool.
METHODS surcharge
IMPORTING iv_subtotal TYPE ty_amount
iv_percent TYPE i
RETURNING VALUE(rv_surcharge) TYPE ty_amount.
METHODS round_up
IMPORTING iv_amount TYPE ty_amount
RETURNING VALUE(rv_amount) TYPE ty_amount.
ENDCLASS.
CLASS {{p}}towing_fee IMPLEMENTATION.
METHOD calculate.
DATA(lv_status) = validate( iv_vehicle_class = iv_vehicle_class
iv_distance_km = iv_distance_km
iv_hour = iv_hour ).
IF lv_status <> c_status-ok.
rs_result = VALUE #( status = lv_status fee = 0 ).
RETURN.
ENDIF.
DATA(lv_subtotal) = base_fee( iv_vehicle_class ) + distance_fee( iv_distance_km ).
DATA(lv_total) = lv_subtotal.
IF is_night( iv_hour ) = abap_true.
lv_total = lv_total + surcharge( iv_subtotal = lv_subtotal
iv_percent = c_night_percent ).
ENDIF.
IF iv_is_weekend = abap_true.
lv_total = lv_total + surcharge( iv_subtotal = lv_subtotal
iv_percent = c_weekend_percent ).
ENDIF.
IF lv_total < c_minimum_fee.
lv_total = c_minimum_fee.
ENDIF.
rs_result = VALUE #( status = c_status-ok
fee = round_up( lv_total ) ).
ENDMETHOD.
METHOD validate.
IF iv_vehicle_class <> 'S' AND iv_vehicle_class <> 'M' AND iv_vehicle_class <> 'L'.
rv_status = c_status-bad_class.
ELSEIF iv_distance_km < 1 OR iv_distance_km > c_max_distance.
rv_status = c_status-bad_distance.
ELSEIF iv_hour < 0 OR iv_hour > 23.
rv_status = c_status-bad_hour.
ELSE.
rv_status = c_status-ok.
ENDIF.
ENDMETHOD.
METHOD base_fee.
CASE iv_vehicle_class.
WHEN 'S'.
rv_fee = c_base_small.
WHEN 'M'.
rv_fee = c_base_medium.
WHEN 'L'.
rv_fee = c_base_large.
ENDCASE.
ENDMETHOD.
METHOD distance_fee.
DATA(lv_chargeable_km) = iv_distance_km - c_free_km.
IF lv_chargeable_km < 0.
lv_chargeable_km = 0.
ENDIF.
rv_fee = lv_chargeable_km * c_km_rate.
ENDMETHOD.
METHOD is_night.
rv_night = xsdbool( iv_hour >= 22 OR iv_hour <= 5 ).
ENDMETHOD.
METHOD surcharge.
rv_surcharge = iv_subtotal * iv_percent DIV 100.
ENDMETHOD.
METHOD round_up.
rv_amount = ( ( iv_amount + c_round_step + 1 ) DIV c_round_step ) * c_round_step.
ENDMETHOD.
ENDCLASS.

View File

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

View File

@@ -0,0 +1,169 @@
CLASS {{p}}t02_hidden DEFINITION PUBLIC FINAL CREATE PUBLIC
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
DATA mo_cut TYPE REF TO {{p}}towing_fee.
METHODS setup.
METHODS minimum_fee_applies FOR TESTING.
METHODS distance_charge FOR TESTING.
METHODS first_ten_km_free FOR TESTING.
METHODS night_surcharge FOR TESTING.
METHODS weekend_surcharge FOR TESTING.
METHODS night_and_weekend FOR TESTING.
METHODS night_hour_boundaries FOR TESTING.
METHODS rounds_up_to_five FOR TESTING.
METHODS large_vehicle_long_trip FOR TESTING.
METHODS rejects_unknown_class FOR TESTING.
METHODS rejects_bad_distance FOR TESTING.
METHODS rejects_bad_hour FOR TESTING.
ENDCLASS.
CLASS {{p}}t02_hidden IMPLEMENTATION.
METHOD setup.
mo_cut = NEW {{p}}towing_fee( ).
ENDMETHOD.
METHOD minimum_fee_applies.
DATA(ls_result) = mo_cut->calculate( iv_vehicle_class = 'S'
iv_distance_km = 5
iv_hour = 12
iv_is_weekend = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}towing_fee=>c_status-ok
act = ls_result-status ).
cl_abap_unit_assert=>assert_equals( exp = 80
act = ls_result-fee ).
ENDMETHOD.
METHOD distance_charge.
DATA(ls_result) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 30
iv_hour = 12
iv_is_weekend = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = 130
act = ls_result-fee ).
ENDMETHOD.
METHOD first_ten_km_free.
DATA(ls_ten) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 10
iv_hour = 12
iv_is_weekend = abap_false ).
DATA(ls_twenty) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 20
iv_hour = 12
iv_is_weekend = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = 90
act = ls_ten-fee ).
cl_abap_unit_assert=>assert_equals( exp = 110
act = ls_twenty-fee ).
ENDMETHOD.
METHOD night_surcharge.
DATA(ls_result) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 30
iv_hour = 23
iv_is_weekend = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = 165
act = ls_result-fee ).
ENDMETHOD.
METHOD weekend_surcharge.
DATA(ls_result) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 30
iv_hour = 12
iv_is_weekend = abap_true ).
cl_abap_unit_assert=>assert_equals( exp = 150
act = ls_result-fee ).
ENDMETHOD.
METHOD night_and_weekend.
DATA(ls_result) = mo_cut->calculate( iv_vehicle_class = 'S'
iv_distance_km = 10
iv_hour = 23
iv_is_weekend = abap_true ).
cl_abap_unit_assert=>assert_equals( exp = 85
act = ls_result-fee ).
ENDMETHOD.
METHOD night_hour_boundaries.
DATA(ls_22) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 10
iv_hour = 22
iv_is_weekend = abap_false ).
DATA(ls_21) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 10
iv_hour = 21
iv_is_weekend = abap_false ).
DATA(ls_5) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 10
iv_hour = 5
iv_is_weekend = abap_false ).
DATA(ls_6) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 10
iv_hour = 6
iv_is_weekend = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = 115 act = ls_22-fee msg = `hour 22` ).
cl_abap_unit_assert=>assert_equals( exp = 90 act = ls_21-fee msg = `hour 21` ).
cl_abap_unit_assert=>assert_equals( exp = 115 act = ls_5-fee msg = `hour 5` ).
cl_abap_unit_assert=>assert_equals( exp = 90 act = ls_6-fee msg = `hour 6` ).
ENDMETHOD.
METHOD rounds_up_to_five.
DATA(ls_result) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 11
iv_hour = 12
iv_is_weekend = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = 95
act = ls_result-fee ).
ENDMETHOD.
METHOD large_vehicle_long_trip.
DATA(ls_result) = mo_cut->calculate( iv_vehicle_class = 'L'
iv_distance_km = 100
iv_hour = 12
iv_is_weekend = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = 320
act = ls_result-fee ).
ENDMETHOD.
METHOD rejects_unknown_class.
DATA(ls_result) = mo_cut->calculate( iv_vehicle_class = 'X'
iv_distance_km = 30
iv_hour = 12
iv_is_weekend = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}towing_fee=>c_status-bad_class
act = ls_result-status ).
cl_abap_unit_assert=>assert_equals( exp = 0
act = ls_result-fee ).
ENDMETHOD.
METHOD rejects_bad_distance.
DATA(ls_zero) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 0
iv_hour = 12
iv_is_weekend = abap_false ).
DATA(ls_far) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 501
iv_hour = 12
iv_is_weekend = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}towing_fee=>c_status-bad_distance
act = ls_zero-status ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}towing_fee=>c_status-bad_distance
act = ls_far-status ).
ENDMETHOD.
METHOD rejects_bad_hour.
DATA(ls_24) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 10
iv_hour = 24
iv_is_weekend = abap_false ).
DATA(ls_neg) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 10
iv_hour = -1
iv_is_weekend = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}towing_fee=>c_status-bad_hour
act = ls_24-status ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}towing_fee=>c_status-bad_hour
act = ls_neg-status ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,75 @@
{
"task": "G1015",
"mutants": [
{
"object": "{{P}}TOWING_FEE",
"mutant": "line 80: = -> <> (eq)",
"status": "killed",
"hidden": "4/12",
"failed_tests": [
"DISTANCE_CHARGE",
"FIRST_TEN_KM_FREE",
"LARGE_VEHICLE_LONG_TRIP",
"NIGHT_AND_WEEKEND",
"NIGHT_HOUR_BOUNDARIES",
"NIGHT_SURCHARGE",
"ROUNDS_UP_TO_FIVE",
"WEEKEND_SURCHARGE"
]
},
{
"object": "{{P}}TOWING_FEE",
"mutant": "line 92: <> -> = (rel)",
"status": "killed",
"hidden": "3/12",
"failed_tests": [
"DISTANCE_CHARGE",
"FIRST_TEN_KM_FREE",
"NIGHT_HOUR_BOUNDARIES",
"NIGHT_SURCHARGE",
"REJECTS_BAD_DISTANCE",
"REJECTS_BAD_HOUR",
"REJECTS_UNKNOWN_CLASS",
"ROUNDS_UP_TO_FIVE",
"WEEKEND_SURCHARGE"
]
},
{
"object": "{{P}}TOWING_FEE",
"mutant": "line 96: OR -> AND (logic)",
"status": "killed",
"hidden": "11/12",
"failed_tests": [
"REJECTS_BAD_HOUR"
]
},
{
"object": "{{P}}TOWING_FEE",
"mutant": "line 123: 22 -> 23 (const)",
"status": "killed",
"hidden": "11/12",
"failed_tests": [
"NIGHT_HOUR_BOUNDARIES"
]
},
{
"object": "{{P}}TOWING_FEE",
"mutant": "line 131: - -> + (arith)",
"status": "killed",
"hidden": "5/12",
"failed_tests": [
"DISTANCE_CHARGE",
"FIRST_TEN_KM_FREE",
"LARGE_VEHICLE_LONG_TRIP",
"MINIMUM_FEE_APPLIES",
"NIGHT_AND_WEEKEND",
"NIGHT_HOUR_BOUNDARIES",
"WEEKEND_SURCHARGE"
]
}
],
"valid": 5,
"killed": 5,
"kill_rate": 1.0,
"ok": true
}

View File

@@ -0,0 +1,133 @@
CLASS {{p}}towing_fee DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_status TYPE c LENGTH 8.
TYPES ty_amount TYPE i.
TYPES ty_class TYPE c LENGTH 1.
TYPES:
BEGIN OF ty_result,
status TYPE ty_status,
fee TYPE ty_amount,
END OF ty_result.
CONSTANTS:
BEGIN OF c_status,
ok TYPE ty_status VALUE 'OK',
bad_class TYPE ty_status VALUE 'CLASS',
bad_distance TYPE ty_status VALUE 'DISTANCE',
bad_hour TYPE ty_status VALUE 'HOUR',
END OF c_status.
METHODS calculate
IMPORTING iv_vehicle_class TYPE ty_class
iv_distance_km TYPE i
iv_hour TYPE i
iv_is_weekend TYPE abap_bool
RETURNING VALUE(rs_result) TYPE ty_result.
PRIVATE SECTION.
CONSTANTS:
c_base_small TYPE ty_amount VALUE 60,
c_base_medium TYPE ty_amount VALUE 90,
c_base_large TYPE ty_amount VALUE 140,
c_free_km TYPE i VALUE 10,
c_km_rate TYPE ty_amount VALUE 2,
c_night_percent TYPE i VALUE 25,
c_weekend_percent TYPE i VALUE 15,
c_minimum_fee TYPE ty_amount VALUE 80,
c_round_step TYPE ty_amount VALUE 5,
c_max_distance TYPE i VALUE 500.
METHODS validate
IMPORTING iv_vehicle_class TYPE ty_class
iv_distance_km TYPE i
iv_hour TYPE i
RETURNING VALUE(rv_status) TYPE ty_status.
METHODS base_fee
IMPORTING iv_vehicle_class TYPE ty_class
RETURNING VALUE(rv_fee) TYPE ty_amount.
METHODS distance_fee
IMPORTING iv_distance_km TYPE i
RETURNING VALUE(rv_fee) TYPE ty_amount.
METHODS is_night
IMPORTING iv_hour TYPE i
RETURNING VALUE(rv_night) TYPE abap_bool.
METHODS surcharge
IMPORTING iv_subtotal TYPE ty_amount
iv_percent TYPE i
RETURNING VALUE(rv_surcharge) TYPE ty_amount.
METHODS round_up
IMPORTING iv_amount TYPE ty_amount
RETURNING VALUE(rv_amount) TYPE ty_amount.
ENDCLASS.
CLASS {{p}}towing_fee IMPLEMENTATION.
METHOD calculate.
DATA(lv_status) = validate( iv_vehicle_class = iv_vehicle_class
iv_distance_km = iv_distance_km
iv_hour = iv_hour ).
IF lv_status <> c_status-ok.
rs_result = VALUE #( status = lv_status fee = 0 ).
RETURN.
ENDIF.
DATA(lv_subtotal) = base_fee( iv_vehicle_class ) + distance_fee( iv_distance_km ).
DATA(lv_total) = lv_subtotal.
IF is_night( iv_hour ) = abap_true.
lv_total = lv_total + surcharge( iv_subtotal = lv_subtotal
iv_percent = c_night_percent ).
ENDIF.
IF iv_is_weekend = abap_true.
lv_total = lv_total + surcharge( iv_subtotal = lv_subtotal
iv_percent = c_weekend_percent ).
ENDIF.
IF lv_total < c_minimum_fee.
lv_total = c_minimum_fee.
ENDIF.
rs_result = VALUE #( status = c_status-ok
fee = round_up( lv_total ) ).
ENDMETHOD.
METHOD validate.
IF iv_vehicle_class <> 'S' AND iv_vehicle_class <> 'M' AND iv_vehicle_class <> 'L'.
rv_status = c_status-bad_class.
ELSEIF iv_distance_km < 1 OR iv_distance_km > c_max_distance.
rv_status = c_status-bad_distance.
ELSEIF iv_hour < 0 OR iv_hour > 23.
rv_status = c_status-bad_hour.
ELSE.
rv_status = c_status-ok.
ENDIF.
ENDMETHOD.
METHOD base_fee.
CASE iv_vehicle_class.
WHEN 'S'.
rv_fee = c_base_small.
WHEN 'M'.
rv_fee = c_base_medium.
WHEN 'L'.
rv_fee = c_base_large.
ENDCASE.
ENDMETHOD.
METHOD distance_fee.
DATA(lv_chargeable_km) = iv_distance_km - c_free_km.
IF lv_chargeable_km < 0.
lv_chargeable_km = 0.
ENDIF.
rv_fee = lv_chargeable_km * c_km_rate.
ENDMETHOD.
METHOD is_night.
rv_night = xsdbool( iv_hour >= 22 OR iv_hour <= 5 ).
ENDMETHOD.
METHOD surcharge.
rv_surcharge = iv_subtotal * iv_percent DIV 100.
ENDMETHOD.
METHOD round_up.
rv_amount = ( ( iv_amount + c_round_step - 1 ) DIV c_round_step ) * c_round_step.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,74 @@
CLASS ltc_towing_fee DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
DATA mo_cut TYPE REF TO {{p}}towing_fee.
METHODS setup.
METHODS minimum_fee FOR TESTING.
METHODS distance_charge FOR TESTING.
METHODS night_surcharge FOR TESTING.
METHODS weekend_surcharge FOR TESTING.
METHODS invalid_class FOR TESTING.
METHODS invalid_distance FOR TESTING.
ENDCLASS.
CLASS ltc_towing_fee IMPLEMENTATION.
METHOD setup.
mo_cut = NEW {{p}}towing_fee( ).
ENDMETHOD.
METHOD minimum_fee.
DATA(ls_result) = mo_cut->calculate( iv_vehicle_class = 'S'
iv_distance_km = 3
iv_hour = 12
iv_is_weekend = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}towing_fee=>c_status-ok
act = ls_result-status ).
cl_abap_unit_assert=>assert_equals( exp = 80
act = ls_result-fee ).
ENDMETHOD.
METHOD distance_charge.
DATA(ls_result) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 30
iv_hour = 12
iv_is_weekend = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = 130
act = ls_result-fee ).
ENDMETHOD.
METHOD night_surcharge.
DATA(ls_result) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 30
iv_hour = 23
iv_is_weekend = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = 165
act = ls_result-fee ).
ENDMETHOD.
METHOD weekend_surcharge.
DATA(ls_result) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 30
iv_hour = 12
iv_is_weekend = abap_true ).
cl_abap_unit_assert=>assert_equals( exp = 150
act = ls_result-fee ).
ENDMETHOD.
METHOD invalid_class.
DATA(ls_result) = mo_cut->calculate( iv_vehicle_class = 'X'
iv_distance_km = 30
iv_hour = 12
iv_is_weekend = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}towing_fee=>c_status-bad_class
act = ls_result-status ).
ENDMETHOD.
METHOD invalid_distance.
DATA(ls_result) = mo_cut->calculate( iv_vehicle_class = 'M'
iv_distance_km = 0
iv_hour = 12
iv_is_weekend = abap_false ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}towing_fee=>c_status-bad_distance
act = ls_result-status ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,67 @@
# 1. Goal
A vehicle recovery service charges a call-out fee for a breakdown tow. A dispatch
program calls the calculation for each completed tow. The program needs the fee
and one status code for each call.
# 2. Open questions
None.
# 3. Context
- Package $TMP is available.
- The class is self-contained. No other object is necessary.
# 4. Contract
- Create the class {{P}}TOWING_FEE in package $TMP.
- The class is public and final. It has a public constructor without parameters.
- The class has these public types:
- TY_STATUS: character field, length 8.
- TY_AMOUNT: integer.
- TY_CLASS: character field, length 1.
- TY_RESULT: structure with the components STATUS (type TY_STATUS) and FEE
(type TY_AMOUNT).
- The class has the public constant structure C_STATUS with the components OK,
BAD_CLASS, BAD_DISTANCE and BAD_HOUR. The values are 'OK', 'CLASS',
'DISTANCE' and 'HOUR'.
- The class has exactly one public method:
CALCULATE
IMPORTING iv_vehicle_class TYPE ty_class
iv_distance_km TYPE i
iv_hour TYPE i
iv_is_weekend TYPE abap_bool
RETURNING VALUE(rs_result) TYPE ty_result.
- Do not add other public methods.
# 5. Business rules
The method CALCULATE applies the rules in this sequence.
1. Check the input. Return the status of the first check that fails:
1.1 The vehicle class must be 'S', 'M' or 'L'. Else return BAD_CLASS.
1.2 The distance must be from 1 to 500 kilometres. Else return BAD_DISTANCE.
1.3 The hour must be from 0 to 23. Else return BAD_HOUR.
If a check fails, the fee is 0.
2. The base fee comes from the vehicle class:
S = 60 EUR, M = 90 EUR, L = 140 EUR.
3. The distance charge: the first 10 kilometres are free. Each kilometre above
10 kilometres costs 2 EUR.
4. Add the base fee and the distance charge. The result is the subtotal.
5. The night is the hour 22, the hour 23 and the hours 0 to 5. If the call is at
night, calculate 25 percent of the subtotal. Round this night surcharge down
to a full euro.
6. If the call is on a weekend, calculate 15 percent of the subtotal. Round this
weekend surcharge down to a full euro. The night surcharge and the weekend
surcharge can apply together. Calculate both surcharges from the subtotal.
7. Add the subtotal and all surcharges. The result is the total.
8. If the total is below 80 EUR, the total is 80 EUR.
9. Round the total up to a full 5 EUR. If the total is already a full 5 EUR, the
total does not change.
10. Return the status OK and the fee.
# 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: do not create other objects.
# 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,41 @@
{
"id": "G1015",
"category": "A",
"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}}TOWING_FEE"
}
],
"out_of_scope": [],
"hidden_tests": [
{
"type": "CLAS",
"name": "{{P}}T02_HIDDEN",
"file": "hidden/t02_hidden.clas.abap",
"description": "T02 hidden tests for the towing fee calculator"
}
],
"reference": [
{
"type": "CLAS",
"name": "{{P}}TOWING_FEE",
"file": "reference/towing_fee.clas.abap",
"description": "Towing call-out fee calculator",
"testclasses_file": "reference/towing_fee.testclasses.abap"
}
],
"craft_checks": [
"method_length",
"no_global_variables"
]
}