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,34 @@
{
"id": "G1047",
"pool": "train",
"object_type": "CLAS",
"category": "H",
"attempts": [
{
"stage": "bundle",
"errors": [
"seed/grv_ord.tabl.abap: a table needs the annotation @AbapCatalog.tableCategory (for example #TRANSPARENT, #A)",
"seed/grv_ord.tabl.abap: a table needs the annotation @AbapCatalog.deliveryClass (for example #TRANSPARENT, #A)"
],
"by_check": {
"static": 2
}
},
{
"stage": "validate",
"oracle": null,
"null": null
},
{
"stage": "validate",
"oracle": null,
"null": null
},
{
"stage": "validate",
"oracle": null,
"null": null
}
],
"accepted": false
}

View File

@@ -0,0 +1,98 @@
CLASS {{p}}gravel_pricer DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_order_id TYPE c LENGTH 10.
TYPES ty_grade TYPE c LENGTH 1.
TYPES ty_tonnes TYPE i.
TYPES ty_amount TYPE p LENGTH 8 DECIMALS 2.
TYPES ty_reason TYPE c LENGTH 10.
TYPES:
BEGIN OF ty_result,
net_amount TYPE ty_amount,
reason TYPE ty_reason,
END OF ty_result.
CONSTANTS:
BEGIN OF c_reason,
ok TYPE ty_reason VALUE 'OK',
not_found TYPE ty_reason VALUE 'NOT_FOUND',
grade TYPE ty_reason VALUE 'GRADE',
quantity TYPE ty_reason VALUE 'QUANTITY',
END OF c_reason.
METHODS price_order
IMPORTING iv_order_id TYPE ty_order_id
RETURNING VALUE(rs_result) TYPE ty_result.
PRIVATE SECTION.
TYPES ty_work TYPE p LENGTH 15 DECIMALS 2.
TYPES:
BEGIN OF ty_order,
order_id TYPE ty_order_id,
grade TYPE ty_grade,
tonnes TYPE ty_tonnes,
END OF ty_order.
METHODS read_order
IMPORTING iv_order_id TYPE ty_order_id
RETURNING VALUE(rs_order) TYPE ty_order.
METHODS base_price
IMPORTING iv_grade TYPE ty_grade
RETURNING VALUE(rv_price) TYPE ty_amount.
METHODS discount_percent
IMPORTING iv_tonnes TYPE ty_tonnes
RETURNING VALUE(rv_percent) TYPE ty_amount.
ENDCLASS.
CLASS {{p}}gravel_pricer IMPLEMENTATION.
METHOD price_order.
DATA(ls_order) = read_order( iv_order_id ).
IF ls_order-order_id IS INITIAL.
rs_result-reason = c_reason-not_found.
RETURN.
ENDIF.
DATA(lv_price) = base_price( ls_order-grade ).
IF lv_price IS INITIAL.
rs_result-reason = c_reason-grade.
RETURN.
ENDIF.
IF ls_order-tonnes <= 0.
rs_result-reason = c_reason-quantity.
RETURN.
ENDIF.
DATA(lv_gross) = CONV ty_work( lv_price ) * CONV ty_work( ls_order-tonnes ).
DATA(lv_factor) = CONV ty_work( 100 ) - discount_percent( ls_order-tonnes ).
DATA(lv_net) = lv_gross * lv_factor / 100.
rs_result-net_amount = round( val = lv_net dec = 2 ).
rs_result-reason = c_reason-ok.
ENDMETHOD.
METHOD read_order.
SELECT SINGLE order_id, grade, tonnes
FROM {{p}}grv_ord
WHERE order_id = @iv_order_id
INTO @rs_order.
ENDMETHOD.
METHOD base_price.
CASE iv_grade.
WHEN 'F'.
rv_price = '42.00'.
WHEN 'M'.
rv_price = '36.00'.
WHEN 'C'.
rv_price = '30.00'.
ENDCASE.
ENDMETHOD.
METHOD discount_percent.
IF iv_tonnes >= 20.
rv_percent = '10.00'.
ELSEIF iv_tonnes >= 5.
rv_percent = '5.00'.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,103 @@
CLASS ltc_gravel_pricer DEFINITION FINAL FOR TESTING
DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
CLASS-DATA mo_env TYPE REF TO if_osql_test_environment.
DATA mo_cut TYPE REF TO {{p}}gravel_pricer.
CLASS-METHODS class_setup.
CLASS-METHODS class_teardown.
METHODS setup.
METHODS small_order_ok FOR TESTING.
METHODS medium_order_discount FOR TESTING.
METHODS bulk_order_discount FOR TESTING.
METHODS five_tonnes_discount FOR TESTING.
METHODS unknown_order FOR TESTING.
METHODS unknown_grade FOR TESTING.
METHODS zero_quantity FOR TESTING.
ENDCLASS.
CLASS ltc_gravel_pricer IMPLEMENTATION.
METHOD class_setup.
mo_env = cl_osql_test_environment=>create( VALUE #( ( '{{P}}GRV_ORD' ) ) ).
DATA lt_order TYPE STANDARD TABLE OF {{p}}grv_ord WITH EMPTY KEY.
lt_order = VALUE #(
( order_id = 'ORD0000001' grade = 'F' tonnes = 3 customer = 'BuildIt Ltd' )
( order_id = 'ORD0000002' grade = 'M' tonnes = 12 customer = 'Roadworks AG' )
( order_id = 'ORD0000003' grade = 'C' tonnes = 25 customer = 'City Council' )
( order_id = 'ORD0000004' grade = 'F' tonnes = 5 customer = 'Stone and Co' )
( order_id = 'ORD0000005' grade = 'X' tonnes = 7 customer = 'Bad Data Ltd' )
( order_id = 'ORD0000006' grade = 'M' tonnes = 0 customer = 'Zero Ltd' ) ).
mo_env->insert_test_data( lt_order ).
ENDMETHOD.
METHOD class_teardown.
mo_env->destroy( ).
ENDMETHOD.
METHOD setup.
mo_cut = NEW {{p}}gravel_pricer( ).
ENDMETHOD.
METHOD small_order_ok.
DATA(ls_result) = mo_cut->price_order( 'ORD0000001' ).
cl_abap_unit_assert=>assert_equals(
exp = CONV {{p}}gravel_pricer=>ty_amount( '126.00' )
act = ls_result-net_amount ).
cl_abap_unit_assert=>assert_equals(
exp = {{p}}gravel_pricer=>c_reason-ok
act = ls_result-reason ).
ENDMETHOD.
METHOD medium_order_discount.
DATA(ls_result) = mo_cut->price_order( 'ORD0000002' ).
cl_abap_unit_assert=>assert_equals(
exp = CONV {{p}}gravel_pricer=>ty_amount( '410.40' )
act = ls_result-net_amount ).
cl_abap_unit_assert=>assert_equals(
exp = {{p}}gravel_pricer=>c_reason-ok
act = ls_result-reason ).
ENDMETHOD.
METHOD bulk_order_discount.
DATA(ls_result) = mo_cut->price_order( 'ORD0000003' ).
cl_abap_unit_assert=>assert_equals(
exp = CONV {{p}}gravel_pricer=>ty_amount( '675.00' )
act = ls_result-net_amount ).
cl_abap_unit_assert=>assert_equals(
exp = {{p}}gravel_pricer=>c_reason-ok
act = ls_result-reason ).
ENDMETHOD.
METHOD five_tonnes_discount.
DATA(ls_result) = mo_cut->price_order( 'ORD0000004' ).
cl_abap_unit_assert=>assert_equals(
exp = CONV {{p}}gravel_pricer=>ty_amount( '199.50' )
act = ls_result-net_amount ).
cl_abap_unit_assert=>assert_equals(
exp = {{p}}gravel_pricer=>c_reason-ok
act = ls_result-reason ).
ENDMETHOD.
METHOD unknown_order.
DATA(ls_result) = mo_cut->price_order( 'ORD9999999' ).
cl_abap_unit_assert=>assert_equals(
exp = {{p}}gravel_pricer=>c_reason-not_found
act = ls_result-reason ).
ENDMETHOD.
METHOD unknown_grade.
DATA(ls_result) = mo_cut->price_order( 'ORD0000005' ).
cl_abap_unit_assert=>assert_equals(
exp = {{p}}gravel_pricer=>c_reason-grade
act = ls_result-reason ).
ENDMETHOD.
METHOD zero_quantity.
DATA(ls_result) = mo_cut->price_order( 'ORD0000006' ).
cl_abap_unit_assert=>assert_equals(
exp = {{p}}gravel_pricer=>c_reason-quantity
act = ls_result-reason ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,9 @@
@EndUserText.label : 'Gravel orders'
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
define table {{p}}grv_ord {
key order_id : abap.char(10);
grade : abap.char(1);
tonnes : abap.int4;
customer : abap.char(30);
}

View File

@@ -0,0 +1,19 @@
CLASS {{p}}seed_grv DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
ENDCLASS.
CLASS {{p}}seed_grv IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
DATA lt_order TYPE STANDARD TABLE OF {{p}}grv_ord WITH EMPTY KEY.
lt_order = VALUE #(
( order_id = 'ORD0000001' grade = 'F' tonnes = 3 customer = 'BuildIt Ltd' )
( order_id = 'ORD0000002' grade = 'M' tonnes = 12 customer = 'Roadworks AG' )
( order_id = 'ORD0000003' grade = 'C' tonnes = 25 customer = 'City Council' )
( order_id = 'ORD0000004' grade = 'F' tonnes = 5 customer = 'Stone and Co' ) ).
DELETE FROM {{p}}grv_ord.
INSERT {{p}}grv_ord FROM TABLE @lt_order.
out->write( |{ sy-dbcnt } orders inserted| ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,63 @@
# 1. Goal
A quarry sells gravel to building companies. A sales program calls the price
calculation for each order. Calculate the net amount of one gravel order.
# 2. Open questions
None.
# 3. Context
- The table {{P}}GRV_ORD exists in package $TMP. It contains the gravel orders.
The columns are:
- ORDER_ID (CHAR 10): the order number.
- GRADE (CHAR 1): the gravel grade.
- TONNES (INT4): the order quantity in whole tonnes.
- CUSTOMER (CHAR 30): the name of the customer.
- The seed class {{P}}SEED_GRV fills the table with test data.
# 4. Contract
- Create the class {{P}}GRAVEL_PRICER in package $TMP.
- The class is public, final, and has a public constructor without parameters.
- Define these public types:
- TY_ORDER_ID TYPE c LENGTH 10.
- TY_GRADE TYPE c LENGTH 1.
- TY_TONNES TYPE i.
- TY_AMOUNT TYPE p LENGTH 8 DECIMALS 2.
- TY_REASON TYPE c LENGTH 10.
- TY_RESULT: a structure with the components NET_AMOUNT (TYPE ty_amount) and
REASON (TYPE ty_reason).
- Define the public constant structure C_REASON with these components of type
TY_REASON: OK, NOT_FOUND, GRADE, QUANTITY.
- Define one public method:
PRICE_ORDER
IMPORTING iv_order_id TYPE ty_order_id
RETURNING VALUE(rs_result) TYPE ty_result.
- Do not add other public methods.
# 5. Business rules
Apply the rules in this sequence. Return the reason of the first rule that fails.
1. Read the order with the number iv_order_id from the table {{P}}GRV_ORD. If
the table has no order with this number, return NOT_FOUND.
2. The grade must be F (fine), M (medium) or C (coarse). If the grade is not
one of these three letters, return GRADE.
3. The quantity must be greater than zero. If the quantity is zero or negative,
return QUANTITY.
4. The base price of one tonne is 42.00 EUR for grade F, 36.00 EUR for grade M
and 30.00 EUR for grade C.
5. The discount depends on the order quantity:
- An order of up to 4 tonnes gets no discount.
- An order of 6 to 19 tonnes gets a discount of 5 percent.
- An order of 20 tonnes or more gets a discount of 10 percent.
6. The net amount is the base price multiplied by the quantity, less the
discount. Round the net amount to 2 decimals. Return OK.
# 6. Constraints
- Release target: 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 the table {{P}}GRV_ORD and the seed class
{{P}}SEED_GRV.
# 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,68 @@
{
"id": "G1047",
"category": "H",
"object_type": "CLAS",
"difficulty": 2,
"release_target": "v816",
"expected_outcome": "stop",
"expected_gap": {
"description": "The business rules do not state the discount for an order of exactly 5 tonnes, so the net amount of such an order cannot be calculated.",
"keywords": [
[
"discount",
"tonnes"
],
[
"5",
"tonnes"
],
[
"5",
"discount"
]
]
},
"budget": {
"max_tool_calls": 60,
"max_activations": 15
},
"seed": [
{
"type": "TABL",
"name": "{{P}}GRV_ORD",
"file": "seed/grv_ord.tabl.abap",
"description": "Gravel orders of the quarry"
},
{
"type": "CLAS",
"name": "{{P}}SEED_GRV",
"file": "seed/seed_grv.clas.abap",
"description": "Fills the gravel order table with test data",
"run": true
}
],
"contract": [
{
"type": "CLAS",
"name": "{{P}}GRAVEL_PRICER"
}
],
"out_of_scope": [
"{{P}}GRV_ORD",
"{{P}}SEED_GRV"
],
"hidden_tests": [],
"reference": [
{
"type": "CLAS",
"name": "{{P}}GRAVEL_PRICER",
"file": "reference/gravel_pricer.clas.abap",
"description": "Calculates the net amount of one gravel order",
"testclasses_file": "reference/gravel_pricer.testclasses.abap"
}
],
"craft_checks": [
"method_length",
"db_operation_in_loop"
]
}