# add-calc > Adds new CNC machining calculation types (pocket, slot, chamfer, etc.) to the manufacturing time estimator. - Author: ductrantrong - Repository: ductrantrong/cnc-time-estimator - Version: 20260126164838 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-06 - Source: https://github.com/ductrantrong/cnc-time-estimator - Web: https://mule.run/skillshub/@@ductrantrong/cnc-time-estimator~add-calc:20260126164838 --- --- name: add-calc description: Adds new CNC machining calculation types (pocket, slot, chamfer, etc.) to the manufacturing time estimator. --- # Adding a New Calculation Step Guide for adding new machining calculation types to the CNC manufacturing time estimator. ## Decision Tree 1. **Parameter source?** Image (drawing) / Notes / Both 2. **Calculation type?** Simple math → Pure Python | Complex reasoning → LLM-based 3. **Tool types?** DRILL, ENDMILL, TAP, FACE, REAMER from `BANG_CHE_DO_CAT.csv` ## File Modification Checklist Modify **10 file categories** (14+ actual files) in order: | # | Category | Path | Type | |:--|:---------|:-----|:-----| | A | Extractor | `backend/extractors/{feature}.py` | NEW | | B | Calculator | `backend/core/{feature}_calc.py` | NEW | | C | Pipeline | `backend/analysis/_extractors/{feature}.py` | NEW | | D | Facade Export | `backend/analysis/extractors.py` | EDIT | | E | Registry | `backend/analysis/registry.py` | EDIT (1 line) | | F | Tools Facade | `backend/tools.py` | EDIT | | G | Formula Doc | `docs/{feature}.md` | NEW | | H | Prompt Partial | `prompts/partials/_{feature}.jinja` | NEW | | I | Documentation | 4× CLAUDE.md files | EDIT | | J | Debug-Logs | `.claude/skills/debug-logs/scripts/*.py` | EDIT | **Note**: streaming.py no longer needs modification - the Feature Registry handles it automatically. ## Quick Links - [Extractor patterns](extractor.md) - LLM/regex extraction from images/notes - [Calculator patterns](calculator.md) - Pure Python and LLM-based formulas - [Pipeline integration](pipeline.md) - Connecting extractor + calculator + registry - [Prompt templates](prompt-partial.md) - Jinja partials for LLM display - [Complete checklist](checklist.md) - Full implementation checklist ## Feature Registry Pattern Adding a new calculation now uses a **data-driven registry** instead of manual streaming.py edits. ### Adding a New Feature (Minimal Steps) 1. Create extractor, calculator, pipeline (steps A-C above) 2. Export from facade (step D) 3. Add ONE line to `backend/analysis/registry.py`: ```python FeatureConfig(name="feature", extractor=extract_feature_and_calculate), ``` **No changes needed in streaming.py** - the registry loops handle submission, error collection, merging, and yielding automatically. ### FeatureConfig Options ```python @dataclass(frozen=True) class FeatureConfig: name: str # e.g., "tap", "drill" extractor: Callable # extract_X_and_calculate function requires_client: bool = True # False for regex-only (no LLM) merge_into: Optional[str] = None # Merge results into another feature skip_yield: bool = False # Don't yield to frontend skip_use_flag: bool = False # Don't set use_{name} in config skip_info: bool = False # Don't set {name}_info in config ``` ### Special Case Examples | Feature | Behavior | Registry Config | |:--------|:---------|:----------------| | Standard | Default (yield, use_flag, info) | `FeatureConfig(name="tap", extractor=extract_tap_and_calculate)` | | `face` | No use_flag or info stored | `skip_use_flag=True, skip_info=True` | | `lathe_drill` | Regex-only, merges into drill | `requires_client=False, merge_into="drill", skip_yield=True, skip_use_flag=True, skip_info=True` | ## Config Key Naming Convention ```python config["use_{feature}"] = True # Boolean flag config["{feature}_info"] = [...] # Extracted data (List[Dict]) config["{feature}_calculated"] = {...} # Calculation results ``` ## Return Dict Structure (Required) All calculators must return this exact structure: ```python { "tool_info": { "tool_name": {"name": str, "S": int, "F": float, "AP": float} }, "calculations": { "param1": value, "step1": {"formula": str, "substitution": str, "time_minutes": float} }, "total_time_minutes": float, # Rounded to 4 decimals "summary": "Vietnamese summary" } ``` ## Extraction Types | Type | When to Use | Example | |:-----|:------------|:--------| | LLM-based | Complex patterns, context-dependent | TAP, precision holes | | Regex-based | Simple patterns, fixed format | C via L (`C via L=50`), vát đĩa (`Gia công n vát đĩa`) | | Notes-only | Explicit production notes | Drill, pocket | | Image-only | Geometric features | Normal holes | ## Calculation Complexity | Type | Tool Lookup | Material-Dependent | Example | |:-----|:------------|:-------------------|:--------| | Full | Yes (database) | Yes | Drill, pocket, counterbore | | Partial | No | Yes (F constant varies) | C via L | | Simple | No | No (all constants fixed) | Vát đĩa | ## Key Rules - Always return `List[Dict]` from extractors - Always validate NaN and positive values in calculators - Get tool parameters from database **OR** use hardcoded constants (for simple formulas like C via L) - Always add prompt.jinja section (or results won't appear in final analysis) - Always update all 4 CLAUDE.md files