Replace fixed DSL fields with parameterized metric expressions
This commit is contained in:
+4
-13
@@ -38,7 +38,6 @@ def extract(text):
|
||||
"cohorts": [],
|
||||
"comparison": "period",
|
||||
"reduce": None,
|
||||
"long_run": 10.0,
|
||||
"route": None,
|
||||
}
|
||||
seen, lines = set(), text.splitlines()
|
||||
@@ -61,12 +60,6 @@ def extract(text):
|
||||
if not 1 <= minutes <= 180:
|
||||
raise QueryError("Use 1–180 matched minutes per run.", number)
|
||||
options["reduce"] = minutes
|
||||
elif match := re.fullmatch(r"long run distance >= (\d+(?:\.\d+)?) km", line):
|
||||
once("long_run", number)
|
||||
distance = float(match[1])
|
||||
if not 1 <= distance <= 100:
|
||||
raise QueryError("Use a long-run threshold of 1–100 km.", number)
|
||||
options["long_run"] = distance
|
||||
elif match := re.fullmatch(r"route similar to (\d+)", line):
|
||||
once("route", number)
|
||||
options["route"] = int(match[1])
|
||||
@@ -156,6 +149,8 @@ def extract(text):
|
||||
|
||||
|
||||
def validate(q, catalog):
|
||||
if q["source"] in {"days", "health"} and any("best_distance" in s for s in q["derived"]):
|
||||
raise QueryError("best_time requires the runs source.")
|
||||
if q["flag"] and q["source"] in {"laps", "segments", "intervals"} and not q["reduce"]:
|
||||
raise QueryError("Reduce recordings to independent runs before using a deviation flag.")
|
||||
if q["reduce"] and q["source"] not in {"intervals", "segments"}:
|
||||
@@ -201,10 +196,6 @@ def validate(q, catalog):
|
||||
"distance_change",
|
||||
"pace_change",
|
||||
"heart_rate_change",
|
||||
"rolling_7d_distance",
|
||||
"rolling_28d_distance",
|
||||
"rolling_7d_count",
|
||||
"rolling_28d_count",
|
||||
"run_day_streak",
|
||||
}
|
||||
fields = {
|
||||
@@ -226,13 +217,13 @@ def validate(q, catalog):
|
||||
if q["bin"]:
|
||||
fields.add(q["bin"]["field"])
|
||||
for spec in q["derived"]:
|
||||
if "window" not in spec:
|
||||
if not any(key in spec for key in ("window", "since", "best_distance")):
|
||||
fields.update(
|
||||
node.id
|
||||
for node in ast.walk(ast.parse(spec["expression"], mode="eval"))
|
||||
if isinstance(node, ast.Name)
|
||||
)
|
||||
if fields & temporal or any("window" in spec for spec in q["derived"]):
|
||||
if fields & temporal or any(any(key in spec for key in ("window", "since", "best_distance")) for spec in q["derived"]):
|
||||
raise QueryError(
|
||||
"Run-history metrics and rolling calculations require the runs source."
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user