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.
|
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 | İş |
|
| 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. |
|
| 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():
|
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()
|
s = spent()
|
||||||
if s >= limit:
|
if s >= limit:
|
||||||
raise BudgetExceeded(f"cycle spend {s} USD >= limit {limit} USD")
|
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"}
|
ERROR_CATEGORY = {"named-type": "A", "reserved-word": "D", "long-names": "C"}
|
||||||
|
|
||||||
|
|
||||||
def build_plan():
|
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."""
|
"""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())
|
share_sum = sum(CATEGORY_SHARE.values())
|
||||||
items = []
|
items = []
|
||||||
for cat, share in CATEGORY_SHARE.items():
|
for cat, share in CATEGORY_SHARE.items():
|
||||||
k_cat = round(N_SLOTS * share / share_sum)
|
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
|
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]
|
slots = [x for x in SLOTS if x[0] == cat]
|
||||||
weight = sum(n for _, _, n, _ in slots)
|
weight = sum(n for _, _, n, _ in slots)
|
||||||
k_rest = k_cat - k_err
|
k_rest = k_cat - k_err
|
||||||
@@ -69,16 +72,19 @@ def build_plan():
|
|||||||
for kind, text in ERROR_HINTS:
|
for kind, text in ERROR_HINTS:
|
||||||
if ERROR_CATEGORY[kind] != cat:
|
if ERROR_CATEGORY[kind] != cat:
|
||||||
continue
|
continue
|
||||||
for i in range(N_ERROR // 3):
|
for i in range(per_kind):
|
||||||
t = ERROR_TYPES[i % len(ERROR_TYPES)]
|
t = ERROR_TYPES[i % len(ERROR_TYPES)]
|
||||||
pos += 1
|
pos += 1
|
||||||
items.append({"category": cat, "object_type": t, "topic": text, "error_kind": kind,
|
items.append({"category": cat, "object_type": t, "topic": text, "error_kind": kind,
|
||||||
"frac": pos / (k_cat + 1)})
|
"frac": pos / (k_cat + 1)})
|
||||||
items.sort(key=lambda x: (x["frac"], x["category"], x["object_type"])) # interleave: a cut keeps the mix
|
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):
|
for n, it in enumerate(items):
|
||||||
it.pop("frac")
|
it.pop("frac")
|
||||||
it["id"] = f"G{FIRST_ID + n:04d}"
|
it["id"] = f"G{first_id + n:04d}"
|
||||||
it["run_base"] = RUN_BASE + 40 * n
|
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
|
return items
|
||||||
|
|
||||||
|
|
||||||
@@ -92,12 +98,42 @@ def accepted_count():
|
|||||||
return n
|
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)
|
os.makedirs(POOL, exist_ok=True)
|
||||||
if not os.path.exists(PLAN):
|
if not os.path.exists(plan_path(name)):
|
||||||
json.dump({"slots": build_plan(), "ledger_at_start": spent(), "stop_ledger": stop_ledger,
|
if name == "plan":
|
||||||
"target": target, "created": time.strftime("%F %T")}, open(PLAN, "w"), indent=1)
|
slots, tgt, stop = build_plan(), target, stop_ledger
|
||||||
plan = json.load(open(PLAN))
|
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"]
|
stop_at = plan["ledger_at_start"] + plan["stop_ledger"]
|
||||||
base_url = os.environ.get("LLM_BASE_URL", "http://127.0.0.1:11434/v1")
|
base_url = os.environ.get("LLM_BASE_URL", "http://127.0.0.1:11434/v1")
|
||||||
evals = overlap.load_pool("eval")
|
evals = overlap.load_pool("eval")
|
||||||
@@ -106,7 +142,16 @@ def run(part, parts, target, stop_ledger):
|
|||||||
continue
|
continue
|
||||||
if os.path.exists(os.path.join(POOL, "_logs", s["id"] + ".json")):
|
if os.path.exists(os.path.join(POOL, "_logs", s["id"] + ".json")):
|
||||||
continue # done or failed: not tried again (delete the log to retry)
|
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)
|
print("TARGET reached", flush=True)
|
||||||
break
|
break
|
||||||
if spent() >= stop_at:
|
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."
|
f"names {sc['name']:.2f}). Choose a different business topic and different object names."
|
||||||
for i, sc in hits[:3]]
|
for i, sc in hits[:3]]
|
||||||
try:
|
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)
|
base_url, s["run_base"], topic, extra_check=extra)
|
||||||
except BudgetExceeded as e:
|
except BudgetExceeded as e:
|
||||||
print("BUDGET", e, flush=True)
|
print("BUDGET", e, flush=True)
|
||||||
break
|
break
|
||||||
except Exception as e: # noqa: BLE001
|
except Exception as e: # noqa: BLE001
|
||||||
log = {"id": s["id"], "error": str(e)[:500]}
|
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)
|
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)
|
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
|
stray = os.path.join(POOL, "generation.json") # generate() writes here when no task dir exists
|
||||||
@@ -156,7 +202,7 @@ def run_k(count):
|
|||||||
continue
|
continue
|
||||||
used = {json.load(open(f)).get("base_task") for f in glob.glob(os.path.join(POOL, "_logs", "G13*.json"))}
|
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
|
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))
|
lg = json.load(open(f))
|
||||||
if lg.get("accepted") and lg.get("category") not in ("H", "K") and lg["id"] not in used:
|
if lg.get("accepted") and lg.get("category") not in ("H", "K") and lg["id"] not in used:
|
||||||
cands.append(lg)
|
cands.append(lg)
|
||||||
@@ -170,8 +216,7 @@ def run_k(count):
|
|||||||
otype = min(kinds, key=lambda t: done_types.count(t))
|
otype = min(kinds, key=lambda t: done_types.count(t))
|
||||||
src = kinds[otype][0]
|
src = kinds[otype][0]
|
||||||
style = K_STYLES_CYCLE[n % 2]
|
style = K_STYLES_CYCLE[n % 2]
|
||||||
if spent() >= json.load(open(PLAN))["ledger_at_start"] + json.load(open(PLAN))["stop_ledger"]:
|
if os.path.exists(STOP_FLAG):
|
||||||
print("PHASE LIMIT", flush=True)
|
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
log = make_k_variant(src["id"], new_id, style, "deepseek-v4.1-flash:cloud", base_url,
|
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("--part", type=int, default=0)
|
||||||
ap.add_argument("--parts", type=int, default=1)
|
ap.add_argument("--parts", type=int, default=1)
|
||||||
ap.add_argument("--target", type=int, default=200)
|
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)")
|
ap.add_argument("--stop-ledger", type=float, default=27.0, help="ledger USD for this phase (10 USD usage = 27)")
|
||||||
a = ap.parse_args()
|
a = ap.parse_args()
|
||||||
if a.cmd == "plan":
|
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))
|
print(collections.Counter(x["object_type"] for x in p), collections.Counter(x.get("error_kind") for x in p))
|
||||||
return
|
return
|
||||||
if a.cmd == "k":
|
if a.cmd == "k":
|
||||||
run_k(K_COUNT)
|
run_k(a.k_count)
|
||||||
return
|
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__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ from .runner import Runner
|
|||||||
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
POOL = os.path.join(ROOT, "tasks_gen", "train")
|
POOL = os.path.join(ROOT, "tasks_gen", "train")
|
||||||
OUT = os.path.join(ROOT, "runs", "traj")
|
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"
|
MODEL = "deepseek-v4.1-flash:cloud"
|
||||||
LOCK = threading.Lock()
|
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