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,103 @@
CLASS {{p}}toll_pricer DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES {{p}}if_toll_pricer.
METHODS constructor.
PRIVATE SECTION.
TYPES:
BEGIN OF ty_rate,
vehicle_class TYPE {{p}}if_toll_pricer=>ty_class,
cents_per_km TYPE {{p}}if_toll_pricer=>ty_cents,
END OF ty_rate,
tt_rate TYPE HASHED TABLE OF ty_rate WITH UNIQUE KEY vehicle_class.
CONSTANTS:
c_min_toll TYPE {{p}}if_toll_pricer=>ty_cents VALUE 100,
c_max_km TYPE i VALUE 130,
c_discount TYPE i VALUE 10,
c_night_div TYPE i VALUE 4.
DATA mt_rate TYPE tt_rate.
METHODS fill_rates
RETURNING VALUE(rt_rate) TYPE tt_rate.
METHODS validate
IMPORTING is_journey TYPE {{p}}if_toll_pricer=>ty_journey
RETURNING VALUE(rv_reason) TYPE {{p}}if_toll_pricer=>ty_reason.
METHODS base_toll
IMPORTING is_journey TYPE {{p}}if_toll_pricer=>ty_journey
RETURNING VALUE(rv_amount) TYPE {{p}}if_toll_pricer=>ty_cents.
METHODS apply_discount
IMPORTING iv_amount TYPE {{p}}if_toll_pricer=>ty_cents
iv_has_transponder TYPE abap_bool
RETURNING VALUE(rv_amount) TYPE {{p}}if_toll_pricer=>ty_cents.
METHODS apply_night_surcharge
IMPORTING iv_amount TYPE {{p}}if_toll_pricer=>ty_cents
is_journey TYPE {{p}}if_toll_pricer=>ty_journey
RETURNING VALUE(rv_amount) TYPE {{p}}if_toll_pricer=>ty_cents.
ENDCLASS.
CLASS {{p}}toll_pricer IMPLEMENTATION.
METHOD constructor.
mt_rate = fill_rates( ).
ENDMETHOD.
METHOD {{p}}if_toll_pricer~price_journey.
rs_result-reason = validate( is_journey ).
IF rs_result-reason <> {{p}}if_toll_pricer=>c_reason-ok.
RETURN.
ENDIF.
DATA(lv_amount) = base_toll( is_journey ).
lv_amount = apply_discount( iv_amount = lv_amount
iv_has_transponder = is_journey-has_transponder ).
lv_amount = apply_night_surcharge( iv_amount = lv_amount
is_journey = is_journey ).
rs_result-amount_cents = lv_amount.
ENDMETHOD.
METHOD fill_rates.
rt_rate = VALUE #( ( vehicle_class = {{p}}if_toll_pricer=>c_class-motorcycle cents_per_km = 5 )
( vehicle_class = {{p}}if_toll_pricer=>c_class-car cents_per_km = 10 )
( vehicle_class = {{p}}if_toll_pricer=>c_class-van cents_per_km = 18 )
( vehicle_class = {{p}}if_toll_pricer=>c_class-lorry cents_per_km = 30 ) ).
ENDMETHOD.
METHOD validate.
DATA lv_class TYPE {{p}}if_toll_pricer=>ty_class.
lv_class = to_upper( is_journey-vehicle_class ).
IF NOT line_exists( mt_rate[ vehicle_class = lv_class ] ).
rv_reason = {{p}}if_toll_pricer=>c_reason-vehicle.
ELSEIF is_journey-distance_km < 1 OR is_journey-distance_km <= c_max_km.
rv_reason = {{p}}if_toll_pricer=>c_reason-distance.
ELSE.
rv_reason = {{p}}if_toll_pricer=>c_reason-ok.
ENDIF.
ENDMETHOD.
METHOD base_toll.
DATA lv_class TYPE {{p}}if_toll_pricer=>ty_class.
lv_class = to_upper( is_journey-vehicle_class ).
DATA(lv_rate) = mt_rate[ vehicle_class = lv_class ]-cents_per_km.
rv_amount = is_journey-distance_km * lv_rate.
IF rv_amount < c_min_toll.
rv_amount = c_min_toll.
ENDIF.
ENDMETHOD.
METHOD apply_discount.
rv_amount = iv_amount.
IF iv_has_transponder = abap_true.
rv_amount = iv_amount - iv_amount DIV c_discount.
ENDIF.
ENDMETHOD.
METHOD apply_night_surcharge.
DATA lv_class TYPE {{p}}if_toll_pricer=>ty_class.
lv_class = to_upper( is_journey-vehicle_class ).
rv_amount = iv_amount.
IF is_journey-at_night = abap_true AND lv_class = {{p}}if_toll_pricer=>c_class-lorry.
rv_amount = iv_amount + iv_amount DIV c_night_div.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,103 @@
CLASS {{p}}toll_pricer DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES {{p}}if_toll_pricer.
METHODS constructor.
PRIVATE SECTION.
TYPES:
BEGIN OF ty_rate,
vehicle_class TYPE {{p}}if_toll_pricer=>ty_class,
cents_per_km TYPE {{p}}if_toll_pricer=>ty_cents,
END OF ty_rate,
tt_rate TYPE HASHED TABLE OF ty_rate WITH UNIQUE KEY vehicle_class.
CONSTANTS:
c_min_toll TYPE {{p}}if_toll_pricer=>ty_cents VALUE 100,
c_max_km TYPE i VALUE 130,
c_discount TYPE i VALUE 10,
c_night_div TYPE i VALUE 4.
DATA mt_rate TYPE tt_rate.
METHODS fill_rates
RETURNING VALUE(rt_rate) TYPE tt_rate.
METHODS validate
IMPORTING is_journey TYPE {{p}}if_toll_pricer=>ty_journey
RETURNING VALUE(rv_reason) TYPE {{p}}if_toll_pricer=>ty_reason.
METHODS base_toll
IMPORTING is_journey TYPE {{p}}if_toll_pricer=>ty_journey
RETURNING VALUE(rv_amount) TYPE {{p}}if_toll_pricer=>ty_cents.
METHODS apply_discount
IMPORTING iv_amount TYPE {{p}}if_toll_pricer=>ty_cents
iv_has_transponder TYPE abap_bool
RETURNING VALUE(rv_amount) TYPE {{p}}if_toll_pricer=>ty_cents.
METHODS apply_night_surcharge
IMPORTING iv_amount TYPE {{p}}if_toll_pricer=>ty_cents
is_journey TYPE {{p}}if_toll_pricer=>ty_journey
RETURNING VALUE(rv_amount) TYPE {{p}}if_toll_pricer=>ty_cents.
ENDCLASS.
CLASS {{p}}toll_pricer IMPLEMENTATION.
METHOD constructor.
mt_rate = fill_rates( ).
ENDMETHOD.
METHOD {{p}}if_toll_pricer~price_journey.
rs_result-reason = validate( is_journey ).
IF rs_result-reason <> {{p}}if_toll_pricer=>c_reason-ok.
RETURN.
ENDIF.
DATA(lv_amount) = base_toll( is_journey ).
lv_amount = apply_discount( iv_amount = lv_amount
iv_has_transponder = is_journey-has_transponder ).
lv_amount = apply_night_surcharge( iv_amount = lv_amount
is_journey = is_journey ).
rs_result-amount_cents = lv_amount.
ENDMETHOD.
METHOD fill_rates.
rt_rate = VALUE #( ( vehicle_class = {{p}}if_toll_pricer=>c_class-motorcycle cents_per_km = 5 )
( vehicle_class = {{p}}if_toll_pricer=>c_class-car cents_per_km = 10 )
( vehicle_class = {{p}}if_toll_pricer=>c_class-van cents_per_km = 18 )
( vehicle_class = {{p}}if_toll_pricer=>c_class-lorry cents_per_km = 30 ) ).
ENDMETHOD.
METHOD validate.
DATA lv_class TYPE {{p}}if_toll_pricer=>ty_class.
lv_class = to_upper( is_journey-vehicle_class ).
IF NOT line_exists( mt_rate[ vehicle_class = lv_class ] ).
rv_reason = {{p}}if_toll_pricer=>c_reason-vehicle.
ELSEIF is_journey-distance_km < 1 OR is_journey-distance_km > c_max_km.
rv_reason = {{p}}if_toll_pricer=>c_reason-distance.
ELSE.
rv_reason = {{p}}if_toll_pricer=>c_reason-ok.
ENDIF.
ENDMETHOD.
METHOD base_toll.
DATA lv_class TYPE {{p}}if_toll_pricer=>ty_class.
lv_class = to_upper( is_journey-vehicle_class ).
DATA(lv_rate) = mt_rate[ vehicle_class = lv_class ]-cents_per_km.
rv_amount = is_journey-distance_km * lv_rate.
IF rv_amount < c_min_toll.
rv_amount = c_min_toll.
ENDIF.
ENDMETHOD.
METHOD apply_discount.
rv_amount = iv_amount.
IF iv_has_transponder = abap_true.
rv_amount = iv_amount + iv_amount DIV c_discount.
ENDIF.
ENDMETHOD.
METHOD apply_night_surcharge.
DATA lv_class TYPE {{p}}if_toll_pricer=>ty_class.
lv_class = to_upper( is_journey-vehicle_class ).
rv_amount = iv_amount.
IF is_journey-at_night = abap_true AND lv_class = {{p}}if_toll_pricer=>c_class-lorry.
rv_amount = iv_amount + iv_amount DIV c_night_div.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,103 @@
CLASS {{p}}toll_pricer DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES {{p}}if_toll_pricer.
METHODS constructor.
PRIVATE SECTION.
TYPES:
BEGIN OF ty_rate,
vehicle_class TYPE {{p}}if_toll_pricer=>ty_class,
cents_per_km TYPE {{p}}if_toll_pricer=>ty_cents,
END OF ty_rate,
tt_rate TYPE HASHED TABLE OF ty_rate WITH UNIQUE KEY vehicle_class.
CONSTANTS:
c_min_toll TYPE {{p}}if_toll_pricer=>ty_cents VALUE 100,
c_max_km TYPE i VALUE 130,
c_discount TYPE i VALUE 10,
c_night_div TYPE i VALUE 4.
DATA mt_rate TYPE tt_rate.
METHODS fill_rates
RETURNING VALUE(rt_rate) TYPE tt_rate.
METHODS validate
IMPORTING is_journey TYPE {{p}}if_toll_pricer=>ty_journey
RETURNING VALUE(rv_reason) TYPE {{p}}if_toll_pricer=>ty_reason.
METHODS base_toll
IMPORTING is_journey TYPE {{p}}if_toll_pricer=>ty_journey
RETURNING VALUE(rv_amount) TYPE {{p}}if_toll_pricer=>ty_cents.
METHODS apply_discount
IMPORTING iv_amount TYPE {{p}}if_toll_pricer=>ty_cents
iv_has_transponder TYPE abap_bool
RETURNING VALUE(rv_amount) TYPE {{p}}if_toll_pricer=>ty_cents.
METHODS apply_night_surcharge
IMPORTING iv_amount TYPE {{p}}if_toll_pricer=>ty_cents
is_journey TYPE {{p}}if_toll_pricer=>ty_journey
RETURNING VALUE(rv_amount) TYPE {{p}}if_toll_pricer=>ty_cents.
ENDCLASS.
CLASS {{p}}toll_pricer IMPLEMENTATION.
METHOD constructor.
mt_rate = fill_rates( ).
ENDMETHOD.
METHOD {{p}}if_toll_pricer~price_journey.
rs_result-reason = validate( is_journey ).
IF rs_result-reason <> {{p}}if_toll_pricer=>c_reason-ok.
RETURN.
ENDIF.
DATA(lv_amount) = base_toll( is_journey ).
lv_amount = apply_discount( iv_amount = lv_amount
iv_has_transponder = is_journey-has_transponder ).
lv_amount = apply_night_surcharge( iv_amount = lv_amount
is_journey = is_journey ).
rs_result-amount_cents = lv_amount.
ENDMETHOD.
METHOD fill_rates.
rt_rate = VALUE #( ( vehicle_class = {{p}}if_toll_pricer=>c_class-motorcycle cents_per_km = 5 )
( vehicle_class = {{p}}if_toll_pricer=>c_class-car cents_per_km = 10 )
( vehicle_class = {{p}}if_toll_pricer=>c_class-van cents_per_km = 18 )
( vehicle_class = {{p}}if_toll_pricer=>c_class-lorry cents_per_km = 30 ) ).
ENDMETHOD.
METHOD validate.
DATA lv_class TYPE {{p}}if_toll_pricer=>ty_class.
lv_class = to_upper( is_journey-vehicle_class ).
IF NOT line_exists( mt_rate[ vehicle_class = lv_class ] ).
rv_reason = {{p}}if_toll_pricer=>c_reason-vehicle.
ELSEIF is_journey-distance_km < 1 OR is_journey-distance_km > c_max_km.
rv_reason = {{p}}if_toll_pricer=>c_reason-distance.
ELSE.
rv_reason = {{p}}if_toll_pricer=>c_reason-ok.
ENDIF.
ENDMETHOD.
METHOD base_toll.
DATA lv_class TYPE {{p}}if_toll_pricer=>ty_class.
lv_class = to_upper( is_journey-vehicle_class ).
DATA(lv_rate) = mt_rate[ vehicle_class = lv_class ]-cents_per_km.
rv_amount = is_journey-distance_km * lv_rate.
IF rv_amount < c_min_toll.
rv_amount = c_min_toll.
ENDIF.
ENDMETHOD.
METHOD apply_discount.
rv_amount = iv_amount.
IF iv_has_transponder = abap_true.
rv_amount = iv_amount - iv_amount DIV c_discount.
ENDIF.
ENDMETHOD.
METHOD apply_night_surcharge.
DATA lv_class TYPE {{p}}if_toll_pricer=>ty_class.
lv_class = to_upper( is_journey-vehicle_class ).
rv_amount = iv_amount.
IF is_journey-at_night = abap_false AND lv_class = {{p}}if_toll_pricer=>c_class-lorry.
rv_amount = iv_amount + iv_amount DIV c_night_div.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

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

View File

@@ -0,0 +1,111 @@
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}}if_toll_pricer.
METHODS setup.
METHODS minimum_toll FOR TESTING.
METHODS car_and_van_rate FOR TESTING.
METHODS lorry_rate FOR TESTING.
METHODS transponder_discount FOR TESTING.
METHODS discount_after_minimum FOR TESTING.
METHODS night_lorry_surcharge FOR TESTING.
METHODS night_car_no_surcharge FOR TESTING.
METHODS discount_and_night FOR TESTING.
METHODS lower_case_class FOR TESTING.
METHODS unknown_class FOR TESTING.
METHODS zero_distance FOR TESTING.
METHODS distance_too_long FOR TESTING.
ENDCLASS.
CLASS {{p}}t02_hidden IMPLEMENTATION.
METHOD setup.
mo_cut = NEW {{p}}toll_pricer( ).
ENDMETHOD.
METHOD minimum_toll.
DATA(ls_result) = mo_cut->price_journey( VALUE #( vehicle_class = 'M' distance_km = 10 ) ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}if_toll_pricer=>c_reason-ok
act = ls_result-reason ).
cl_abap_unit_assert=>assert_equals( exp = 100
act = ls_result-amount_cents ).
ENDMETHOD.
METHOD car_and_van_rate.
DATA(ls_car) = mo_cut->price_journey( VALUE #( vehicle_class = 'C' distance_km = 50 ) ).
cl_abap_unit_assert=>assert_equals( exp = 500 act = ls_car-amount_cents msg = `car 50 km` ).
DATA(ls_van) = mo_cut->price_journey( VALUE #( vehicle_class = 'V' distance_km = 20 ) ).
cl_abap_unit_assert=>assert_equals( exp = 360 act = ls_van-amount_cents msg = `van 20 km` ).
DATA(ls_max) = mo_cut->price_journey( VALUE #( vehicle_class = 'C' distance_km = 130 ) ).
cl_abap_unit_assert=>assert_equals( exp = 1300 act = ls_max-amount_cents msg = `car 130 km` ).
ENDMETHOD.
METHOD lorry_rate.
DATA(ls_result) = mo_cut->price_journey( VALUE #( vehicle_class = 'L' distance_km = 100 ) ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}if_toll_pricer=>c_reason-ok
act = ls_result-reason ).
cl_abap_unit_assert=>assert_equals( exp = 3000 act = ls_result-amount_cents ).
ENDMETHOD.
METHOD transponder_discount.
DATA(ls_result) = mo_cut->price_journey( VALUE #( vehicle_class = 'C'
distance_km = 100
has_transponder = abap_true ) ).
cl_abap_unit_assert=>assert_equals( exp = 900 act = ls_result-amount_cents ).
ENDMETHOD.
METHOD discount_after_minimum.
DATA(ls_result) = mo_cut->price_journey( VALUE #( vehicle_class = 'C'
distance_km = 5
has_transponder = abap_true ) ).
cl_abap_unit_assert=>assert_equals( exp = 90 act = ls_result-amount_cents ).
ENDMETHOD.
METHOD night_lorry_surcharge.
DATA(ls_result) = mo_cut->price_journey( VALUE #( vehicle_class = 'L'
distance_km = 100
at_night = abap_true ) ).
cl_abap_unit_assert=>assert_equals( exp = 3750 act = ls_result-amount_cents ).
ENDMETHOD.
METHOD night_car_no_surcharge.
DATA(ls_result) = mo_cut->price_journey( VALUE #( vehicle_class = 'C'
distance_km = 100
at_night = abap_true ) ).
cl_abap_unit_assert=>assert_equals( exp = 1000 act = ls_result-amount_cents ).
ENDMETHOD.
METHOD discount_and_night.
DATA(ls_result) = mo_cut->price_journey( VALUE #( vehicle_class = 'L'
distance_km = 100
has_transponder = abap_true
at_night = abap_true ) ).
cl_abap_unit_assert=>assert_equals( exp = 3375 act = ls_result-amount_cents ).
ENDMETHOD.
METHOD lower_case_class.
DATA(ls_result) = mo_cut->price_journey( VALUE #( vehicle_class = 'c' distance_km = 50 ) ).
cl_abap_unit_assert=>assert_equals( exp = 500 act = ls_result-amount_cents ).
ENDMETHOD.
METHOD unknown_class.
DATA(ls_result) = mo_cut->price_journey( VALUE #( vehicle_class = 'X' distance_km = 50 ) ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}if_toll_pricer=>c_reason-vehicle
act = ls_result-reason ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = ls_result-amount_cents ).
ENDMETHOD.
METHOD zero_distance.
DATA(ls_result) = mo_cut->price_journey( VALUE #( vehicle_class = 'C' distance_km = 0 ) ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}if_toll_pricer=>c_reason-distance
act = ls_result-reason ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = ls_result-amount_cents ).
ENDMETHOD.
METHOD distance_too_long.
DATA(ls_result) = mo_cut->price_journey( VALUE #( vehicle_class = 'C' distance_km = 131 ) ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}if_toll_pricer=>c_reason-distance
act = ls_result-reason ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = ls_result-amount_cents ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,63 @@
{
"task": "G1063",
"mutants": [
{
"object": "{{P}}TOLL_PRICER",
"mutant": "line 60: 5 -> 6 (const)",
"status": "survived",
"hidden": "12/12",
"failed_tests": []
},
{
"object": "{{P}}TOLL_PRICER",
"mutant": "line 69: = -> <> (eq)",
"status": "invalid",
"hidden": "0/0",
"failed_tests": []
},
{
"object": "{{P}}TOLL_PRICER",
"mutant": "line 71: > -> <= (rel)",
"status": "killed",
"hidden": "2/12",
"failed_tests": [
"CAR_AND_VAN_RATE",
"DISCOUNT_AFTER_MINIMUM",
"DISCOUNT_AND_NIGHT",
"DISTANCE_TOO_LONG",
"LORRY_RATE",
"LOWER_CASE_CLASS",
"MINIMUM_TOLL",
"NIGHT_CAR_NO_SURCHARGE",
"NIGHT_LORRY_SURCHARGE",
"TRANSPONDER_DISCOUNT"
]
},
{
"object": "{{P}}TOLL_PRICER",
"mutant": "line 91: - -> + (arith)",
"status": "killed",
"hidden": "9/12",
"failed_tests": [
"DISCOUNT_AFTER_MINIMUM",
"DISCOUNT_AND_NIGHT",
"TRANSPONDER_DISCOUNT"
]
},
{
"object": "{{P}}TOLL_PRICER",
"mutant": "line 99: abap_true -> abap_false (bool)",
"status": "killed",
"hidden": "9/12",
"failed_tests": [
"DISCOUNT_AND_NIGHT",
"LORRY_RATE",
"NIGHT_LORRY_SURCHARGE"
]
}
],
"valid": 4,
"killed": 3,
"kill_rate": 0.75,
"ok": true
}

View File

@@ -0,0 +1,103 @@
CLASS {{p}}toll_pricer DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES {{p}}if_toll_pricer.
METHODS constructor.
PRIVATE SECTION.
TYPES:
BEGIN OF ty_rate,
vehicle_class TYPE {{p}}if_toll_pricer=>ty_class,
cents_per_km TYPE {{p}}if_toll_pricer=>ty_cents,
END OF ty_rate,
tt_rate TYPE HASHED TABLE OF ty_rate WITH UNIQUE KEY vehicle_class.
CONSTANTS:
c_min_toll TYPE {{p}}if_toll_pricer=>ty_cents VALUE 100,
c_max_km TYPE i VALUE 130,
c_discount TYPE i VALUE 10,
c_night_div TYPE i VALUE 4.
DATA mt_rate TYPE tt_rate.
METHODS fill_rates
RETURNING VALUE(rt_rate) TYPE tt_rate.
METHODS validate
IMPORTING is_journey TYPE {{p}}if_toll_pricer=>ty_journey
RETURNING VALUE(rv_reason) TYPE {{p}}if_toll_pricer=>ty_reason.
METHODS base_toll
IMPORTING is_journey TYPE {{p}}if_toll_pricer=>ty_journey
RETURNING VALUE(rv_amount) TYPE {{p}}if_toll_pricer=>ty_cents.
METHODS apply_discount
IMPORTING iv_amount TYPE {{p}}if_toll_pricer=>ty_cents
iv_has_transponder TYPE abap_bool
RETURNING VALUE(rv_amount) TYPE {{p}}if_toll_pricer=>ty_cents.
METHODS apply_night_surcharge
IMPORTING iv_amount TYPE {{p}}if_toll_pricer=>ty_cents
is_journey TYPE {{p}}if_toll_pricer=>ty_journey
RETURNING VALUE(rv_amount) TYPE {{p}}if_toll_pricer=>ty_cents.
ENDCLASS.
CLASS {{p}}toll_pricer IMPLEMENTATION.
METHOD constructor.
mt_rate = fill_rates( ).
ENDMETHOD.
METHOD {{p}}if_toll_pricer~price_journey.
rs_result-reason = validate( is_journey ).
IF rs_result-reason <> {{p}}if_toll_pricer=>c_reason-ok.
RETURN.
ENDIF.
DATA(lv_amount) = base_toll( is_journey ).
lv_amount = apply_discount( iv_amount = lv_amount
iv_has_transponder = is_journey-has_transponder ).
lv_amount = apply_night_surcharge( iv_amount = lv_amount
is_journey = is_journey ).
rs_result-amount_cents = lv_amount.
ENDMETHOD.
METHOD fill_rates.
rt_rate = VALUE #( ( vehicle_class = {{p}}if_toll_pricer=>c_class-motorcycle cents_per_km = 5 )
( vehicle_class = {{p}}if_toll_pricer=>c_class-car cents_per_km = 10 )
( vehicle_class = {{p}}if_toll_pricer=>c_class-van cents_per_km = 18 )
( vehicle_class = {{p}}if_toll_pricer=>c_class-lorry cents_per_km = 30 ) ).
ENDMETHOD.
METHOD validate.
DATA lv_class TYPE {{p}}if_toll_pricer=>ty_class.
lv_class = to_upper( is_journey-vehicle_class ).
IF NOT line_exists( mt_rate[ vehicle_class = lv_class ] ).
rv_reason = {{p}}if_toll_pricer=>c_reason-vehicle.
ELSEIF is_journey-distance_km < 1 OR is_journey-distance_km > c_max_km.
rv_reason = {{p}}if_toll_pricer=>c_reason-distance.
ELSE.
rv_reason = {{p}}if_toll_pricer=>c_reason-ok.
ENDIF.
ENDMETHOD.
METHOD base_toll.
DATA lv_class TYPE {{p}}if_toll_pricer=>ty_class.
lv_class = to_upper( is_journey-vehicle_class ).
DATA(lv_rate) = mt_rate[ vehicle_class = lv_class ]-cents_per_km.
rv_amount = is_journey-distance_km * lv_rate.
IF rv_amount < c_min_toll.
rv_amount = c_min_toll.
ENDIF.
ENDMETHOD.
METHOD apply_discount.
rv_amount = iv_amount.
IF iv_has_transponder = abap_true.
rv_amount = iv_amount - iv_amount DIV c_discount.
ENDIF.
ENDMETHOD.
METHOD apply_night_surcharge.
DATA lv_class TYPE {{p}}if_toll_pricer=>ty_class.
lv_class = to_upper( is_journey-vehicle_class ).
rv_amount = iv_amount.
IF is_journey-at_night = abap_true AND lv_class = {{p}}if_toll_pricer=>c_class-lorry.
rv_amount = iv_amount + iv_amount DIV c_night_div.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,56 @@
CLASS ltc_toll_pricer DEFINITION FINAL FOR TESTING
DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
DATA mo_cut TYPE REF TO {{p}}if_toll_pricer.
METHODS setup.
METHODS car_toll FOR TESTING.
METHODS minimum_toll FOR TESTING.
METHODS transponder_discount FOR TESTING.
METHODS night_lorry FOR TESTING.
METHODS unknown_class FOR TESTING.
METHODS distance_out_of_range FOR TESTING.
ENDCLASS.
CLASS ltc_toll_pricer IMPLEMENTATION.
METHOD setup.
mo_cut = NEW {{p}}toll_pricer( ).
ENDMETHOD.
METHOD car_toll.
DATA(ls_result) = mo_cut->price_journey( VALUE #( vehicle_class = 'C' distance_km = 50 ) ).
cl_abap_unit_assert=>assert_equals( exp = 500 act = ls_result-amount_cents ).
ENDMETHOD.
METHOD minimum_toll.
DATA(ls_result) = mo_cut->price_journey( VALUE #( vehicle_class = 'M' distance_km = 5 ) ).
cl_abap_unit_assert=>assert_equals( exp = 100 act = ls_result-amount_cents ).
ENDMETHOD.
METHOD transponder_discount.
DATA(ls_result) = mo_cut->price_journey( VALUE #( vehicle_class = 'C'
distance_km = 100
has_transponder = abap_true ) ).
cl_abap_unit_assert=>assert_equals( exp = 900 act = ls_result-amount_cents ).
ENDMETHOD.
METHOD night_lorry.
DATA(ls_result) = mo_cut->price_journey( VALUE #( vehicle_class = 'L'
distance_km = 100
at_night = abap_true ) ).
cl_abap_unit_assert=>assert_equals( exp = 3750 act = ls_result-amount_cents ).
ENDMETHOD.
METHOD unknown_class.
DATA(ls_result) = mo_cut->price_journey( VALUE #( vehicle_class = 'X' distance_km = 50 ) ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}if_toll_pricer=>c_reason-vehicle
act = ls_result-reason ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = ls_result-amount_cents ).
ENDMETHOD.
METHOD distance_out_of_range.
DATA(ls_result) = mo_cut->price_journey( VALUE #( vehicle_class = 'C' distance_km = 131 ) ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}if_toll_pricer=>c_reason-distance
act = ls_result-reason ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,38 @@
INTERFACE {{p}}if_toll_pricer PUBLIC.
TYPES ty_class TYPE c LENGTH 1.
TYPES ty_reason TYPE c LENGTH 10.
TYPES ty_cents TYPE i.
TYPES:
BEGIN OF ty_journey,
vehicle_class TYPE ty_class,
distance_km TYPE i,
has_transponder TYPE abap_bool,
at_night TYPE abap_bool,
END OF ty_journey.
TYPES:
BEGIN OF ty_result,
reason TYPE ty_reason,
amount_cents TYPE ty_cents,
END OF ty_result.
CONSTANTS:
BEGIN OF c_class,
motorcycle TYPE ty_class VALUE 'M',
car TYPE ty_class VALUE 'C',
van TYPE ty_class VALUE 'V',
lorry TYPE ty_class VALUE 'L',
END OF c_class.
CONSTANTS:
BEGIN OF c_reason,
ok TYPE ty_reason VALUE 'OK',
vehicle TYPE ty_reason VALUE 'VEHICLE',
distance TYPE ty_reason VALUE 'DISTANCE',
END OF c_reason.
METHODS price_journey
IMPORTING is_journey TYPE ty_journey
RETURNING VALUE(rs_result) TYPE ty_result.
ENDINTERFACE.

View File

@@ -0,0 +1,49 @@
# 1. Goal
Calculate the toll that a vehicle pays for one journey on a toll road. A billing
program calls the calculation for each journey. The program needs the toll in
cents and one reason code for each journey.
# 2. Open questions
None.
# 3. Context
- The interface {{P}}IF_TOLL_PRICER exists in package $TMP. It is active.
- The interface contains the type TY_JOURNEY for the input, the type TY_RESULT
for the output, the constant structure C_CLASS with the vehicle classes, the
constant structure C_REASON with the reason codes, and one method:
PRICE_JOURNEY IMPORTING is_journey TYPE ty_journey
RETURNING VALUE(rs_result) TYPE ty_result.
# 4. Contract
- Create the class {{P}}TOLL_PRICER in package $TMP.
- The class is public, final and has a public constructor without parameters.
- The class implements {{P}}IF_TOLL_PRICER.
- Do not add other public methods.
# 5. Business rules
Apply the rules in this sequence. All amounts are in cents. Use integer
arithmetic and discard remainders.
1. Convert the vehicle class to upper case. The valid classes are M
(motorcycle), C (car), V (van) and L (lorry). If the class is not valid,
return the reason VEHICLE and the amount 0.
2. The distance must be 1 kilometre or more and 130 kilometres or less. If not,
return the reason DISTANCE and the amount 0.
3. The rate for each kilometre is 5 cents for M, 10 cents for C, 18 cents for V
and 30 cents for L. The toll is the distance multiplied by the rate.
4. If the toll is below 100 cents, set the toll to 100 cents.
5. If the vehicle has a transponder, subtract one tenth of the toll from the
toll. Example: a toll of 1000 cents becomes 900 cents.
6. If the journey is at night and the vehicle class is L, add one quarter of the
toll to the toll. Example: a toll of 3000 cents becomes 3750 cents.
7. Return the reason OK and the toll in the component amount_cents.
# 6. Constraints
- Release target: 8.16 (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 change {{P}}IF_TOLL_PRICER.
# 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,51 @@
{
"id": "G1063",
"category": "A",
"object_type": "CLAS",
"difficulty": 2,
"release_target": "v816",
"expected_outcome": "implement",
"budget": {
"max_tool_calls": 60,
"max_activations": 15
},
"seed": [
{
"type": "INTF",
"name": "{{P}}IF_TOLL_PRICER",
"file": "seed/if_toll_pricer.intf.abap",
"description": "Toll pricing contract: input type, result type, vehicle classes, reason codes and the method"
}
],
"contract": [
{
"type": "CLAS",
"name": "{{P}}TOLL_PRICER",
"implements": "{{P}}IF_TOLL_PRICER"
}
],
"out_of_scope": [
"{{P}}IF_TOLL_PRICER"
],
"hidden_tests": [
{
"type": "CLAS",
"name": "{{P}}T02_HIDDEN",
"file": "hidden/t02_hidden.clas.abap",
"description": "T02 hidden tests for the toll calculation"
}
],
"reference": [
{
"type": "CLAS",
"name": "{{P}}TOLL_PRICER",
"file": "reference/toll_pricer.clas.abap",
"description": "Toll calculation for one journey",
"testclasses_file": "reference/toll_pricer.testclasses.abap"
}
],
"craft_checks": [
"method_length",
"nesting_depth"
]
}