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:
@@ -132,6 +132,8 @@ Bitti sayılır: tek baz model seçildi, gerekçesi yazıldı.
|
||||
|
||||
Durum (2026-10-05): 3.1 eğitim modu hazır (`harness/trainset.py`, havuz `tasks_gen/train`, eval ile çakışma kontrolü `harness/overlap.py`, 30 hata-odaklı görev dahil), üretim 12:00'de başladı (hedef 200 kabul, ~10 $ usage). 3.2 için proxy (yerel abaplint ile "save failed" ayrıntısı), yörünge kaydı (`harness/record.py`), Qwen çevirici (`train/to_qwen.py`) ve kabul süzgeci (`train/accept.py`) hazır; yörünge koşuları (`harness/trajectories.py`, 6 worker) üretim bitince.
|
||||
|
||||
<!-- stage2-summaries -->
|
||||
|
||||
| Alt adım | İş |
|
||||
|---|---|
|
||||
| 3.1 | Görev üreteci: eval görevleriyle aynı şemada binlerce sentetik görev. Eval görevleriyle çakışma yok. Girdilerin bir kısmı serbest metin; yörüngelerin az bir kısmı farklı tool isim/şemalarıyla. |
|
||||
|
||||
@@ -35,7 +35,8 @@ def spent(since=None):
|
||||
|
||||
|
||||
def check_budget():
|
||||
limit = float(os.environ.get("BUDGET_LIMIT_USD", "45"))
|
||||
# BUDGET_RESERVE_USD: ledger USD kept back (second teacher test later); the guard stops at limit - reserve
|
||||
limit = float(os.environ.get("BUDGET_LIMIT_USD", "45")) - float(os.environ.get("BUDGET_RESERVE_USD", "0"))
|
||||
s = spent()
|
||||
if s >= limit:
|
||||
raise BudgetExceeded(f"cycle spend {s} USD >= limit {limit} USD")
|
||||
|
||||
353
harness/pipeline.py
Normal file
353
harness/pipeline.py
Normal file
@@ -0,0 +1,353 @@
|
||||
"""Stage 2 pipeline controller (rules of 2026-10-05, Opus 5.5 + Kral).
|
||||
|
||||
Runs in the background; nobody polls it. It
|
||||
- starts plan 2 generation (3 workers, hard and error share raised, no fixed target) when the first plan has
|
||||
ended, until --gen-deadline or the budget guard; adds K (free-text) variants at about 10 % of the other tasks;
|
||||
- runs trajectories with 2 workers (1 after any A4H error), at most 2 attempts per task: a second attempt only
|
||||
when the first one failed or was accepted without a repair;
|
||||
- writes a summary to train/STATE.md and docs/yol-haritasi.md every 50 accepted trajectories, and commits;
|
||||
- stops and reports (runs/pipeline/STOPPED.txt, STOP flag for the generators) when: acceptance over the last
|
||||
30 runs is below 50 %, one harness error pattern appears 3 times, the budget guard stops, or the deadline.
|
||||
|
||||
python3 -m harness.pipeline [--wait-pid PID] [--workers 2] [--gen-deadline 2026-10-10T18:00]
|
||||
[--traj-deadline 2026-10-11T23:30]
|
||||
Budget: BUDGET_LIMIT_USD and BUDGET_RESERVE_USD in .env (the reserve stays for a second teacher test).
|
||||
"""
|
||||
import argparse
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import statistics
|
||||
import subprocess
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
|
||||
from .adt_client import load_env
|
||||
from . import trainset, trajectories
|
||||
from .ledger import spent
|
||||
|
||||
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
sys.path.insert(0, os.path.join(ROOT, "train"))
|
||||
import accept as acc # noqa: E402 (train/accept.py)
|
||||
|
||||
OUT = trajectories.OUT
|
||||
PIPE = os.path.join(ROOT, "runs", "pipeline")
|
||||
BASE_LEDGER = 66.9665 # ledger when Part B started (2026-10-05 morning)
|
||||
LEDGER_TO_USAGE = 2.7
|
||||
ALLOWANCE_USAGE = 35.0 # until 11 October, without asking (Kral)
|
||||
MARKER = "<!-- stage2-summaries -->"
|
||||
GIT_ENV = dict(os.environ, GIT_AUTHOR_NAME="Kral", GIT_AUTHOR_EMAIL="kral@local",
|
||||
GIT_COMMITTER_NAME="Kral", GIT_COMMITTER_EMAIL="kral@local")
|
||||
HARNESS_MATCH = acc.HARNESS_ERRORS
|
||||
|
||||
|
||||
def log(*a):
|
||||
print(time.strftime("%F %T"), *a, flush=True)
|
||||
|
||||
|
||||
def ts(text):
|
||||
return time.mktime(time.strptime(text, "%Y-%m-%dT%H:%M"))
|
||||
|
||||
|
||||
class Pipeline:
|
||||
def __init__(self, a):
|
||||
self.a = a
|
||||
self.lock = threading.Lock()
|
||||
self.stop = threading.Event()
|
||||
self.reason = None
|
||||
self.max_workers = a.workers
|
||||
self.inflight = set()
|
||||
self.cache = {} # run_dir -> evaluation
|
||||
self.events = {} # harness error key -> count
|
||||
self.task_meta = {}
|
||||
self.gen_deadline, self.traj_deadline = ts(a.gen_deadline), ts(a.traj_deadline)
|
||||
self.children = []
|
||||
rows = self.rows()
|
||||
for r in rows:
|
||||
self.evaluate(r)
|
||||
self.milestone = self.accepted_total() // 50
|
||||
|
||||
# ---- data -----------------------------------------------------------------------------------------------
|
||||
def rows(self):
|
||||
p = os.path.join(OUT, "summary.jsonl")
|
||||
return [json.loads(l) for l in open(p)] if os.path.exists(p) else []
|
||||
|
||||
def meta(self, task_id):
|
||||
if task_id not in self.task_meta:
|
||||
try:
|
||||
t = json.load(open(os.path.join(trajectories.POOL, task_id, "task.json")))
|
||||
except OSError:
|
||||
t = {}
|
||||
self.task_meta[task_id] = {"category": t.get("category"), "object_type": t.get("object_type")}
|
||||
return self.task_meta[task_id]
|
||||
|
||||
def evaluate(self, row):
|
||||
"""{accepted, repair, reasons, event_keys, hints, tokens-free} of one summary row (cached)."""
|
||||
key = row.get("run_dir") or f"{row['task']}_{row['attempt']}"
|
||||
if key in self.cache:
|
||||
return self.cache[key]
|
||||
ev = {"task": row["task"], "attempt": row["attempt"], "accepted": False, "repair": False,
|
||||
"reasons": [], "events": [], "hints": 0}
|
||||
path = os.path.join(OUT, row.get("run_dir") or "-", "record.json")
|
||||
if row.get("harness_error"):
|
||||
ev["reasons"].append("harness_error")
|
||||
ev["events"].append("harness:" + str(row.get("error"))[:60])
|
||||
if row.get("setup_failed"):
|
||||
ev["reasons"].append("setup_failed")
|
||||
ev["events"].append("setup_failed")
|
||||
if os.path.exists(path):
|
||||
rec = json.load(open(path))
|
||||
ok, why = acc.judge(rec, row, self.a.min_score)
|
||||
ev["accepted"], ev["reasons"] = ok, why or ev["reasons"]
|
||||
ev["hints"] = rec["metadata"].get("syntax_hints") or 0
|
||||
if ok:
|
||||
ev["repair"] = acc.has_repair(acc.trim_loops(rec["messages"])[0])
|
||||
for r in rec["tool_results_raw"]:
|
||||
m = HARNESS_MATCH.search(r.get("result") or "")
|
||||
if m and not r.get("tool", "").startswith("sap_run_unit"):
|
||||
ev["events"].append("text:" + m.group(0)[:40])
|
||||
break
|
||||
if row.get("teardown_ok") is False:
|
||||
ev["events"].append("teardown")
|
||||
elif not ev["reasons"]:
|
||||
ev["reasons"].append("no_record")
|
||||
self.cache[key] = ev
|
||||
return ev
|
||||
|
||||
def evaluated(self):
|
||||
return [self.evaluate(r) for r in self.rows()]
|
||||
|
||||
def accepted_total(self):
|
||||
return sum(e["accepted"] for e in self.evaluated())
|
||||
|
||||
# ---- jobs -----------------------------------------------------------------------------------------------
|
||||
def next_job(self):
|
||||
with self.lock:
|
||||
rows = self.rows()
|
||||
done = {(r["task"], r["attempt"]) for r in rows}
|
||||
ev0 = {r["task"]: self.evaluate(r) for r in rows if r["attempt"] == 0}
|
||||
tasks = trajectories.accepted_tasks()
|
||||
for t in tasks: # first attempt for every task first
|
||||
if (t, 0) not in done and (t, 0) not in self.inflight:
|
||||
self.inflight.add((t, 0))
|
||||
return t, 0
|
||||
for t in tasks: # second attempt: first failed, or accepted without a repair
|
||||
e = ev0.get(t)
|
||||
if e and (t, 1) not in done and (t, 1) not in self.inflight and (not e["accepted"] or not e["repair"]):
|
||||
self.inflight.add((t, 1))
|
||||
return t, 1
|
||||
return None
|
||||
|
||||
def worker(self, i):
|
||||
while not self.stop.is_set():
|
||||
if time.time() > self.traj_deadline:
|
||||
self.halt("trajectory deadline reached")
|
||||
return
|
||||
if i >= self.max_workers:
|
||||
time.sleep(30)
|
||||
continue
|
||||
job = self.next_job()
|
||||
if not job:
|
||||
if self.generation_alive() or self.inflight:
|
||||
time.sleep(60)
|
||||
continue
|
||||
self.halt("no job left and generation ended")
|
||||
return
|
||||
trajectories.one(job[0], job[1], self.stop)
|
||||
with self.lock:
|
||||
self.inflight.discard(job)
|
||||
self.after_run(job)
|
||||
if self.stop.is_set() and not self.reason:
|
||||
self.halt("budget guard stopped a run")
|
||||
|
||||
# ---- rules ----------------------------------------------------------------------------------------------
|
||||
def after_run(self, job):
|
||||
rows = self.rows()
|
||||
row = next((r for r in reversed(rows) if (r["task"], r["attempt"]) == job), None)
|
||||
if row is None:
|
||||
return
|
||||
ev = self.evaluate(row)
|
||||
for k in ev["events"]:
|
||||
self.events[k] = self.events.get(k, 0) + 1
|
||||
log("A4H/harness event:", k, "x", self.events[k], "->", row.get("run_dir"))
|
||||
if self.max_workers > 1:
|
||||
self.max_workers = 1
|
||||
log("harness error seen: trajectory workers 2 -> 1")
|
||||
if self.events[k] >= 3:
|
||||
self.halt(f"harness error pattern repeated 3 times: {k}")
|
||||
evs = self.evaluated()
|
||||
if len(evs) >= 30:
|
||||
rate = sum(e["accepted"] for e in evs[-30:]) / 30
|
||||
if rate < 0.5:
|
||||
self.halt(f"acceptance {rate:.0%} over the last 30 runs (below 50 %)")
|
||||
try:
|
||||
from .ledger import check_budget
|
||||
check_budget()
|
||||
except Exception as e: # noqa: BLE001 BudgetExceeded
|
||||
self.halt(f"budget guard: {e}")
|
||||
total = sum(e["accepted"] for e in evs)
|
||||
while total // 50 > self.milestone and not self.reason:
|
||||
self.milestone += 1
|
||||
self.summary(self.milestone * 50)
|
||||
|
||||
def halt(self, reason):
|
||||
if self.stop.is_set() and self.reason:
|
||||
return
|
||||
self.reason = reason
|
||||
self.stop.set()
|
||||
os.makedirs(PIPE, exist_ok=True)
|
||||
open(trainset.STOP_FLAG, "w").write(reason + "\n") # generators end after their current slot
|
||||
log("STOP:", reason)
|
||||
|
||||
# ---- generation side --------------------------------------------------------------------------------------
|
||||
def generation_alive(self):
|
||||
if self.reason:
|
||||
return False
|
||||
out = subprocess.run(["pgrep", "-f", r"harness\.trainset (run|k)"], capture_output=True, text=True).stdout
|
||||
return bool(out.split()) or time.time() < self.gen_deadline
|
||||
|
||||
def old_generators(self):
|
||||
out = subprocess.run(["pgrep", "-fl", r"harness\.trainset run --part"], capture_output=True, text=True).stdout
|
||||
return [l for l in out.splitlines() if "--plan plan2" not in l]
|
||||
|
||||
def supervisor(self):
|
||||
launched = False
|
||||
k_proc = None
|
||||
crashes = 0
|
||||
while not self.stop.is_set():
|
||||
time.sleep(60)
|
||||
if time.time() > self.gen_deadline or os.path.exists(trainset.STOP_FLAG):
|
||||
continue
|
||||
if not launched and not self.old_generators():
|
||||
trainset.ensure_plan("plan2")
|
||||
dl = self.a.gen_deadline
|
||||
for i in range(3):
|
||||
f = open(os.path.join(ROOT, "runs", "gen_train", f"p2_w{i}.log"), "a")
|
||||
self.children.append(subprocess.Popen(
|
||||
[sys.executable, "-m", "harness.trainset", "run", "--plan", "plan2", "--part", str(i),
|
||||
"--parts", "3", "--deadline", dl], cwd=ROOT, stdout=f, stderr=f))
|
||||
launched = True
|
||||
log("plan 2 generators started (3 workers, deadline", dl + ")")
|
||||
elif launched:
|
||||
for i, c in enumerate(self.children):
|
||||
if c.poll() not in (None, 0) and crashes < 3:
|
||||
crashes += 1
|
||||
log("generator", i, "exited with", c.returncode, "- restarted")
|
||||
f = open(os.path.join(ROOT, "runs", "gen_train", f"p2_w{i}.log"), "a")
|
||||
self.children[i] = subprocess.Popen(
|
||||
[sys.executable, "-m", "harness.trainset", "run", "--plan", "plan2", "--part", str(i),
|
||||
"--parts", "3", "--deadline", self.a.gen_deadline], cwd=ROOT, stdout=f, stderr=f)
|
||||
# K variants: free text, about 10 % of the other accepted training tasks
|
||||
if k_proc is None or k_proc.poll() is not None:
|
||||
logs = [json.load(open(f)) for f in glob.glob(os.path.join(trainset.POOL, "_logs", "G*.json"))]
|
||||
base = sum(1 for l in logs if l.get("accepted") and l.get("category") != "K")
|
||||
have = sum(1 for l in logs if l.get("category") == "K")
|
||||
want = min(99, int(0.1 * base))
|
||||
if want > have:
|
||||
f = open(os.path.join(ROOT, "runs", "gen_train", "k.log"), "a")
|
||||
k_proc = subprocess.Popen([sys.executable, "-m", "harness.trainset", "k", "--k-count", str(want)],
|
||||
cwd=ROOT, stdout=f, stderr=f)
|
||||
|
||||
# ---- summary ----------------------------------------------------------------------------------------------
|
||||
def summary(self, n):
|
||||
log("summary at", n, "accepted trajectories")
|
||||
subprocess.run([sys.executable, "train/accept.py", "--min-score", str(self.a.min_score)], cwd=ROOT,
|
||||
capture_output=True)
|
||||
vp = os.path.join(ROOT, "train", ".venv", "bin", "python")
|
||||
subprocess.run([vp, "train/to_qwen.py", os.path.join(OUT, "accepted.jsonl"), os.path.join(OUT, "qwen.jsonl")],
|
||||
cwd=ROOT, capture_output=True)
|
||||
toks = sorted(json.loads(l)["n_tokens"] for l in open(os.path.join(OUT, "qwen.jsonl")))
|
||||
pct = lambda p: toks[min(len(toks) - 1, int(p * len(toks)))] if toks else None # noqa: E731
|
||||
rows, evs = self.rows(), self.evaluated()
|
||||
logs = [json.load(open(f)) for f in glob.glob(os.path.join(trainset.POOL, "_logs", "G*.json"))]
|
||||
acc_t = sum(1 for l in logs if l.get("accepted"))
|
||||
accepted = [e for e in evs if e["accepted"]]
|
||||
repairs = sum(e["repair"] for e in accepted)
|
||||
|
||||
def table(keyname):
|
||||
agg = {}
|
||||
for e in evs:
|
||||
k = self.meta(e["task"])[keyname] or "?"
|
||||
a = agg.setdefault(k, [0, 0, 0])
|
||||
a[0] += 1
|
||||
a[1] += e["accepted"]
|
||||
a[2] += e["accepted"] and e["repair"]
|
||||
return "; ".join(f"{k} {v[1]}/{v[0]} (repair {v[2]})" for k, v in sorted(agg.items()))
|
||||
s = spent()
|
||||
used = (s - BASE_LEDGER) / LEDGER_TO_USAGE
|
||||
guard = float(os.environ.get("BUDGET_LIMIT_USD", "0")) - float(os.environ.get("BUDGET_RESERVE_USD", "0"))
|
||||
text = f"""### Stage 2 summary at {n} accepted trajectories ({time.strftime('%Y-%m-%d %H:%M')})
|
||||
|
||||
- Tasks: {acc_t} accepted of {len(logs)} generated (K variants {sum(1 for l in logs if l.get('category') == 'K')}); \
|
||||
trajectory runs {len(rows)}, accepted trajectories {len(accepted)} (acceptance {len(accepted) / max(len(rows), 1):.0%}).
|
||||
- Budget: used {used:.1f} usage (ledger {s - BASE_LEDGER:.1f}) since 2026-10-05; left to the guard {(guard - s) / LEDGER_TO_USAGE:.1f} usage \
|
||||
(ledger {guard - s:.1f}; reserve {os.environ.get('BUDGET_RESERVE_USD', '0')} ledger kept); allowance until 11 October {ALLOWANCE_USAGE - used:.1f} usage.
|
||||
- Repair share (accepted trajectories with an error followed by a fix): {repairs}/{len(accepted)} = {repairs / max(len(accepted), 1):.0%}.
|
||||
- By category, accepted/runs: {table('category')}.
|
||||
- By object type, accepted/runs: {table('object_type')}.
|
||||
- Tokens of accepted samples (20 tool schemas kept): p50 {pct(0.5)}, p90 {pct(0.9)}, p95 {pct(0.95)}, max {toks[-1] if toks else None}, n {len(toks)}.
|
||||
- Syntax hints (proxy syntaxCheck added): {sum(e['hints'] for e in evs)} in {sum(1 for e in evs if e['hints'])} runs.
|
||||
- Harness events: {sum(self.events.values())} ({self.events or 'none'}); trajectory workers now {self.max_workers}.
|
||||
"""
|
||||
if getattr(self.a, "dry_summary", False):
|
||||
print(text)
|
||||
return
|
||||
with open(os.path.join(ROOT, "train", "STATE.md"), "a") as f:
|
||||
f.write("\n" + text)
|
||||
p = os.path.join(ROOT, "docs", "yol-haritasi.md")
|
||||
d = open(p).read()
|
||||
d = d.replace(MARKER, MARKER + "\n\n" + text, 1) if MARKER in d else d + "\n" + text
|
||||
open(p, "w").write(d)
|
||||
subprocess.run(["git", "add", "train/STATE.md", "docs/yol-haritasi.md", "tasks_gen/train", "harness", "train"],
|
||||
cwd=ROOT, env=GIT_ENV, capture_output=True)
|
||||
subprocess.run(["git", "commit", "-q", "-m", f"Stage 2 summary at {n} accepted trajectories\n\n"
|
||||
"Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>"],
|
||||
cwd=ROOT, env=GIT_ENV, capture_output=True)
|
||||
|
||||
# ---- main -------------------------------------------------------------------------------------------------
|
||||
def run(self):
|
||||
os.makedirs(PIPE, exist_ok=True)
|
||||
if os.path.exists(trainset.STOP_FLAG):
|
||||
os.remove(trainset.STOP_FLAG)
|
||||
log("pipeline start: workers", self.max_workers, "accepted", self.accepted_total(), "spent", spent())
|
||||
threads = [threading.Thread(target=self.worker, args=(i,)) for i in range(self.a.workers)]
|
||||
threading.Thread(target=self.supervisor, daemon=True).start()
|
||||
for t in threads:
|
||||
t.start()
|
||||
for t in threads:
|
||||
t.join()
|
||||
evs = self.evaluated()
|
||||
text = (f"reason: {self.reason}\ntime: {time.strftime('%F %T')}\nruns: {len(evs)}, accepted "
|
||||
f"{sum(e['accepted'] for e in evs)}\nspent ledger: {spent()}\nevents: {self.events}\n")
|
||||
open(os.path.join(PIPE, "STOPPED.txt"), "w").write(text)
|
||||
log("pipeline ended:", text.replace("\n", " | "))
|
||||
|
||||
|
||||
def main():
|
||||
load_env(os.path.join(ROOT, ".env"))
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--wait-pid", type=int, help="start when this process has ended (the first trajectory batch)")
|
||||
ap.add_argument("--workers", type=int, default=2)
|
||||
ap.add_argument("--min-score", type=float, default=80)
|
||||
ap.add_argument("--gen-deadline", default="2026-10-10T18:00")
|
||||
ap.add_argument("--traj-deadline", default="2026-10-11T23:30")
|
||||
ap.add_argument("--dry-summary", action="store_true", help="print the summary text and exit (no file, no commit)")
|
||||
a = ap.parse_args()
|
||||
if a.dry_summary:
|
||||
Pipeline(a).summary(0)
|
||||
return
|
||||
if a.wait_pid:
|
||||
while True:
|
||||
try:
|
||||
os.kill(a.wait_pid, 0)
|
||||
except OSError:
|
||||
break
|
||||
time.sleep(30)
|
||||
os.makedirs(OUT, exist_ok=True)
|
||||
Pipeline(a).run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -46,13 +46,16 @@ CATEGORY_SHARE = {"A": 10, "B": 15, "C": 15, "D": 10, "E": 15, "F": 10, "G": 10,
|
||||
ERROR_CATEGORY = {"named-type": "A", "reserved-word": "D", "long-names": "C"}
|
||||
|
||||
|
||||
def build_plan():
|
||||
"""Category shares as in the eval plan; object types inside a category as in evalset.SLOTS."""
|
||||
def build_plan(n_slots=N_SLOTS, n_error=N_ERROR, hard_share=0.0, first_id=FIRST_ID, run_base=RUN_BASE):
|
||||
"""Category shares as in the eval plan; object types inside a category as in evalset.SLOTS.
|
||||
n_error slots target the common errors (named-type, reserved-word, long-names); hard_share of the other
|
||||
slots get difficulty 3 (every 10th slot pattern, deterministic)."""
|
||||
share_sum = sum(CATEGORY_SHARE.values())
|
||||
items = []
|
||||
for cat, share in CATEGORY_SHARE.items():
|
||||
k_cat = round(N_SLOTS * share / share_sum)
|
||||
k_err = sum(1 for k in ERROR_CATEGORY if ERROR_CATEGORY[k] == cat) * N_ERROR // 3
|
||||
k_cat = round(n_slots * share / share_sum)
|
||||
per_kind = n_error // 3
|
||||
k_err = sum(1 for k in ERROR_CATEGORY if ERROR_CATEGORY[k] == cat) * per_kind
|
||||
slots = [x for x in SLOTS if x[0] == cat]
|
||||
weight = sum(n for _, _, n, _ in slots)
|
||||
k_rest = k_cat - k_err
|
||||
@@ -69,16 +72,19 @@ def build_plan():
|
||||
for kind, text in ERROR_HINTS:
|
||||
if ERROR_CATEGORY[kind] != cat:
|
||||
continue
|
||||
for i in range(N_ERROR // 3):
|
||||
for i in range(per_kind):
|
||||
t = ERROR_TYPES[i % len(ERROR_TYPES)]
|
||||
pos += 1
|
||||
items.append({"category": cat, "object_type": t, "topic": text, "error_kind": kind,
|
||||
"frac": pos / (k_cat + 1)})
|
||||
items.sort(key=lambda x: (x["frac"], x["category"], x["object_type"])) # interleave: a cut keeps the mix
|
||||
hard_every = round(1 / hard_share) if hard_share else 0
|
||||
for n, it in enumerate(items):
|
||||
it.pop("frac")
|
||||
it["id"] = f"G{FIRST_ID + n:04d}"
|
||||
it["run_base"] = RUN_BASE + 40 * n
|
||||
it["id"] = f"G{first_id + n:04d}"
|
||||
it["run_base"] = run_base + 40 * n
|
||||
if hard_every and it["category"] != "H" and n % hard_every == hard_every // 2:
|
||||
it["difficulty"] = 3
|
||||
return items
|
||||
|
||||
|
||||
@@ -92,12 +98,42 @@ def accepted_count():
|
||||
return n
|
||||
|
||||
|
||||
def run(part, parts, target, stop_ledger):
|
||||
STOP_FLAG = os.path.join(ROOT, "runs", "pipeline", "STOP") # the pipeline writes it: workers end after the current slot
|
||||
BACKLOG_LIMIT = 40 # accepted tasks without a first trajectory run: generation waits above this
|
||||
PLAN2 = {"n_slots": 500, "n_error": 100, "hard_share": 0.3, "first_id": 1400, "run_base": 100000}
|
||||
# plan 2 (2026-10-05, Opus 5.5 rules): error tasks 20 % (plan 1: 13 %, +50 %), hard (difficulty 3) 30 % of the
|
||||
# other slots (plan 1: 20 % assumed from the pilot hard batch), same category shares, ids G1400+, no fixed target
|
||||
|
||||
|
||||
def plan_path(name):
|
||||
return os.path.join(POOL, name + ".json")
|
||||
|
||||
|
||||
def ensure_plan(name, stop_ledger=27.0, target=200):
|
||||
os.makedirs(POOL, exist_ok=True)
|
||||
if not os.path.exists(PLAN):
|
||||
json.dump({"slots": build_plan(), "ledger_at_start": spent(), "stop_ledger": stop_ledger,
|
||||
"target": target, "created": time.strftime("%F %T")}, open(PLAN, "w"), indent=1)
|
||||
plan = json.load(open(PLAN))
|
||||
if not os.path.exists(plan_path(name)):
|
||||
if name == "plan":
|
||||
slots, tgt, stop = build_plan(), target, stop_ledger
|
||||
else:
|
||||
slots, tgt, stop = build_plan(**PLAN2), None, 1e6 # only the budget guard and the deadline stop it
|
||||
json.dump({"slots": slots, "ledger_at_start": spent(), "stop_ledger": stop, "target": tgt,
|
||||
"created": time.strftime("%F %T")}, open(plan_path(name), "w"), indent=1)
|
||||
return json.load(open(plan_path(name)))
|
||||
|
||||
|
||||
def backlog():
|
||||
"""Accepted training tasks that have no first trajectory run yet."""
|
||||
done = set()
|
||||
sp = os.path.join(ROOT, "runs", "traj", "summary.jsonl")
|
||||
if os.path.exists(sp):
|
||||
done = {json.loads(l)["task"] for l in open(sp) if json.loads(l)["attempt"] == 0}
|
||||
acc = {os.path.basename(os.path.dirname(f)) for f in glob.glob(os.path.join(POOL, "G*", "generation.json"))
|
||||
if json.load(open(f)).get("accepted")}
|
||||
return len(acc - done)
|
||||
|
||||
|
||||
def run(part, parts, target, stop_ledger, plan_name="plan", deadline=None):
|
||||
plan = ensure_plan(plan_name, stop_ledger, target)
|
||||
stop_at = plan["ledger_at_start"] + plan["stop_ledger"]
|
||||
base_url = os.environ.get("LLM_BASE_URL", "http://127.0.0.1:11434/v1")
|
||||
evals = overlap.load_pool("eval")
|
||||
@@ -106,7 +142,16 @@ def run(part, parts, target, stop_ledger):
|
||||
continue
|
||||
if os.path.exists(os.path.join(POOL, "_logs", s["id"] + ".json")):
|
||||
continue # done or failed: not tried again (delete the log to retry)
|
||||
if accepted_count() >= plan["target"]:
|
||||
while backlog() > BACKLOG_LIMIT and not os.path.exists(STOP_FLAG) \
|
||||
and not (deadline and time.time() > deadline):
|
||||
time.sleep(120) # trajectories are the slower side: do not generate tasks that wait for days
|
||||
if os.path.exists(STOP_FLAG):
|
||||
print("STOP flag", flush=True)
|
||||
break
|
||||
if deadline and time.time() > deadline:
|
||||
print("DEADLINE", flush=True)
|
||||
break
|
||||
if plan["target"] and accepted_count() >= plan["target"]:
|
||||
print("TARGET reached", flush=True)
|
||||
break
|
||||
if spent() >= stop_at:
|
||||
@@ -124,14 +169,15 @@ def run(part, parts, target, stop_ledger):
|
||||
f"names {sc['name']:.2f}). Choose a different business topic and different object names."
|
||||
for i, sc in hits[:3]]
|
||||
try:
|
||||
log = generate(s["id"], "train", s["object_type"], s["category"], 2, "deepseek-v4.1-flash:cloud",
|
||||
log = generate(s["id"], "train", s["object_type"], s["category"], s.get("difficulty", 2),
|
||||
"deepseek-v4.1-flash:cloud",
|
||||
base_url, s["run_base"], topic, extra_check=extra)
|
||||
except BudgetExceeded as e:
|
||||
print("BUDGET", e, flush=True)
|
||||
break
|
||||
except Exception as e: # noqa: BLE001
|
||||
log = {"id": s["id"], "error": str(e)[:500]}
|
||||
log.update(error_kind=s.get("error_kind"), spent_total=spent())
|
||||
log.update(error_kind=s.get("error_kind"), difficulty=s.get("difficulty", 2), spent_total=spent())
|
||||
os.makedirs(os.path.join(POOL, "_logs"), exist_ok=True)
|
||||
json.dump(log, open(os.path.join(POOL, "_logs", s["id"] + ".json"), "w"), indent=1)
|
||||
stray = os.path.join(POOL, "generation.json") # generate() writes here when no task dir exists
|
||||
@@ -156,7 +202,7 @@ def run_k(count):
|
||||
continue
|
||||
used = {json.load(open(f)).get("base_task") for f in glob.glob(os.path.join(POOL, "_logs", "G13*.json"))}
|
||||
cands = [] # accepted, not K, not H (a stop task has no free-text form), not used yet
|
||||
for f in sorted(glob.glob(os.path.join(POOL, "_logs", "G1[0-2]*.json"))):
|
||||
for f in sorted(glob.glob(os.path.join(POOL, "_logs", "G1*.json"))):
|
||||
lg = json.load(open(f))
|
||||
if lg.get("accepted") and lg.get("category") not in ("H", "K") and lg["id"] not in used:
|
||||
cands.append(lg)
|
||||
@@ -170,8 +216,7 @@ def run_k(count):
|
||||
otype = min(kinds, key=lambda t: done_types.count(t))
|
||||
src = kinds[otype][0]
|
||||
style = K_STYLES_CYCLE[n % 2]
|
||||
if spent() >= json.load(open(PLAN))["ledger_at_start"] + json.load(open(PLAN))["stop_ledger"]:
|
||||
print("PHASE LIMIT", flush=True)
|
||||
if os.path.exists(STOP_FLAG):
|
||||
return
|
||||
try:
|
||||
log = make_k_variant(src["id"], new_id, style, "deepseek-v4.1-flash:cloud", base_url,
|
||||
@@ -195,6 +240,9 @@ def main():
|
||||
ap.add_argument("--part", type=int, default=0)
|
||||
ap.add_argument("--parts", type=int, default=1)
|
||||
ap.add_argument("--target", type=int, default=200)
|
||||
ap.add_argument("--plan", default="plan", help="plan (first 223 slots) or plan2 (hard and error share raised)")
|
||||
ap.add_argument("--deadline", help="YYYY-MM-DDTHH:MM local time: no new slot after it")
|
||||
ap.add_argument("--k-count", type=int, default=K_COUNT)
|
||||
ap.add_argument("--stop-ledger", type=float, default=27.0, help="ledger USD for this phase (10 USD usage = 27)")
|
||||
a = ap.parse_args()
|
||||
if a.cmd == "plan":
|
||||
@@ -204,9 +252,10 @@ def main():
|
||||
print(collections.Counter(x["object_type"] for x in p), collections.Counter(x.get("error_kind") for x in p))
|
||||
return
|
||||
if a.cmd == "k":
|
||||
run_k(K_COUNT)
|
||||
run_k(a.k_count)
|
||||
return
|
||||
run(a.part, a.parts, a.target, a.stop_ledger)
|
||||
dl = time.mktime(time.strptime(a.deadline, "%Y-%m-%dT%H:%M")) if a.deadline else None
|
||||
run(a.part, a.parts, a.target, a.stop_ledger, a.plan, dl)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -24,7 +24,7 @@ from .runner import Runner
|
||||
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
POOL = os.path.join(ROOT, "tasks_gen", "train")
|
||||
OUT = os.path.join(ROOT, "runs", "traj")
|
||||
RUN_BASE = 41000 # 41000 + (task number - 1000) * 3 + attempt; below 36**3 * ... (prefix rule)
|
||||
RUN_BASE = 200000 # 200000 + (task number - 1000) * 3 + attempt (a digit must lead the 4-char base36 run: < 466560)
|
||||
MODEL = "deepseek-v4.1-flash:cloud"
|
||||
LOCK = threading.Lock()
|
||||
|
||||
|
||||
18
tasks_gen/train/G1000/faulty/m0_i_cont_weight.ddls.asddls
Normal file
18
tasks_gen/train/G1000/faulty/m0_i_cont_weight.ddls.asddls
Normal file
@@ -0,0 +1,18 @@
|
||||
@AccessControl.authorizationCheck: #NOT_REQUIRED
|
||||
@EndUserText.label: 'Container weight check'
|
||||
define view entity {{P}}I_CONT_WEIGHT
|
||||
as select from {{p}}cont as cont
|
||||
inner join {{p}}weigh as weigh on weigh.cont_id <> cont.cont_id
|
||||
{
|
||||
key cont.cont_id as cont_id,
|
||||
cont.customer as customer,
|
||||
cont.decl_kg as decl_kg,
|
||||
weigh.meas_kg as meas_kg,
|
||||
cast( abs( weigh.meas_kg - cont.decl_kg ) as abap.dec(15,2) ) as deviation_kg,
|
||||
division( abs( weigh.meas_kg - cont.decl_kg ) * 100, cont.decl_kg, 2 ) as deviation_pct,
|
||||
case
|
||||
when weigh.meas_kg > cont.max_kg then 'HOLD'
|
||||
when division( abs( weigh.meas_kg - cont.decl_kg ) * 100, cont.decl_kg, 2 ) > 5 then 'WARN'
|
||||
else 'LOAD'
|
||||
end as status
|
||||
}
|
||||
18
tasks_gen/train/G1000/faulty/m1_i_cont_weight.ddls.asddls
Normal file
18
tasks_gen/train/G1000/faulty/m1_i_cont_weight.ddls.asddls
Normal file
@@ -0,0 +1,18 @@
|
||||
@AccessControl.authorizationCheck: #NOT_REQUIRED
|
||||
@EndUserText.label: 'Container weight check'
|
||||
define view entity {{P}}I_CONT_WEIGHT
|
||||
as select from {{p}}cont as cont
|
||||
inner join {{p}}weigh as weigh on weigh.cont_id = cont.cont_id
|
||||
{
|
||||
key cont.cont_id as cont_id,
|
||||
cont.customer as customer,
|
||||
cont.decl_kg as decl_kg,
|
||||
weigh.meas_kg as meas_kg,
|
||||
cast( abs( weigh.meas_kg - cont.decl_kg ) as abap.dec(15,2) ) as deviation_kg,
|
||||
division( abs( weigh.meas_kg + cont.decl_kg ) * 100, cont.decl_kg, 2 ) as deviation_pct,
|
||||
case
|
||||
when weigh.meas_kg > cont.max_kg then 'HOLD'
|
||||
when division( abs( weigh.meas_kg - cont.decl_kg ) * 100, cont.decl_kg, 2 ) > 5 then 'WARN'
|
||||
else 'LOAD'
|
||||
end as status
|
||||
}
|
||||
18
tasks_gen/train/G1000/faulty/m2_i_cont_weight.ddls.asddls
Normal file
18
tasks_gen/train/G1000/faulty/m2_i_cont_weight.ddls.asddls
Normal file
@@ -0,0 +1,18 @@
|
||||
@AccessControl.authorizationCheck: #NOT_REQUIRED
|
||||
@EndUserText.label: 'Container weight check'
|
||||
define view entity {{P}}I_CONT_WEIGHT
|
||||
as select from {{p}}cont as cont
|
||||
inner join {{p}}weigh as weigh on weigh.cont_id = cont.cont_id
|
||||
{
|
||||
key cont.cont_id as cont_id,
|
||||
cont.customer as customer,
|
||||
cont.decl_kg as decl_kg,
|
||||
weigh.meas_kg as meas_kg,
|
||||
cast( abs( weigh.meas_kg - cont.decl_kg ) as abap.dec(15,2) ) as deviation_kg,
|
||||
division( abs( weigh.meas_kg - cont.decl_kg ) * 100, cont.decl_kg, 2 ) as deviation_pct,
|
||||
case
|
||||
when weigh.meas_kg <= cont.max_kg then 'HOLD'
|
||||
when division( abs( weigh.meas_kg - cont.decl_kg ) * 100, cont.decl_kg, 2 ) > 5 then 'WARN'
|
||||
else 'LOAD'
|
||||
end as status
|
||||
}
|
||||
18
tasks_gen/train/G1000/faulty/m3_i_cont_weight.ddls.asddls
Normal file
18
tasks_gen/train/G1000/faulty/m3_i_cont_weight.ddls.asddls
Normal file
@@ -0,0 +1,18 @@
|
||||
@AccessControl.authorizationCheck: #NOT_REQUIRED
|
||||
@EndUserText.label: 'Container weight check'
|
||||
define view entity {{P}}I_CONT_WEIGHT
|
||||
as select from {{p}}cont as cont
|
||||
inner join {{p}}weigh as weigh on weigh.cont_id = cont.cont_id
|
||||
{
|
||||
key cont.cont_id as cont_id,
|
||||
cont.customer as customer,
|
||||
cont.decl_kg as decl_kg,
|
||||
weigh.meas_kg as meas_kg,
|
||||
cast( abs( weigh.meas_kg - cont.decl_kg ) as abap.dec(15,2) ) as deviation_kg,
|
||||
division( abs( weigh.meas_kg - cont.decl_kg ) * 100, cont.decl_kg, 2 ) as deviation_pct,
|
||||
case
|
||||
when weigh.meas_kg > cont.max_kg then 'HOLD'
|
||||
when division( abs( weigh.meas_kg - cont.decl_kg ) * 101, cont.decl_kg, 2 ) > 5 then 'WARN'
|
||||
else 'LOAD'
|
||||
end as status
|
||||
}
|
||||
18
tasks_gen/train/G1000/faulty/m4_i_cont_weight.ddls.asddls
Normal file
18
tasks_gen/train/G1000/faulty/m4_i_cont_weight.ddls.asddls
Normal file
@@ -0,0 +1,18 @@
|
||||
@AccessControl.authorizationCheck: #NOT_REQUIRED
|
||||
@EndUserText.label: 'Container weight check'
|
||||
define view entity {{P}}I_CONT_WEIGHT
|
||||
as select from {{p}}cont as cont
|
||||
inner join {{p}}weigh as weigh on weigh.cont_id = cont.cont_id
|
||||
{
|
||||
key cont.cont_id as cont_id,
|
||||
cont.customer as customer,
|
||||
cont.decl_kg as decl_kg,
|
||||
weigh.meas_kg as meas_kg,
|
||||
cast( abs( weigh.meas_kg - cont.decl_kg ) as abap.dec(15,2) ) as deviation_kg,
|
||||
division( abs( weigh.meas_kg - cont.decl_kg ) * 100, cont.decl_kg, 2 ) as deviation_pct,
|
||||
case
|
||||
when weigh.meas_kg > cont.max_kg then 'HOLD'
|
||||
when division( abs( weigh.meas_kg - cont.decl_kg ) * 100, cont.decl_kg, 2 ) > 5 then 'WARN'
|
||||
else 'ZOAD'
|
||||
end as status
|
||||
}
|
||||
19
tasks_gen/train/G1000/generation.json
Normal file
19
tasks_gen/train/G1000/generation.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"id": "G1000",
|
||||
"pool": "train",
|
||||
"object_type": "DDLS",
|
||||
"category": "B",
|
||||
"attempts": [
|
||||
{
|
||||
"stage": "validate",
|
||||
"oracle": 100.0,
|
||||
"null": 0,
|
||||
"mutation": {
|
||||
"valid": 5,
|
||||
"killed": 5,
|
||||
"ok": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"accepted": true
|
||||
}
|
||||
108
tasks_gen/train/G1000/hidden/t20_hidden.clas.abap
Normal file
108
tasks_gen/train/G1000/hidden/t20_hidden.clas.abap
Normal file
@@ -0,0 +1,108 @@
|
||||
CLASS {{p}}t20_hidden DEFINITION PUBLIC FINAL CREATE PUBLIC
|
||||
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
|
||||
PRIVATE SECTION.
|
||||
CLASS-DATA go_env TYPE REF TO if_cds_test_environment.
|
||||
CLASS-METHODS class_setup.
|
||||
CLASS-METHODS class_teardown.
|
||||
METHODS setup.
|
||||
METHODS deviation_below FOR TESTING.
|
||||
METHODS deviation_zero FOR TESTING.
|
||||
METHODS deviation_above FOR TESTING.
|
||||
METHODS percent_rounded FOR TESTING.
|
||||
METHODS status_hold FOR TESTING.
|
||||
METHODS status_warn FOR TESTING.
|
||||
METHODS status_load FOR TESTING.
|
||||
METHODS status_at_five_pct FOR TESTING.
|
||||
METHODS unweighed_hidden FOR TESTING.
|
||||
METHODS customer_shown FOR TESTING.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}t20_hidden IMPLEMENTATION.
|
||||
METHOD class_setup.
|
||||
go_env = cl_cds_test_environment=>create( i_for_entity = '{{P}}I_CONT_WEIGHT' ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD class_teardown.
|
||||
go_env->destroy( ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD setup.
|
||||
DATA lt_cont TYPE STANDARD TABLE OF {{p}}cont WITH EMPTY KEY.
|
||||
DATA lt_weigh TYPE STANDARD TABLE OF {{p}}weigh WITH EMPTY KEY.
|
||||
go_env->clear_doubles( ).
|
||||
lt_cont = VALUE #(
|
||||
( cont_id = 'C1' customer = 'ALPHA' decl_kg = '1000.00' max_kg = '1200.00' )
|
||||
( cont_id = 'C2' customer = 'BETA' decl_kg = '1000.00' max_kg = '1200.00' )
|
||||
( cont_id = 'C3' customer = 'GAMMA' decl_kg = '1000.00' max_kg = '1200.00' )
|
||||
( cont_id = 'C4' customer = 'DELTA' decl_kg = '500.00' max_kg = '600.00' )
|
||||
( cont_id = 'C5' customer = 'EPSILON' decl_kg = '1000.00' max_kg = '1200.00' )
|
||||
( cont_id = 'C6' customer = 'ZETA' decl_kg = '1000.00' max_kg = '1200.00' )
|
||||
( cont_id = 'C7' customer = 'ETA' decl_kg = '800.00' max_kg = '900.00' )
|
||||
( cont_id = 'C8' customer = 'THETA' decl_kg = '300.00' max_kg = '400.00' ) ).
|
||||
lt_weigh = VALUE #(
|
||||
( cont_id = 'C1' meas_kg = '1020.00' )
|
||||
( cont_id = 'C2' meas_kg = '1100.00' )
|
||||
( cont_id = 'C3' meas_kg = '1300.00' )
|
||||
( cont_id = 'C4' meas_kg = '450.00' )
|
||||
( cont_id = 'C5' meas_kg = '950.00' )
|
||||
( cont_id = 'C7' meas_kg = '800.00' )
|
||||
( cont_id = 'C8' meas_kg = '310.00' ) ).
|
||||
go_env->insert_test_data( lt_cont ).
|
||||
go_env->insert_test_data( lt_weigh ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD deviation_below.
|
||||
SELECT SINGLE deviation_kg FROM {{p}}i_cont_weight WHERE cont_id = 'C4' INTO @DATA(lv_dev).
|
||||
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '50.00' )
|
||||
act = CONV decfloat34( lv_dev ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD deviation_zero.
|
||||
SELECT SINGLE deviation_kg FROM {{p}}i_cont_weight WHERE cont_id = 'C7' INTO @DATA(lv_dev).
|
||||
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '0.00' )
|
||||
act = CONV decfloat34( lv_dev ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD deviation_above.
|
||||
SELECT SINGLE deviation_kg FROM {{p}}i_cont_weight WHERE cont_id = 'C1' INTO @DATA(lv_dev).
|
||||
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '20.00' )
|
||||
act = CONV decfloat34( lv_dev ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD percent_rounded.
|
||||
SELECT SINGLE deviation_pct FROM {{p}}i_cont_weight WHERE cont_id = 'C8' INTO @DATA(lv_pct).
|
||||
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '3.33' )
|
||||
act = CONV decfloat34( lv_pct ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD status_hold.
|
||||
SELECT SINGLE status FROM {{p}}i_cont_weight WHERE cont_id = 'C3' INTO @DATA(lv_status).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'HOLD' act = lv_status ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD status_warn.
|
||||
SELECT SINGLE status FROM {{p}}i_cont_weight WHERE cont_id = 'C2' INTO @DATA(lv_status).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'WARN' act = lv_status ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD status_load.
|
||||
SELECT SINGLE status FROM {{p}}i_cont_weight WHERE cont_id = 'C1' INTO @DATA(lv_status).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'LOAD' act = lv_status ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD status_at_five_pct.
|
||||
SELECT SINGLE status FROM {{p}}i_cont_weight WHERE cont_id = 'C5' INTO @DATA(lv_status).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'LOAD' act = lv_status ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD unweighed_hidden.
|
||||
SELECT COUNT(*) FROM {{p}}i_cont_weight INTO @DATA(lv_rows).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 7 act = lv_rows ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD customer_shown.
|
||||
SELECT SINGLE customer FROM {{p}}i_cont_weight WHERE cont_id = 'C4' INTO @DATA(lv_cust).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'DELTA' act = lv_cust ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
65
tasks_gen/train/G1000/mutation.json
Normal file
65
tasks_gen/train/G1000/mutation.json
Normal file
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"task": "G1000",
|
||||
"mutants": [
|
||||
{
|
||||
"object": "{{P}}I_CONT_WEIGHT",
|
||||
"mutant": "line 5: = -> <> (eq)",
|
||||
"status": "killed",
|
||||
"hidden": "2/10",
|
||||
"failed_tests": [
|
||||
"DEVIATION_ABOVE",
|
||||
"DEVIATION_BELOW",
|
||||
"DEVIATION_ZERO",
|
||||
"PERCENT_ROUNDED",
|
||||
"STATUS_HOLD",
|
||||
"STATUS_LOAD",
|
||||
"STATUS_WARN",
|
||||
"UNWEIGHED_HIDDEN"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}I_CONT_WEIGHT",
|
||||
"mutant": "line 12: - -> + (arith)",
|
||||
"status": "killed",
|
||||
"hidden": "9/10",
|
||||
"failed_tests": [
|
||||
"PERCENT_ROUNDED"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}I_CONT_WEIGHT",
|
||||
"mutant": "line 14: > -> <= (rel)",
|
||||
"status": "killed",
|
||||
"hidden": "6/10",
|
||||
"failed_tests": [
|
||||
"STATUS_AT_FIVE_PCT",
|
||||
"STATUS_HOLD",
|
||||
"STATUS_LOAD",
|
||||
"STATUS_WARN"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}I_CONT_WEIGHT",
|
||||
"mutant": "line 15: 100 -> 101 (const)",
|
||||
"status": "killed",
|
||||
"hidden": "9/10",
|
||||
"failed_tests": [
|
||||
"STATUS_AT_FIVE_PCT"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}I_CONT_WEIGHT",
|
||||
"mutant": "line 16: 'LOAD' -> 'ZOAD' (lit)",
|
||||
"status": "killed",
|
||||
"hidden": "8/10",
|
||||
"failed_tests": [
|
||||
"STATUS_AT_FIVE_PCT",
|
||||
"STATUS_LOAD"
|
||||
]
|
||||
}
|
||||
],
|
||||
"valid": 5,
|
||||
"killed": 5,
|
||||
"kill_rate": 1.0,
|
||||
"ok": true
|
||||
}
|
||||
18
tasks_gen/train/G1000/reference/i_cont_weight.ddls.asddls
Normal file
18
tasks_gen/train/G1000/reference/i_cont_weight.ddls.asddls
Normal file
@@ -0,0 +1,18 @@
|
||||
@AccessControl.authorizationCheck: #NOT_REQUIRED
|
||||
@EndUserText.label: 'Container weight check'
|
||||
define view entity {{P}}I_CONT_WEIGHT
|
||||
as select from {{p}}cont as cont
|
||||
inner join {{p}}weigh as weigh on weigh.cont_id = cont.cont_id
|
||||
{
|
||||
key cont.cont_id as cont_id,
|
||||
cont.customer as customer,
|
||||
cont.decl_kg as decl_kg,
|
||||
weigh.meas_kg as meas_kg,
|
||||
cast( abs( weigh.meas_kg - cont.decl_kg ) as abap.dec(15,2) ) as deviation_kg,
|
||||
division( abs( weigh.meas_kg - cont.decl_kg ) * 100, cont.decl_kg, 2 ) as deviation_pct,
|
||||
case
|
||||
when weigh.meas_kg > cont.max_kg then 'HOLD'
|
||||
when division( abs( weigh.meas_kg - cont.decl_kg ) * 100, cont.decl_kg, 2 ) > 5 then 'WARN'
|
||||
else 'LOAD'
|
||||
end as status
|
||||
}
|
||||
53
tasks_gen/train/G1000/reference/t20_test.clas.abap
Normal file
53
tasks_gen/train/G1000/reference/t20_test.clas.abap
Normal file
@@ -0,0 +1,53 @@
|
||||
CLASS {{p}}t20_test DEFINITION PUBLIC FINAL CREATE PUBLIC
|
||||
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
|
||||
PRIVATE SECTION.
|
||||
CLASS-DATA go_env TYPE REF TO if_cds_test_environment.
|
||||
CLASS-METHODS class_setup.
|
||||
CLASS-METHODS class_teardown.
|
||||
METHODS setup.
|
||||
METHODS hold_for_heavy FOR TESTING.
|
||||
METHODS load_for_light FOR TESTING.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}t20_test IMPLEMENTATION.
|
||||
METHOD class_setup.
|
||||
go_env = cl_cds_test_environment=>create( i_for_entity = '{{P}}I_CONT_WEIGHT' ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD class_teardown.
|
||||
go_env->destroy( ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD setup.
|
||||
DATA lt_cont TYPE STANDARD TABLE OF {{p}}cont WITH EMPTY KEY.
|
||||
DATA lt_weigh TYPE STANDARD TABLE OF {{p}}weigh WITH EMPTY KEY.
|
||||
go_env->clear_doubles( ).
|
||||
lt_cont = VALUE #( ( cont_id = 'A' customer = 'CUST_A' decl_kg = '1000.00' max_kg = '1100.00' )
|
||||
( cont_id = 'B' customer = 'CUST_B' decl_kg = '1000.00' max_kg = '1100.00' ) ).
|
||||
lt_weigh = VALUE #( ( cont_id = 'A' meas_kg = '1150.00' )
|
||||
( cont_id = 'B' meas_kg = '1010.00' ) ).
|
||||
go_env->insert_test_data( lt_cont ).
|
||||
go_env->insert_test_data( lt_weigh ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD hold_for_heavy.
|
||||
SELECT SINGLE deviation_kg, deviation_pct, status FROM {{p}}i_cont_weight
|
||||
WHERE cont_id = 'A' INTO @DATA(ls_row).
|
||||
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '150.00' )
|
||||
act = CONV decfloat34( ls_row-deviation_kg ) ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '15.00' )
|
||||
act = CONV decfloat34( ls_row-deviation_pct ) ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'HOLD' act = ls_row-status ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD load_for_light.
|
||||
SELECT SINGLE deviation_kg, deviation_pct, status FROM {{p}}i_cont_weight
|
||||
WHERE cont_id = 'B' INTO @DATA(ls_row).
|
||||
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '10.00' )
|
||||
act = CONV decfloat34( ls_row-deviation_kg ) ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '1.00' )
|
||||
act = CONV decfloat34( ls_row-deviation_pct ) ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'LOAD' act = ls_row-status ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
12
tasks_gen/train/G1000/seed/cont.tabl.asabap
Normal file
12
tasks_gen/train/G1000/seed/cont.tabl.asabap
Normal file
@@ -0,0 +1,12 @@
|
||||
@EndUserText.label : 'Container'
|
||||
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
|
||||
@AbapCatalog.tableCategory : #TRANSPARENT
|
||||
@AbapCatalog.deliveryClass : #A
|
||||
@AbapCatalog.dataMaintenance : #RESTRICTED
|
||||
define table {{p}}cont {
|
||||
key client : abap.clnt not null;
|
||||
key cont_id : abap.char(10) not null;
|
||||
customer : abap.char(10);
|
||||
decl_kg : abap.dec(15,2);
|
||||
max_kg : abap.dec(15,2);
|
||||
}
|
||||
10
tasks_gen/train/G1000/seed/weigh.tabl.asabap
Normal file
10
tasks_gen/train/G1000/seed/weigh.tabl.asabap
Normal file
@@ -0,0 +1,10 @@
|
||||
@EndUserText.label : 'Weighbridge record'
|
||||
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
|
||||
@AbapCatalog.tableCategory : #TRANSPARENT
|
||||
@AbapCatalog.deliveryClass : #A
|
||||
@AbapCatalog.dataMaintenance : #RESTRICTED
|
||||
define table {{p}}weigh {
|
||||
key client : abap.clnt not null;
|
||||
key cont_id : abap.char(10) not null;
|
||||
meas_kg : abap.dec(15,2);
|
||||
}
|
||||
41
tasks_gen/train/G1000/spec.md
Normal file
41
tasks_gen/train/G1000/spec.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# 1. Goal
|
||||
Show the weight check of each container at a container terminal. A report and an
|
||||
OData service will read the check, so the calculation must be in the database,
|
||||
in a CDS view.
|
||||
|
||||
# 2. Open questions
|
||||
None.
|
||||
|
||||
# 3. Context
|
||||
- Table {{P}}CONT (container master), package $TMP. Key: CONT_ID (CHAR 10).
|
||||
Fields: CUSTOMER (CHAR 10), DECL_KG (DEC 15,2, declared weight in kilograms),
|
||||
MAX_KG (DEC 15,2, maximum permitted weight in kilograms).
|
||||
- Table {{P}}WEIGH (weighbridge record), package $TMP. Key: CONT_ID (CHAR 10).
|
||||
Field: MEAS_KG (DEC 15,2, measured weight in kilograms).
|
||||
|
||||
# 4. Contract
|
||||
- Create the CDS view entity {{P}}I_CONT_WEIGHT in package $TMP.
|
||||
- Elements, with these names: CONT_ID (key), CUSTOMER, DECL_KG, MEAS_KG,
|
||||
DEVIATION_KG, DEVIATION_PCT, STATUS.
|
||||
- No authorization check (#NOT_REQUIRED).
|
||||
|
||||
# 5. Business rules
|
||||
1. Show one row for each container that has a weighbridge record. Do not show a
|
||||
container without a weighbridge record.
|
||||
2. DEVIATION_KG is the difference between MEAS_KG and DECL_KG, without a sign.
|
||||
It is always positive or zero and it has 2 decimals.
|
||||
3. DEVIATION_PCT is DEVIATION_KG as a percentage of DECL_KG. It has 2 decimals.
|
||||
4. STATUS is 'HOLD' if MEAS_KG is greater than MAX_KG.
|
||||
5. STATUS is 'WARN' if rule 4 is not true and DEVIATION_PCT is greater than 5.
|
||||
6. STATUS is 'LOAD' in all other cases.
|
||||
7. DECL_KG is always greater than zero.
|
||||
|
||||
# 6. Constraints
|
||||
- Release target: 8.16.
|
||||
- Use Clean ABAP. Keep every method below 40 statements.
|
||||
- Out of scope: do not change {{P}}CONT and {{P}}WEIGH.
|
||||
|
||||
# 7. Acceptance
|
||||
- The view is active and has no syntax error.
|
||||
- The hidden tests pass.
|
||||
- Write ABAP Unit tests with CL_CDS_TEST_ENVIRONMENT in a global test class.
|
||||
68
tasks_gen/train/G1000/task.json
Normal file
68
tasks_gen/train/G1000/task.json
Normal file
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"id": "G1000",
|
||||
"category": "B",
|
||||
"object_type": "DDLS",
|
||||
"difficulty": 2,
|
||||
"release_target": "v816",
|
||||
"expected_outcome": "implement",
|
||||
"budget": {
|
||||
"max_tool_calls": 60,
|
||||
"max_activations": 15
|
||||
},
|
||||
"seed": [
|
||||
{
|
||||
"type": "TABL",
|
||||
"name": "{{P}}CONT",
|
||||
"file": "seed/cont.tabl.asabap",
|
||||
"description": "Container master"
|
||||
},
|
||||
{
|
||||
"type": "TABL",
|
||||
"name": "{{P}}WEIGH",
|
||||
"file": "seed/weigh.tabl.asabap",
|
||||
"description": "Weighbridge record"
|
||||
}
|
||||
],
|
||||
"contract": [
|
||||
{
|
||||
"type": "DDLS",
|
||||
"name": "{{P}}I_CONT_WEIGHT",
|
||||
"fields": [
|
||||
"CONT_ID",
|
||||
"CUSTOMER",
|
||||
"DECL_KG",
|
||||
"MEAS_KG",
|
||||
"DEVIATION_KG",
|
||||
"DEVIATION_PCT",
|
||||
"STATUS"
|
||||
]
|
||||
}
|
||||
],
|
||||
"out_of_scope": [
|
||||
"{{P}}CONT",
|
||||
"{{P}}WEIGH"
|
||||
],
|
||||
"hidden_tests": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}T20_HIDDEN",
|
||||
"file": "hidden/t20_hidden.clas.abap",
|
||||
"description": "T20 hidden tests"
|
||||
}
|
||||
],
|
||||
"reference": [
|
||||
{
|
||||
"type": "DDLS",
|
||||
"name": "{{P}}I_CONT_WEIGHT",
|
||||
"file": "reference/i_cont_weight.ddls.asddls",
|
||||
"description": "Container weight check"
|
||||
},
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}T20_TEST",
|
||||
"file": "reference/t20_test.clas.abap",
|
||||
"description": "T20 own tests"
|
||||
}
|
||||
],
|
||||
"craft_checks": []
|
||||
}
|
||||
71
tasks_gen/train/G1001/faulty/m0_harvest_evaluator.clas.abap
Normal file
71
tasks_gen/train/G1001/faulty/m0_harvest_evaluator.clas.abap
Normal file
@@ -0,0 +1,71 @@
|
||||
CLASS {{p}}harvest_evaluator DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
METHODS evaluate
|
||||
IMPORTING it_report TYPE {{p}}if_harvest=>tt_report
|
||||
it_member TYPE {{p}}if_harvest=>tt_member
|
||||
RETURNING VALUE(rt_result) TYPE {{p}}if_harvest=>tt_result.
|
||||
|
||||
PRIVATE SECTION.
|
||||
TYPES tt_member_key TYPE HASHED TABLE OF {{p}}if_harvest=>ty_member
|
||||
WITH UNIQUE KEY member_id.
|
||||
TYPES tt_member_id TYPE SORTED TABLE OF {{p}}if_harvest=>ty_member_id
|
||||
WITH UNIQUE KEY table_line.
|
||||
TYPES tt_report_key TYPE SORTED TABLE OF {{p}}if_harvest=>ty_report
|
||||
WITH NON-UNIQUE KEY variety member_id.
|
||||
|
||||
METHODS countable_reports
|
||||
IMPORTING it_report TYPE {{p}}if_harvest=>tt_report
|
||||
it_member TYPE tt_member_key
|
||||
RETURNING VALUE(rt_report) TYPE tt_report_key.
|
||||
METHODS is_countable
|
||||
IMPORTING is_report TYPE {{p}}if_harvest=>ty_report
|
||||
it_member TYPE tt_member_key
|
||||
RETURNING VALUE(rv_count) TYPE abap_bool.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}harvest_evaluator IMPLEMENTATION.
|
||||
METHOD evaluate.
|
||||
DATA lt_member TYPE tt_member_key.
|
||||
lt_member = it_member.
|
||||
|
||||
DATA(lt_report) = countable_reports( it_report = it_report
|
||||
it_member = lt_member ).
|
||||
|
||||
DATA lt_result TYPE {{p}}if_harvest=>tt_result.
|
||||
DATA lt_member_id TYPE tt_member_id.
|
||||
LOOP AT lt_report ASSIGNING FIELD-SYMBOL(<ls_report>) GROUP BY <ls_report>-variety.
|
||||
DATA(lv_variety) = <ls_report>-variety.
|
||||
DATA(lv_total) = 0.
|
||||
CLEAR lt_member_id.
|
||||
LOOP AT GROUP <ls_report> ASSIGNING FIELD-SYMBOL(<ls_grouped>).
|
||||
lv_total = lv_total - <ls_grouped>-quantity_kg.
|
||||
INSERT <ls_grouped>-member_id INTO TABLE lt_member_id.
|
||||
ENDLOOP.
|
||||
APPEND VALUE {{p}}if_harvest=>ty_result(
|
||||
variety = lv_variety
|
||||
total_kg = lv_total
|
||||
member_count = lines( lt_member_id ) ) TO lt_result.
|
||||
ENDLOOP.
|
||||
|
||||
SORT lt_result BY total_kg DESCENDING variety ASCENDING.
|
||||
rt_result = lt_result.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD countable_reports.
|
||||
LOOP AT it_report INTO DATA(ls_report).
|
||||
IF is_countable( is_report = ls_report
|
||||
it_member = it_member ) = abap_false.
|
||||
CONTINUE.
|
||||
ENDIF.
|
||||
INSERT ls_report INTO TABLE rt_report.
|
||||
ENDLOOP.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD is_countable.
|
||||
IF is_report-quantity_kg <= 0.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
rv_count = xsdbool( line_exists( it_member[ member_id = is_report-member_id ] ) ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
71
tasks_gen/train/G1001/faulty/m2_harvest_evaluator.clas.abap
Normal file
71
tasks_gen/train/G1001/faulty/m2_harvest_evaluator.clas.abap
Normal file
@@ -0,0 +1,71 @@
|
||||
CLASS {{p}}harvest_evaluator DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
METHODS evaluate
|
||||
IMPORTING it_report TYPE {{p}}if_harvest=>tt_report
|
||||
it_member TYPE {{p}}if_harvest=>tt_member
|
||||
RETURNING VALUE(rt_result) TYPE {{p}}if_harvest=>tt_result.
|
||||
|
||||
PRIVATE SECTION.
|
||||
TYPES tt_member_key TYPE HASHED TABLE OF {{p}}if_harvest=>ty_member
|
||||
WITH UNIQUE KEY member_id.
|
||||
TYPES tt_member_id TYPE SORTED TABLE OF {{p}}if_harvest=>ty_member_id
|
||||
WITH UNIQUE KEY table_line.
|
||||
TYPES tt_report_key TYPE SORTED TABLE OF {{p}}if_harvest=>ty_report
|
||||
WITH NON-UNIQUE KEY variety member_id.
|
||||
|
||||
METHODS countable_reports
|
||||
IMPORTING it_report TYPE {{p}}if_harvest=>tt_report
|
||||
it_member TYPE tt_member_key
|
||||
RETURNING VALUE(rt_report) TYPE tt_report_key.
|
||||
METHODS is_countable
|
||||
IMPORTING is_report TYPE {{p}}if_harvest=>ty_report
|
||||
it_member TYPE tt_member_key
|
||||
RETURNING VALUE(rv_count) TYPE abap_bool.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}harvest_evaluator IMPLEMENTATION.
|
||||
METHOD evaluate.
|
||||
DATA lt_member TYPE tt_member_key.
|
||||
lt_member = it_member.
|
||||
|
||||
DATA(lt_report) = countable_reports( it_report = it_report
|
||||
it_member = lt_member ).
|
||||
|
||||
DATA lt_result TYPE {{p}}if_harvest=>tt_result.
|
||||
DATA lt_member_id TYPE tt_member_id.
|
||||
LOOP AT lt_report ASSIGNING FIELD-SYMBOL(<ls_report>) GROUP BY <ls_report>-variety.
|
||||
DATA(lv_variety) = <ls_report>-variety.
|
||||
DATA(lv_total) = 0.
|
||||
CLEAR lt_member_id.
|
||||
LOOP AT GROUP <ls_report> ASSIGNING FIELD-SYMBOL(<ls_grouped>).
|
||||
lv_total = lv_total + <ls_grouped>-quantity_kg.
|
||||
INSERT <ls_grouped>-member_id INTO TABLE lt_member_id.
|
||||
ENDLOOP.
|
||||
APPEND VALUE {{p}}if_harvest=>ty_result(
|
||||
variety = lv_variety
|
||||
total_kg = lv_total
|
||||
member_count = lines( lt_member_id ) ) TO lt_result.
|
||||
ENDLOOP.
|
||||
|
||||
SORT lt_result BY total_kg DESCENDING variety ASCENDING.
|
||||
rt_result = lt_result.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD countable_reports.
|
||||
LOOP AT it_report INTO DATA(ls_report).
|
||||
IF is_countable( is_report = ls_report
|
||||
it_member = it_member ) = abap_true.
|
||||
CONTINUE.
|
||||
ENDIF.
|
||||
INSERT ls_report INTO TABLE rt_report.
|
||||
ENDLOOP.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD is_countable.
|
||||
IF is_report-quantity_kg <= 0.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
rv_count = xsdbool( line_exists( it_member[ member_id = is_report-member_id ] ) ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
71
tasks_gen/train/G1001/faulty/m3_harvest_evaluator.clas.abap
Normal file
71
tasks_gen/train/G1001/faulty/m3_harvest_evaluator.clas.abap
Normal file
@@ -0,0 +1,71 @@
|
||||
CLASS {{p}}harvest_evaluator DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
METHODS evaluate
|
||||
IMPORTING it_report TYPE {{p}}if_harvest=>tt_report
|
||||
it_member TYPE {{p}}if_harvest=>tt_member
|
||||
RETURNING VALUE(rt_result) TYPE {{p}}if_harvest=>tt_result.
|
||||
|
||||
PRIVATE SECTION.
|
||||
TYPES tt_member_key TYPE HASHED TABLE OF {{p}}if_harvest=>ty_member
|
||||
WITH UNIQUE KEY member_id.
|
||||
TYPES tt_member_id TYPE SORTED TABLE OF {{p}}if_harvest=>ty_member_id
|
||||
WITH UNIQUE KEY table_line.
|
||||
TYPES tt_report_key TYPE SORTED TABLE OF {{p}}if_harvest=>ty_report
|
||||
WITH NON-UNIQUE KEY variety member_id.
|
||||
|
||||
METHODS countable_reports
|
||||
IMPORTING it_report TYPE {{p}}if_harvest=>tt_report
|
||||
it_member TYPE tt_member_key
|
||||
RETURNING VALUE(rt_report) TYPE tt_report_key.
|
||||
METHODS is_countable
|
||||
IMPORTING is_report TYPE {{p}}if_harvest=>ty_report
|
||||
it_member TYPE tt_member_key
|
||||
RETURNING VALUE(rv_count) TYPE abap_bool.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}harvest_evaluator IMPLEMENTATION.
|
||||
METHOD evaluate.
|
||||
DATA lt_member TYPE tt_member_key.
|
||||
lt_member = it_member.
|
||||
|
||||
DATA(lt_report) = countable_reports( it_report = it_report
|
||||
it_member = lt_member ).
|
||||
|
||||
DATA lt_result TYPE {{p}}if_harvest=>tt_result.
|
||||
DATA lt_member_id TYPE tt_member_id.
|
||||
LOOP AT lt_report ASSIGNING FIELD-SYMBOL(<ls_report>) GROUP BY <ls_report>-variety.
|
||||
DATA(lv_variety) = <ls_report>-variety.
|
||||
DATA(lv_total) = 0.
|
||||
CLEAR lt_member_id.
|
||||
LOOP AT GROUP <ls_report> ASSIGNING FIELD-SYMBOL(<ls_grouped>).
|
||||
lv_total = lv_total + <ls_grouped>-quantity_kg.
|
||||
INSERT <ls_grouped>-member_id INTO TABLE lt_member_id.
|
||||
ENDLOOP.
|
||||
APPEND VALUE {{p}}if_harvest=>ty_result(
|
||||
variety = lv_variety
|
||||
total_kg = lv_total
|
||||
member_count = lines( lt_member_id ) ) TO lt_result.
|
||||
ENDLOOP.
|
||||
|
||||
SORT lt_result BY total_kg DESCENDING variety ASCENDING.
|
||||
rt_result = lt_result.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD countable_reports.
|
||||
LOOP AT it_report INTO DATA(ls_report).
|
||||
IF is_countable( is_report = ls_report
|
||||
it_member = it_member ) = abap_false.
|
||||
CONTINUE.
|
||||
ENDIF.
|
||||
INSERT ls_report INTO TABLE rt_report.
|
||||
ENDLOOP.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD is_countable.
|
||||
IF is_report-quantity_kg > 0.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
rv_count = xsdbool( line_exists( it_member[ member_id = is_report-member_id ] ) ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
19
tasks_gen/train/G1001/generation.json
Normal file
19
tasks_gen/train/G1001/generation.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"id": "G1001",
|
||||
"pool": "train",
|
||||
"object_type": "CLAS",
|
||||
"category": "C",
|
||||
"attempts": [
|
||||
{
|
||||
"stage": "validate",
|
||||
"oracle": 100.0,
|
||||
"null": 0,
|
||||
"mutation": {
|
||||
"valid": 3,
|
||||
"killed": 3,
|
||||
"ok": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"accepted": true
|
||||
}
|
||||
193
tasks_gen/train/G1001/hidden/harvest_hidden.clas.abap
Normal file
193
tasks_gen/train/G1001/hidden/harvest_hidden.clas.abap
Normal file
@@ -0,0 +1,193 @@
|
||||
CLASS {{p}}harvest_hidden DEFINITION PUBLIC FINAL CREATE PUBLIC
|
||||
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
|
||||
|
||||
PRIVATE SECTION.
|
||||
DATA mo_cut TYPE REF TO {{p}}harvest_evaluator.
|
||||
|
||||
METHODS setup.
|
||||
METHODS assert_rows
|
||||
IMPORTING it_act TYPE {{p}}if_harvest=>tt_result
|
||||
it_exp TYPE {{p}}if_harvest=>tt_result
|
||||
iv_msg TYPE string.
|
||||
|
||||
METHODS empty_input FOR TESTING.
|
||||
METHODS unknown_member_ignored FOR TESTING.
|
||||
METHODS zero_quantity_ignored FOR TESTING.
|
||||
METHODS negative_quantity_ignored FOR TESTING.
|
||||
METHODS same_member_counts_once FOR TESTING.
|
||||
METHODS two_varieties_separated FOR TESTING.
|
||||
METHODS sorted_by_total_desc FOR TESTING.
|
||||
METHODS tie_broken_by_variety FOR TESTING.
|
||||
METHODS all_reports_ignored FOR TESTING.
|
||||
METHODS member_without_report FOR TESTING.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}harvest_hidden IMPLEMENTATION.
|
||||
METHOD setup.
|
||||
mo_cut = NEW {{p}}harvest_evaluator( ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD assert_rows.
|
||||
cl_abap_unit_assert=>assert_equals( exp = lines( it_exp )
|
||||
act = lines( it_act )
|
||||
msg = |{ iv_msg }: number of rows| ).
|
||||
LOOP AT it_exp ASSIGNING FIELD-SYMBOL(<ls_exp>).
|
||||
READ TABLE it_act ASSIGNING FIELD-SYMBOL(<ls_act>) INDEX sy-tabix.
|
||||
IF sy-subrc <> 0.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
cl_abap_unit_assert=>assert_equals( exp = <ls_exp>-variety
|
||||
act = <ls_act>-variety
|
||||
msg = |{ iv_msg }: variety| ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = <ls_exp>-total_kg
|
||||
act = <ls_act>-total_kg
|
||||
msg = |{ iv_msg }: total_kg| ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = <ls_exp>-member_count
|
||||
act = <ls_act>-member_count
|
||||
msg = |{ iv_msg }: member_count| ).
|
||||
ENDLOOP.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD empty_input.
|
||||
DATA lt_report TYPE {{p}}if_harvest=>tt_report.
|
||||
DATA lt_member TYPE {{p}}if_harvest=>tt_member.
|
||||
DATA(lt_result) = mo_cut->evaluate( it_report = lt_report
|
||||
it_member = lt_member ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 0 act = lines( lt_result ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD unknown_member_ignored.
|
||||
DATA(lt_member) = VALUE {{p}}if_harvest=>tt_member(
|
||||
( member_id = 'M00001' member_name = 'Hof Adler' )
|
||||
( member_id = 'M00002' member_name = 'Hof Birke' ) ).
|
||||
DATA(lt_report) = VALUE {{p}}if_harvest=>tt_report(
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 100 )
|
||||
( member_id = 'M00009' variety = 'RIES' quantity_kg = 50 ) ).
|
||||
DATA(lt_result) = mo_cut->evaluate( it_report = lt_report
|
||||
it_member = lt_member ).
|
||||
assert_rows( it_act = lt_result
|
||||
it_exp = VALUE #( ( variety = 'RIES' total_kg = 100 member_count = 1 ) )
|
||||
iv_msg = 'unknown member' ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD zero_quantity_ignored.
|
||||
DATA(lt_member) = VALUE {{p}}if_harvest=>tt_member(
|
||||
( member_id = 'M00001' member_name = 'Hof Adler' ) ).
|
||||
DATA(lt_report) = VALUE {{p}}if_harvest=>tt_report(
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 0 )
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 30 ) ).
|
||||
DATA(lt_result) = mo_cut->evaluate( it_report = lt_report
|
||||
it_member = lt_member ).
|
||||
assert_rows( it_act = lt_result
|
||||
it_exp = VALUE #( ( variety = 'RIES' total_kg = 30 member_count = 1 ) )
|
||||
iv_msg = 'zero quantity' ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD negative_quantity_ignored.
|
||||
DATA(lt_member) = VALUE {{p}}if_harvest=>tt_member(
|
||||
( member_id = 'M00001' member_name = 'Hof Adler' ) ).
|
||||
DATA(lt_report) = VALUE {{p}}if_harvest=>tt_report(
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = -5 )
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 20 ) ).
|
||||
DATA(lt_result) = mo_cut->evaluate( it_report = lt_report
|
||||
it_member = lt_member ).
|
||||
assert_rows( it_act = lt_result
|
||||
it_exp = VALUE #( ( variety = 'RIES' total_kg = 20 member_count = 1 ) )
|
||||
iv_msg = 'negative quantity' ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD same_member_counts_once.
|
||||
DATA(lt_member) = VALUE {{p}}if_harvest=>tt_member(
|
||||
( member_id = 'M00001' member_name = 'Hof Adler' )
|
||||
( member_id = 'M00002' member_name = 'Hof Birke' ) ).
|
||||
DATA(lt_report) = VALUE {{p}}if_harvest=>tt_report(
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 10 )
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 20 )
|
||||
( member_id = 'M00002' variety = 'RIES' quantity_kg = 5 ) ).
|
||||
DATA(lt_result) = mo_cut->evaluate( it_report = lt_report
|
||||
it_member = lt_member ).
|
||||
assert_rows( it_act = lt_result
|
||||
it_exp = VALUE #( ( variety = 'RIES' total_kg = 35 member_count = 2 ) )
|
||||
iv_msg = 'same member' ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD two_varieties_separated.
|
||||
DATA(lt_member) = VALUE {{p}}if_harvest=>tt_member(
|
||||
( member_id = 'M00001' member_name = 'Hof Adler' )
|
||||
( member_id = 'M00002' member_name = 'Hof Birke' ) ).
|
||||
DATA(lt_report) = VALUE {{p}}if_harvest=>tt_report(
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 10 )
|
||||
( member_id = 'M00002' variety = 'RIES' quantity_kg = 10 )
|
||||
( member_id = 'M00001' variety = 'SPAE' quantity_kg = 7 ) ).
|
||||
DATA(lt_result) = mo_cut->evaluate( it_report = lt_report
|
||||
it_member = lt_member ).
|
||||
assert_rows( it_act = lt_result
|
||||
it_exp = VALUE #( ( variety = 'RIES' total_kg = 20 member_count = 2 )
|
||||
( variety = 'SPAE' total_kg = 7 member_count = 1 ) )
|
||||
iv_msg = 'two varieties' ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD sorted_by_total_desc.
|
||||
DATA(lt_member) = VALUE {{p}}if_harvest=>tt_member(
|
||||
( member_id = 'M00001' member_name = 'Hof Adler' )
|
||||
( member_id = 'M00002' member_name = 'Hof Birke' )
|
||||
( member_id = 'M00003' member_name = 'Hof Zeder' )
|
||||
( member_id = 'M00004' member_name = 'Hof Eiche' ) ).
|
||||
DATA(lt_report) = VALUE {{p}}if_harvest=>tt_report(
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 10 )
|
||||
( member_id = 'M00002' variety = 'SPAE' quantity_kg = 30 )
|
||||
( member_id = 'M00003' variety = 'SILV' quantity_kg = 20 )
|
||||
( member_id = 'M00004' variety = 'SPAE' quantity_kg = 5 ) ).
|
||||
DATA(lt_result) = mo_cut->evaluate( it_report = lt_report
|
||||
it_member = lt_member ).
|
||||
assert_rows( it_act = lt_result
|
||||
it_exp = VALUE #( ( variety = 'SPAE' total_kg = 35 member_count = 2 )
|
||||
( variety = 'SILV' total_kg = 20 member_count = 1 )
|
||||
( variety = 'RIES' total_kg = 10 member_count = 1 ) )
|
||||
iv_msg = 'sort by total' ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD tie_broken_by_variety.
|
||||
DATA(lt_member) = VALUE {{p}}if_harvest=>tt_member(
|
||||
( member_id = 'M00001' member_name = 'Hof Adler' )
|
||||
( member_id = 'M00002' member_name = 'Hof Birke' )
|
||||
( member_id = 'M00003' member_name = 'Hof Zeder' ) ).
|
||||
DATA(lt_report) = VALUE {{p}}if_harvest=>tt_report(
|
||||
( member_id = 'M00001' variety = 'SPAE' quantity_kg = 10 )
|
||||
( member_id = 'M00002' variety = 'RIES' quantity_kg = 10 )
|
||||
( member_id = 'M00003' variety = 'SILV' quantity_kg = 10 ) ).
|
||||
DATA(lt_result) = mo_cut->evaluate( it_report = lt_report
|
||||
it_member = lt_member ).
|
||||
assert_rows( it_act = lt_result
|
||||
it_exp = VALUE #( ( variety = 'RIES' total_kg = 10 member_count = 1 )
|
||||
( variety = 'SILV' total_kg = 10 member_count = 1 )
|
||||
( variety = 'SPAE' total_kg = 10 member_count = 1 ) )
|
||||
iv_msg = 'tie by variety' ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD all_reports_ignored.
|
||||
DATA(lt_member) = VALUE {{p}}if_harvest=>tt_member(
|
||||
( member_id = 'M00001' member_name = 'Hof Adler' ) ).
|
||||
DATA(lt_report) = VALUE {{p}}if_harvest=>tt_report(
|
||||
( member_id = 'M00009' variety = 'RIES' quantity_kg = 10 )
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 0 )
|
||||
( member_id = 'M00001' variety = 'SPAE' quantity_kg = -3 ) ).
|
||||
DATA(lt_result) = mo_cut->evaluate( it_report = lt_report
|
||||
it_member = lt_member ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 0 act = lines( lt_result ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD member_without_report.
|
||||
DATA(lt_member) = VALUE {{p}}if_harvest=>tt_member(
|
||||
( member_id = 'M00001' member_name = 'Hof Adler' )
|
||||
( member_id = 'M00002' member_name = 'Hof Birke' ) ).
|
||||
DATA(lt_report) = VALUE {{p}}if_harvest=>tt_report(
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 5 ) ).
|
||||
DATA(lt_result) = mo_cut->evaluate( it_report = lt_report
|
||||
it_member = lt_member ).
|
||||
assert_rows( it_act = lt_result
|
||||
it_exp = VALUE #( ( variety = 'RIES' total_kg = 5 member_count = 1 ) )
|
||||
iv_msg = 'member without report' ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
66
tasks_gen/train/G1001/mutation.json
Normal file
66
tasks_gen/train/G1001/mutation.json
Normal file
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"task": "G1001",
|
||||
"mutants": [
|
||||
{
|
||||
"object": "{{P}}HARVEST_EVALUATOR",
|
||||
"mutant": "line 42: + -> - (arith)",
|
||||
"status": "killed",
|
||||
"hidden": "2/10",
|
||||
"failed_tests": [
|
||||
"MEMBER_WITHOUT_REPORT",
|
||||
"NEGATIVE_QUANTITY_IGNORED",
|
||||
"SAME_MEMBER_COUNTS_ONCE",
|
||||
"SORTED_BY_TOTAL_DESC",
|
||||
"TIE_BROKEN_BY_VARIETY",
|
||||
"TWO_VARIETIES_SEPARATED",
|
||||
"UNKNOWN_MEMBER_IGNORED",
|
||||
"ZERO_QUANTITY_IGNORED"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}HARVEST_EVALUATOR",
|
||||
"mutant": "line 57: = -> <> (eq)",
|
||||
"status": "invalid",
|
||||
"hidden": "0/0",
|
||||
"failed_tests": []
|
||||
},
|
||||
{
|
||||
"object": "{{P}}HARVEST_EVALUATOR",
|
||||
"mutant": "line 58: abap_false -> abap_true (bool)",
|
||||
"status": "killed",
|
||||
"hidden": "1/10",
|
||||
"failed_tests": [
|
||||
"ALL_REPORTS_IGNORED",
|
||||
"MEMBER_WITHOUT_REPORT",
|
||||
"NEGATIVE_QUANTITY_IGNORED",
|
||||
"SAME_MEMBER_COUNTS_ONCE",
|
||||
"SORTED_BY_TOTAL_DESC",
|
||||
"TIE_BROKEN_BY_VARIETY",
|
||||
"TWO_VARIETIES_SEPARATED",
|
||||
"UNKNOWN_MEMBER_IGNORED",
|
||||
"ZERO_QUANTITY_IGNORED"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}HARVEST_EVALUATOR",
|
||||
"mutant": "line 66: <= -> > (rel)",
|
||||
"status": "killed",
|
||||
"hidden": "1/10",
|
||||
"failed_tests": [
|
||||
"ALL_REPORTS_IGNORED",
|
||||
"MEMBER_WITHOUT_REPORT",
|
||||
"NEGATIVE_QUANTITY_IGNORED",
|
||||
"SAME_MEMBER_COUNTS_ONCE",
|
||||
"SORTED_BY_TOTAL_DESC",
|
||||
"TIE_BROKEN_BY_VARIETY",
|
||||
"TWO_VARIETIES_SEPARATED",
|
||||
"UNKNOWN_MEMBER_IGNORED",
|
||||
"ZERO_QUANTITY_IGNORED"
|
||||
]
|
||||
}
|
||||
],
|
||||
"valid": 3,
|
||||
"killed": 3,
|
||||
"kill_rate": 1.0,
|
||||
"ok": true
|
||||
}
|
||||
71
tasks_gen/train/G1001/reference/harvest_evaluator.clas.abap
Normal file
71
tasks_gen/train/G1001/reference/harvest_evaluator.clas.abap
Normal file
@@ -0,0 +1,71 @@
|
||||
CLASS {{p}}harvest_evaluator DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
METHODS evaluate
|
||||
IMPORTING it_report TYPE {{p}}if_harvest=>tt_report
|
||||
it_member TYPE {{p}}if_harvest=>tt_member
|
||||
RETURNING VALUE(rt_result) TYPE {{p}}if_harvest=>tt_result.
|
||||
|
||||
PRIVATE SECTION.
|
||||
TYPES tt_member_key TYPE HASHED TABLE OF {{p}}if_harvest=>ty_member
|
||||
WITH UNIQUE KEY member_id.
|
||||
TYPES tt_member_id TYPE SORTED TABLE OF {{p}}if_harvest=>ty_member_id
|
||||
WITH UNIQUE KEY table_line.
|
||||
TYPES tt_report_key TYPE SORTED TABLE OF {{p}}if_harvest=>ty_report
|
||||
WITH NON-UNIQUE KEY variety member_id.
|
||||
|
||||
METHODS countable_reports
|
||||
IMPORTING it_report TYPE {{p}}if_harvest=>tt_report
|
||||
it_member TYPE tt_member_key
|
||||
RETURNING VALUE(rt_report) TYPE tt_report_key.
|
||||
METHODS is_countable
|
||||
IMPORTING is_report TYPE {{p}}if_harvest=>ty_report
|
||||
it_member TYPE tt_member_key
|
||||
RETURNING VALUE(rv_count) TYPE abap_bool.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}harvest_evaluator IMPLEMENTATION.
|
||||
METHOD evaluate.
|
||||
DATA lt_member TYPE tt_member_key.
|
||||
lt_member = it_member.
|
||||
|
||||
DATA(lt_report) = countable_reports( it_report = it_report
|
||||
it_member = lt_member ).
|
||||
|
||||
DATA lt_result TYPE {{p}}if_harvest=>tt_result.
|
||||
DATA lt_member_id TYPE tt_member_id.
|
||||
LOOP AT lt_report ASSIGNING FIELD-SYMBOL(<ls_report>) GROUP BY <ls_report>-variety.
|
||||
DATA(lv_variety) = <ls_report>-variety.
|
||||
DATA(lv_total) = 0.
|
||||
CLEAR lt_member_id.
|
||||
LOOP AT GROUP <ls_report> ASSIGNING FIELD-SYMBOL(<ls_grouped>).
|
||||
lv_total = lv_total + <ls_grouped>-quantity_kg.
|
||||
INSERT <ls_grouped>-member_id INTO TABLE lt_member_id.
|
||||
ENDLOOP.
|
||||
APPEND VALUE {{p}}if_harvest=>ty_result(
|
||||
variety = lv_variety
|
||||
total_kg = lv_total
|
||||
member_count = lines( lt_member_id ) ) TO lt_result.
|
||||
ENDLOOP.
|
||||
|
||||
SORT lt_result BY total_kg DESCENDING variety ASCENDING.
|
||||
rt_result = lt_result.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD countable_reports.
|
||||
LOOP AT it_report INTO DATA(ls_report).
|
||||
IF is_countable( is_report = ls_report
|
||||
it_member = it_member ) = abap_false.
|
||||
CONTINUE.
|
||||
ENDIF.
|
||||
INSERT ls_report INTO TABLE rt_report.
|
||||
ENDLOOP.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD is_countable.
|
||||
IF is_report-quantity_kg <= 0.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
rv_count = xsdbool( line_exists( it_member[ member_id = is_report-member_id ] ) ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
@@ -0,0 +1,84 @@
|
||||
CLASS ltc_harvest_evaluator DEFINITION FINAL FOR TESTING
|
||||
DURATION SHORT RISK LEVEL HARMLESS.
|
||||
|
||||
PRIVATE SECTION.
|
||||
DATA mo_cut TYPE REF TO {{p}}harvest_evaluator.
|
||||
METHODS setup.
|
||||
METHODS sums_quantities FOR TESTING.
|
||||
METHODS counts_members_once FOR TESTING.
|
||||
METHODS ignores_unknown_member FOR TESTING.
|
||||
METHODS ignores_zero_quantity FOR TESTING.
|
||||
METHODS sorts_by_total FOR TESTING.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS ltc_harvest_evaluator IMPLEMENTATION.
|
||||
METHOD setup.
|
||||
mo_cut = NEW {{p}}harvest_evaluator( ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD sums_quantities.
|
||||
DATA(lt_member) = VALUE {{p}}if_harvest=>tt_member(
|
||||
( member_id = 'M00001' member_name = 'Hof Adler' ) ).
|
||||
DATA(lt_report) = VALUE {{p}}if_harvest=>tt_report(
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 10 )
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 15 ) ).
|
||||
DATA(lt_result) = mo_cut->evaluate( it_report = lt_report
|
||||
it_member = lt_member ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_result ) ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 25 act = lt_result[ 1 ]-total_kg ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD counts_members_once.
|
||||
DATA(lt_member) = VALUE {{p}}if_harvest=>tt_member(
|
||||
( member_id = 'M00001' member_name = 'Hof Adler' )
|
||||
( member_id = 'M00002' member_name = 'Hof Birke' ) ).
|
||||
DATA(lt_report) = VALUE {{p}}if_harvest=>tt_report(
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 10 )
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 5 )
|
||||
( member_id = 'M00002' variety = 'RIES' quantity_kg = 5 ) ).
|
||||
DATA(lt_result) = mo_cut->evaluate( it_report = lt_report
|
||||
it_member = lt_member ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 20 act = lt_result[ 1 ]-total_kg ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 2 act = lt_result[ 1 ]-member_count ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD ignores_unknown_member.
|
||||
DATA(lt_member) = VALUE {{p}}if_harvest=>tt_member(
|
||||
( member_id = 'M00001' member_name = 'Hof Adler' ) ).
|
||||
DATA(lt_report) = VALUE {{p}}if_harvest=>tt_report(
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 10 )
|
||||
( member_id = 'M00009' variety = 'RIES' quantity_kg = 99 ) ).
|
||||
DATA(lt_result) = mo_cut->evaluate( it_report = lt_report
|
||||
it_member = lt_member ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 10 act = lt_result[ 1 ]-total_kg ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 1 act = lt_result[ 1 ]-member_count ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD ignores_zero_quantity.
|
||||
DATA(lt_member) = VALUE {{p}}if_harvest=>tt_member(
|
||||
( member_id = 'M00001' member_name = 'Hof Adler' ) ).
|
||||
DATA(lt_report) = VALUE {{p}}if_harvest=>tt_report(
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 0 )
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 40 ) ).
|
||||
DATA(lt_result) = mo_cut->evaluate( it_report = lt_report
|
||||
it_member = lt_member ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 40 act = lt_result[ 1 ]-total_kg ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD sorts_by_total.
|
||||
DATA(lt_member) = VALUE {{p}}if_harvest=>tt_member(
|
||||
( member_id = 'M00001' member_name = 'Hof Adler' )
|
||||
( member_id = 'M00002' member_name = 'Hof Birke' )
|
||||
( member_id = 'M00003' member_name = 'Hof Zeder' ) ).
|
||||
DATA(lt_report) = VALUE {{p}}if_harvest=>tt_report(
|
||||
( member_id = 'M00001' variety = 'RIES' quantity_kg = 5 )
|
||||
( member_id = 'M00002' variety = 'SPAE' quantity_kg = 30 )
|
||||
( member_id = 'M00003' variety = 'SILV' quantity_kg = 20 ) ).
|
||||
DATA(lt_result) = mo_cut->evaluate( it_report = lt_report
|
||||
it_member = lt_member ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'SPAE' act = lt_result[ 1 ]-variety ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'SILV' act = lt_result[ 2 ]-variety ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'RIES' act = lt_result[ 3 ]-variety ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
26
tasks_gen/train/G1001/seed/if_harvest.intf.abap
Normal file
26
tasks_gen/train/G1001/seed/if_harvest.intf.abap
Normal file
@@ -0,0 +1,26 @@
|
||||
INTERFACE {{p}}if_harvest PUBLIC.
|
||||
TYPES ty_member_id TYPE c LENGTH 6.
|
||||
TYPES ty_variety TYPE c LENGTH 4.
|
||||
TYPES ty_name TYPE c LENGTH 30.
|
||||
TYPES ty_quantity TYPE i.
|
||||
|
||||
TYPES: BEGIN OF ty_member,
|
||||
member_id TYPE ty_member_id,
|
||||
member_name TYPE ty_name,
|
||||
END OF ty_member.
|
||||
TYPES tt_member TYPE STANDARD TABLE OF ty_member WITH EMPTY KEY.
|
||||
|
||||
TYPES: BEGIN OF ty_report,
|
||||
member_id TYPE ty_member_id,
|
||||
variety TYPE ty_variety,
|
||||
quantity_kg TYPE ty_quantity,
|
||||
END OF ty_report.
|
||||
TYPES tt_report TYPE STANDARD TABLE OF ty_report WITH EMPTY KEY.
|
||||
|
||||
TYPES: BEGIN OF ty_result,
|
||||
variety TYPE ty_variety,
|
||||
total_kg TYPE ty_quantity,
|
||||
member_count TYPE i,
|
||||
END OF ty_result.
|
||||
TYPES tt_result TYPE STANDARD TABLE OF ty_result WITH EMPTY KEY.
|
||||
ENDINTERFACE.
|
||||
52
tasks_gen/train/G1001/spec.md
Normal file
52
tasks_gen/train/G1001/spec.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# 1. Goal
|
||||
A vineyard cooperative collects the harvest reports of its members. The
|
||||
cooperative needs one evaluation of the harvest for each grape variety. A
|
||||
planning program calls the evaluation before it plans the transport of the
|
||||
grapes to the winery.
|
||||
|
||||
# 2. Open questions
|
||||
None.
|
||||
|
||||
# 3. Context
|
||||
- The interface {{P}}IF_HARVEST exists in package $TMP. It is active.
|
||||
- The interface contains the data types for the harvest reports, for the member
|
||||
master data, and for the result. Read the interface before you start to work.
|
||||
- A harvest report has a member, a grape variety, and a quantity in kilograms.
|
||||
- The member master data has a member ID and a member name.
|
||||
|
||||
# 4. Contract
|
||||
- Create the class {{P}}HARVEST_EVALUATOR in package $TMP.
|
||||
- The class is public and final. It has a public constructor without
|
||||
parameters.
|
||||
- The class has one public method:
|
||||
EVALUATE
|
||||
IMPORTING it_report TYPE {{P}}IF_HARVEST=>TT_REPORT
|
||||
it_member TYPE {{P}}IF_HARVEST=>TT_MEMBER
|
||||
RETURNING VALUE(rt_result) TYPE {{P}}IF_HARVEST=>TT_RESULT.
|
||||
- Do not add other public methods.
|
||||
|
||||
# 5. Business rules
|
||||
A harvest report is countable when rule 1 and rule 2 are true.
|
||||
1. The member_id of the report occurs in it_member. A member_id occurs at most
|
||||
one time in it_member.
|
||||
2. The quantity_kg of the report is greater than 0.
|
||||
3. Group the countable reports by variety. Create one result row for each
|
||||
variety that has at least one countable report.
|
||||
4. The total_kg of a result row is the sum of the quantity_kg of all countable
|
||||
reports of the variety.
|
||||
5. The member_count of a result row is the number of different member_id
|
||||
values in the countable reports of the variety.
|
||||
6. Sort the result rows by total_kg in descending order. When two rows have the
|
||||
same total_kg, sort these rows by variety in ascending order.
|
||||
7. When no report is countable, return an empty table.
|
||||
|
||||
# 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_HARVEST.
|
||||
|
||||
# 7. Acceptance
|
||||
- The class is active and has no syntax error.
|
||||
- The hidden tests pass.
|
||||
- Write your own ABAP Unit tests for the class.
|
||||
53
tasks_gen/train/G1001/task.json
Normal file
53
tasks_gen/train/G1001/task.json
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"id": "G1001",
|
||||
"category": "C",
|
||||
"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_HARVEST",
|
||||
"file": "seed/if_harvest.intf.abap",
|
||||
"description": "Data types for harvest reports, member master data, and the evaluation result"
|
||||
}
|
||||
],
|
||||
"contract": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}HARVEST_EVALUATOR",
|
||||
"description": "Evaluates the harvest reports per grape variety"
|
||||
}
|
||||
],
|
||||
"out_of_scope": [
|
||||
"{{P}}IF_HARVEST"
|
||||
],
|
||||
"hidden_tests": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}HARVEST_HIDDEN",
|
||||
"file": "hidden/harvest_hidden.clas.abap",
|
||||
"description": "Hidden tests for the harvest evaluation"
|
||||
}
|
||||
],
|
||||
"reference": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}HARVEST_EVALUATOR",
|
||||
"file": "reference/harvest_evaluator.clas.abap",
|
||||
"description": "Harvest evaluator",
|
||||
"testclasses_file": "reference/harvest_evaluator.testclasses.abap"
|
||||
}
|
||||
],
|
||||
"craft_checks": [
|
||||
"table_kind",
|
||||
"key_kind",
|
||||
"access_path",
|
||||
"method_length"
|
||||
]
|
||||
}
|
||||
109
tasks_gen/train/G1002/faulty/m0_glasses_pricer.clas.abap
Normal file
109
tasks_gen/train/G1002/faulty/m0_glasses_pricer.clas.abap
Normal file
@@ -0,0 +1,109 @@
|
||||
CLASS {{p}}glasses_pricer DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC.
|
||||
|
||||
PUBLIC SECTION.
|
||||
TYPES ty_amount TYPE p LENGTH 9 DECIMALS 2.
|
||||
TYPES ty_lens TYPE c LENGTH 1.
|
||||
TYPES ty_coat TYPE c LENGTH 1.
|
||||
METHODS price
|
||||
IMPORTING iv_frame TYPE ty_amount
|
||||
iv_lens TYPE ty_lens
|
||||
iv_coat TYPE ty_coat
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_price) TYPE ty_amount.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_max_qty TYPE i VALUE 100,
|
||||
c_discount_qty TYPE i VALUE 3,
|
||||
c_discount_percent TYPE i VALUE 10,
|
||||
c_lens_standard TYPE ty_amount VALUE '40.00',
|
||||
c_lens_bifocal TYPE ty_amount VALUE '90.00',
|
||||
c_lens_progressive TYPE ty_amount VALUE '150.00',
|
||||
c_coat_simple TYPE ty_amount VALUE '25.00',
|
||||
c_coat_premium TYPE ty_amount VALUE '35.00',
|
||||
c_coat_none TYPE ty_amount VALUE '0.00'.
|
||||
|
||||
METHODS capped_qty
|
||||
IMPORTING iv_qty TYPE i
|
||||
RETURNING VALUE(rv_qty) TYPE i.
|
||||
METHODS lens_surcharge
|
||||
IMPORTING iv_lens TYPE ty_lens
|
||||
RETURNING VALUE(rv_amount) TYPE ty_amount.
|
||||
METHODS coat_surcharge
|
||||
IMPORTING iv_coat TYPE ty_coat
|
||||
RETURNING VALUE(rv_amount) TYPE ty_amount.
|
||||
METHODS total_price
|
||||
IMPORTING iv_frame TYPE ty_amount
|
||||
iv_lens TYPE ty_amount
|
||||
iv_coat TYPE ty_amount
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_total) TYPE ty_amount.
|
||||
METHODS with_discount
|
||||
IMPORTING iv_total TYPE ty_amount
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_price) TYPE ty_amount.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}glasses_pricer IMPLEMENTATION.
|
||||
|
||||
METHOD price.
|
||||
DATA(lv_qty) = capped_qty( iv_qty ).
|
||||
IF lv_qty < 1.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
|
||||
DATA(lv_total) = total_price( iv_frame = iv_frame
|
||||
iv_lens = lens_surcharge( iv_lens )
|
||||
iv_coat = coat_surcharge( iv_coat )
|
||||
iv_qty = lv_qty ).
|
||||
|
||||
rv_price = with_discount( iv_total = lv_total
|
||||
iv_qty = lv_qty ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD capped_qty.
|
||||
rv_qty = iv_qty.
|
||||
IF rv_qty > c_max_qty.
|
||||
rv_qty = c_max_qty.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD lens_surcharge.
|
||||
CASE iv_lens.
|
||||
WHEN 'B'.
|
||||
rv_amount = c_lens_bifocal.
|
||||
WHEN 'P'.
|
||||
rv_amount = c_lens_progressive.
|
||||
WHEN OTHERS.
|
||||
rv_amount = c_lens_standard.
|
||||
ENDCASE.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD coat_surcharge.
|
||||
CASE iv_coat.
|
||||
WHEN 'A'.
|
||||
rv_amount = c_coat_simple.
|
||||
WHEN 'B'.
|
||||
rv_amount = c_coat_premium.
|
||||
WHEN OTHERS.
|
||||
rv_amount = c_coat_none.
|
||||
ENDCASE.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD total_price.
|
||||
rv_total = iv_frame * iv_qty.
|
||||
rv_total = rv_total + iv_lens / iv_qty.
|
||||
rv_total = rv_total + iv_coat * iv_qty.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD with_discount.
|
||||
rv_price = iv_total.
|
||||
IF iv_qty >= c_discount_qty.
|
||||
rv_price = iv_total - iv_total * c_discount_percent / 100.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
109
tasks_gen/train/G1002/faulty/m1_glasses_pricer.clas.abap
Normal file
109
tasks_gen/train/G1002/faulty/m1_glasses_pricer.clas.abap
Normal file
@@ -0,0 +1,109 @@
|
||||
CLASS {{p}}glasses_pricer DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC.
|
||||
|
||||
PUBLIC SECTION.
|
||||
TYPES ty_amount TYPE p LENGTH 9 DECIMALS 2.
|
||||
TYPES ty_lens TYPE c LENGTH 1.
|
||||
TYPES ty_coat TYPE c LENGTH 1.
|
||||
METHODS price
|
||||
IMPORTING iv_frame TYPE ty_amount
|
||||
iv_lens TYPE ty_lens
|
||||
iv_coat TYPE ty_coat
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_price) TYPE ty_amount.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_max_qty TYPE i VALUE 100,
|
||||
c_discount_qty TYPE i VALUE 3,
|
||||
c_discount_percent TYPE i VALUE 10,
|
||||
c_lens_standard TYPE ty_amount VALUE '40.00',
|
||||
c_lens_bifocal TYPE ty_amount VALUE '90.00',
|
||||
c_lens_progressive TYPE ty_amount VALUE '150.00',
|
||||
c_coat_simple TYPE ty_amount VALUE '25.00',
|
||||
c_coat_premium TYPE ty_amount VALUE '35.00',
|
||||
c_coat_none TYPE ty_amount VALUE '0.00'.
|
||||
|
||||
METHODS capped_qty
|
||||
IMPORTING iv_qty TYPE i
|
||||
RETURNING VALUE(rv_qty) TYPE i.
|
||||
METHODS lens_surcharge
|
||||
IMPORTING iv_lens TYPE ty_lens
|
||||
RETURNING VALUE(rv_amount) TYPE ty_amount.
|
||||
METHODS coat_surcharge
|
||||
IMPORTING iv_coat TYPE ty_coat
|
||||
RETURNING VALUE(rv_amount) TYPE ty_amount.
|
||||
METHODS total_price
|
||||
IMPORTING iv_frame TYPE ty_amount
|
||||
iv_lens TYPE ty_amount
|
||||
iv_coat TYPE ty_amount
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_total) TYPE ty_amount.
|
||||
METHODS with_discount
|
||||
IMPORTING iv_total TYPE ty_amount
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_price) TYPE ty_amount.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}glasses_pricer IMPLEMENTATION.
|
||||
|
||||
METHOD price.
|
||||
DATA(lv_qty) = capped_qty( iv_qty ).
|
||||
IF lv_qty < 1.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
|
||||
DATA(lv_total) = total_price( iv_frame = iv_frame
|
||||
iv_lens = lens_surcharge( iv_lens )
|
||||
iv_coat = coat_surcharge( iv_coat )
|
||||
iv_qty = lv_qty ).
|
||||
|
||||
rv_price = with_discount( iv_total = lv_total
|
||||
iv_qty = lv_qty ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD capped_qty.
|
||||
rv_qty = iv_qty.
|
||||
IF rv_qty > c_max_qty.
|
||||
rv_qty = c_max_qty.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD lens_surcharge.
|
||||
CASE iv_lens.
|
||||
WHEN 'B'.
|
||||
rv_amount = c_lens_bifocal.
|
||||
WHEN 'P'.
|
||||
rv_amount = c_lens_progressive.
|
||||
WHEN OTHERS.
|
||||
rv_amount = c_lens_standard.
|
||||
ENDCASE.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD coat_surcharge.
|
||||
CASE iv_coat.
|
||||
WHEN 'A'.
|
||||
rv_amount = c_coat_simple.
|
||||
WHEN 'B'.
|
||||
rv_amount = c_coat_premium.
|
||||
WHEN OTHERS.
|
||||
rv_amount = c_coat_none.
|
||||
ENDCASE.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD total_price.
|
||||
rv_total = iv_frame * iv_qty.
|
||||
rv_total = rv_total + iv_lens * iv_qty.
|
||||
rv_total = rv_total - iv_coat * iv_qty.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD with_discount.
|
||||
rv_price = iv_total.
|
||||
IF iv_qty >= c_discount_qty.
|
||||
rv_price = iv_total - iv_total * c_discount_percent / 100.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
109
tasks_gen/train/G1002/faulty/m2_glasses_pricer.clas.abap
Normal file
109
tasks_gen/train/G1002/faulty/m2_glasses_pricer.clas.abap
Normal file
@@ -0,0 +1,109 @@
|
||||
CLASS {{p}}glasses_pricer DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC.
|
||||
|
||||
PUBLIC SECTION.
|
||||
TYPES ty_amount TYPE p LENGTH 9 DECIMALS 2.
|
||||
TYPES ty_lens TYPE c LENGTH 1.
|
||||
TYPES ty_coat TYPE c LENGTH 1.
|
||||
METHODS price
|
||||
IMPORTING iv_frame TYPE ty_amount
|
||||
iv_lens TYPE ty_lens
|
||||
iv_coat TYPE ty_coat
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_price) TYPE ty_amount.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_max_qty TYPE i VALUE 100,
|
||||
c_discount_qty TYPE i VALUE 3,
|
||||
c_discount_percent TYPE i VALUE 10,
|
||||
c_lens_standard TYPE ty_amount VALUE '40.00',
|
||||
c_lens_bifocal TYPE ty_amount VALUE '90.00',
|
||||
c_lens_progressive TYPE ty_amount VALUE '150.00',
|
||||
c_coat_simple TYPE ty_amount VALUE '25.00',
|
||||
c_coat_premium TYPE ty_amount VALUE '35.00',
|
||||
c_coat_none TYPE ty_amount VALUE '0.00'.
|
||||
|
||||
METHODS capped_qty
|
||||
IMPORTING iv_qty TYPE i
|
||||
RETURNING VALUE(rv_qty) TYPE i.
|
||||
METHODS lens_surcharge
|
||||
IMPORTING iv_lens TYPE ty_lens
|
||||
RETURNING VALUE(rv_amount) TYPE ty_amount.
|
||||
METHODS coat_surcharge
|
||||
IMPORTING iv_coat TYPE ty_coat
|
||||
RETURNING VALUE(rv_amount) TYPE ty_amount.
|
||||
METHODS total_price
|
||||
IMPORTING iv_frame TYPE ty_amount
|
||||
iv_lens TYPE ty_amount
|
||||
iv_coat TYPE ty_amount
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_total) TYPE ty_amount.
|
||||
METHODS with_discount
|
||||
IMPORTING iv_total TYPE ty_amount
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_price) TYPE ty_amount.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}glasses_pricer IMPLEMENTATION.
|
||||
|
||||
METHOD price.
|
||||
DATA(lv_qty) = capped_qty( iv_qty ).
|
||||
IF lv_qty < 1.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
|
||||
DATA(lv_total) = total_price( iv_frame = iv_frame
|
||||
iv_lens = lens_surcharge( iv_lens )
|
||||
iv_coat = coat_surcharge( iv_coat )
|
||||
iv_qty = lv_qty ).
|
||||
|
||||
rv_price = with_discount( iv_total = lv_total
|
||||
iv_qty = lv_qty ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD capped_qty.
|
||||
rv_qty = iv_qty.
|
||||
IF rv_qty > c_max_qty.
|
||||
rv_qty = c_max_qty.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD lens_surcharge.
|
||||
CASE iv_lens.
|
||||
WHEN 'B'.
|
||||
rv_amount = c_lens_bifocal.
|
||||
WHEN 'P'.
|
||||
rv_amount = c_lens_progressive.
|
||||
WHEN OTHERS.
|
||||
rv_amount = c_lens_standard.
|
||||
ENDCASE.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD coat_surcharge.
|
||||
CASE iv_coat.
|
||||
WHEN 'A'.
|
||||
rv_amount = c_coat_simple.
|
||||
WHEN 'B'.
|
||||
rv_amount = c_coat_premium.
|
||||
WHEN OTHERS.
|
||||
rv_amount = c_coat_none.
|
||||
ENDCASE.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD total_price.
|
||||
rv_total = iv_frame * iv_qty.
|
||||
rv_total = rv_total + iv_lens * iv_qty.
|
||||
rv_total = rv_total + iv_coat / iv_qty.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD with_discount.
|
||||
rv_price = iv_total.
|
||||
IF iv_qty >= c_discount_qty.
|
||||
rv_price = iv_total - iv_total * c_discount_percent / 100.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
109
tasks_gen/train/G1002/faulty/m3_glasses_pricer.clas.abap
Normal file
109
tasks_gen/train/G1002/faulty/m3_glasses_pricer.clas.abap
Normal file
@@ -0,0 +1,109 @@
|
||||
CLASS {{p}}glasses_pricer DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC.
|
||||
|
||||
PUBLIC SECTION.
|
||||
TYPES ty_amount TYPE p LENGTH 9 DECIMALS 2.
|
||||
TYPES ty_lens TYPE c LENGTH 1.
|
||||
TYPES ty_coat TYPE c LENGTH 1.
|
||||
METHODS price
|
||||
IMPORTING iv_frame TYPE ty_amount
|
||||
iv_lens TYPE ty_lens
|
||||
iv_coat TYPE ty_coat
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_price) TYPE ty_amount.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_max_qty TYPE i VALUE 100,
|
||||
c_discount_qty TYPE i VALUE 3,
|
||||
c_discount_percent TYPE i VALUE 10,
|
||||
c_lens_standard TYPE ty_amount VALUE '40.00',
|
||||
c_lens_bifocal TYPE ty_amount VALUE '90.00',
|
||||
c_lens_progressive TYPE ty_amount VALUE '150.00',
|
||||
c_coat_simple TYPE ty_amount VALUE '25.00',
|
||||
c_coat_premium TYPE ty_amount VALUE '35.00',
|
||||
c_coat_none TYPE ty_amount VALUE '0.00'.
|
||||
|
||||
METHODS capped_qty
|
||||
IMPORTING iv_qty TYPE i
|
||||
RETURNING VALUE(rv_qty) TYPE i.
|
||||
METHODS lens_surcharge
|
||||
IMPORTING iv_lens TYPE ty_lens
|
||||
RETURNING VALUE(rv_amount) TYPE ty_amount.
|
||||
METHODS coat_surcharge
|
||||
IMPORTING iv_coat TYPE ty_coat
|
||||
RETURNING VALUE(rv_amount) TYPE ty_amount.
|
||||
METHODS total_price
|
||||
IMPORTING iv_frame TYPE ty_amount
|
||||
iv_lens TYPE ty_amount
|
||||
iv_coat TYPE ty_amount
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_total) TYPE ty_amount.
|
||||
METHODS with_discount
|
||||
IMPORTING iv_total TYPE ty_amount
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_price) TYPE ty_amount.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}glasses_pricer IMPLEMENTATION.
|
||||
|
||||
METHOD price.
|
||||
DATA(lv_qty) = capped_qty( iv_qty ).
|
||||
IF lv_qty < 1.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
|
||||
DATA(lv_total) = total_price( iv_frame = iv_frame
|
||||
iv_lens = lens_surcharge( iv_lens )
|
||||
iv_coat = coat_surcharge( iv_coat )
|
||||
iv_qty = lv_qty ).
|
||||
|
||||
rv_price = with_discount( iv_total = lv_total
|
||||
iv_qty = lv_qty ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD capped_qty.
|
||||
rv_qty = iv_qty.
|
||||
IF rv_qty > c_max_qty.
|
||||
rv_qty = c_max_qty.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD lens_surcharge.
|
||||
CASE iv_lens.
|
||||
WHEN 'B'.
|
||||
rv_amount = c_lens_bifocal.
|
||||
WHEN 'P'.
|
||||
rv_amount = c_lens_progressive.
|
||||
WHEN OTHERS.
|
||||
rv_amount = c_lens_standard.
|
||||
ENDCASE.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD coat_surcharge.
|
||||
CASE iv_coat.
|
||||
WHEN 'A'.
|
||||
rv_amount = c_coat_simple.
|
||||
WHEN 'B'.
|
||||
rv_amount = c_coat_premium.
|
||||
WHEN OTHERS.
|
||||
rv_amount = c_coat_none.
|
||||
ENDCASE.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD total_price.
|
||||
rv_total = iv_frame * iv_qty.
|
||||
rv_total = rv_total + iv_lens * iv_qty.
|
||||
rv_total = rv_total + iv_coat * iv_qty.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD with_discount.
|
||||
rv_price = iv_total.
|
||||
IF iv_qty < c_discount_qty.
|
||||
rv_price = iv_total - iv_total * c_discount_percent / 100.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
109
tasks_gen/train/G1002/faulty/m4_glasses_pricer.clas.abap
Normal file
109
tasks_gen/train/G1002/faulty/m4_glasses_pricer.clas.abap
Normal file
@@ -0,0 +1,109 @@
|
||||
CLASS {{p}}glasses_pricer DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC.
|
||||
|
||||
PUBLIC SECTION.
|
||||
TYPES ty_amount TYPE p LENGTH 9 DECIMALS 2.
|
||||
TYPES ty_lens TYPE c LENGTH 1.
|
||||
TYPES ty_coat TYPE c LENGTH 1.
|
||||
METHODS price
|
||||
IMPORTING iv_frame TYPE ty_amount
|
||||
iv_lens TYPE ty_lens
|
||||
iv_coat TYPE ty_coat
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_price) TYPE ty_amount.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_max_qty TYPE i VALUE 100,
|
||||
c_discount_qty TYPE i VALUE 3,
|
||||
c_discount_percent TYPE i VALUE 10,
|
||||
c_lens_standard TYPE ty_amount VALUE '40.00',
|
||||
c_lens_bifocal TYPE ty_amount VALUE '90.00',
|
||||
c_lens_progressive TYPE ty_amount VALUE '150.00',
|
||||
c_coat_simple TYPE ty_amount VALUE '25.00',
|
||||
c_coat_premium TYPE ty_amount VALUE '35.00',
|
||||
c_coat_none TYPE ty_amount VALUE '0.00'.
|
||||
|
||||
METHODS capped_qty
|
||||
IMPORTING iv_qty TYPE i
|
||||
RETURNING VALUE(rv_qty) TYPE i.
|
||||
METHODS lens_surcharge
|
||||
IMPORTING iv_lens TYPE ty_lens
|
||||
RETURNING VALUE(rv_amount) TYPE ty_amount.
|
||||
METHODS coat_surcharge
|
||||
IMPORTING iv_coat TYPE ty_coat
|
||||
RETURNING VALUE(rv_amount) TYPE ty_amount.
|
||||
METHODS total_price
|
||||
IMPORTING iv_frame TYPE ty_amount
|
||||
iv_lens TYPE ty_amount
|
||||
iv_coat TYPE ty_amount
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_total) TYPE ty_amount.
|
||||
METHODS with_discount
|
||||
IMPORTING iv_total TYPE ty_amount
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_price) TYPE ty_amount.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}glasses_pricer IMPLEMENTATION.
|
||||
|
||||
METHOD price.
|
||||
DATA(lv_qty) = capped_qty( iv_qty ).
|
||||
IF lv_qty < 1.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
|
||||
DATA(lv_total) = total_price( iv_frame = iv_frame
|
||||
iv_lens = lens_surcharge( iv_lens )
|
||||
iv_coat = coat_surcharge( iv_coat )
|
||||
iv_qty = lv_qty ).
|
||||
|
||||
rv_price = with_discount( iv_total = lv_total
|
||||
iv_qty = lv_qty ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD capped_qty.
|
||||
rv_qty = iv_qty.
|
||||
IF rv_qty > c_max_qty.
|
||||
rv_qty = c_max_qty.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD lens_surcharge.
|
||||
CASE iv_lens.
|
||||
WHEN 'B'.
|
||||
rv_amount = c_lens_bifocal.
|
||||
WHEN 'P'.
|
||||
rv_amount = c_lens_progressive.
|
||||
WHEN OTHERS.
|
||||
rv_amount = c_lens_standard.
|
||||
ENDCASE.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD coat_surcharge.
|
||||
CASE iv_coat.
|
||||
WHEN 'A'.
|
||||
rv_amount = c_coat_simple.
|
||||
WHEN 'B'.
|
||||
rv_amount = c_coat_premium.
|
||||
WHEN OTHERS.
|
||||
rv_amount = c_coat_none.
|
||||
ENDCASE.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD total_price.
|
||||
rv_total = iv_frame * iv_qty.
|
||||
rv_total = rv_total + iv_lens * iv_qty.
|
||||
rv_total = rv_total + iv_coat * iv_qty.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD with_discount.
|
||||
rv_price = iv_total.
|
||||
IF iv_qty >= c_discount_qty.
|
||||
rv_price = iv_total + iv_total * c_discount_percent / 100.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
24
tasks_gen/train/G1002/generation.json
Normal file
24
tasks_gen/train/G1002/generation.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": "G1002",
|
||||
"pool": "train",
|
||||
"object_type": "CLAS",
|
||||
"category": "E",
|
||||
"attempts": [
|
||||
{
|
||||
"stage": "validate",
|
||||
"oracle": null,
|
||||
"null": null
|
||||
},
|
||||
{
|
||||
"stage": "validate",
|
||||
"oracle": 100.0,
|
||||
"null": 0,
|
||||
"mutation": {
|
||||
"valid": 5,
|
||||
"killed": 5,
|
||||
"ok": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"accepted": true
|
||||
}
|
||||
100
tasks_gen/train/G1002/hidden/glasses_hidden.clas.abap
Normal file
100
tasks_gen/train/G1002/hidden/glasses_hidden.clas.abap
Normal file
@@ -0,0 +1,100 @@
|
||||
CLASS {{p}}glasses_hidden DEFINITION PUBLIC FINAL CREATE PUBLIC
|
||||
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS c_frame TYPE {{p}}glasses_pricer=>ty_amount VALUE '100.00'.
|
||||
DATA mo_cut TYPE REF TO {{p}}glasses_pricer.
|
||||
|
||||
METHODS setup.
|
||||
METHODS zero_qty_is_free FOR TESTING.
|
||||
METHODS negative_qty_is_free FOR TESTING.
|
||||
METHODS single_vision_price FOR TESTING.
|
||||
METHODS bifocal_with_coating FOR TESTING.
|
||||
METHODS progressive_blue_filter FOR TESTING.
|
||||
METHODS unknown_lens_defaults FOR TESTING.
|
||||
METHODS unknown_coat_is_free FOR TESTING.
|
||||
METHODS discount_from_three FOR TESTING.
|
||||
METHODS no_discount_for_two FOR TESTING.
|
||||
METHODS qty_capped_at_hundred FOR TESTING.
|
||||
METHODS discount_on_total FOR TESTING.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}glasses_hidden IMPLEMENTATION.
|
||||
|
||||
METHOD setup.
|
||||
mo_cut = NEW {{p}}glasses_pricer( ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD zero_qty_is_free.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '0.00' )
|
||||
act = mo_cut->price( iv_frame = c_frame iv_lens = 'S' iv_coat = 'A' iv_qty = 0 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD negative_qty_is_free.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '0.00' )
|
||||
act = mo_cut->price( iv_frame = c_frame iv_lens = 'P' iv_coat = 'B' iv_qty = -2 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD single_vision_price.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '140.00' )
|
||||
act = mo_cut->price( iv_frame = c_frame iv_lens = 'S' iv_coat = 'N' iv_qty = 1 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD bifocal_with_coating.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '430.00' )
|
||||
act = mo_cut->price( iv_frame = c_frame iv_lens = 'B' iv_coat = 'A' iv_qty = 2 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD progressive_blue_filter.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '235.00' )
|
||||
act = mo_cut->price( iv_frame = CONV {{p}}glasses_pricer=>ty_amount( '50.00' )
|
||||
iv_lens = 'P' iv_coat = 'B' iv_qty = 1 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD unknown_lens_defaults.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '140.00' )
|
||||
act = mo_cut->price( iv_frame = c_frame iv_lens = 'Z' iv_coat = 'N' iv_qty = 1 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD unknown_coat_is_free.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '140.00' )
|
||||
act = mo_cut->price( iv_frame = c_frame iv_lens = 'S' iv_coat = 'X' iv_qty = 1 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD discount_from_three.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '378.00' )
|
||||
act = mo_cut->price( iv_frame = c_frame iv_lens = 'S' iv_coat = 'N' iv_qty = 3 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD no_discount_for_two.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '280.00' )
|
||||
act = mo_cut->price( iv_frame = c_frame iv_lens = 'S' iv_coat = 'N' iv_qty = 2 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD qty_capped_at_hundred.
|
||||
DATA(lv_capped) = mo_cut->price( iv_frame = c_frame iv_lens = 'S' iv_coat = 'N' iv_qty = 100 ).
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '12600.00' )
|
||||
act = lv_capped ).
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = lv_capped
|
||||
act = mo_cut->price( iv_frame = c_frame iv_lens = 'S' iv_coat = 'N' iv_qty = 150 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD discount_on_total.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '499.50' )
|
||||
act = mo_cut->price( iv_frame = CONV {{p}}glasses_pricer=>ty_amount( '0.00' )
|
||||
iv_lens = 'P' iv_coat = 'B' iv_qty = 3 ) ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
71
tasks_gen/train/G1002/mutation.json
Normal file
71
tasks_gen/train/G1002/mutation.json
Normal file
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"task": "G1002",
|
||||
"mutants": [
|
||||
{
|
||||
"object": "{{P}}GLASSES_PRICER",
|
||||
"mutant": "line 99: * -> / (arith)",
|
||||
"status": "killed",
|
||||
"hidden": "6/11",
|
||||
"failed_tests": [
|
||||
"BIFOCAL_WITH_COATING",
|
||||
"DISCOUNT_FROM_THREE",
|
||||
"DISCOUNT_ON_TOTAL",
|
||||
"NO_DISCOUNT_FOR_TWO",
|
||||
"QTY_CAPPED_AT_HUNDRED"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}GLASSES_PRICER",
|
||||
"mutant": "line 100: + -> - (arith)",
|
||||
"status": "killed",
|
||||
"hidden": "8/11",
|
||||
"failed_tests": [
|
||||
"BIFOCAL_WITH_COATING",
|
||||
"DISCOUNT_ON_TOTAL",
|
||||
"PROGRESSIVE_BLUE_FILTER"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}GLASSES_PRICER",
|
||||
"mutant": "line 100: * -> / (arith)",
|
||||
"status": "killed",
|
||||
"hidden": "9/11",
|
||||
"failed_tests": [
|
||||
"BIFOCAL_WITH_COATING",
|
||||
"DISCOUNT_ON_TOTAL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}GLASSES_PRICER",
|
||||
"mutant": "line 105: >= -> < (rel)",
|
||||
"status": "killed",
|
||||
"hidden": "2/11",
|
||||
"failed_tests": [
|
||||
"BIFOCAL_WITH_COATING",
|
||||
"DISCOUNT_FROM_THREE",
|
||||
"DISCOUNT_ON_TOTAL",
|
||||
"NO_DISCOUNT_FOR_TWO",
|
||||
"PROGRESSIVE_BLUE_FILTER",
|
||||
"QTY_CAPPED_AT_HUNDRED",
|
||||
"SINGLE_VISION_PRICE",
|
||||
"UNKNOWN_COAT_IS_FREE",
|
||||
"UNKNOWN_LENS_DEFAULTS"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}GLASSES_PRICER",
|
||||
"mutant": "line 106: - -> + (arith)",
|
||||
"status": "killed",
|
||||
"hidden": "8/11",
|
||||
"failed_tests": [
|
||||
"DISCOUNT_FROM_THREE",
|
||||
"DISCOUNT_ON_TOTAL",
|
||||
"QTY_CAPPED_AT_HUNDRED"
|
||||
]
|
||||
}
|
||||
],
|
||||
"valid": 5,
|
||||
"killed": 5,
|
||||
"kill_rate": 1.0,
|
||||
"ok": true
|
||||
}
|
||||
109
tasks_gen/train/G1002/reference/glasses_pricer.clas.abap
Normal file
109
tasks_gen/train/G1002/reference/glasses_pricer.clas.abap
Normal file
@@ -0,0 +1,109 @@
|
||||
CLASS {{p}}glasses_pricer DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC.
|
||||
|
||||
PUBLIC SECTION.
|
||||
TYPES ty_amount TYPE p LENGTH 9 DECIMALS 2.
|
||||
TYPES ty_lens TYPE c LENGTH 1.
|
||||
TYPES ty_coat TYPE c LENGTH 1.
|
||||
METHODS price
|
||||
IMPORTING iv_frame TYPE ty_amount
|
||||
iv_lens TYPE ty_lens
|
||||
iv_coat TYPE ty_coat
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_price) TYPE ty_amount.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_max_qty TYPE i VALUE 100,
|
||||
c_discount_qty TYPE i VALUE 3,
|
||||
c_discount_percent TYPE i VALUE 10,
|
||||
c_lens_standard TYPE ty_amount VALUE '40.00',
|
||||
c_lens_bifocal TYPE ty_amount VALUE '90.00',
|
||||
c_lens_progressive TYPE ty_amount VALUE '150.00',
|
||||
c_coat_simple TYPE ty_amount VALUE '25.00',
|
||||
c_coat_premium TYPE ty_amount VALUE '35.00',
|
||||
c_coat_none TYPE ty_amount VALUE '0.00'.
|
||||
|
||||
METHODS capped_qty
|
||||
IMPORTING iv_qty TYPE i
|
||||
RETURNING VALUE(rv_qty) TYPE i.
|
||||
METHODS lens_surcharge
|
||||
IMPORTING iv_lens TYPE ty_lens
|
||||
RETURNING VALUE(rv_amount) TYPE ty_amount.
|
||||
METHODS coat_surcharge
|
||||
IMPORTING iv_coat TYPE ty_coat
|
||||
RETURNING VALUE(rv_amount) TYPE ty_amount.
|
||||
METHODS total_price
|
||||
IMPORTING iv_frame TYPE ty_amount
|
||||
iv_lens TYPE ty_amount
|
||||
iv_coat TYPE ty_amount
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_total) TYPE ty_amount.
|
||||
METHODS with_discount
|
||||
IMPORTING iv_total TYPE ty_amount
|
||||
iv_qty TYPE i
|
||||
RETURNING VALUE(rv_price) TYPE ty_amount.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}glasses_pricer IMPLEMENTATION.
|
||||
|
||||
METHOD price.
|
||||
DATA(lv_qty) = capped_qty( iv_qty ).
|
||||
IF lv_qty < 1.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
|
||||
DATA(lv_total) = total_price( iv_frame = iv_frame
|
||||
iv_lens = lens_surcharge( iv_lens )
|
||||
iv_coat = coat_surcharge( iv_coat )
|
||||
iv_qty = lv_qty ).
|
||||
|
||||
rv_price = with_discount( iv_total = lv_total
|
||||
iv_qty = lv_qty ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD capped_qty.
|
||||
rv_qty = iv_qty.
|
||||
IF rv_qty > c_max_qty.
|
||||
rv_qty = c_max_qty.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD lens_surcharge.
|
||||
CASE iv_lens.
|
||||
WHEN 'B'.
|
||||
rv_amount = c_lens_bifocal.
|
||||
WHEN 'P'.
|
||||
rv_amount = c_lens_progressive.
|
||||
WHEN OTHERS.
|
||||
rv_amount = c_lens_standard.
|
||||
ENDCASE.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD coat_surcharge.
|
||||
CASE iv_coat.
|
||||
WHEN 'A'.
|
||||
rv_amount = c_coat_simple.
|
||||
WHEN 'B'.
|
||||
rv_amount = c_coat_premium.
|
||||
WHEN OTHERS.
|
||||
rv_amount = c_coat_none.
|
||||
ENDCASE.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD total_price.
|
||||
rv_total = iv_frame * iv_qty.
|
||||
rv_total = rv_total + iv_lens * iv_qty.
|
||||
rv_total = rv_total + iv_coat * iv_qty.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD with_discount.
|
||||
rv_price = iv_total.
|
||||
IF iv_qty >= c_discount_qty.
|
||||
rv_price = iv_total - iv_total * c_discount_percent / 100.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
@@ -0,0 +1,83 @@
|
||||
CLASS ltc_glasses_pricer DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS c_frame TYPE {{p}}glasses_pricer=>ty_amount VALUE '100.00'.
|
||||
DATA mo_cut TYPE REF TO {{p}}glasses_pricer.
|
||||
|
||||
METHODS setup.
|
||||
METHODS single_vision FOR TESTING.
|
||||
METHODS bifocal_with_coating FOR TESTING.
|
||||
METHODS progressive_with_blue FOR TESTING.
|
||||
METHODS unknown_lens_defaults FOR TESTING.
|
||||
METHODS unknown_coat_is_free FOR TESTING.
|
||||
METHODS discount_from_three FOR TESTING.
|
||||
METHODS no_discount_for_two FOR TESTING.
|
||||
METHODS zero_qty_is_free FOR TESTING.
|
||||
METHODS qty_capped_at_hundred FOR TESTING.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS ltc_glasses_pricer IMPLEMENTATION.
|
||||
|
||||
METHOD setup.
|
||||
mo_cut = NEW #( ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD single_vision.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '140.00' )
|
||||
act = mo_cut->price( iv_frame = c_frame iv_lens = 'S' iv_coat = 'N' iv_qty = 1 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD bifocal_with_coating.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '430.00' )
|
||||
act = mo_cut->price( iv_frame = c_frame iv_lens = 'B' iv_coat = 'A' iv_qty = 2 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD progressive_with_blue.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '235.00' )
|
||||
act = mo_cut->price( iv_frame = CONV {{p}}glasses_pricer=>ty_amount( '50.00' )
|
||||
iv_lens = 'P' iv_coat = 'B' iv_qty = 1 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD unknown_lens_defaults.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '140.00' )
|
||||
act = mo_cut->price( iv_frame = c_frame iv_lens = 'Z' iv_coat = 'N' iv_qty = 1 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD unknown_coat_is_free.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '140.00' )
|
||||
act = mo_cut->price( iv_frame = c_frame iv_lens = 'S' iv_coat = 'X' iv_qty = 1 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD discount_from_three.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '378.00' )
|
||||
act = mo_cut->price( iv_frame = c_frame iv_lens = 'S' iv_coat = 'N' iv_qty = 3 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD no_discount_for_two.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '280.00' )
|
||||
act = mo_cut->price( iv_frame = c_frame iv_lens = 'S' iv_coat = 'N' iv_qty = 2 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD zero_qty_is_free.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '0.00' )
|
||||
act = mo_cut->price( iv_frame = c_frame iv_lens = 'S' iv_coat = 'A' iv_qty = 0 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD qty_capped_at_hundred.
|
||||
DATA(lv_capped) = mo_cut->price( iv_frame = c_frame iv_lens = 'S' iv_coat = 'N' iv_qty = 100 ).
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = CONV {{p}}glasses_pricer=>ty_amount( '12600.00' )
|
||||
act = lv_capped ).
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = lv_capped
|
||||
act = mo_cut->price( iv_frame = c_frame iv_lens = 'S' iv_coat = 'N' iv_qty = 150 ) ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
75
tasks_gen/train/G1002/seed/glasses_pricer.clas.abap
Normal file
75
tasks_gen/train/G1002/seed/glasses_pricer.clas.abap
Normal file
@@ -0,0 +1,75 @@
|
||||
CLASS {{p}}glasses_pricer DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC .
|
||||
|
||||
PUBLIC SECTION.
|
||||
TYPES ty_amount TYPE p LENGTH 9 DECIMALS 2 .
|
||||
TYPES ty_lens TYPE c LENGTH 1 .
|
||||
TYPES ty_coat TYPE c LENGTH 1 .
|
||||
METHODS price
|
||||
IMPORTING
|
||||
iv_frame TYPE ty_amount
|
||||
iv_lens TYPE ty_lens
|
||||
iv_coat TYPE ty_coat
|
||||
iv_qty TYPE i
|
||||
RETURNING
|
||||
VALUE(rv_price) TYPE ty_amount .
|
||||
PROTECTED SECTION.
|
||||
PRIVATE SECTION.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}glasses_pricer IMPLEMENTATION.
|
||||
|
||||
METHOD price.
|
||||
|
||||
DATA lv_qty TYPE i .
|
||||
DATA lv_frame TYPE ty_amount .
|
||||
DATA lv_lens TYPE ty_amount .
|
||||
DATA lv_coat TYPE ty_amount .
|
||||
DATA lv_total TYPE ty_amount .
|
||||
|
||||
lv_qty = iv_qty .
|
||||
IF lv_qty > 100 .
|
||||
lv_qty = 100 .
|
||||
ENDIF .
|
||||
|
||||
IF lv_qty < 1 .
|
||||
rv_price = 0 .
|
||||
RETURN .
|
||||
ENDIF .
|
||||
|
||||
lv_frame = iv_frame * lv_qty .
|
||||
|
||||
IF iv_lens = 'S' .
|
||||
lv_lens = 40 .
|
||||
ELSEIF iv_lens = 'B' .
|
||||
lv_lens = 90 .
|
||||
ELSEIF iv_lens = 'P' .
|
||||
lv_lens = 150 .
|
||||
ELSE .
|
||||
lv_lens = 40 .
|
||||
ENDIF .
|
||||
lv_lens = lv_lens * lv_qty .
|
||||
|
||||
CASE iv_coat .
|
||||
WHEN 'A' .
|
||||
lv_coat = 25 .
|
||||
WHEN 'B' .
|
||||
lv_coat = 35 .
|
||||
WHEN OTHERS .
|
||||
lv_coat = 0 .
|
||||
ENDCASE .
|
||||
lv_coat = lv_coat * lv_qty .
|
||||
|
||||
lv_total = lv_frame + lv_lens + lv_coat .
|
||||
|
||||
IF lv_qty >= 3 .
|
||||
lv_total = lv_total - lv_total * 10 / 100 .
|
||||
ENDIF .
|
||||
|
||||
rv_price = lv_total .
|
||||
|
||||
ENDMETHOD .
|
||||
ENDCLASS.
|
||||
12
tasks_gen/train/G1002/seed/optic_quote_rpt.prog.abap
Normal file
12
tasks_gen/train/G1002/seed/optic_quote_rpt.prog.abap
Normal file
@@ -0,0 +1,12 @@
|
||||
REPORT {{p}}optic_quote_rpt.
|
||||
|
||||
DATA lo_pricer TYPE REF TO {{p}}glasses_pricer.
|
||||
DATA lv_price TYPE {{p}}glasses_pricer=>ty_amount.
|
||||
|
||||
lo_pricer = NEW #( ).
|
||||
lv_price = lo_pricer->price( iv_frame = CONV {{p}}glasses_pricer=>ty_amount( '120.00' )
|
||||
iv_lens = 'P'
|
||||
iv_coat = 'A'
|
||||
iv_qty = 2 ).
|
||||
|
||||
WRITE: / 'Quotation:', lv_price.
|
||||
51
tasks_gen/train/G1002/spec.md
Normal file
51
tasks_gen/train/G1002/spec.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# 1. Goal
|
||||
The optician shop uses the class {{P}}GLASSES_PRICER to calculate the price of a
|
||||
glasses order. A sales program calls the class for each quotation. The class is
|
||||
legacy code. It is hard to read and hard to test. Refactor the class. The
|
||||
behavior must stay the same.
|
||||
|
||||
# 2. Open questions
|
||||
None.
|
||||
|
||||
# 3. Context
|
||||
- The class {{P}}GLASSES_PRICER exists in package $TMP. It is active.
|
||||
- The class is public and final. It has a public constructor without parameters.
|
||||
- The public interface of the class is:
|
||||
- the type TY_AMOUNT (packed number, length 9, 2 decimals),
|
||||
- the type TY_LENS (character, length 1),
|
||||
- the type TY_COAT (character, length 1),
|
||||
- the method PRICE with the importing parameters IV_FRAME (TY_AMOUNT),
|
||||
IV_LENS (TY_LENS), IV_COAT (TY_COAT), IV_QTY (TYPE i) and the returning
|
||||
parameter RV_PRICE (TY_AMOUNT).
|
||||
- The program {{P}}OPTIC_QUOTE_RPT calls the class.
|
||||
- The legacy implementation is the specification of the behavior.
|
||||
|
||||
# 4. Contract
|
||||
- Refactor the class {{P}}GLASSES_PRICER in package $TMP. The name stays the same.
|
||||
- The class stays public and final and keeps its public constructor without
|
||||
parameters.
|
||||
- Keep the public types TY_AMOUNT, TY_LENS and TY_COAT.
|
||||
- Keep the method PRICE with the same parameter names, the same parameter types
|
||||
and the same sequence.
|
||||
- Do not add public methods or public attributes.
|
||||
- Do not create other objects.
|
||||
|
||||
# 5. Business rules
|
||||
- The behavior of the class must not change. For every input, PRICE must return
|
||||
the same value as the legacy method.
|
||||
- The legacy code holds all rules, including its limits and its default values.
|
||||
- Do not add a rule. Do not remove a rule. Do not correct a rule.
|
||||
- PRICE returns a price in the currency of the order.
|
||||
|
||||
# 6. Constraints
|
||||
- Release target: ABAP Platform 2025 (SAP_BASIS 816).
|
||||
- Coding standards: Clean ABAP. One method does one thing. Method length below
|
||||
40 statements. No deep nesting. No magic numbers: use constants. No duplicated
|
||||
code. No dead code. No global variables. No comment that restates the code.
|
||||
- Out of scope: do not change the program {{P}}OPTIC_QUOTE_RPT. Do not change
|
||||
the public interface of the class.
|
||||
|
||||
# 7. Acceptance
|
||||
- The class is active and has no syntax error.
|
||||
- The hidden tests pass.
|
||||
- Write your own ABAP Unit tests for the class.
|
||||
57
tasks_gen/train/G1002/task.json
Normal file
57
tasks_gen/train/G1002/task.json
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"id": "G1002",
|
||||
"category": "E",
|
||||
"object_type": "CLAS",
|
||||
"difficulty": 2,
|
||||
"release_target": "v816",
|
||||
"expected_outcome": "implement",
|
||||
"budget": {
|
||||
"max_tool_calls": 70,
|
||||
"max_activations": 18
|
||||
},
|
||||
"seed": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}GLASSES_PRICER",
|
||||
"file": "seed/glasses_pricer.clas.abap",
|
||||
"description": "Legacy price calculator for glasses orders"
|
||||
},
|
||||
{
|
||||
"type": "PROG",
|
||||
"name": "{{P}}OPTIC_QUOTE_RPT",
|
||||
"file": "seed/optic_quote_rpt.prog.abap",
|
||||
"description": "Report that calls the legacy class"
|
||||
}
|
||||
],
|
||||
"contract": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}GLASSES_PRICER"
|
||||
}
|
||||
],
|
||||
"out_of_scope": [
|
||||
"{{P}}OPTIC_QUOTE_RPT"
|
||||
],
|
||||
"hidden_tests": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}GLASSES_HIDDEN",
|
||||
"file": "hidden/glasses_hidden.clas.abap",
|
||||
"description": "Hidden behavior tests for the refactored class"
|
||||
}
|
||||
],
|
||||
"reference": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}GLASSES_PRICER",
|
||||
"file": "reference/glasses_pricer.clas.abap",
|
||||
"description": "Refactored glasses price calculator",
|
||||
"testclasses_file": "reference/glasses_pricer.testclasses.abap"
|
||||
}
|
||||
],
|
||||
"craft_checks": [
|
||||
"method_length",
|
||||
"nesting_depth",
|
||||
"magic_numbers"
|
||||
]
|
||||
}
|
||||
49
tasks_gen/train/G1003/faulty/m0_drone_checker.clas.abap
Normal file
49
tasks_gen/train/G1003/faulty/m0_drone_checker.clas.abap
Normal file
@@ -0,0 +1,49 @@
|
||||
CLASS {{p}}drone_checker DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
INTERFACES {{p}}if_drone_check.
|
||||
|
||||
METHODS required_battery
|
||||
IMPORTING iv_distance TYPE {{p}}if_drone_check=>ty_distance
|
||||
RETURNING VALUE(rv_percent) TYPE {{p}}if_drone_check=>ty_percent.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_max_payload TYPE {{p}}if_drone_check=>ty_weight VALUE '5.00',
|
||||
c_max_distance TYPE {{p}}if_drone_check=>ty_distance VALUE '20.00',
|
||||
c_max_wind TYPE {{p}}if_drone_check=>ty_speed VALUE '12.00',
|
||||
c_reserve TYPE {{p}}if_drone_check=>ty_percent VALUE 10,
|
||||
c_percent_per_km TYPE {{p}}if_drone_check=>ty_percent VALUE 2.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}drone_checker IMPLEMENTATION.
|
||||
METHOD {{p}}if_drone_check~check.
|
||||
IF iv_payload <= 0 AND iv_payload > c_max_payload.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-payload.
|
||||
ELSEIF iv_distance <= 0 OR iv_distance > c_max_distance.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-distance.
|
||||
ELSEIF iv_wind_speed > c_max_wind.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-wind.
|
||||
ELSEIF iv_battery < required_battery( iv_distance ).
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-battery.
|
||||
ELSEIF iv_in_zone = abap_false.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-zone.
|
||||
ELSEIF iv_daylight = abap_false.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-light.
|
||||
ELSE.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-ok.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD required_battery.
|
||||
IF iv_distance <= 0.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
DATA lv_km TYPE i.
|
||||
lv_km = iv_distance.
|
||||
IF lv_km < iv_distance.
|
||||
lv_km = lv_km + 1.
|
||||
ENDIF.
|
||||
rv_percent = lv_km * c_percent_per_km + c_reserve.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
49
tasks_gen/train/G1003/faulty/m1_drone_checker.clas.abap
Normal file
49
tasks_gen/train/G1003/faulty/m1_drone_checker.clas.abap
Normal file
@@ -0,0 +1,49 @@
|
||||
CLASS {{p}}drone_checker DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
INTERFACES {{p}}if_drone_check.
|
||||
|
||||
METHODS required_battery
|
||||
IMPORTING iv_distance TYPE {{p}}if_drone_check=>ty_distance
|
||||
RETURNING VALUE(rv_percent) TYPE {{p}}if_drone_check=>ty_percent.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_max_payload TYPE {{p}}if_drone_check=>ty_weight VALUE '5.00',
|
||||
c_max_distance TYPE {{p}}if_drone_check=>ty_distance VALUE '20.00',
|
||||
c_max_wind TYPE {{p}}if_drone_check=>ty_speed VALUE '12.00',
|
||||
c_reserve TYPE {{p}}if_drone_check=>ty_percent VALUE 10,
|
||||
c_percent_per_km TYPE {{p}}if_drone_check=>ty_percent VALUE 2.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}drone_checker IMPLEMENTATION.
|
||||
METHOD {{p}}if_drone_check~check.
|
||||
IF iv_payload <= 0 OR iv_payload > c_max_payload.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-payload.
|
||||
ELSEIF iv_distance <= 0 OR iv_distance <= c_max_distance.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-distance.
|
||||
ELSEIF iv_wind_speed > c_max_wind.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-wind.
|
||||
ELSEIF iv_battery < required_battery( iv_distance ).
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-battery.
|
||||
ELSEIF iv_in_zone = abap_false.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-zone.
|
||||
ELSEIF iv_daylight = abap_false.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-light.
|
||||
ELSE.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-ok.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD required_battery.
|
||||
IF iv_distance <= 0.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
DATA lv_km TYPE i.
|
||||
lv_km = iv_distance.
|
||||
IF lv_km < iv_distance.
|
||||
lv_km = lv_km + 1.
|
||||
ENDIF.
|
||||
rv_percent = lv_km * c_percent_per_km + c_reserve.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
49
tasks_gen/train/G1003/faulty/m2_drone_checker.clas.abap
Normal file
49
tasks_gen/train/G1003/faulty/m2_drone_checker.clas.abap
Normal file
@@ -0,0 +1,49 @@
|
||||
CLASS {{p}}drone_checker DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
INTERFACES {{p}}if_drone_check.
|
||||
|
||||
METHODS required_battery
|
||||
IMPORTING iv_distance TYPE {{p}}if_drone_check=>ty_distance
|
||||
RETURNING VALUE(rv_percent) TYPE {{p}}if_drone_check=>ty_percent.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_max_payload TYPE {{p}}if_drone_check=>ty_weight VALUE '5.00',
|
||||
c_max_distance TYPE {{p}}if_drone_check=>ty_distance VALUE '20.00',
|
||||
c_max_wind TYPE {{p}}if_drone_check=>ty_speed VALUE '12.00',
|
||||
c_reserve TYPE {{p}}if_drone_check=>ty_percent VALUE 10,
|
||||
c_percent_per_km TYPE {{p}}if_drone_check=>ty_percent VALUE 2.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}drone_checker IMPLEMENTATION.
|
||||
METHOD {{p}}if_drone_check~check.
|
||||
IF iv_payload <= 0 OR iv_payload > c_max_payload.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-payload.
|
||||
ELSEIF iv_distance <= 0 OR iv_distance > c_max_distance.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-distance.
|
||||
ELSEIF iv_wind_speed > c_max_wind.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-wind.
|
||||
ELSEIF iv_battery < required_battery( iv_distance ).
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-battery.
|
||||
ELSEIF iv_in_zone <> abap_false.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-zone.
|
||||
ELSEIF iv_daylight = abap_false.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-light.
|
||||
ELSE.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-ok.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD required_battery.
|
||||
IF iv_distance <= 0.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
DATA lv_km TYPE i.
|
||||
lv_km = iv_distance.
|
||||
IF lv_km < iv_distance.
|
||||
lv_km = lv_km + 1.
|
||||
ENDIF.
|
||||
rv_percent = lv_km * c_percent_per_km + c_reserve.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
49
tasks_gen/train/G1003/faulty/m3_drone_checker.clas.abap
Normal file
49
tasks_gen/train/G1003/faulty/m3_drone_checker.clas.abap
Normal file
@@ -0,0 +1,49 @@
|
||||
CLASS {{p}}drone_checker DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
INTERFACES {{p}}if_drone_check.
|
||||
|
||||
METHODS required_battery
|
||||
IMPORTING iv_distance TYPE {{p}}if_drone_check=>ty_distance
|
||||
RETURNING VALUE(rv_percent) TYPE {{p}}if_drone_check=>ty_percent.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_max_payload TYPE {{p}}if_drone_check=>ty_weight VALUE '5.00',
|
||||
c_max_distance TYPE {{p}}if_drone_check=>ty_distance VALUE '20.00',
|
||||
c_max_wind TYPE {{p}}if_drone_check=>ty_speed VALUE '12.00',
|
||||
c_reserve TYPE {{p}}if_drone_check=>ty_percent VALUE 10,
|
||||
c_percent_per_km TYPE {{p}}if_drone_check=>ty_percent VALUE 2.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}drone_checker IMPLEMENTATION.
|
||||
METHOD {{p}}if_drone_check~check.
|
||||
IF iv_payload <= 0 OR iv_payload > c_max_payload.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-payload.
|
||||
ELSEIF iv_distance <= 0 OR iv_distance > c_max_distance.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-distance.
|
||||
ELSEIF iv_wind_speed > c_max_wind.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-wind.
|
||||
ELSEIF iv_battery < required_battery( iv_distance ).
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-battery.
|
||||
ELSEIF iv_in_zone = abap_false.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-zone.
|
||||
ELSEIF iv_daylight = abap_true.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-light.
|
||||
ELSE.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-ok.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD required_battery.
|
||||
IF iv_distance <= 0.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
DATA lv_km TYPE i.
|
||||
lv_km = iv_distance.
|
||||
IF lv_km < iv_distance.
|
||||
lv_km = lv_km + 1.
|
||||
ENDIF.
|
||||
rv_percent = lv_km * c_percent_per_km + c_reserve.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
24
tasks_gen/train/G1003/generation.json
Normal file
24
tasks_gen/train/G1003/generation.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": "G1003",
|
||||
"pool": "train",
|
||||
"object_type": "CLAS",
|
||||
"category": "A",
|
||||
"attempts": [
|
||||
{
|
||||
"stage": "validate",
|
||||
"oracle": 70.0,
|
||||
"null": 0
|
||||
},
|
||||
{
|
||||
"stage": "validate",
|
||||
"oracle": 100.0,
|
||||
"null": 0,
|
||||
"mutation": {
|
||||
"valid": 5,
|
||||
"killed": 4,
|
||||
"ok": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"accepted": true
|
||||
}
|
||||
172
tasks_gen/train/G1003/hidden/t21_hidden.clas.abap
Normal file
172
tasks_gen/train/G1003/hidden/t21_hidden.clas.abap
Normal file
@@ -0,0 +1,172 @@
|
||||
CLASS {{p}}t21_hidden DEFINITION PUBLIC FINAL CREATE PUBLIC
|
||||
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
|
||||
PRIVATE SECTION.
|
||||
DATA mo_cut TYPE REF TO {{p}}if_drone_check.
|
||||
DATA mo_drone TYPE REF TO {{p}}drone_checker.
|
||||
|
||||
METHODS setup.
|
||||
|
||||
METHODS ok_flight FOR TESTING.
|
||||
METHODS payload_zero FOR TESTING.
|
||||
METHODS payload_too_heavy FOR TESTING.
|
||||
METHODS distance_zero FOR TESTING.
|
||||
METHODS distance_too_far FOR TESTING.
|
||||
METHODS wind_too_strong FOR TESTING.
|
||||
METHODS battery_too_low FOR TESTING.
|
||||
METHODS battery_exact_ok FOR TESTING.
|
||||
METHODS outside_zone FOR TESTING.
|
||||
METHODS no_daylight FOR TESTING.
|
||||
METHODS required_battery_rounds_up FOR TESTING.
|
||||
METHODS order_payload_first FOR TESTING.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}t21_hidden IMPLEMENTATION.
|
||||
METHOD setup.
|
||||
mo_drone = NEW {{p}}drone_checker( ).
|
||||
mo_cut = mo_drone.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD ok_flight.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-ok
|
||||
act = mo_cut->check( iv_payload = '2.00'
|
||||
iv_distance = '10.00'
|
||||
iv_wind_speed = '5.00'
|
||||
iv_battery = 30
|
||||
iv_in_zone = abap_true
|
||||
iv_daylight = abap_true ) ).
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-ok
|
||||
act = mo_cut->check( iv_payload = '5.00'
|
||||
iv_distance = '20.00'
|
||||
iv_wind_speed = '12.00'
|
||||
iv_battery = 50
|
||||
iv_in_zone = abap_true
|
||||
iv_daylight = abap_true ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD payload_zero.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-payload
|
||||
act = mo_cut->check( iv_payload = '0.00'
|
||||
iv_distance = '10.00'
|
||||
iv_wind_speed = '5.00'
|
||||
iv_battery = 30
|
||||
iv_in_zone = abap_true
|
||||
iv_daylight = abap_true ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD payload_too_heavy.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-payload
|
||||
act = mo_cut->check( iv_payload = '5.01'
|
||||
iv_distance = '10.00'
|
||||
iv_wind_speed = '5.00'
|
||||
iv_battery = 30
|
||||
iv_in_zone = abap_true
|
||||
iv_daylight = abap_true ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD distance_zero.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-distance
|
||||
act = mo_cut->check( iv_payload = '2.00'
|
||||
iv_distance = '0.00'
|
||||
iv_wind_speed = '5.00'
|
||||
iv_battery = 30
|
||||
iv_in_zone = abap_true
|
||||
iv_daylight = abap_true ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD distance_too_far.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-distance
|
||||
act = mo_cut->check( iv_payload = '2.00'
|
||||
iv_distance = '20.01'
|
||||
iv_wind_speed = '5.00'
|
||||
iv_battery = 60
|
||||
iv_in_zone = abap_true
|
||||
iv_daylight = abap_true ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD wind_too_strong.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-wind
|
||||
act = mo_cut->check( iv_payload = '2.00'
|
||||
iv_distance = '10.00'
|
||||
iv_wind_speed = '12.01'
|
||||
iv_battery = 30
|
||||
iv_in_zone = abap_true
|
||||
iv_daylight = abap_true ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD battery_too_low.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-battery
|
||||
act = mo_cut->check( iv_payload = '2.00'
|
||||
iv_distance = '10.00'
|
||||
iv_wind_speed = '5.00'
|
||||
iv_battery = 29
|
||||
iv_in_zone = abap_true
|
||||
iv_daylight = abap_true ) ).
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-battery
|
||||
act = mo_cut->check( iv_payload = '2.00'
|
||||
iv_distance = '7.50'
|
||||
iv_wind_speed = '5.00'
|
||||
iv_battery = 25
|
||||
iv_in_zone = abap_true
|
||||
iv_daylight = abap_true ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD battery_exact_ok.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-ok
|
||||
act = mo_cut->check( iv_payload = '2.00'
|
||||
iv_distance = '10.00'
|
||||
iv_wind_speed = '5.00'
|
||||
iv_battery = 30
|
||||
iv_in_zone = abap_true
|
||||
iv_daylight = abap_true ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD outside_zone.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-zone
|
||||
act = mo_cut->check( iv_payload = '2.00'
|
||||
iv_distance = '10.00'
|
||||
iv_wind_speed = '5.00'
|
||||
iv_battery = 30
|
||||
iv_in_zone = abap_false
|
||||
iv_daylight = abap_true ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD no_daylight.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-light
|
||||
act = mo_cut->check( iv_payload = '2.00'
|
||||
iv_distance = '10.00'
|
||||
iv_wind_speed = '5.00'
|
||||
iv_battery = 30
|
||||
iv_in_zone = abap_true
|
||||
iv_daylight = abap_false ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD required_battery_rounds_up.
|
||||
cl_abap_unit_assert=>assert_equals( exp = 26 act = mo_drone->required_battery( '7.50' ) ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 50 act = mo_drone->required_battery( '20.00' ) ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 0 act = mo_drone->required_battery( '0.00' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD order_payload_first.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-payload
|
||||
act = mo_cut->check( iv_payload = '6.00'
|
||||
iv_distance = '25.00'
|
||||
iv_wind_speed = '20.00'
|
||||
iv_battery = 0
|
||||
iv_in_zone = abap_false
|
||||
iv_daylight = abap_false ) ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
65
tasks_gen/train/G1003/mutation.json
Normal file
65
tasks_gen/train/G1003/mutation.json
Normal file
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"task": "G1003",
|
||||
"mutants": [
|
||||
{
|
||||
"object": "{{P}}DRONE_CHECKER",
|
||||
"mutant": "line 21: OR -> AND (logic)",
|
||||
"status": "killed",
|
||||
"hidden": "9/12",
|
||||
"failed_tests": [
|
||||
"ORDER_PAYLOAD_FIRST",
|
||||
"PAYLOAD_TOO_HEAVY",
|
||||
"PAYLOAD_ZERO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}DRONE_CHECKER",
|
||||
"mutant": "line 23: > -> <= (rel)",
|
||||
"status": "killed",
|
||||
"hidden": "5/12",
|
||||
"failed_tests": [
|
||||
"BATTERY_EXACT_OK",
|
||||
"BATTERY_TOO_LOW",
|
||||
"DISTANCE_TOO_FAR",
|
||||
"NO_DAYLIGHT",
|
||||
"OK_FLIGHT",
|
||||
"OUTSIDE_ZONE",
|
||||
"WIND_TOO_STRONG"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}DRONE_CHECKER",
|
||||
"mutant": "line 29: = -> <> (eq)",
|
||||
"status": "killed",
|
||||
"hidden": "8/12",
|
||||
"failed_tests": [
|
||||
"BATTERY_EXACT_OK",
|
||||
"NO_DAYLIGHT",
|
||||
"OK_FLIGHT",
|
||||
"OUTSIDE_ZONE"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}DRONE_CHECKER",
|
||||
"mutant": "line 31: abap_false -> abap_true (bool)",
|
||||
"status": "killed",
|
||||
"hidden": "9/12",
|
||||
"failed_tests": [
|
||||
"BATTERY_EXACT_OK",
|
||||
"NO_DAYLIGHT",
|
||||
"OK_FLIGHT"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}DRONE_CHECKER",
|
||||
"mutant": "line 45: + -> - (arith)",
|
||||
"status": "survived",
|
||||
"hidden": "12/12",
|
||||
"failed_tests": []
|
||||
}
|
||||
],
|
||||
"valid": 5,
|
||||
"killed": 4,
|
||||
"kill_rate": 0.8,
|
||||
"ok": true
|
||||
}
|
||||
49
tasks_gen/train/G1003/reference/drone_checker.clas.abap
Normal file
49
tasks_gen/train/G1003/reference/drone_checker.clas.abap
Normal file
@@ -0,0 +1,49 @@
|
||||
CLASS {{p}}drone_checker DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
INTERFACES {{p}}if_drone_check.
|
||||
|
||||
METHODS required_battery
|
||||
IMPORTING iv_distance TYPE {{p}}if_drone_check=>ty_distance
|
||||
RETURNING VALUE(rv_percent) TYPE {{p}}if_drone_check=>ty_percent.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_max_payload TYPE {{p}}if_drone_check=>ty_weight VALUE '5.00',
|
||||
c_max_distance TYPE {{p}}if_drone_check=>ty_distance VALUE '20.00',
|
||||
c_max_wind TYPE {{p}}if_drone_check=>ty_speed VALUE '12.00',
|
||||
c_reserve TYPE {{p}}if_drone_check=>ty_percent VALUE 10,
|
||||
c_percent_per_km TYPE {{p}}if_drone_check=>ty_percent VALUE 2.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}drone_checker IMPLEMENTATION.
|
||||
METHOD {{p}}if_drone_check~check.
|
||||
IF iv_payload <= 0 OR iv_payload > c_max_payload.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-payload.
|
||||
ELSEIF iv_distance <= 0 OR iv_distance > c_max_distance.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-distance.
|
||||
ELSEIF iv_wind_speed > c_max_wind.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-wind.
|
||||
ELSEIF iv_battery < required_battery( iv_distance ).
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-battery.
|
||||
ELSEIF iv_in_zone = abap_false.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-zone.
|
||||
ELSEIF iv_daylight = abap_false.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-light.
|
||||
ELSE.
|
||||
rv_reason = {{p}}if_drone_check=>c_reason-ok.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD required_battery.
|
||||
IF iv_distance <= 0.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
DATA lv_km TYPE i.
|
||||
lv_km = iv_distance.
|
||||
IF lv_km < iv_distance.
|
||||
lv_km = lv_km + 1.
|
||||
ENDIF.
|
||||
rv_percent = lv_km * c_percent_per_km + c_reserve.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
110
tasks_gen/train/G1003/reference/drone_checker.testclasses.abap
Normal file
110
tasks_gen/train/G1003/reference/drone_checker.testclasses.abap
Normal file
@@ -0,0 +1,110 @@
|
||||
CLASS ltc_drone_checker DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
|
||||
PRIVATE SECTION.
|
||||
DATA mo_cut TYPE REF TO {{p}}if_drone_check.
|
||||
DATA mo_drone TYPE REF TO {{p}}drone_checker.
|
||||
|
||||
METHODS setup.
|
||||
METHODS valid_request_is_ok FOR TESTING.
|
||||
METHODS heavy_payload_is_rejected FOR TESTING.
|
||||
METHODS strong_wind_is_rejected FOR TESTING.
|
||||
METHODS low_battery_is_rejected FOR TESTING.
|
||||
METHODS required_battery_is_rounded_up FOR TESTING.
|
||||
METHODS zone_and_light_are_checked FOR TESTING.
|
||||
METHODS reason_order_is_kept FOR TESTING.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS ltc_drone_checker IMPLEMENTATION.
|
||||
METHOD setup.
|
||||
mo_drone = NEW {{p}}drone_checker( ).
|
||||
mo_cut = mo_drone.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD valid_request_is_ok.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-ok
|
||||
act = mo_cut->check( iv_payload = '2.00'
|
||||
iv_distance = '10.00'
|
||||
iv_wind_speed = '5.00'
|
||||
iv_battery = 30
|
||||
iv_in_zone = abap_true
|
||||
iv_daylight = abap_true ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD heavy_payload_is_rejected.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-payload
|
||||
act = mo_cut->check( iv_payload = '5.01'
|
||||
iv_distance = '10.00'
|
||||
iv_wind_speed = '5.00'
|
||||
iv_battery = 30
|
||||
iv_in_zone = abap_true
|
||||
iv_daylight = abap_true ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD strong_wind_is_rejected.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-wind
|
||||
act = mo_cut->check( iv_payload = '2.00'
|
||||
iv_distance = '10.00'
|
||||
iv_wind_speed = '12.01'
|
||||
iv_battery = 30
|
||||
iv_in_zone = abap_true
|
||||
iv_daylight = abap_true ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD low_battery_is_rejected.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-battery
|
||||
act = mo_cut->check( iv_payload = '2.00'
|
||||
iv_distance = '10.00'
|
||||
iv_wind_speed = '5.00'
|
||||
iv_battery = 29
|
||||
iv_in_zone = abap_true
|
||||
iv_daylight = abap_true ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD required_battery_is_rounded_up.
|
||||
cl_abap_unit_assert=>assert_equals( exp = 26 act = mo_drone->required_battery( '7.50' ) ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 30 act = mo_drone->required_battery( '10.00' ) ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 0 act = mo_drone->required_battery( '0.00' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD zone_and_light_are_checked.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-zone
|
||||
act = mo_cut->check( iv_payload = '2.00'
|
||||
iv_distance = '10.00'
|
||||
iv_wind_speed = '5.00'
|
||||
iv_battery = 30
|
||||
iv_in_zone = abap_false
|
||||
iv_daylight = abap_true ) ).
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-light
|
||||
act = mo_cut->check( iv_payload = '2.00'
|
||||
iv_distance = '10.00'
|
||||
iv_wind_speed = '5.00'
|
||||
iv_battery = 30
|
||||
iv_in_zone = abap_true
|
||||
iv_daylight = abap_false ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD reason_order_is_kept.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-payload
|
||||
act = mo_cut->check( iv_payload = '6.00'
|
||||
iv_distance = '25.00'
|
||||
iv_wind_speed = '20.00'
|
||||
iv_battery = 0
|
||||
iv_in_zone = abap_false
|
||||
iv_daylight = abap_false ) ).
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_drone_check=>c_reason-distance
|
||||
act = mo_cut->check( iv_payload = '2.00'
|
||||
iv_distance = '25.00'
|
||||
iv_wind_speed = '20.00'
|
||||
iv_battery = 0
|
||||
iv_in_zone = abap_false
|
||||
iv_daylight = abap_false ) ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
25
tasks_gen/train/G1003/seed/if_drone_check.intf.abap
Normal file
25
tasks_gen/train/G1003/seed/if_drone_check.intf.abap
Normal file
@@ -0,0 +1,25 @@
|
||||
INTERFACE {{p}}if_drone_check PUBLIC.
|
||||
TYPES ty_reason TYPE c LENGTH 10.
|
||||
TYPES ty_weight TYPE p LENGTH 8 DECIMALS 2.
|
||||
TYPES ty_distance TYPE p LENGTH 8 DECIMALS 2.
|
||||
TYPES ty_speed TYPE p LENGTH 8 DECIMALS 2.
|
||||
TYPES ty_percent TYPE i.
|
||||
CONSTANTS:
|
||||
BEGIN OF c_reason,
|
||||
ok TYPE ty_reason VALUE 'OK',
|
||||
payload TYPE ty_reason VALUE 'PAYLOAD',
|
||||
distance TYPE ty_reason VALUE 'DISTANCE',
|
||||
wind TYPE ty_reason VALUE 'WIND',
|
||||
battery TYPE ty_reason VALUE 'BATTERY',
|
||||
zone TYPE ty_reason VALUE 'ZONE',
|
||||
light TYPE ty_reason VALUE 'LIGHT',
|
||||
END OF c_reason.
|
||||
METHODS check
|
||||
IMPORTING iv_payload TYPE ty_weight
|
||||
iv_distance TYPE ty_distance
|
||||
iv_wind_speed TYPE ty_speed
|
||||
iv_battery TYPE ty_percent
|
||||
iv_in_zone TYPE abap_bool
|
||||
iv_daylight TYPE abap_bool
|
||||
RETURNING VALUE(rv_reason) TYPE ty_reason.
|
||||
ENDINTERFACE.
|
||||
65
tasks_gen/train/G1003/spec.md
Normal file
65
tasks_gen/train/G1003/spec.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# 1. Goal
|
||||
A drone delivery operator checks a delivery request before it releases a drone.
|
||||
The dispatch program calls one check for each request. The program needs one
|
||||
reason code for each request and the battery charge that the flight needs.
|
||||
|
||||
# 2. Open questions
|
||||
None.
|
||||
|
||||
# 3. Context
|
||||
- The interface {{P}}IF_DRONE_CHECK exists in package $TMP. It is active.
|
||||
- The interface has the types TY_REASON (character, length 10), TY_WEIGHT
|
||||
(packed number, length 8, 2 decimals), TY_DISTANCE (packed number, length 8,
|
||||
2 decimals), TY_SPEED (packed number, length 8, 2 decimals) and TY_PERCENT
|
||||
(integer).
|
||||
- The interface has the constant structure C_REASON with the components OK,
|
||||
PAYLOAD, DISTANCE, WIND, BATTERY, ZONE and LIGHT.
|
||||
- The interface has one method:
|
||||
CHECK
|
||||
IMPORTING iv_payload TYPE ty_weight
|
||||
iv_distance TYPE ty_distance
|
||||
iv_wind_speed TYPE ty_speed
|
||||
iv_battery TYPE ty_percent
|
||||
iv_in_zone TYPE abap_bool
|
||||
iv_daylight TYPE abap_bool
|
||||
RETURNING VALUE(rv_reason) TYPE ty_reason.
|
||||
|
||||
# 4. Contract
|
||||
- Create the class {{P}}DRONE_CHECKER in package $TMP.
|
||||
- The class is public, final, and has a public constructor without parameters.
|
||||
- The class implements {{P}}IF_DRONE_CHECK.
|
||||
- The class has the public method REQUIRED_BATTERY:
|
||||
IMPORTING iv_distance TYPE {{P}}IF_DRONE_CHECK=>TY_DISTANCE
|
||||
RETURNING VALUE(rv_percent) TYPE {{P}}IF_DRONE_CHECK=>TY_PERCENT.
|
||||
- Do not add other public methods.
|
||||
|
||||
# 5. Business rules
|
||||
The payload is in kilograms, the distance in kilometres, the wind speed in
|
||||
metres per second, and the battery charge in percent.
|
||||
The check applies the rules in this sequence and returns the reason of the
|
||||
first rule that fails.
|
||||
1. If the payload is less than or equal to zero, or greater than 5.00, return
|
||||
PAYLOAD.
|
||||
2. If the distance is less than or equal to zero, or greater than 20.00, return
|
||||
DISTANCE.
|
||||
3. If the wind speed is greater than 12.00, return WIND.
|
||||
4. If the battery charge is less than the charge that the flight needs, return
|
||||
BATTERY.
|
||||
5. If iv_in_zone is abap_false, return ZONE.
|
||||
6. If iv_daylight is abap_false, return LIGHT.
|
||||
7. Else return OK.
|
||||
The charge that a flight needs is the result of REQUIRED_BATTERY:
|
||||
- If the distance is less than or equal to zero, the result is 0.
|
||||
- Else the result is 2 percent for each started kilometre plus a reserve of
|
||||
10 percent. A started kilometre counts as a full kilometre.
|
||||
|
||||
# 6. Constraints
|
||||
- Release target: SAP_BASIS 816 (ABAP Platform 2025).
|
||||
- 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_DRONE_CHECK.
|
||||
|
||||
# 7. Acceptance
|
||||
- The class is active and has no syntax error.
|
||||
- The hidden tests pass.
|
||||
- Write your own ABAP Unit tests for the class.
|
||||
51
tasks_gen/train/G1003/task.json
Normal file
51
tasks_gen/train/G1003/task.json
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"id": "G1003",
|
||||
"category": "A",
|
||||
"object_type": "CLAS",
|
||||
"difficulty": 2,
|
||||
"release_target": "v816",
|
||||
"expected_outcome": "implement",
|
||||
"budget": {
|
||||
"max_tool_calls": 80,
|
||||
"max_activations": 20
|
||||
},
|
||||
"seed": [
|
||||
{
|
||||
"type": "INTF",
|
||||
"name": "{{P}}IF_DRONE_CHECK",
|
||||
"file": "seed/if_drone_check.intf.abap",
|
||||
"description": "Drone flight check contract"
|
||||
}
|
||||
],
|
||||
"contract": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}DRONE_CHECKER",
|
||||
"implements": "{{P}}IF_DRONE_CHECK"
|
||||
}
|
||||
],
|
||||
"out_of_scope": [
|
||||
"{{P}}IF_DRONE_CHECK"
|
||||
],
|
||||
"hidden_tests": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}T21_HIDDEN",
|
||||
"file": "hidden/t21_hidden.clas.abap",
|
||||
"description": "T21 hidden tests"
|
||||
}
|
||||
],
|
||||
"reference": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}DRONE_CHECKER",
|
||||
"file": "reference/drone_checker.clas.abap",
|
||||
"description": "Drone flight checker",
|
||||
"testclasses_file": "reference/drone_checker.testclasses.abap"
|
||||
}
|
||||
],
|
||||
"craft_checks": [
|
||||
"method_length",
|
||||
"db_operation_in_loop"
|
||||
]
|
||||
}
|
||||
52
tasks_gen/train/G1004/faulty/m0_balloon_checker.clas.abap
Normal file
52
tasks_gen/train/G1004/faulty/m0_balloon_checker.clas.abap
Normal file
@@ -0,0 +1,52 @@
|
||||
CLASS {{p}}balloon_checker DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
METHODS check_flight
|
||||
IMPORTING iv_passengers TYPE i
|
||||
iv_weight_kg TYPE i
|
||||
iv_wind_kmh TYPE i
|
||||
iv_cloud_base_m TYPE i
|
||||
RETURNING VALUE(rv_free_kg) TYPE i
|
||||
RAISING {{p}}cx_balloon_flight.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_max_passengers TYPE i VALUE 8,
|
||||
c_max_weight_kg TYPE i VALUE 640,
|
||||
c_max_wind_kmh TYPE i VALUE 18,
|
||||
c_min_cloud_base_m TYPE i VALUE 300.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}balloon_checker IMPLEMENTATION.
|
||||
METHOD check_flight.
|
||||
IF iv_passengers <= c_max_passengers.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_crew
|
||||
EXPORTING
|
||||
iv_passengers = iv_passengers
|
||||
iv_limit = c_max_passengers.
|
||||
ENDIF.
|
||||
|
||||
IF iv_weight_kg > c_max_weight_kg.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_weight
|
||||
EXPORTING
|
||||
iv_weight_kg = iv_weight_kg
|
||||
iv_limit_kg = c_max_weight_kg.
|
||||
ENDIF.
|
||||
|
||||
IF iv_wind_kmh > c_max_wind_kmh.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_wind
|
||||
EXPORTING
|
||||
iv_wind_kmh = iv_wind_kmh
|
||||
iv_limit_kmh = c_max_wind_kmh.
|
||||
ENDIF.
|
||||
|
||||
IF iv_cloud_base_m < c_min_cloud_base_m.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_cloud
|
||||
EXPORTING
|
||||
iv_cloud_base_m = iv_cloud_base_m
|
||||
iv_limit_m = c_min_cloud_base_m.
|
||||
ENDIF.
|
||||
|
||||
rv_free_kg = c_max_weight_kg - iv_weight_kg.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
52
tasks_gen/train/G1004/faulty/m1_balloon_checker.clas.abap
Normal file
52
tasks_gen/train/G1004/faulty/m1_balloon_checker.clas.abap
Normal file
@@ -0,0 +1,52 @@
|
||||
CLASS {{p}}balloon_checker DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
METHODS check_flight
|
||||
IMPORTING iv_passengers TYPE i
|
||||
iv_weight_kg TYPE i
|
||||
iv_wind_kmh TYPE i
|
||||
iv_cloud_base_m TYPE i
|
||||
RETURNING VALUE(rv_free_kg) TYPE i
|
||||
RAISING {{p}}cx_balloon_flight.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_max_passengers TYPE i VALUE 8,
|
||||
c_max_weight_kg TYPE i VALUE 640,
|
||||
c_max_wind_kmh TYPE i VALUE 18,
|
||||
c_min_cloud_base_m TYPE i VALUE 300.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}balloon_checker IMPLEMENTATION.
|
||||
METHOD check_flight.
|
||||
IF iv_passengers > c_max_passengers.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_crew
|
||||
EXPORTING
|
||||
iv_passengers = iv_passengers
|
||||
iv_limit = c_max_passengers.
|
||||
ENDIF.
|
||||
|
||||
IF iv_weight_kg <= c_max_weight_kg.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_weight
|
||||
EXPORTING
|
||||
iv_weight_kg = iv_weight_kg
|
||||
iv_limit_kg = c_max_weight_kg.
|
||||
ENDIF.
|
||||
|
||||
IF iv_wind_kmh > c_max_wind_kmh.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_wind
|
||||
EXPORTING
|
||||
iv_wind_kmh = iv_wind_kmh
|
||||
iv_limit_kmh = c_max_wind_kmh.
|
||||
ENDIF.
|
||||
|
||||
IF iv_cloud_base_m < c_min_cloud_base_m.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_cloud
|
||||
EXPORTING
|
||||
iv_cloud_base_m = iv_cloud_base_m
|
||||
iv_limit_m = c_min_cloud_base_m.
|
||||
ENDIF.
|
||||
|
||||
rv_free_kg = c_max_weight_kg - iv_weight_kg.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
52
tasks_gen/train/G1004/faulty/m2_balloon_checker.clas.abap
Normal file
52
tasks_gen/train/G1004/faulty/m2_balloon_checker.clas.abap
Normal file
@@ -0,0 +1,52 @@
|
||||
CLASS {{p}}balloon_checker DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
METHODS check_flight
|
||||
IMPORTING iv_passengers TYPE i
|
||||
iv_weight_kg TYPE i
|
||||
iv_wind_kmh TYPE i
|
||||
iv_cloud_base_m TYPE i
|
||||
RETURNING VALUE(rv_free_kg) TYPE i
|
||||
RAISING {{p}}cx_balloon_flight.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_max_passengers TYPE i VALUE 8,
|
||||
c_max_weight_kg TYPE i VALUE 640,
|
||||
c_max_wind_kmh TYPE i VALUE 18,
|
||||
c_min_cloud_base_m TYPE i VALUE 300.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}balloon_checker IMPLEMENTATION.
|
||||
METHOD check_flight.
|
||||
IF iv_passengers > c_max_passengers.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_crew
|
||||
EXPORTING
|
||||
iv_passengers = iv_passengers
|
||||
iv_limit = c_max_passengers.
|
||||
ENDIF.
|
||||
|
||||
IF iv_weight_kg > c_max_weight_kg.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_weight
|
||||
EXPORTING
|
||||
iv_weight_kg = iv_weight_kg
|
||||
iv_limit_kg = c_max_weight_kg.
|
||||
ENDIF.
|
||||
|
||||
IF iv_wind_kmh <= c_max_wind_kmh.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_wind
|
||||
EXPORTING
|
||||
iv_wind_kmh = iv_wind_kmh
|
||||
iv_limit_kmh = c_max_wind_kmh.
|
||||
ENDIF.
|
||||
|
||||
IF iv_cloud_base_m < c_min_cloud_base_m.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_cloud
|
||||
EXPORTING
|
||||
iv_cloud_base_m = iv_cloud_base_m
|
||||
iv_limit_m = c_min_cloud_base_m.
|
||||
ENDIF.
|
||||
|
||||
rv_free_kg = c_max_weight_kg - iv_weight_kg.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
52
tasks_gen/train/G1004/faulty/m3_balloon_checker.clas.abap
Normal file
52
tasks_gen/train/G1004/faulty/m3_balloon_checker.clas.abap
Normal file
@@ -0,0 +1,52 @@
|
||||
CLASS {{p}}balloon_checker DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
METHODS check_flight
|
||||
IMPORTING iv_passengers TYPE i
|
||||
iv_weight_kg TYPE i
|
||||
iv_wind_kmh TYPE i
|
||||
iv_cloud_base_m TYPE i
|
||||
RETURNING VALUE(rv_free_kg) TYPE i
|
||||
RAISING {{p}}cx_balloon_flight.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_max_passengers TYPE i VALUE 8,
|
||||
c_max_weight_kg TYPE i VALUE 640,
|
||||
c_max_wind_kmh TYPE i VALUE 18,
|
||||
c_min_cloud_base_m TYPE i VALUE 300.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}balloon_checker IMPLEMENTATION.
|
||||
METHOD check_flight.
|
||||
IF iv_passengers > c_max_passengers.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_crew
|
||||
EXPORTING
|
||||
iv_passengers = iv_passengers
|
||||
iv_limit = c_max_passengers.
|
||||
ENDIF.
|
||||
|
||||
IF iv_weight_kg > c_max_weight_kg.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_weight
|
||||
EXPORTING
|
||||
iv_weight_kg = iv_weight_kg
|
||||
iv_limit_kg = c_max_weight_kg.
|
||||
ENDIF.
|
||||
|
||||
IF iv_wind_kmh > c_max_wind_kmh.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_wind
|
||||
EXPORTING
|
||||
iv_wind_kmh = iv_wind_kmh
|
||||
iv_limit_kmh = c_max_wind_kmh.
|
||||
ENDIF.
|
||||
|
||||
IF iv_cloud_base_m >= c_min_cloud_base_m.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_cloud
|
||||
EXPORTING
|
||||
iv_cloud_base_m = iv_cloud_base_m
|
||||
iv_limit_m = c_min_cloud_base_m.
|
||||
ENDIF.
|
||||
|
||||
rv_free_kg = c_max_weight_kg - iv_weight_kg.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
52
tasks_gen/train/G1004/faulty/m4_balloon_checker.clas.abap
Normal file
52
tasks_gen/train/G1004/faulty/m4_balloon_checker.clas.abap
Normal file
@@ -0,0 +1,52 @@
|
||||
CLASS {{p}}balloon_checker DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
METHODS check_flight
|
||||
IMPORTING iv_passengers TYPE i
|
||||
iv_weight_kg TYPE i
|
||||
iv_wind_kmh TYPE i
|
||||
iv_cloud_base_m TYPE i
|
||||
RETURNING VALUE(rv_free_kg) TYPE i
|
||||
RAISING {{p}}cx_balloon_flight.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_max_passengers TYPE i VALUE 8,
|
||||
c_max_weight_kg TYPE i VALUE 640,
|
||||
c_max_wind_kmh TYPE i VALUE 18,
|
||||
c_min_cloud_base_m TYPE i VALUE 300.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}balloon_checker IMPLEMENTATION.
|
||||
METHOD check_flight.
|
||||
IF iv_passengers > c_max_passengers.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_crew
|
||||
EXPORTING
|
||||
iv_passengers = iv_passengers
|
||||
iv_limit = c_max_passengers.
|
||||
ENDIF.
|
||||
|
||||
IF iv_weight_kg > c_max_weight_kg.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_weight
|
||||
EXPORTING
|
||||
iv_weight_kg = iv_weight_kg
|
||||
iv_limit_kg = c_max_weight_kg.
|
||||
ENDIF.
|
||||
|
||||
IF iv_wind_kmh > c_max_wind_kmh.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_wind
|
||||
EXPORTING
|
||||
iv_wind_kmh = iv_wind_kmh
|
||||
iv_limit_kmh = c_max_wind_kmh.
|
||||
ENDIF.
|
||||
|
||||
IF iv_cloud_base_m < c_min_cloud_base_m.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_cloud
|
||||
EXPORTING
|
||||
iv_cloud_base_m = iv_cloud_base_m
|
||||
iv_limit_m = c_min_cloud_base_m.
|
||||
ENDIF.
|
||||
|
||||
rv_free_kg = c_max_weight_kg + iv_weight_kg.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
24
tasks_gen/train/G1004/generation.json
Normal file
24
tasks_gen/train/G1004/generation.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": "G1004",
|
||||
"pool": "train",
|
||||
"object_type": "CLAS",
|
||||
"category": "D",
|
||||
"attempts": [
|
||||
{
|
||||
"stage": "validate",
|
||||
"oracle": 0,
|
||||
"null": 0
|
||||
},
|
||||
{
|
||||
"stage": "validate",
|
||||
"oracle": 100.0,
|
||||
"null": 0,
|
||||
"mutation": {
|
||||
"valid": 5,
|
||||
"killed": 5,
|
||||
"ok": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"accepted": true
|
||||
}
|
||||
169
tasks_gen/train/G1004/hidden/balloon_hidden.clas.abap
Normal file
169
tasks_gen/train/G1004/hidden/balloon_hidden.clas.abap
Normal file
@@ -0,0 +1,169 @@
|
||||
CLASS {{p}}balloon_hidden DEFINITION PUBLIC FINAL CREATE PUBLIC
|
||||
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
|
||||
|
||||
PRIVATE SECTION.
|
||||
DATA mo_cut TYPE REF TO {{p}}balloon_checker.
|
||||
|
||||
METHODS setup.
|
||||
METHODS free_payload
|
||||
IMPORTING iv_passengers TYPE i
|
||||
iv_weight_kg TYPE i
|
||||
iv_wind_kmh TYPE i
|
||||
iv_cloud_base_m TYPE i
|
||||
RETURNING VALUE(rv_free_kg) TYPE i.
|
||||
|
||||
METHODS valid_flight_is_released FOR TESTING.
|
||||
METHODS crew_above_limit FOR TESTING.
|
||||
METHODS weight_above_limit FOR TESTING.
|
||||
METHODS wind_above_limit FOR TESTING.
|
||||
METHODS cloud_base_below_limit FOR TESTING.
|
||||
METHODS crew_is_checked_first FOR TESTING.
|
||||
METHODS weight_is_checked_second FOR TESTING.
|
||||
METHODS wind_is_checked_third FOR TESTING.
|
||||
METHODS limits_are_accepted FOR TESTING.
|
||||
METHODS free_payload_is_returned FOR TESTING.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}balloon_hidden IMPLEMENTATION.
|
||||
METHOD setup.
|
||||
mo_cut = NEW {{p}}balloon_checker( ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD free_payload.
|
||||
TRY.
|
||||
rv_free_kg = mo_cut->check_flight( iv_passengers = iv_passengers
|
||||
iv_weight_kg = iv_weight_kg
|
||||
iv_wind_kmh = iv_wind_kmh
|
||||
iv_cloud_base_m = iv_cloud_base_m ).
|
||||
CATCH {{p}}cx_balloon_flight.
|
||||
rv_free_kg = -1.
|
||||
ENDTRY.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD valid_flight_is_released.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = 140
|
||||
act = free_payload( iv_passengers = 4 iv_weight_kg = 500
|
||||
iv_wind_kmh = 10 iv_cloud_base_m = 2000 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD crew_above_limit.
|
||||
DATA lv_text TYPE string.
|
||||
TRY.
|
||||
mo_cut->check_flight( iv_passengers = 9 iv_weight_kg = 500
|
||||
iv_wind_kmh = 10 iv_cloud_base_m = 2000 ).
|
||||
cl_abap_unit_assert=>fail( msg = 'No exception was raised' ).
|
||||
CATCH {{p}}cx_balloon_crew INTO DATA(lo_exc).
|
||||
lv_text = lo_exc->mv_text.
|
||||
CATCH {{p}}cx_balloon_flight.
|
||||
cl_abap_unit_assert=>fail( msg = 'Wrong exception type' ).
|
||||
ENDTRY.
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'Passengers 9 exceeds the limit 8'
|
||||
act = lv_text ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD weight_above_limit.
|
||||
DATA lv_text TYPE string.
|
||||
TRY.
|
||||
mo_cut->check_flight( iv_passengers = 4 iv_weight_kg = 700
|
||||
iv_wind_kmh = 10 iv_cloud_base_m = 2000 ).
|
||||
cl_abap_unit_assert=>fail( msg = 'No exception was raised' ).
|
||||
CATCH {{p}}cx_balloon_weight INTO DATA(lo_exc).
|
||||
lv_text = lo_exc->mv_text.
|
||||
CATCH {{p}}cx_balloon_flight.
|
||||
cl_abap_unit_assert=>fail( msg = 'Wrong exception type' ).
|
||||
ENDTRY.
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'Weight 700 kg exceeds the limit 640 kg'
|
||||
act = lv_text ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD wind_above_limit.
|
||||
DATA lv_text TYPE string.
|
||||
TRY.
|
||||
mo_cut->check_flight( iv_passengers = 4 iv_weight_kg = 500
|
||||
iv_wind_kmh = 25 iv_cloud_base_m = 2000 ).
|
||||
cl_abap_unit_assert=>fail( msg = 'No exception was raised' ).
|
||||
CATCH {{p}}cx_balloon_wind INTO DATA(lo_exc).
|
||||
lv_text = lo_exc->mv_text.
|
||||
CATCH {{p}}cx_balloon_flight.
|
||||
cl_abap_unit_assert=>fail( msg = 'Wrong exception type' ).
|
||||
ENDTRY.
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'Wind 25 km/h exceeds the limit 18 km/h'
|
||||
act = lv_text ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD cloud_base_below_limit.
|
||||
DATA lv_text TYPE string.
|
||||
TRY.
|
||||
mo_cut->check_flight( iv_passengers = 4 iv_weight_kg = 500
|
||||
iv_wind_kmh = 10 iv_cloud_base_m = 200 ).
|
||||
cl_abap_unit_assert=>fail( msg = 'No exception was raised' ).
|
||||
CATCH {{p}}cx_balloon_cloud INTO DATA(lo_exc).
|
||||
lv_text = lo_exc->mv_text.
|
||||
CATCH {{p}}cx_balloon_flight.
|
||||
cl_abap_unit_assert=>fail( msg = 'Wrong exception type' ).
|
||||
ENDTRY.
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'Cloud base 200 m is below the limit 300 m'
|
||||
act = lv_text ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD crew_is_checked_first.
|
||||
DATA lv_text TYPE string.
|
||||
TRY.
|
||||
mo_cut->check_flight( iv_passengers = 9 iv_weight_kg = 700
|
||||
iv_wind_kmh = 25 iv_cloud_base_m = 100 ).
|
||||
cl_abap_unit_assert=>fail( msg = 'No exception was raised' ).
|
||||
CATCH {{p}}cx_balloon_crew INTO DATA(lo_exc).
|
||||
lv_text = lo_exc->mv_text.
|
||||
CATCH {{p}}cx_balloon_flight.
|
||||
cl_abap_unit_assert=>fail( msg = 'Wrong exception type' ).
|
||||
ENDTRY.
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'Passengers 9 exceeds the limit 8'
|
||||
act = lv_text ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD weight_is_checked_second.
|
||||
DATA lv_text TYPE string.
|
||||
TRY.
|
||||
mo_cut->check_flight( iv_passengers = 4 iv_weight_kg = 700
|
||||
iv_wind_kmh = 25 iv_cloud_base_m = 100 ).
|
||||
cl_abap_unit_assert=>fail( msg = 'No exception was raised' ).
|
||||
CATCH {{p}}cx_balloon_weight INTO DATA(lo_exc).
|
||||
lv_text = lo_exc->mv_text.
|
||||
CATCH {{p}}cx_balloon_flight.
|
||||
cl_abap_unit_assert=>fail( msg = 'Wrong exception type' ).
|
||||
ENDTRY.
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'Weight 700 kg exceeds the limit 640 kg'
|
||||
act = lv_text ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD wind_is_checked_third.
|
||||
DATA lv_text TYPE string.
|
||||
TRY.
|
||||
mo_cut->check_flight( iv_passengers = 4 iv_weight_kg = 500
|
||||
iv_wind_kmh = 25 iv_cloud_base_m = 100 ).
|
||||
cl_abap_unit_assert=>fail( msg = 'No exception was raised' ).
|
||||
CATCH {{p}}cx_balloon_wind INTO DATA(lo_exc).
|
||||
lv_text = lo_exc->mv_text.
|
||||
CATCH {{p}}cx_balloon_flight.
|
||||
cl_abap_unit_assert=>fail( msg = 'Wrong exception type' ).
|
||||
ENDTRY.
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'Wind 25 km/h exceeds the limit 18 km/h'
|
||||
act = lv_text ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD limits_are_accepted.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = 0
|
||||
act = free_payload( iv_passengers = 8 iv_weight_kg = 640
|
||||
iv_wind_kmh = 18 iv_cloud_base_m = 300 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD free_payload_is_returned.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = 40
|
||||
act = free_payload( iv_passengers = 2 iv_weight_kg = 600
|
||||
iv_wind_kmh = 12 iv_cloud_base_m = 1200 ) ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
80
tasks_gen/train/G1004/mutation.json
Normal file
80
tasks_gen/train/G1004/mutation.json
Normal file
@@ -0,0 +1,80 @@
|
||||
{
|
||||
"task": "G1004",
|
||||
"mutants": [
|
||||
{
|
||||
"object": "{{P}}BALLOON_CHECKER",
|
||||
"mutant": "line 22: > -> <= (rel)",
|
||||
"status": "killed",
|
||||
"hidden": "0/10",
|
||||
"failed_tests": [
|
||||
"CLOUD_BASE_BELOW_LIMIT",
|
||||
"CREW_ABOVE_LIMIT",
|
||||
"CREW_IS_CHECKED_FIRST",
|
||||
"FREE_PAYLOAD_IS_RETURNED",
|
||||
"LIMITS_ARE_ACCEPTED",
|
||||
"VALID_FLIGHT_IS_RELEASED",
|
||||
"WEIGHT_ABOVE_LIMIT",
|
||||
"WEIGHT_IS_CHECKED_SECOND",
|
||||
"WIND_ABOVE_LIMIT",
|
||||
"WIND_IS_CHECKED_THIRD"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}BALLOON_CHECKER",
|
||||
"mutant": "line 29: > -> <= (rel)",
|
||||
"status": "killed",
|
||||
"hidden": "2/10",
|
||||
"failed_tests": [
|
||||
"CLOUD_BASE_BELOW_LIMIT",
|
||||
"FREE_PAYLOAD_IS_RETURNED",
|
||||
"LIMITS_ARE_ACCEPTED",
|
||||
"VALID_FLIGHT_IS_RELEASED",
|
||||
"WEIGHT_ABOVE_LIMIT",
|
||||
"WEIGHT_IS_CHECKED_SECOND",
|
||||
"WIND_ABOVE_LIMIT",
|
||||
"WIND_IS_CHECKED_THIRD"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}BALLOON_CHECKER",
|
||||
"mutant": "line 36: > -> <= (rel)",
|
||||
"status": "killed",
|
||||
"hidden": "4/10",
|
||||
"failed_tests": [
|
||||
"CLOUD_BASE_BELOW_LIMIT",
|
||||
"FREE_PAYLOAD_IS_RETURNED",
|
||||
"LIMITS_ARE_ACCEPTED",
|
||||
"VALID_FLIGHT_IS_RELEASED",
|
||||
"WIND_ABOVE_LIMIT",
|
||||
"WIND_IS_CHECKED_THIRD"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}BALLOON_CHECKER",
|
||||
"mutant": "line 43: < -> >= (rel)",
|
||||
"status": "killed",
|
||||
"hidden": "6/10",
|
||||
"failed_tests": [
|
||||
"CLOUD_BASE_BELOW_LIMIT",
|
||||
"FREE_PAYLOAD_IS_RETURNED",
|
||||
"LIMITS_ARE_ACCEPTED",
|
||||
"VALID_FLIGHT_IS_RELEASED"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}BALLOON_CHECKER",
|
||||
"mutant": "line 50: - -> + (arith)",
|
||||
"status": "killed",
|
||||
"hidden": "7/10",
|
||||
"failed_tests": [
|
||||
"FREE_PAYLOAD_IS_RETURNED",
|
||||
"LIMITS_ARE_ACCEPTED",
|
||||
"VALID_FLIGHT_IS_RELEASED"
|
||||
]
|
||||
}
|
||||
],
|
||||
"valid": 5,
|
||||
"killed": 5,
|
||||
"kill_rate": 1.0,
|
||||
"ok": true
|
||||
}
|
||||
52
tasks_gen/train/G1004/reference/balloon_checker.clas.abap
Normal file
52
tasks_gen/train/G1004/reference/balloon_checker.clas.abap
Normal file
@@ -0,0 +1,52 @@
|
||||
CLASS {{p}}balloon_checker DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
METHODS check_flight
|
||||
IMPORTING iv_passengers TYPE i
|
||||
iv_weight_kg TYPE i
|
||||
iv_wind_kmh TYPE i
|
||||
iv_cloud_base_m TYPE i
|
||||
RETURNING VALUE(rv_free_kg) TYPE i
|
||||
RAISING {{p}}cx_balloon_flight.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_max_passengers TYPE i VALUE 8,
|
||||
c_max_weight_kg TYPE i VALUE 640,
|
||||
c_max_wind_kmh TYPE i VALUE 18,
|
||||
c_min_cloud_base_m TYPE i VALUE 300.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}balloon_checker IMPLEMENTATION.
|
||||
METHOD check_flight.
|
||||
IF iv_passengers > c_max_passengers.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_crew
|
||||
EXPORTING
|
||||
iv_passengers = iv_passengers
|
||||
iv_limit = c_max_passengers.
|
||||
ENDIF.
|
||||
|
||||
IF iv_weight_kg > c_max_weight_kg.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_weight
|
||||
EXPORTING
|
||||
iv_weight_kg = iv_weight_kg
|
||||
iv_limit_kg = c_max_weight_kg.
|
||||
ENDIF.
|
||||
|
||||
IF iv_wind_kmh > c_max_wind_kmh.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_wind
|
||||
EXPORTING
|
||||
iv_wind_kmh = iv_wind_kmh
|
||||
iv_limit_kmh = c_max_wind_kmh.
|
||||
ENDIF.
|
||||
|
||||
IF iv_cloud_base_m < c_min_cloud_base_m.
|
||||
RAISE EXCEPTION TYPE {{p}}cx_balloon_cloud
|
||||
EXPORTING
|
||||
iv_cloud_base_m = iv_cloud_base_m
|
||||
iv_limit_m = c_min_cloud_base_m.
|
||||
ENDIF.
|
||||
|
||||
rv_free_kg = c_max_weight_kg - iv_weight_kg.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
@@ -0,0 +1,89 @@
|
||||
CLASS ltc_balloon_checker DEFINITION FINAL FOR TESTING
|
||||
DURATION SHORT RISK LEVEL HARMLESS.
|
||||
|
||||
PRIVATE SECTION.
|
||||
DATA mo_cut TYPE REF TO {{p}}balloon_checker.
|
||||
|
||||
METHODS setup.
|
||||
METHODS free_payload
|
||||
IMPORTING iv_passengers TYPE i
|
||||
iv_weight_kg TYPE i
|
||||
iv_wind_kmh TYPE i
|
||||
iv_cloud_base_m TYPE i
|
||||
RETURNING VALUE(rv_free_kg) TYPE i.
|
||||
|
||||
METHODS released_flight FOR TESTING.
|
||||
METHODS crew_limit FOR TESTING.
|
||||
METHODS weight_limit FOR TESTING.
|
||||
METHODS wind_limit FOR TESTING.
|
||||
METHODS cloud_limit FOR TESTING.
|
||||
METHODS check_sequence FOR TESTING.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS ltc_balloon_checker IMPLEMENTATION.
|
||||
METHOD setup.
|
||||
mo_cut = NEW {{p}}balloon_checker( ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD free_payload.
|
||||
TRY.
|
||||
rv_free_kg = mo_cut->check_flight( iv_passengers = iv_passengers
|
||||
iv_weight_kg = iv_weight_kg
|
||||
iv_wind_kmh = iv_wind_kmh
|
||||
iv_cloud_base_m = iv_cloud_base_m ).
|
||||
CATCH {{p}}cx_balloon_flight.
|
||||
rv_free_kg = -1.
|
||||
ENDTRY.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD released_flight.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = 140
|
||||
act = free_payload( iv_passengers = 4 iv_weight_kg = 500
|
||||
iv_wind_kmh = 10 iv_cloud_base_m = 2000 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD crew_limit.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = -1
|
||||
act = free_payload( iv_passengers = 9 iv_weight_kg = 500
|
||||
iv_wind_kmh = 10 iv_cloud_base_m = 2000 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD weight_limit.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = -1
|
||||
act = free_payload( iv_passengers = 4 iv_weight_kg = 700
|
||||
iv_wind_kmh = 10 iv_cloud_base_m = 2000 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD wind_limit.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = -1
|
||||
act = free_payload( iv_passengers = 4 iv_weight_kg = 500
|
||||
iv_wind_kmh = 25 iv_cloud_base_m = 2000 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD cloud_limit.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = -1
|
||||
act = free_payload( iv_passengers = 4 iv_weight_kg = 500
|
||||
iv_wind_kmh = 10 iv_cloud_base_m = 200 ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD check_sequence.
|
||||
DATA lv_text TYPE string.
|
||||
TRY.
|
||||
mo_cut->check_flight( iv_passengers = 9 iv_weight_kg = 700
|
||||
iv_wind_kmh = 25 iv_cloud_base_m = 100 ).
|
||||
cl_abap_unit_assert=>fail( msg = 'No exception was raised' ).
|
||||
CATCH {{p}}cx_balloon_crew INTO DATA(lo_exc).
|
||||
lv_text = lo_exc->mv_text.
|
||||
CATCH {{p}}cx_balloon_flight.
|
||||
cl_abap_unit_assert=>fail( msg = 'Wrong exception type' ).
|
||||
ENDTRY.
|
||||
cl_abap_unit_assert=>assert_equals( exp = 'Passengers 9 exceeds the limit 8'
|
||||
act = lv_text ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
16
tasks_gen/train/G1004/reference/cx_balloon_cloud.clas.abap
Normal file
16
tasks_gen/train/G1004/reference/cx_balloon_cloud.clas.abap
Normal file
@@ -0,0 +1,16 @@
|
||||
CLASS {{p}}cx_balloon_cloud DEFINITION PUBLIC INHERITING FROM {{p}}cx_balloon_flight FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
METHODS constructor
|
||||
IMPORTING iv_cloud_base_m TYPE i
|
||||
iv_limit_m TYPE i.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS c_dummy TYPE i VALUE 0.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}cx_balloon_cloud IMPLEMENTATION.
|
||||
METHOD constructor.
|
||||
super->constructor( iv_text = |Cloud base { iv_cloud_base_m } m is below the limit { iv_limit_m } m| ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
16
tasks_gen/train/G1004/reference/cx_balloon_crew.clas.abap
Normal file
16
tasks_gen/train/G1004/reference/cx_balloon_crew.clas.abap
Normal file
@@ -0,0 +1,16 @@
|
||||
CLASS {{p}}cx_balloon_crew DEFINITION PUBLIC INHERITING FROM {{p}}cx_balloon_flight FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
METHODS constructor
|
||||
IMPORTING iv_passengers TYPE i
|
||||
iv_limit TYPE i.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS c_dummy TYPE i VALUE 0.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}cx_balloon_crew IMPLEMENTATION.
|
||||
METHOD constructor.
|
||||
super->constructor( iv_text = |Passengers { iv_passengers } exceeds the limit { iv_limit }| ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
16
tasks_gen/train/G1004/reference/cx_balloon_weight.clas.abap
Normal file
16
tasks_gen/train/G1004/reference/cx_balloon_weight.clas.abap
Normal file
@@ -0,0 +1,16 @@
|
||||
CLASS {{p}}cx_balloon_weight DEFINITION PUBLIC INHERITING FROM {{p}}cx_balloon_flight FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
METHODS constructor
|
||||
IMPORTING iv_weight_kg TYPE i
|
||||
iv_limit_kg TYPE i.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS c_dummy TYPE i VALUE 0.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}cx_balloon_weight IMPLEMENTATION.
|
||||
METHOD constructor.
|
||||
super->constructor( iv_text = |Weight { iv_weight_kg } kg exceeds the limit { iv_limit_kg } kg| ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
16
tasks_gen/train/G1004/reference/cx_balloon_wind.clas.abap
Normal file
16
tasks_gen/train/G1004/reference/cx_balloon_wind.clas.abap
Normal file
@@ -0,0 +1,16 @@
|
||||
CLASS {{p}}cx_balloon_wind DEFINITION PUBLIC INHERITING FROM {{p}}cx_balloon_flight FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
METHODS constructor
|
||||
IMPORTING iv_wind_kmh TYPE i
|
||||
iv_limit_kmh TYPE i.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS c_dummy TYPE i VALUE 0.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}cx_balloon_wind IMPLEMENTATION.
|
||||
METHOD constructor.
|
||||
super->constructor( iv_text = |Wind { iv_wind_kmh } km/h exceeds the limit { iv_limit_kmh } km/h| ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
18
tasks_gen/train/G1004/seed/cx_balloon_flight.clas.abap
Normal file
18
tasks_gen/train/G1004/seed/cx_balloon_flight.clas.abap
Normal file
@@ -0,0 +1,18 @@
|
||||
CLASS {{p}}cx_balloon_flight DEFINITION PUBLIC INHERITING FROM cx_static_check CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
DATA mv_text TYPE string READ-ONLY.
|
||||
|
||||
METHODS constructor
|
||||
IMPORTING iv_text TYPE string.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS c_dummy TYPE i VALUE 0.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}cx_balloon_flight IMPLEMENTATION.
|
||||
METHOD constructor.
|
||||
super->constructor( ).
|
||||
mv_text = iv_text.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
76
tasks_gen/train/G1004/spec.md
Normal file
76
tasks_gen/train/G1004/spec.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# 1. Goal
|
||||
Check a hot-air balloon flight before the launch. The flight office calls the
|
||||
check for each planned flight. The check must stop a flight when a limit is
|
||||
exceeded. The caller needs one exception for each reason.
|
||||
|
||||
# 2. Open questions
|
||||
None.
|
||||
|
||||
# 3. Context
|
||||
- The exception class {{P}}CX_BALLOON_FLIGHT exists in package $TMP. It is
|
||||
active. It inherits from CX_STATIC_CHECK. It has the public read-only
|
||||
attribute MV_TEXT (type string) and a constructor with the importing
|
||||
parameter IV_TEXT (type string). The constructor writes IV_TEXT to MV_TEXT.
|
||||
- The flight office knows four figures of a flight: the number of passengers,
|
||||
the total take-off weight in kilograms, the wind speed in kilometres per
|
||||
hour, and the height of the cloud base in metres.
|
||||
|
||||
# 4. Contract
|
||||
- Create the class {{P}}BALLOON_CHECKER in package $TMP.
|
||||
- The class is public and final. It can be created without constructor
|
||||
parameters.
|
||||
- The class has the public method CHECK_FLIGHT with these parameters:
|
||||
- importing IV_PASSENGERS type i
|
||||
- importing IV_WEIGHT_KG type i
|
||||
- importing IV_WIND_KMH type i
|
||||
- importing IV_CLOUD_BASE_M type i
|
||||
- returning RV_FREE_KG type i
|
||||
- raising {{P}}CX_BALLOON_FLIGHT
|
||||
- Do not add other public methods.
|
||||
- Create these exception classes in package $TMP. Each class inherits from
|
||||
{{P}}CX_BALLOON_FLIGHT.
|
||||
- {{P}}CX_BALLOON_CREW with the constructor importing IV_PASSENGERS type i
|
||||
and IV_LIMIT type i.
|
||||
- {{P}}CX_BALLOON_WEIGHT with the constructor importing IV_WEIGHT_KG type i
|
||||
and IV_LIMIT_KG type i.
|
||||
- {{P}}CX_BALLOON_WIND with the constructor importing IV_WIND_KMH type i and
|
||||
IV_LIMIT_KMH type i.
|
||||
- {{P}}CX_BALLOON_CLOUD with the constructor importing IV_CLOUD_BASE_M type i
|
||||
and IV_LIMIT_M type i.
|
||||
- Each constructor writes the message text to MV_TEXT. Rule 1 to rule 4 of the
|
||||
business rules give the text of each exception.
|
||||
|
||||
# 5. Business rules
|
||||
The method CHECK_FLIGHT applies the rules in this sequence. It raises the
|
||||
exception of the first rule that fails. If no rule fails, the method returns the
|
||||
free payload.
|
||||
|
||||
1. Passengers. The limit is 8. If IV_PASSENGERS is greater than 8, raise
|
||||
{{P}}CX_BALLOON_CREW. The message text is
|
||||
"Passengers <passengers> exceeds the limit <limit>". Example: 12 passengers
|
||||
give the text "Passengers 12 exceeds the limit 8".
|
||||
2. Weight. The limit is 640 kilograms. If IV_WEIGHT_KG is greater than 640,
|
||||
raise {{P}}CX_BALLOON_WEIGHT. The message text is
|
||||
"Weight <weight> kg exceeds the limit <limit> kg". Example: 700 kilograms
|
||||
give the text "Weight 700 kg exceeds the limit 640 kg".
|
||||
3. Wind. The limit is 18 kilometres per hour. If IV_WIND_KMH is greater than 18,
|
||||
raise {{P}}CX_BALLOON_WIND. The message text is
|
||||
"Wind <wind> km/h exceeds the limit <limit> km/h". Example: 25 kilometres per
|
||||
hour give the text "Wind 25 km/h exceeds the limit 18 km/h".
|
||||
4. Cloud base. The limit is 300 metres. If IV_CLOUD_BASE_M is less than 300,
|
||||
raise {{P}}CX_BALLOON_CLOUD. The message text is
|
||||
"Cloud base <cloud base> m is below the limit <limit> m". Example: 200 metres
|
||||
give the text "Cloud base 200 m is below the limit 300 m".
|
||||
5. Free payload. If no rule fails, the free payload is 640 minus IV_WEIGHT_KG.
|
||||
Return the free payload in RV_FREE_KG.
|
||||
|
||||
# 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 change {{P}}CX_BALLOON_FLIGHT.
|
||||
|
||||
# 7. Acceptance
|
||||
- The classes are active and have no syntax error.
|
||||
- The hidden tests pass.
|
||||
- Write your own ABAP Unit tests for the class.
|
||||
90
tasks_gen/train/G1004/task.json
Normal file
90
tasks_gen/train/G1004/task.json
Normal file
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"id": "G1004",
|
||||
"category": "D",
|
||||
"object_type": "CLAS",
|
||||
"difficulty": 2,
|
||||
"release_target": "v816",
|
||||
"expected_outcome": "implement",
|
||||
"budget": {
|
||||
"max_tool_calls": 70,
|
||||
"max_activations": 18
|
||||
},
|
||||
"seed": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}CX_BALLOON_FLIGHT",
|
||||
"file": "seed/cx_balloon_flight.clas.abap",
|
||||
"description": "Base exception class of a rejected balloon flight"
|
||||
}
|
||||
],
|
||||
"contract": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}BALLOON_CHECKER"
|
||||
},
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}CX_BALLOON_CREW"
|
||||
},
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}CX_BALLOON_WEIGHT"
|
||||
},
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}CX_BALLOON_WIND"
|
||||
},
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}CX_BALLOON_CLOUD"
|
||||
}
|
||||
],
|
||||
"out_of_scope": [
|
||||
"{{P}}CX_BALLOON_FLIGHT"
|
||||
],
|
||||
"hidden_tests": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}BALLOON_HIDDEN",
|
||||
"file": "hidden/balloon_hidden.clas.abap",
|
||||
"description": "Hidden tests for the balloon flight check"
|
||||
}
|
||||
],
|
||||
"reference": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}CX_BALLOON_CREW",
|
||||
"file": "reference/cx_balloon_crew.clas.abap",
|
||||
"description": "Too many passengers"
|
||||
},
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}CX_BALLOON_WEIGHT",
|
||||
"file": "reference/cx_balloon_weight.clas.abap",
|
||||
"description": "Weight above the limit"
|
||||
},
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}CX_BALLOON_WIND",
|
||||
"file": "reference/cx_balloon_wind.clas.abap",
|
||||
"description": "Wind above the limit"
|
||||
},
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}CX_BALLOON_CLOUD",
|
||||
"file": "reference/cx_balloon_cloud.clas.abap",
|
||||
"description": "Cloud base below the limit"
|
||||
},
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}BALLOON_CHECKER",
|
||||
"file": "reference/balloon_checker.clas.abap",
|
||||
"description": "Balloon flight check with class-based exceptions",
|
||||
"testclasses_file": "reference/balloon_checker.testclasses.abap"
|
||||
}
|
||||
],
|
||||
"craft_checks": [
|
||||
"method_length",
|
||||
"db_operation_in_loop"
|
||||
]
|
||||
}
|
||||
59
tasks_gen/train/G1005/faulty/m0_credit_checker.clas.abap
Normal file
59
tasks_gen/train/G1005/faulty/m0_credit_checker.clas.abap
Normal file
@@ -0,0 +1,59 @@
|
||||
CLASS {{p}}credit_checker DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
INTERFACES {{p}}if_credit_check.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS c_income_factor TYPE i VALUE 3.
|
||||
CONSTANTS c_plan_reduction TYPE {{p}}if_credit_check=>ty_amount VALUE '500.00'.
|
||||
CONSTANTS c_min_age TYPE i VALUE 18.
|
||||
CONSTANTS c_full_limit_age TYPE i VALUE 21.
|
||||
CONSTANTS c_max_open_plans TYPE i VALUE 2.
|
||||
CONSTANTS c_hundred TYPE i VALUE 100.
|
||||
|
||||
METHODS credit_limit_cents
|
||||
IMPORTING iv_age TYPE i
|
||||
iv_income TYPE {{p}}if_credit_check=>ty_amount
|
||||
iv_open_plans TYPE i
|
||||
RETURNING VALUE(rv_cents) TYPE i.
|
||||
METHODS to_cents
|
||||
IMPORTING iv_amount TYPE {{p}}if_credit_check=>ty_amount
|
||||
RETURNING VALUE(rv_cents) TYPE i.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}credit_checker IMPLEMENTATION.
|
||||
METHOD {{p}}if_credit_check~check.
|
||||
IF iv_age < c_min_age.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-age.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF iv_income > 0.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-income.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF iv_open_plans >= c_max_open_plans.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-open_plan.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF to_cents( iv_order_amount ) > credit_limit_cents( iv_age = iv_age
|
||||
iv_income = iv_income
|
||||
iv_open_plans = iv_open_plans ).
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-limit.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-ok.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD credit_limit_cents.
|
||||
rv_cents = to_cents( iv_income ) * c_income_factor
|
||||
- to_cents( c_plan_reduction ) * iv_open_plans.
|
||||
IF iv_age < c_full_limit_age.
|
||||
rv_cents = rv_cents DIV 2.
|
||||
rv_cents = rv_cents DIV c_hundred * c_hundred.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD to_cents.
|
||||
rv_cents = iv_amount * c_hundred.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
59
tasks_gen/train/G1005/faulty/m2_credit_checker.clas.abap
Normal file
59
tasks_gen/train/G1005/faulty/m2_credit_checker.clas.abap
Normal file
@@ -0,0 +1,59 @@
|
||||
CLASS {{p}}credit_checker DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
INTERFACES {{p}}if_credit_check.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS c_income_factor TYPE i VALUE 3.
|
||||
CONSTANTS c_plan_reduction TYPE {{p}}if_credit_check=>ty_amount VALUE '500.00'.
|
||||
CONSTANTS c_min_age TYPE i VALUE 18.
|
||||
CONSTANTS c_full_limit_age TYPE i VALUE 21.
|
||||
CONSTANTS c_max_open_plans TYPE i VALUE 2.
|
||||
CONSTANTS c_hundred TYPE i VALUE 100.
|
||||
|
||||
METHODS credit_limit_cents
|
||||
IMPORTING iv_age TYPE i
|
||||
iv_income TYPE {{p}}if_credit_check=>ty_amount
|
||||
iv_open_plans TYPE i
|
||||
RETURNING VALUE(rv_cents) TYPE i.
|
||||
METHODS to_cents
|
||||
IMPORTING iv_amount TYPE {{p}}if_credit_check=>ty_amount
|
||||
RETURNING VALUE(rv_cents) TYPE i.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}credit_checker IMPLEMENTATION.
|
||||
METHOD {{p}}if_credit_check~check.
|
||||
IF iv_age < c_min_age.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-age.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF iv_income <= 0.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-income.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF iv_open_plans >= c_max_open_plans.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-open_plan.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF to_cents( iv_order_amount ) > credit_limit_cents( iv_age = iv_age
|
||||
iv_income = iv_income
|
||||
iv_open_plans = iv_open_plans ).
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-limit.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-ok.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD credit_limit_cents.
|
||||
rv_cents = to_cents( iv_income ) / c_income_factor
|
||||
- to_cents( c_plan_reduction ) * iv_open_plans.
|
||||
IF iv_age < c_full_limit_age.
|
||||
rv_cents = rv_cents DIV 2.
|
||||
rv_cents = rv_cents DIV c_hundred * c_hundred.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD to_cents.
|
||||
rv_cents = iv_amount * c_hundred.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
59
tasks_gen/train/G1005/faulty/m3_credit_checker.clas.abap
Normal file
59
tasks_gen/train/G1005/faulty/m3_credit_checker.clas.abap
Normal file
@@ -0,0 +1,59 @@
|
||||
CLASS {{p}}credit_checker DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
INTERFACES {{p}}if_credit_check.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS c_income_factor TYPE i VALUE 3.
|
||||
CONSTANTS c_plan_reduction TYPE {{p}}if_credit_check=>ty_amount VALUE '500.00'.
|
||||
CONSTANTS c_min_age TYPE i VALUE 18.
|
||||
CONSTANTS c_full_limit_age TYPE i VALUE 21.
|
||||
CONSTANTS c_max_open_plans TYPE i VALUE 2.
|
||||
CONSTANTS c_hundred TYPE i VALUE 100.
|
||||
|
||||
METHODS credit_limit_cents
|
||||
IMPORTING iv_age TYPE i
|
||||
iv_income TYPE {{p}}if_credit_check=>ty_amount
|
||||
iv_open_plans TYPE i
|
||||
RETURNING VALUE(rv_cents) TYPE i.
|
||||
METHODS to_cents
|
||||
IMPORTING iv_amount TYPE {{p}}if_credit_check=>ty_amount
|
||||
RETURNING VALUE(rv_cents) TYPE i.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}credit_checker IMPLEMENTATION.
|
||||
METHOD {{p}}if_credit_check~check.
|
||||
IF iv_age < c_min_age.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-age.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF iv_income <= 0.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-income.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF iv_open_plans >= c_max_open_plans.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-open_plan.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF to_cents( iv_order_amount ) > credit_limit_cents( iv_age = iv_age
|
||||
iv_income = iv_income
|
||||
iv_open_plans = iv_open_plans ).
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-limit.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-ok.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD credit_limit_cents.
|
||||
rv_cents = to_cents( iv_income ) * c_income_factor
|
||||
- to_cents( c_plan_reduction ) / iv_open_plans.
|
||||
IF iv_age < c_full_limit_age.
|
||||
rv_cents = rv_cents DIV 2.
|
||||
rv_cents = rv_cents DIV c_hundred * c_hundred.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD to_cents.
|
||||
rv_cents = iv_amount * c_hundred.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
59
tasks_gen/train/G1005/faulty/m4_credit_checker.clas.abap
Normal file
59
tasks_gen/train/G1005/faulty/m4_credit_checker.clas.abap
Normal file
@@ -0,0 +1,59 @@
|
||||
CLASS {{p}}credit_checker DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
INTERFACES {{p}}if_credit_check.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS c_income_factor TYPE i VALUE 3.
|
||||
CONSTANTS c_plan_reduction TYPE {{p}}if_credit_check=>ty_amount VALUE '500.00'.
|
||||
CONSTANTS c_min_age TYPE i VALUE 18.
|
||||
CONSTANTS c_full_limit_age TYPE i VALUE 21.
|
||||
CONSTANTS c_max_open_plans TYPE i VALUE 2.
|
||||
CONSTANTS c_hundred TYPE i VALUE 100.
|
||||
|
||||
METHODS credit_limit_cents
|
||||
IMPORTING iv_age TYPE i
|
||||
iv_income TYPE {{p}}if_credit_check=>ty_amount
|
||||
iv_open_plans TYPE i
|
||||
RETURNING VALUE(rv_cents) TYPE i.
|
||||
METHODS to_cents
|
||||
IMPORTING iv_amount TYPE {{p}}if_credit_check=>ty_amount
|
||||
RETURNING VALUE(rv_cents) TYPE i.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}credit_checker IMPLEMENTATION.
|
||||
METHOD {{p}}if_credit_check~check.
|
||||
IF iv_age < c_min_age.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-age.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF iv_income <= 0.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-income.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF iv_open_plans >= c_max_open_plans.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-open_plan.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF to_cents( iv_order_amount ) > credit_limit_cents( iv_age = iv_age
|
||||
iv_income = iv_income
|
||||
iv_open_plans = iv_open_plans ).
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-limit.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-ok.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD credit_limit_cents.
|
||||
rv_cents = to_cents( iv_income ) * c_income_factor
|
||||
- to_cents( c_plan_reduction ) * iv_open_plans.
|
||||
IF iv_age >= c_full_limit_age.
|
||||
rv_cents = rv_cents DIV 2.
|
||||
rv_cents = rv_cents DIV c_hundred * c_hundred.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD to_cents.
|
||||
rv_cents = iv_amount * c_hundred.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
24
tasks_gen/train/G1005/generation.json
Normal file
24
tasks_gen/train/G1005/generation.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"id": "G1005",
|
||||
"pool": "train",
|
||||
"object_type": "CLAS",
|
||||
"category": "F",
|
||||
"attempts": [
|
||||
{
|
||||
"stage": "validate",
|
||||
"oracle": 96.4,
|
||||
"null": 0
|
||||
},
|
||||
{
|
||||
"stage": "validate",
|
||||
"oracle": 100.0,
|
||||
"null": 0,
|
||||
"mutation": {
|
||||
"valid": 4,
|
||||
"killed": 4,
|
||||
"ok": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"accepted": true
|
||||
}
|
||||
129
tasks_gen/train/G1005/hidden/t02_hidden.clas.abap
Normal file
129
tasks_gen/train/G1005/hidden/t02_hidden.clas.abap
Normal file
@@ -0,0 +1,129 @@
|
||||
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_credit_check.
|
||||
METHODS setup.
|
||||
METHODS too_young FOR TESTING.
|
||||
METHODS age_eighteen_is_ok FOR TESTING.
|
||||
METHODS zero_income FOR TESTING.
|
||||
METHODS two_open_plans FOR TESTING.
|
||||
METHODS order_above_limit FOR TESTING.
|
||||
METHODS order_at_limit_is_ok FOR TESTING.
|
||||
METHODS young_limit_halved FOR TESTING.
|
||||
METHODS adult_keeps_limit FOR TESTING.
|
||||
METHODS young_limit_is_floor FOR TESTING.
|
||||
METHODS plan_reduces_limit FOR TESTING.
|
||||
METHODS valid_adult FOR TESTING.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}t02_hidden IMPLEMENTATION.
|
||||
METHOD setup.
|
||||
mo_cut = NEW {{p}}credit_checker( ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD too_young.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-age
|
||||
act = mo_cut->check( iv_age = 17
|
||||
iv_income = '3000.00'
|
||||
iv_open_plans = 0
|
||||
iv_order_amount = '100.00' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD age_eighteen_is_ok.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-ok
|
||||
act = mo_cut->check( iv_age = 18
|
||||
iv_income = '3000.00'
|
||||
iv_open_plans = 0
|
||||
iv_order_amount = '100.00' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD zero_income.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-income
|
||||
act = mo_cut->check( iv_age = 30
|
||||
iv_income = '0.00'
|
||||
iv_open_plans = 0
|
||||
iv_order_amount = '100.00' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD two_open_plans.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-open_plan
|
||||
act = mo_cut->check( iv_age = 30
|
||||
iv_income = '3000.00'
|
||||
iv_open_plans = 2
|
||||
iv_order_amount = '100.00' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD order_above_limit.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-limit
|
||||
act = mo_cut->check( iv_age = 30
|
||||
iv_income = '1000.00'
|
||||
iv_open_plans = 0
|
||||
iv_order_amount = '3000.01' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD order_at_limit_is_ok.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-ok
|
||||
act = mo_cut->check( iv_age = 30
|
||||
iv_income = '1000.00'
|
||||
iv_open_plans = 0
|
||||
iv_order_amount = '3000.00' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD young_limit_halved.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-limit
|
||||
act = mo_cut->check( iv_age = 20
|
||||
iv_income = '1000.00'
|
||||
iv_open_plans = 0
|
||||
iv_order_amount = '1500.01' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD adult_keeps_limit.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-ok
|
||||
act = mo_cut->check( iv_age = 21
|
||||
iv_income = '1000.00'
|
||||
iv_open_plans = 0
|
||||
iv_order_amount = '1500.01' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD young_limit_is_floor.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-limit
|
||||
act = mo_cut->check( iv_age = 20
|
||||
iv_income = '2500.50'
|
||||
iv_open_plans = 0
|
||||
iv_order_amount = '3750.50' ) ).
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-ok
|
||||
act = mo_cut->check( iv_age = 20
|
||||
iv_income = '2500.50'
|
||||
iv_open_plans = 0
|
||||
iv_order_amount = '3750.00' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD plan_reduces_limit.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-limit
|
||||
act = mo_cut->check( iv_age = 30
|
||||
iv_income = '1000.00'
|
||||
iv_open_plans = 1
|
||||
iv_order_amount = '2500.01' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD valid_adult.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-ok
|
||||
act = mo_cut->check( iv_age = 35
|
||||
iv_income = '2000.00'
|
||||
iv_open_plans = 1
|
||||
iv_order_amount = '5500.00' ) ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
73
tasks_gen/train/G1005/mutation.json
Normal file
73
tasks_gen/train/G1005/mutation.json
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"task": "G1005",
|
||||
"mutants": [
|
||||
{
|
||||
"object": "{{P}}CREDIT_CHECKER",
|
||||
"mutant": "line 30: <= -> > (rel)",
|
||||
"status": "killed",
|
||||
"hidden": "1/11",
|
||||
"failed_tests": [
|
||||
"ADULT_KEEPS_LIMIT",
|
||||
"AGE_EIGHTEEN_IS_OK",
|
||||
"ORDER_ABOVE_LIMIT",
|
||||
"ORDER_AT_LIMIT_IS_OK",
|
||||
"PLAN_REDUCES_LIMIT",
|
||||
"TWO_OPEN_PLANS",
|
||||
"VALID_ADULT",
|
||||
"YOUNG_LIMIT_HALVED",
|
||||
"YOUNG_LIMIT_IS_FLOOR",
|
||||
"ZERO_INCOME"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}CREDIT_CHECKER",
|
||||
"mutant": "line 38: = -> <> (eq)",
|
||||
"status": "invalid",
|
||||
"hidden": "0/0",
|
||||
"failed_tests": []
|
||||
},
|
||||
{
|
||||
"object": "{{P}}CREDIT_CHECKER",
|
||||
"mutant": "line 48: * -> / (arith)",
|
||||
"status": "killed",
|
||||
"hidden": "7/11",
|
||||
"failed_tests": [
|
||||
"ADULT_KEEPS_LIMIT",
|
||||
"ORDER_AT_LIMIT_IS_OK",
|
||||
"VALID_ADULT",
|
||||
"YOUNG_LIMIT_IS_FLOOR"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}CREDIT_CHECKER",
|
||||
"mutant": "line 49: * -> / (arith)",
|
||||
"status": "killed",
|
||||
"hidden": "5/11",
|
||||
"failed_tests": [
|
||||
"ADULT_KEEPS_LIMIT",
|
||||
"AGE_EIGHTEEN_IS_OK",
|
||||
"ORDER_ABOVE_LIMIT",
|
||||
"ORDER_AT_LIMIT_IS_OK",
|
||||
"YOUNG_LIMIT_HALVED",
|
||||
"YOUNG_LIMIT_IS_FLOOR"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}CREDIT_CHECKER",
|
||||
"mutant": "line 50: < -> >= (rel)",
|
||||
"status": "killed",
|
||||
"hidden": "6/11",
|
||||
"failed_tests": [
|
||||
"ADULT_KEEPS_LIMIT",
|
||||
"ORDER_AT_LIMIT_IS_OK",
|
||||
"VALID_ADULT",
|
||||
"YOUNG_LIMIT_HALVED",
|
||||
"YOUNG_LIMIT_IS_FLOOR"
|
||||
]
|
||||
}
|
||||
],
|
||||
"valid": 4,
|
||||
"killed": 4,
|
||||
"kill_rate": 1.0,
|
||||
"ok": true
|
||||
}
|
||||
59
tasks_gen/train/G1005/reference/credit_checker.clas.abap
Normal file
59
tasks_gen/train/G1005/reference/credit_checker.clas.abap
Normal file
@@ -0,0 +1,59 @@
|
||||
CLASS {{p}}credit_checker DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
INTERFACES {{p}}if_credit_check.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS c_income_factor TYPE i VALUE 3.
|
||||
CONSTANTS c_plan_reduction TYPE {{p}}if_credit_check=>ty_amount VALUE '500.00'.
|
||||
CONSTANTS c_min_age TYPE i VALUE 18.
|
||||
CONSTANTS c_full_limit_age TYPE i VALUE 21.
|
||||
CONSTANTS c_max_open_plans TYPE i VALUE 2.
|
||||
CONSTANTS c_hundred TYPE i VALUE 100.
|
||||
|
||||
METHODS credit_limit_cents
|
||||
IMPORTING iv_age TYPE i
|
||||
iv_income TYPE {{p}}if_credit_check=>ty_amount
|
||||
iv_open_plans TYPE i
|
||||
RETURNING VALUE(rv_cents) TYPE i.
|
||||
METHODS to_cents
|
||||
IMPORTING iv_amount TYPE {{p}}if_credit_check=>ty_amount
|
||||
RETURNING VALUE(rv_cents) TYPE i.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}credit_checker IMPLEMENTATION.
|
||||
METHOD {{p}}if_credit_check~check.
|
||||
IF iv_age < c_min_age.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-age.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF iv_income <= 0.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-income.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF iv_open_plans >= c_max_open_plans.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-open_plan.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF to_cents( iv_order_amount ) > credit_limit_cents( iv_age = iv_age
|
||||
iv_income = iv_income
|
||||
iv_open_plans = iv_open_plans ).
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-limit.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
rv_reason = {{p}}if_credit_check=>c_reason-ok.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD credit_limit_cents.
|
||||
rv_cents = to_cents( iv_income ) * c_income_factor
|
||||
- to_cents( c_plan_reduction ) * iv_open_plans.
|
||||
IF iv_age < c_full_limit_age.
|
||||
rv_cents = rv_cents DIV 2.
|
||||
rv_cents = rv_cents DIV c_hundred * c_hundred.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD to_cents.
|
||||
rv_cents = iv_amount * c_hundred.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
@@ -0,0 +1,98 @@
|
||||
CLASS ltc_credit_checker DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
|
||||
PRIVATE SECTION.
|
||||
DATA mo_cut TYPE REF TO {{p}}if_credit_check.
|
||||
METHODS setup.
|
||||
METHODS too_young FOR TESTING.
|
||||
METHODS zero_income FOR TESTING.
|
||||
METHODS two_open_plans FOR TESTING.
|
||||
METHODS order_above_limit FOR TESTING.
|
||||
METHODS order_at_limit FOR TESTING.
|
||||
METHODS young_limit_halved FOR TESTING.
|
||||
METHODS young_limit_is_floor FOR TESTING.
|
||||
METHODS valid_adult FOR TESTING.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS ltc_credit_checker IMPLEMENTATION.
|
||||
METHOD setup.
|
||||
mo_cut = NEW {{p}}credit_checker( ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD too_young.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-age
|
||||
act = mo_cut->check( iv_age = 17
|
||||
iv_income = '3000.00'
|
||||
iv_open_plans = 0
|
||||
iv_order_amount = '100.00' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD zero_income.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-income
|
||||
act = mo_cut->check( iv_age = 30
|
||||
iv_income = '0.00'
|
||||
iv_open_plans = 0
|
||||
iv_order_amount = '100.00' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD two_open_plans.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-open_plan
|
||||
act = mo_cut->check( iv_age = 30
|
||||
iv_income = '3000.00'
|
||||
iv_open_plans = 2
|
||||
iv_order_amount = '100.00' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD order_above_limit.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-limit
|
||||
act = mo_cut->check( iv_age = 30
|
||||
iv_income = '1000.00'
|
||||
iv_open_plans = 0
|
||||
iv_order_amount = '3000.01' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD order_at_limit.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-ok
|
||||
act = mo_cut->check( iv_age = 30
|
||||
iv_income = '1000.00'
|
||||
iv_open_plans = 0
|
||||
iv_order_amount = '3000.00' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD young_limit_halved.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-limit
|
||||
act = mo_cut->check( iv_age = 20
|
||||
iv_income = '1000.00'
|
||||
iv_open_plans = 0
|
||||
iv_order_amount = '1500.01' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD young_limit_is_floor.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-limit
|
||||
act = mo_cut->check( iv_age = 20
|
||||
iv_income = '2500.50'
|
||||
iv_open_plans = 0
|
||||
iv_order_amount = '3750.50' ) ).
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-ok
|
||||
act = mo_cut->check( iv_age = 20
|
||||
iv_income = '2500.50'
|
||||
iv_open_plans = 0
|
||||
iv_order_amount = '3750.00' ) ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD valid_adult.
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
exp = {{p}}if_credit_check=>c_reason-ok
|
||||
act = mo_cut->check( iv_age = 35
|
||||
iv_income = '2000.00'
|
||||
iv_open_plans = 1
|
||||
iv_order_amount = '5500.00' ) ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
18
tasks_gen/train/G1005/seed/if_credit_check.intf.abap
Normal file
18
tasks_gen/train/G1005/seed/if_credit_check.intf.abap
Normal file
@@ -0,0 +1,18 @@
|
||||
INTERFACE {{p}}if_credit_check PUBLIC.
|
||||
TYPES ty_reason TYPE c LENGTH 10.
|
||||
TYPES ty_amount TYPE p LENGTH 11 DECIMALS 2.
|
||||
CONSTANTS:
|
||||
BEGIN OF c_reason,
|
||||
ok TYPE ty_reason VALUE 'OK',
|
||||
age TYPE ty_reason VALUE 'AGE',
|
||||
income TYPE ty_reason VALUE 'INCOME',
|
||||
open_plan TYPE ty_reason VALUE 'OPEN_PLAN',
|
||||
limit TYPE ty_reason VALUE 'LIMIT',
|
||||
END OF c_reason.
|
||||
METHODS check
|
||||
IMPORTING iv_age TYPE i
|
||||
iv_income TYPE ty_amount
|
||||
iv_open_plans TYPE i
|
||||
iv_order_amount TYPE ty_amount
|
||||
RETURNING VALUE(rv_reason) TYPE ty_reason.
|
||||
ENDINTERFACE.
|
||||
56
tasks_gen/train/G1005/spec.md
Normal file
56
tasks_gen/train/G1005/spec.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# 1. Goal
|
||||
|
||||
A furniture shop sells furniture on instalment plans. A checkout program calls one
|
||||
check before the shop grants an instalment plan to a customer. The program needs
|
||||
one reason code for each customer.
|
||||
|
||||
# 2. Open questions
|
||||
|
||||
None.
|
||||
|
||||
# 3. Context
|
||||
|
||||
- The interface {{P}}IF_CREDIT_CHECK exists in package $TMP. It is active.
|
||||
- The interface declares the type of the reason, the type of a money amount, the
|
||||
constants of the reason codes, and one method.
|
||||
- The method name, the parameter names and the parameter types are not in this
|
||||
document. Read the interface in the system.
|
||||
- The reason constants have the names OK, AGE, INCOME, OPEN_PLAN and LIMIT.
|
||||
|
||||
# 4. Contract
|
||||
|
||||
- Create the class {{P}}CREDIT_CHECKER in package $TMP.
|
||||
- The class is public and final. It has a public constructor without parameters.
|
||||
- The class implements the interface {{P}}IF_CREDIT_CHECK.
|
||||
- Do not add other public methods.
|
||||
|
||||
# 5. Business rules
|
||||
|
||||
The check receives the age of the customer in years, the net monthly income of the
|
||||
customer, the number of open instalment plans of the customer, and the amount of
|
||||
the new order. Apply the rules in this sequence. Return the reason of the first
|
||||
rule that fails.
|
||||
|
||||
1. If the age is less than 18, return AGE.
|
||||
2. If the net monthly income is zero or less, return INCOME.
|
||||
3. If the number of open instalment plans is 2 or more, return OPEN_PLAN.
|
||||
4. Calculate the credit limit:
|
||||
- Start with three times the net monthly income.
|
||||
- Subtract 500 for each open instalment plan.
|
||||
- If the age is less than 21, halve the limit and round the result down to
|
||||
whole euros. Example: 3750.75 becomes 3750.00.
|
||||
5. If the amount of the new order is more than the credit limit, return LIMIT.
|
||||
6. Else return OK.
|
||||
|
||||
# 6. Constraints
|
||||
|
||||
- Release target: SAP_BASIS 8.16 (ABAP Platform 2025).
|
||||
- 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 interface {{P}}IF_CREDIT_CHECK.
|
||||
|
||||
# 7. Acceptance
|
||||
|
||||
- The class is active and has no syntax error.
|
||||
- The hidden tests pass.
|
||||
- Write your own ABAP Unit tests for the class.
|
||||
51
tasks_gen/train/G1005/task.json
Normal file
51
tasks_gen/train/G1005/task.json
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"id": "G1005",
|
||||
"category": "F",
|
||||
"object_type": "CLAS",
|
||||
"difficulty": 2,
|
||||
"release_target": "v816",
|
||||
"expected_outcome": "implement",
|
||||
"budget": {
|
||||
"max_tool_calls": 70,
|
||||
"max_activations": 18
|
||||
},
|
||||
"seed": [
|
||||
{
|
||||
"type": "INTF",
|
||||
"name": "{{P}}IF_CREDIT_CHECK",
|
||||
"file": "seed/if_credit_check.intf.abap",
|
||||
"description": "Instalment plan check contract"
|
||||
}
|
||||
],
|
||||
"contract": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}CREDIT_CHECKER",
|
||||
"implements": "{{P}}IF_CREDIT_CHECK"
|
||||
}
|
||||
],
|
||||
"out_of_scope": [
|
||||
"{{P}}IF_CREDIT_CHECK"
|
||||
],
|
||||
"hidden_tests": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}T02_HIDDEN",
|
||||
"file": "hidden/t02_hidden.clas.abap",
|
||||
"description": "T02 hidden tests"
|
||||
}
|
||||
],
|
||||
"reference": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}CREDIT_CHECKER",
|
||||
"file": "reference/credit_checker.clas.abap",
|
||||
"description": "Instalment plan credit checker",
|
||||
"testclasses_file": "reference/credit_checker.testclasses.abap"
|
||||
}
|
||||
],
|
||||
"craft_checks": [
|
||||
"method_length",
|
||||
"no_global_variables"
|
||||
]
|
||||
}
|
||||
41
tasks_gen/train/G1006/faulty/m0_auc_premium.func.abap
Normal file
41
tasks_gen/train/G1006/faulty/m0_auc_premium.func.abap
Normal file
@@ -0,0 +1,41 @@
|
||||
FUNCTION {{p}}auc_premium
|
||||
IMPORTING
|
||||
iv_lot_type TYPE string
|
||||
iv_hammer TYPE decfloat34
|
||||
iv_channel TYPE string
|
||||
EXPORTING
|
||||
ev_skip TYPE abap_bool
|
||||
CHANGING
|
||||
cv_fee TYPE decfloat34
|
||||
EXCEPTIONS
|
||||
invalid_hammer.
|
||||
|
||||
DATA lv_premium TYPE decfloat34.
|
||||
|
||||
ev_skip = abap_true.
|
||||
IF iv_hammer < 0.
|
||||
RAISE invalid_hammer.
|
||||
ENDIF.
|
||||
IF iv_lot_type = 'C'.
|
||||
ev_skip = abap_true.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF iv_hammer <= 1000.
|
||||
lv_premium = iv_hammer * 20 / 100.
|
||||
ELSEIF iv_hammer <= 10000.
|
||||
lv_premium = 1000 * 20 / 100 + ( iv_hammer - 1000 ) * 12 / 100.
|
||||
ELSE.
|
||||
lv_premium = 1000 * 20 / 100 + 9000 * 12 / 100 + ( iv_hammer - 10000 ) * 6 / 100.
|
||||
ENDIF.
|
||||
IF iv_channel = 'O'.
|
||||
lv_premium = lv_premium * 90 / 100.
|
||||
ENDIF.
|
||||
lv_premium = round( val = lv_premium dec = 2 mode = cl_abap_math=>round_half_up ).
|
||||
IF lv_premium < 5.
|
||||
lv_premium = 5.
|
||||
ELSEIF lv_premium > 5000.
|
||||
lv_premium = 5000.
|
||||
ENDIF.
|
||||
cv_fee = lv_premium.
|
||||
|
||||
ENDFUNCTION.
|
||||
41
tasks_gen/train/G1006/faulty/m1_auc_premium.func.abap
Normal file
41
tasks_gen/train/G1006/faulty/m1_auc_premium.func.abap
Normal file
@@ -0,0 +1,41 @@
|
||||
FUNCTION {{p}}auc_premium
|
||||
IMPORTING
|
||||
iv_lot_type TYPE string
|
||||
iv_hammer TYPE decfloat34
|
||||
iv_channel TYPE string
|
||||
EXPORTING
|
||||
ev_skip TYPE abap_bool
|
||||
CHANGING
|
||||
cv_fee TYPE decfloat34
|
||||
EXCEPTIONS
|
||||
invalid_hammer.
|
||||
|
||||
DATA lv_premium TYPE decfloat34.
|
||||
|
||||
ev_skip = abap_false.
|
||||
IF iv_hammer < 0.
|
||||
RAISE invalid_hammer.
|
||||
ENDIF.
|
||||
IF iv_lot_type = 'C'.
|
||||
ev_skip = abap_true.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF iv_hammer <= 1000.
|
||||
lv_premium = iv_hammer * 20 / 100.
|
||||
ELSEIF iv_hammer > 10000.
|
||||
lv_premium = 1000 * 20 / 100 + ( iv_hammer - 1000 ) * 12 / 100.
|
||||
ELSE.
|
||||
lv_premium = 1000 * 20 / 100 + 9000 * 12 / 100 + ( iv_hammer - 10000 ) * 6 / 100.
|
||||
ENDIF.
|
||||
IF iv_channel = 'O'.
|
||||
lv_premium = lv_premium * 90 / 100.
|
||||
ENDIF.
|
||||
lv_premium = round( val = lv_premium dec = 2 mode = cl_abap_math=>round_half_up ).
|
||||
IF lv_premium < 5.
|
||||
lv_premium = 5.
|
||||
ELSEIF lv_premium > 5000.
|
||||
lv_premium = 5000.
|
||||
ENDIF.
|
||||
cv_fee = lv_premium.
|
||||
|
||||
ENDFUNCTION.
|
||||
41
tasks_gen/train/G1006/faulty/m2_auc_premium.func.abap
Normal file
41
tasks_gen/train/G1006/faulty/m2_auc_premium.func.abap
Normal file
@@ -0,0 +1,41 @@
|
||||
FUNCTION {{p}}auc_premium
|
||||
IMPORTING
|
||||
iv_lot_type TYPE string
|
||||
iv_hammer TYPE decfloat34
|
||||
iv_channel TYPE string
|
||||
EXPORTING
|
||||
ev_skip TYPE abap_bool
|
||||
CHANGING
|
||||
cv_fee TYPE decfloat34
|
||||
EXCEPTIONS
|
||||
invalid_hammer.
|
||||
|
||||
DATA lv_premium TYPE decfloat34.
|
||||
|
||||
ev_skip = abap_false.
|
||||
IF iv_hammer < 0.
|
||||
RAISE invalid_hammer.
|
||||
ENDIF.
|
||||
IF iv_lot_type = 'C'.
|
||||
ev_skip = abap_true.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF iv_hammer <= 1000.
|
||||
lv_premium = iv_hammer * 20 / 100.
|
||||
ELSEIF iv_hammer <= 10000.
|
||||
lv_premium = 1000 * 20 / 100 + ( iv_hammer - 1000 ) * 12 / 100.
|
||||
ELSE.
|
||||
lv_premium = 1000 * 20 / 100 + 9000 * 12 / 101 + ( iv_hammer - 10000 ) * 6 / 100.
|
||||
ENDIF.
|
||||
IF iv_channel = 'O'.
|
||||
lv_premium = lv_premium * 90 / 100.
|
||||
ENDIF.
|
||||
lv_premium = round( val = lv_premium dec = 2 mode = cl_abap_math=>round_half_up ).
|
||||
IF lv_premium < 5.
|
||||
lv_premium = 5.
|
||||
ELSEIF lv_premium > 5000.
|
||||
lv_premium = 5000.
|
||||
ENDIF.
|
||||
cv_fee = lv_premium.
|
||||
|
||||
ENDFUNCTION.
|
||||
41
tasks_gen/train/G1006/faulty/m3_auc_premium.func.abap
Normal file
41
tasks_gen/train/G1006/faulty/m3_auc_premium.func.abap
Normal file
@@ -0,0 +1,41 @@
|
||||
FUNCTION {{p}}auc_premium
|
||||
IMPORTING
|
||||
iv_lot_type TYPE string
|
||||
iv_hammer TYPE decfloat34
|
||||
iv_channel TYPE string
|
||||
EXPORTING
|
||||
ev_skip TYPE abap_bool
|
||||
CHANGING
|
||||
cv_fee TYPE decfloat34
|
||||
EXCEPTIONS
|
||||
invalid_hammer.
|
||||
|
||||
DATA lv_premium TYPE decfloat34.
|
||||
|
||||
ev_skip = abap_false.
|
||||
IF iv_hammer < 0.
|
||||
RAISE invalid_hammer.
|
||||
ENDIF.
|
||||
IF iv_lot_type = 'C'.
|
||||
ev_skip = abap_true.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF iv_hammer <= 1000.
|
||||
lv_premium = iv_hammer * 20 / 100.
|
||||
ELSEIF iv_hammer <= 10000.
|
||||
lv_premium = 1000 * 20 / 100 + ( iv_hammer - 1000 ) * 12 / 100.
|
||||
ELSE.
|
||||
lv_premium = 1000 * 20 / 100 + 9000 * 12 / 100 + ( iv_hammer - 10000 ) * 6 / 100.
|
||||
ENDIF.
|
||||
IF iv_channel <> 'O'.
|
||||
lv_premium = lv_premium * 90 / 100.
|
||||
ENDIF.
|
||||
lv_premium = round( val = lv_premium dec = 2 mode = cl_abap_math=>round_half_up ).
|
||||
IF lv_premium < 5.
|
||||
lv_premium = 5.
|
||||
ELSEIF lv_premium > 5000.
|
||||
lv_premium = 5000.
|
||||
ENDIF.
|
||||
cv_fee = lv_premium.
|
||||
|
||||
ENDFUNCTION.
|
||||
41
tasks_gen/train/G1006/faulty/m4_auc_premium.func.abap
Normal file
41
tasks_gen/train/G1006/faulty/m4_auc_premium.func.abap
Normal file
@@ -0,0 +1,41 @@
|
||||
FUNCTION {{p}}auc_premium
|
||||
IMPORTING
|
||||
iv_lot_type TYPE string
|
||||
iv_hammer TYPE decfloat34
|
||||
iv_channel TYPE string
|
||||
EXPORTING
|
||||
ev_skip TYPE abap_bool
|
||||
CHANGING
|
||||
cv_fee TYPE decfloat34
|
||||
EXCEPTIONS
|
||||
invalid_hammer.
|
||||
|
||||
DATA lv_premium TYPE decfloat34.
|
||||
|
||||
ev_skip = abap_false.
|
||||
IF iv_hammer < 0.
|
||||
RAISE invalid_hammer.
|
||||
ENDIF.
|
||||
IF iv_lot_type = 'C'.
|
||||
ev_skip = abap_true.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF iv_hammer <= 1000.
|
||||
lv_premium = iv_hammer * 20 / 100.
|
||||
ELSEIF iv_hammer <= 10000.
|
||||
lv_premium = 1000 * 20 / 100 + ( iv_hammer - 1000 ) * 12 / 100.
|
||||
ELSE.
|
||||
lv_premium = 1000 * 20 / 100 + 9000 * 12 / 100 + ( iv_hammer - 10000 ) * 6 / 100.
|
||||
ENDIF.
|
||||
IF iv_channel = 'O'.
|
||||
lv_premium = lv_premium / 90 / 100.
|
||||
ENDIF.
|
||||
lv_premium = round( val = lv_premium dec = 2 mode = cl_abap_math=>round_half_up ).
|
||||
IF lv_premium < 5.
|
||||
lv_premium = 5.
|
||||
ELSEIF lv_premium > 5000.
|
||||
lv_premium = 5000.
|
||||
ENDIF.
|
||||
cv_fee = lv_premium.
|
||||
|
||||
ENDFUNCTION.
|
||||
60
tasks_gen/train/G1006/generation.json
Normal file
60
tasks_gen/train/G1006/generation.json
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"id": "G1006",
|
||||
"pool": "train",
|
||||
"object_type": "FUNC",
|
||||
"category": "G",
|
||||
"attempts": [
|
||||
{
|
||||
"stage": "bundle",
|
||||
"errors": [
|
||||
"hidden/t14_hidden.clas.abap line 47: syntax error for release v702 (abaplint): Statement does not exist in the configured ABAP version(or a parser error), \"cl_abap_unit_assert\"",
|
||||
"hidden/t14_hidden.clas.abap line 53: syntax error for release v702 (abaplint): Statement does not exist in the configured ABAP version(or a parser error), \"cl_abap_unit_assert\"",
|
||||
"hidden/t14_hidden.clas.abap line 59: syntax error for release v702 (abaplint): Statement does not exist in the configured ABAP version(or a parser error), \"cl_abap_unit_assert\"",
|
||||
"hidden/t14_hidden.clas.abap line 65: syntax error for release v702 (abaplint): Statement does not exist in the configured ABAP version(or a parser error), \"cl_abap_unit_assert\"",
|
||||
"hidden/t14_hidden.clas.abap line 71: syntax error for release v702 (abaplint): Statement does not exist in the configured ABAP version(or a parser error), \"cl_abap_unit_assert\"",
|
||||
"hidden/t14_hidden.clas.abap line 77: syntax error for release v702 (abaplint): Statement does not exist in the configured ABAP version(or a parser error), \"cl_abap_unit_assert\"",
|
||||
"hidden/t14_hidden.clas.abap line 83: syntax error for release v702 (abaplint): Statement does not exist in the configured ABAP version(or a parser error), \"cl_abap_unit_assert\"",
|
||||
"hidden/t14_hidden.clas.abap line 89: syntax error for release v702 (abaplint): Statement does not exist in the configured ABAP version(or a parser error), \"cl_abap_unit_assert\"",
|
||||
"hidden/t14_hidden.clas.abap line 96: syntax error for release v702 (abaplint): Statement does not exist in the configured ABAP version(or a parser error), \"cl_abap_unit_assert\"",
|
||||
"Too close to task G0150 (similarity spec 0.60, rules 0.63, names 0.25). Choose a different business topic and different object names.",
|
||||
"Too close to task G0151 (similarity spec 0.70, rules 0.63, names 0.33). Choose a different business topic and different object names.",
|
||||
"Too close to task G0173 (similarity spec 0.65, rules 0.62, names 0.33). Choose a different business topic and different object names."
|
||||
],
|
||||
"by_check": {
|
||||
"abaplint": 9,
|
||||
"extra": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"stage": "bundle",
|
||||
"errors": [
|
||||
"invalid JSON: Invalid \\escape: line 1 column 1374 (char 1373)"
|
||||
],
|
||||
"by_check": {
|
||||
"json": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"stage": "bundle",
|
||||
"errors": [
|
||||
"hidden/t14_hidden.clas.abap line 82: syntax error for release v702 (abaplint): Statement does not exist in the configured ABAP version(or a parser error), \"15\"",
|
||||
"hidden/t14_hidden.clas.abap line 83: syntax error for release v702 (abaplint): Statement does not exist in the configured ABAP version(or a parser error), \"call\"",
|
||||
"hidden/t14_hidden.clas.abap line 83: syntax error for release v702 (abaplint): Statement does not exist in the configured ABAP version(or a parser error), \"56\""
|
||||
],
|
||||
"by_check": {
|
||||
"abaplint": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"stage": "validate",
|
||||
"oracle": 100.0,
|
||||
"null": 0,
|
||||
"mutation": {
|
||||
"valid": 5,
|
||||
"killed": 5,
|
||||
"ok": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"accepted": true
|
||||
}
|
||||
133
tasks_gen/train/G1006/hidden/t14_hidden.clas.abap
Normal file
133
tasks_gen/train/G1006/hidden/t14_hidden.clas.abap
Normal file
@@ -0,0 +1,133 @@
|
||||
CLASS {{p}}t14_hidden DEFINITION PUBLIC FINAL CREATE PUBLIC
|
||||
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
|
||||
PRIVATE SECTION.
|
||||
METHODS call
|
||||
IMPORTING iv_lot_type TYPE string
|
||||
iv_hammer TYPE decfloat34
|
||||
iv_channel TYPE string
|
||||
iv_fee TYPE decfloat34 DEFAULT 7
|
||||
EXPORTING ev_skip TYPE abap_bool
|
||||
ev_fee TYPE decfloat34
|
||||
ev_subrc TYPE sysubrc.
|
||||
METHODS band_first FOR TESTING.
|
||||
METHODS band_second FOR TESTING.
|
||||
METHODS band_third FOR TESTING.
|
||||
METHODS online_reduction FOR TESTING.
|
||||
METHODS premium_rounding FOR TESTING.
|
||||
METHODS minimum_premium FOR TESTING.
|
||||
METHODS maximum_premium FOR TESTING.
|
||||
METHODS charity_skips FOR TESTING.
|
||||
METHODS negative_hammer FOR TESTING.
|
||||
METHODS skip_false_for_sale FOR TESTING.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}t14_hidden IMPLEMENTATION.
|
||||
METHOD call.
|
||||
ev_fee = iv_fee.
|
||||
CALL FUNCTION '{{P}}AUC_PREMIUM'
|
||||
EXPORTING
|
||||
iv_lot_type = iv_lot_type
|
||||
iv_hammer = iv_hammer
|
||||
iv_channel = iv_channel
|
||||
IMPORTING
|
||||
ev_skip = ev_skip
|
||||
CHANGING
|
||||
cv_fee = ev_fee
|
||||
EXCEPTIONS
|
||||
invalid_hammer = 1
|
||||
OTHERS = 2.
|
||||
ev_subrc = sy-subrc.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD band_first.
|
||||
DATA lv_exp TYPE decfloat34.
|
||||
DATA lv_act TYPE decfloat34.
|
||||
lv_exp = 100.
|
||||
call( EXPORTING iv_lot_type = `S` iv_hammer = 500 iv_channel = `B`
|
||||
IMPORTING ev_fee = lv_act ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = lv_exp act = lv_act ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD band_second.
|
||||
DATA lv_exp TYPE decfloat34.
|
||||
DATA lv_act TYPE decfloat34.
|
||||
lv_exp = 320.
|
||||
call( EXPORTING iv_lot_type = `S` iv_hammer = 2000 iv_channel = `B`
|
||||
IMPORTING ev_fee = lv_act ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = lv_exp act = lv_act ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD band_third.
|
||||
DATA lv_exp TYPE decfloat34.
|
||||
DATA lv_act TYPE decfloat34.
|
||||
lv_exp = 1880.
|
||||
call( EXPORTING iv_lot_type = `S` iv_hammer = 20000 iv_channel = `B`
|
||||
IMPORTING ev_fee = lv_act ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = lv_exp act = lv_act ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD online_reduction.
|
||||
DATA lv_exp TYPE decfloat34.
|
||||
DATA lv_act TYPE decfloat34.
|
||||
lv_exp = 90.
|
||||
call( EXPORTING iv_lot_type = `S` iv_hammer = 500 iv_channel = `O`
|
||||
IMPORTING ev_fee = lv_act ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = lv_exp act = lv_act ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD premium_rounding.
|
||||
DATA lv_exp TYPE decfloat34.
|
||||
DATA lv_act TYPE decfloat34.
|
||||
DATA lv_hammer TYPE decfloat34.
|
||||
lv_exp = '228.15'.
|
||||
lv_hammer = '1234.56'.
|
||||
call( EXPORTING iv_lot_type = `S` iv_hammer = lv_hammer iv_channel = `B`
|
||||
IMPORTING ev_fee = lv_act ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = lv_exp act = lv_act ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD minimum_premium.
|
||||
DATA lv_exp TYPE decfloat34.
|
||||
DATA lv_act TYPE decfloat34.
|
||||
lv_exp = 5.
|
||||
call( EXPORTING iv_lot_type = `S` iv_hammer = 10 iv_channel = `B`
|
||||
IMPORTING ev_fee = lv_act ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = lv_exp act = lv_act ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD maximum_premium.
|
||||
DATA lv_exp TYPE decfloat34.
|
||||
DATA lv_act TYPE decfloat34.
|
||||
lv_exp = 5000.
|
||||
call( EXPORTING iv_lot_type = `S` iv_hammer = 100000 iv_channel = `B`
|
||||
IMPORTING ev_fee = lv_act ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = lv_exp act = lv_act ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD charity_skips.
|
||||
DATA lv_skip TYPE abap_bool.
|
||||
DATA lv_fee TYPE decfloat34.
|
||||
DATA lv_exp TYPE decfloat34.
|
||||
lv_fee = 7.
|
||||
lv_exp = 7.
|
||||
call( EXPORTING iv_lot_type = `C` iv_hammer = 5000 iv_channel = `B` iv_fee = 7
|
||||
IMPORTING ev_skip = lv_skip ev_fee = lv_fee ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = abap_true act = lv_skip ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = lv_exp act = lv_fee ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD negative_hammer.
|
||||
DATA lv_rc TYPE sysubrc.
|
||||
call( EXPORTING iv_lot_type = `S` iv_hammer = -1 iv_channel = `B`
|
||||
IMPORTING ev_subrc = lv_rc ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = 1 act = lv_rc ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD skip_false_for_sale.
|
||||
DATA lv_skip TYPE abap_bool.
|
||||
call( EXPORTING iv_lot_type = `S` iv_hammer = 500 iv_channel = `B`
|
||||
IMPORTING ev_skip = lv_skip ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = abap_false act = lv_skip ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
60
tasks_gen/train/G1006/mutation.json
Normal file
60
tasks_gen/train/G1006/mutation.json
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"task": "G1006",
|
||||
"mutants": [
|
||||
{
|
||||
"object": "{{P}}AUC_PREMIUM",
|
||||
"mutant": "line 15: abap_false -> abap_true (bool)",
|
||||
"status": "killed",
|
||||
"hidden": "9/10",
|
||||
"failed_tests": [
|
||||
"SKIP_FALSE_FOR_SALE"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}AUC_PREMIUM",
|
||||
"mutant": "line 25: <= -> > (rel)",
|
||||
"status": "killed",
|
||||
"hidden": "7/10",
|
||||
"failed_tests": [
|
||||
"BAND_SECOND",
|
||||
"BAND_THIRD",
|
||||
"PREMIUM_ROUNDING"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}AUC_PREMIUM",
|
||||
"mutant": "line 28: 100 -> 101 (const)",
|
||||
"status": "killed",
|
||||
"hidden": "9/10",
|
||||
"failed_tests": [
|
||||
"BAND_THIRD"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}AUC_PREMIUM",
|
||||
"mutant": "line 30: = -> <> (eq)",
|
||||
"status": "killed",
|
||||
"hidden": "5/10",
|
||||
"failed_tests": [
|
||||
"BAND_FIRST",
|
||||
"BAND_SECOND",
|
||||
"BAND_THIRD",
|
||||
"ONLINE_REDUCTION",
|
||||
"PREMIUM_ROUNDING"
|
||||
]
|
||||
},
|
||||
{
|
||||
"object": "{{P}}AUC_PREMIUM",
|
||||
"mutant": "line 31: * -> / (arith)",
|
||||
"status": "killed",
|
||||
"hidden": "9/10",
|
||||
"failed_tests": [
|
||||
"ONLINE_REDUCTION"
|
||||
]
|
||||
}
|
||||
],
|
||||
"valid": 5,
|
||||
"killed": 5,
|
||||
"kill_rate": 1.0,
|
||||
"ok": true
|
||||
}
|
||||
41
tasks_gen/train/G1006/reference/auc_premium.func.abap
Normal file
41
tasks_gen/train/G1006/reference/auc_premium.func.abap
Normal file
@@ -0,0 +1,41 @@
|
||||
FUNCTION {{p}}auc_premium
|
||||
IMPORTING
|
||||
iv_lot_type TYPE string
|
||||
iv_hammer TYPE decfloat34
|
||||
iv_channel TYPE string
|
||||
EXPORTING
|
||||
ev_skip TYPE abap_bool
|
||||
CHANGING
|
||||
cv_fee TYPE decfloat34
|
||||
EXCEPTIONS
|
||||
invalid_hammer.
|
||||
|
||||
DATA lv_premium TYPE decfloat34.
|
||||
|
||||
ev_skip = abap_false.
|
||||
IF iv_hammer < 0.
|
||||
RAISE invalid_hammer.
|
||||
ENDIF.
|
||||
IF iv_lot_type = 'C'.
|
||||
ev_skip = abap_true.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
IF iv_hammer <= 1000.
|
||||
lv_premium = iv_hammer * 20 / 100.
|
||||
ELSEIF iv_hammer <= 10000.
|
||||
lv_premium = 1000 * 20 / 100 + ( iv_hammer - 1000 ) * 12 / 100.
|
||||
ELSE.
|
||||
lv_premium = 1000 * 20 / 100 + 9000 * 12 / 100 + ( iv_hammer - 10000 ) * 6 / 100.
|
||||
ENDIF.
|
||||
IF iv_channel = 'O'.
|
||||
lv_premium = lv_premium * 90 / 100.
|
||||
ENDIF.
|
||||
lv_premium = round( val = lv_premium dec = 2 mode = cl_abap_math=>round_half_up ).
|
||||
IF lv_premium < 5.
|
||||
lv_premium = 5.
|
||||
ELSEIF lv_premium > 5000.
|
||||
lv_premium = 5000.
|
||||
ENDIF.
|
||||
cv_fee = lv_premium.
|
||||
|
||||
ENDFUNCTION.
|
||||
99
tasks_gen/train/G1006/reference/t14_test.clas.abap
Normal file
99
tasks_gen/train/G1006/reference/t14_test.clas.abap
Normal file
@@ -0,0 +1,99 @@
|
||||
CLASS {{p}}t14_test DEFINITION PUBLIC FINAL CREATE PUBLIC
|
||||
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
|
||||
PRIVATE SECTION.
|
||||
METHODS premium_for
|
||||
IMPORTING iv_lot_type TYPE string
|
||||
iv_hammer TYPE decfloat34
|
||||
iv_channel TYPE string
|
||||
RETURNING VALUE(rv_fee) TYPE decfloat34.
|
||||
METHODS band_premium FOR TESTING.
|
||||
METHODS online_reduction FOR TESTING.
|
||||
METHODS premium_limits FOR TESTING.
|
||||
METHODS charity_lot FOR TESTING.
|
||||
METHODS negative_hammer FOR TESTING.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}t14_test IMPLEMENTATION.
|
||||
METHOD premium_for.
|
||||
DATA lv_skip TYPE abap_bool.
|
||||
CALL FUNCTION '{{P}}AUC_PREMIUM'
|
||||
EXPORTING
|
||||
iv_lot_type = iv_lot_type
|
||||
iv_hammer = iv_hammer
|
||||
iv_channel = iv_channel
|
||||
IMPORTING
|
||||
ev_skip = lv_skip
|
||||
CHANGING
|
||||
cv_fee = rv_fee
|
||||
EXCEPTIONS
|
||||
invalid_hammer = 1
|
||||
OTHERS = 2.
|
||||
cl_abap_unit_assert=>assert_subrc( exp = 0 ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD band_premium.
|
||||
DATA lv_exp TYPE decfloat34.
|
||||
DATA lv_act TYPE decfloat34.
|
||||
lv_exp = 320.
|
||||
lv_act = premium_for( iv_lot_type = `S` iv_hammer = 2000 iv_channel = `B` ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = lv_exp act = lv_act ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD online_reduction.
|
||||
DATA lv_exp TYPE decfloat34.
|
||||
DATA lv_act TYPE decfloat34.
|
||||
lv_exp = 90.
|
||||
lv_act = premium_for( iv_lot_type = `S` iv_hammer = 500 iv_channel = `O` ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = lv_exp act = lv_act ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD premium_limits.
|
||||
DATA lv_exp TYPE decfloat34.
|
||||
DATA lv_act TYPE decfloat34.
|
||||
lv_exp = 5.
|
||||
lv_act = premium_for( iv_lot_type = `S` iv_hammer = 10 iv_channel = `B` ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = lv_exp act = lv_act ).
|
||||
lv_exp = 5000.
|
||||
lv_act = premium_for( iv_lot_type = `S` iv_hammer = 100000 iv_channel = `B` ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = lv_exp act = lv_act ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD charity_lot.
|
||||
DATA lv_skip TYPE abap_bool.
|
||||
DATA lv_fee TYPE decfloat34.
|
||||
DATA lv_exp TYPE decfloat34.
|
||||
lv_fee = 7.
|
||||
lv_exp = 7.
|
||||
CALL FUNCTION '{{P}}AUC_PREMIUM'
|
||||
EXPORTING
|
||||
iv_lot_type = `C`
|
||||
iv_hammer = 5000
|
||||
iv_channel = `B`
|
||||
IMPORTING
|
||||
ev_skip = lv_skip
|
||||
CHANGING
|
||||
cv_fee = lv_fee
|
||||
EXCEPTIONS
|
||||
invalid_hammer = 1
|
||||
OTHERS = 2.
|
||||
cl_abap_unit_assert=>assert_subrc( exp = 0 ).
|
||||
cl_abap_unit_assert=>assert_true( lv_skip ).
|
||||
cl_abap_unit_assert=>assert_equals( exp = lv_exp act = lv_fee ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD negative_hammer.
|
||||
DATA lv_fee TYPE decfloat34.
|
||||
CALL FUNCTION '{{P}}AUC_PREMIUM'
|
||||
EXPORTING
|
||||
iv_lot_type = `S`
|
||||
iv_hammer = -5
|
||||
iv_channel = `B`
|
||||
CHANGING
|
||||
cv_fee = lv_fee
|
||||
EXCEPTIONS
|
||||
invalid_hammer = 1
|
||||
OTHERS = 2.
|
||||
cl_abap_unit_assert=>assert_equals( exp = 1 act = sy-subrc ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
15
tasks_gen/train/G1006/seed/auc_sample.func.abap
Normal file
15
tasks_gen/train/G1006/seed/auc_sample.func.abap
Normal file
@@ -0,0 +1,15 @@
|
||||
FUNCTION {{p}}auc_sample
|
||||
IMPORTING
|
||||
iv_lot_type TYPE string
|
||||
iv_hammer TYPE decfloat34
|
||||
iv_channel TYPE string
|
||||
EXPORTING
|
||||
ev_skip TYPE abap_bool
|
||||
CHANGING
|
||||
cv_fee TYPE decfloat34
|
||||
EXCEPTIONS
|
||||
invalid_hammer.
|
||||
|
||||
ev_skip = abap_false.
|
||||
|
||||
ENDFUNCTION.
|
||||
47
tasks_gen/train/G1006/spec.md
Normal file
47
tasks_gen/train/G1006/spec.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# 1. Goal
|
||||
An auction house charges a buyer's premium on each lot that it sells. The
|
||||
auction program calls one premium module for each sold lot. The premium module
|
||||
must use the same interface as the sample module {{P}}AUC_SAMPLE, because the
|
||||
auction program calls all premium modules in the same way.
|
||||
|
||||
# 2. Open questions
|
||||
None.
|
||||
|
||||
# 3. Context
|
||||
- Function group {{P}}FG_AUCT exists in package $TMP.
|
||||
- Function module {{P}}AUC_SAMPLE exists in this group. It is the sample
|
||||
premium module. Its interface is the interface that all premium modules must
|
||||
use.
|
||||
|
||||
# 4. Contract
|
||||
- Create the function module {{P}}AUC_PREMIUM in function group {{P}}FG_AUCT.
|
||||
- Use exactly the interface of {{P}}AUC_SAMPLE: the same parameter names, kinds,
|
||||
types, and exceptions.
|
||||
- The exception is INVALID_HAMMER.
|
||||
|
||||
# 5. Business rules
|
||||
1. If the hammer price is less than 0, raise the exception INVALID_HAMMER and
|
||||
stop.
|
||||
2. Set the skip flag to false, except in rule 3.
|
||||
3. Lot type C (charity): set the skip flag to true. Leave the fee unchanged and
|
||||
stop.
|
||||
4. For every other lot type, calculate the band premium from the hammer price:
|
||||
- the part of the hammer price up to 1,000.00: 20 %
|
||||
- the part of the hammer price above 1,000.00 up to 10,000.00: 12 %
|
||||
- the part of the hammer price above 10,000.00: 6 %
|
||||
5. Channel O (online): the premium is 90 % of the band premium. For every other
|
||||
channel the premium is the band premium.
|
||||
6. Round the premium of rule 5 half up to 2 decimals.
|
||||
7. The minimum premium is 5.00. The maximum premium is 5,000.00.
|
||||
8. The fee is the premium of rules 4 to 7.
|
||||
|
||||
# 6. Constraints
|
||||
- Release target: 7.02. The code must run on a 7.02 system. Do not use syntax
|
||||
that was introduced after release 7.02.
|
||||
- Coding standards: Clean ABAP.
|
||||
- Out of scope: do not change {{P}}AUC_SAMPLE.
|
||||
|
||||
# 7. Acceptance
|
||||
- The function module is active and has no syntax error.
|
||||
- The hidden tests pass.
|
||||
- Write ABAP Unit tests for the function module in a global test class.
|
||||
84
tasks_gen/train/G1006/task.json
Normal file
84
tasks_gen/train/G1006/task.json
Normal file
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"id": "G1006",
|
||||
"category": "G",
|
||||
"object_type": "FUNC",
|
||||
"difficulty": 2,
|
||||
"release_target": "v702",
|
||||
"expected_outcome": "implement",
|
||||
"budget": {
|
||||
"max_tool_calls": 60,
|
||||
"max_activations": 15
|
||||
},
|
||||
"seed": [
|
||||
{
|
||||
"type": "FUGR",
|
||||
"name": "{{P}}FG_AUCT",
|
||||
"description": "Buyer's premium modules"
|
||||
},
|
||||
{
|
||||
"type": "FUNC",
|
||||
"name": "{{P}}AUC_SAMPLE",
|
||||
"functionGroup": "{{P}}FG_AUCT",
|
||||
"file": "seed/auc_sample.func.abap",
|
||||
"description": "Sample premium module"
|
||||
}
|
||||
],
|
||||
"contract": [
|
||||
{
|
||||
"type": "FUNC",
|
||||
"name": "{{P}}AUC_PREMIUM",
|
||||
"functionGroup": "{{P}}FG_AUCT",
|
||||
"params": [
|
||||
{
|
||||
"name": "iv_lot_type",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "iv_hammer",
|
||||
"type": "decfloat34"
|
||||
},
|
||||
{
|
||||
"name": "iv_channel",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "ev_skip",
|
||||
"type": "abap_bool"
|
||||
},
|
||||
{
|
||||
"name": "cv_fee",
|
||||
"type": "decfloat34"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"out_of_scope": [
|
||||
"{{P}}AUC_SAMPLE"
|
||||
],
|
||||
"hidden_tests": [
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}T14_HIDDEN",
|
||||
"file": "hidden/t14_hidden.clas.abap",
|
||||
"description": "T14 hidden tests"
|
||||
}
|
||||
],
|
||||
"reference": [
|
||||
{
|
||||
"type": "FUNC",
|
||||
"name": "{{P}}AUC_PREMIUM",
|
||||
"functionGroup": "{{P}}FG_AUCT",
|
||||
"file": "reference/auc_premium.func.abap",
|
||||
"description": "Buyer's premium module"
|
||||
},
|
||||
{
|
||||
"type": "CLAS",
|
||||
"name": "{{P}}T14_TEST",
|
||||
"file": "reference/t14_test.clas.abap",
|
||||
"description": "T14 own tests"
|
||||
}
|
||||
],
|
||||
"craft_checks": [
|
||||
"no_new_syntax"
|
||||
]
|
||||
}
|
||||
14
tasks_gen/train/G1007/generation.json
Normal file
14
tasks_gen/train/G1007/generation.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"id": "G1007",
|
||||
"pool": "train",
|
||||
"object_type": "CLAS",
|
||||
"category": "H",
|
||||
"attempts": [
|
||||
{
|
||||
"stage": "validate",
|
||||
"oracle": 100,
|
||||
"null": 30
|
||||
}
|
||||
],
|
||||
"accepted": true
|
||||
}
|
||||
56
tasks_gen/train/G1007/reference/jump_pricer.clas.abap
Normal file
56
tasks_gen/train/G1007/reference/jump_pricer.clas.abap
Normal file
@@ -0,0 +1,56 @@
|
||||
CLASS {{p}}jump_pricer DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
PUBLIC SECTION.
|
||||
TYPES ty_amount TYPE p LENGTH 8 DECIMALS 2.
|
||||
|
||||
METHODS constructor.
|
||||
METHODS calculate
|
||||
IMPORTING iv_persons TYPE i
|
||||
iv_minutes TYPE i
|
||||
iv_member TYPE abap_bool
|
||||
RETURNING VALUE(rv_price) TYPE ty_amount.
|
||||
|
||||
PRIVATE SECTION.
|
||||
CONSTANTS:
|
||||
c_short_price TYPE ty_amount VALUE '8.00',
|
||||
c_long_price TYPE ty_amount VALUE '12.00',
|
||||
c_member_factor TYPE ty_amount VALUE '0.80',
|
||||
c_group_factor TYPE ty_amount VALUE '0.90',
|
||||
c_group_size TYPE i VALUE 10,
|
||||
c_long_minutes TYPE i VALUE 60.
|
||||
|
||||
METHODS price_per_person
|
||||
IMPORTING iv_minutes TYPE i
|
||||
RETURNING VALUE(rv_price) TYPE ty_amount.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS {{p}}jump_pricer IMPLEMENTATION.
|
||||
METHOD constructor.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD calculate.
|
||||
IF iv_persons < 1 OR iv_minutes < 1.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
|
||||
DATA(lv_price) = CONV ty_amount( price_per_person( iv_minutes ) * iv_persons ).
|
||||
|
||||
IF iv_member = abap_true.
|
||||
lv_price = lv_price * c_member_factor.
|
||||
ENDIF.
|
||||
|
||||
IF iv_persons >= c_group_size.
|
||||
lv_price = lv_price * c_group_factor.
|
||||
ENDIF.
|
||||
|
||||
rv_price = round( val = lv_price dec = 2 ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD price_per_person.
|
||||
IF iv_minutes < c_long_minutes.
|
||||
rv_price = c_short_price.
|
||||
ELSE.
|
||||
rv_price = c_long_price.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user