aboutsummaryrefslogtreecommitdiff
path: root/claude-templates/.ai/scripts/flashcard-stats.py
diff options
context:
space:
mode:
Diffstat (limited to 'claude-templates/.ai/scripts/flashcard-stats.py')
-rwxr-xr-xclaude-templates/.ai/scripts/flashcard-stats.py12
1 files changed, 9 insertions, 3 deletions
diff --git a/claude-templates/.ai/scripts/flashcard-stats.py b/claude-templates/.ai/scripts/flashcard-stats.py
index 1fa5afb..cb580ac 100755
--- a/claude-templates/.ai/scripts/flashcard-stats.py
+++ b/claude-templates/.ai/scripts/flashcard-stats.py
@@ -35,7 +35,12 @@ import re
import sys
from pathlib import Path
-CARD_RE = re.compile(r"^\*\*\s+(.+?)\s+:drill:\s*$")
+# A card is a level-2 heading whose trailing org tag block includes `drill`.
+# Group 1 is the front, group 2 the tag block — so a curated card multi-tagged
+# :fundamental:drill: still counts (it would silently drop under a :drill:$
+# anchor, undercounting the deck). HEADING_RE bounds a card's body.
+CARD_RE = re.compile(r"^\*\*\s+(.+?)\s+(:[A-Za-z0-9_@#%:]+:)\s*$")
+HEADING_RE = re.compile(r"^\*{1,2}\s")
ANSWER_RE = re.compile(r"^\*\*\*\s+Answer\b")
PROP_START_RE = re.compile(r"^\s*:PROPERTIES:\s*$")
PROP_END_RE = re.compile(r"^\s*:END:\s*$")
@@ -177,7 +182,8 @@ def parse_cards(lines: list[str]) -> tuple[list[dict], int]:
n = len(lines)
while i < n:
m = CARD_RE.match(lines[i])
- if not m:
+ tags = [t for t in m.group(2).split(":") if t] if m else []
+ if not (m and "drill" in tags):
i += 1
continue
heading = m.group(1).strip()
@@ -188,7 +194,7 @@ def parse_cards(lines: list[str]) -> tuple[list[dict], int]:
body_lines: list[str] = []
while i < n:
line = lines[i]
- if line.startswith("* ") or CARD_RE.match(line):
+ if HEADING_RE.match(line):
break
if PROP_START_RE.match(line):
prop_count += 1