Download patch_v30_1.py from SupantBT/Beltbot: direct link, hf CLI and curl.
- Browser
- Download file 9.11 kB
-
https://huggingface.co/spaces/SupantBT/Beltbot/resolve/main/patch_v30_1.py
- Command line
-
hf download hf://spaces/SupantBT/Beltbot/patch_v30_1.py
-
curl -L -o patch_v30_1.py https://huggingface.co/spaces/SupantBT/Beltbot/resolve/main/patch_v30_1.py
9.11 kB
| #!/usr/bin/env python3 | |
| """modutech_v30.json → modutech_v30_1.json — แพตช์ก่อน launch prototype เท่านั้น | |
| แก้แค่สองอย่าง ไม่ใช่ v31 | |
| 1. เติม specifications.notes ของ 8 รุ่นที่ว่างเปล่าใน v30 ทั้งที่เล่มพิมพ์หมายเหตุไว้ครบ | |
| ดึงจาก PDF ตรง ๆ ตัดคำนำหน้า "- " ออกอย่างเดียว ไม่เรียบเรียงใหม่ | |
| ทำไมต้องเติม: catalogue_increment_status() อ่าน specifications.notes เท่านั้น | |
| ถ้า notes ว่าง gate จะตรวจค่า "เพิ่มทีละ" ของรุ่นนั้นไม่ได้เลย | |
| 2. ตั้ง temperature_trust = "unconfirmed" ให้ variant md254-rr--pph-pph ตัวเดียว | |
| พร้อมข้อความเตือนใน temperature_unconfirmed_th | |
| บอทยังตอบ 93 °C (ค่าที่เข้มกว่า) แต่แนบคำเตือนไปด้วย แทนที่จะตอบเหมือนเป็นค่ายืนยันแล้ว | |
| ไม่แตะ: ค่าตัวเลขทุกตัว · width_effective · temperature_effective · answering · จำนวนนับ | |
| รัน: python patch_v30_1.py modutech_v30.json <path ของ PDF> [modutech_v30_1.json] | |
| """ | |
| from __future__ import annotations | |
| import copy | |
| import hashlib | |
| import json | |
| import re | |
| import sys | |
| # ── สิ่งที่ตั้งใจจะแก้ ประกาศไว้ล่วงหน้าเพื่อให้ shadow copy ตรวจได้ ── | |
| NOTES_PAGES = { | |
| "SM127 C": 75, "HC127 C": 67, "EC254 GT": 133, "MD254 FG-RT": 157, | |
| "MD254 GT": 163, "MD254 RR": 165, "XP254 C": 113, "XP254 PR22%": 117, | |
| } | |
| UNCONFIRMED_VARIANT = "md254-rr--pph-pph" | |
| UNCONFIRMED_TH = ( | |
| "ค่าสูงสุด 93 °C ยังไม่ยืนยัน — แคตตาล็อกหน้า 165 พิมพ์ +5/+93 °C คู่กับ +40/+230 °F " | |
| "ซึ่ง 230 °F เท่ากับ 110 °C ไม่ใช่ 93 °C และ 93 °C เป็นค่าเดียวกับเกรด POM ที่พิมพ์อยู่สามแถวเหนือขึ้นไป " | |
| "ในเล่มเดียวกันเกรด PPH ของรุ่น HC508 PR22 ระบุ 110 °C และ HP508 RR (ผิว Raised Rib เหมือนกัน) ระบุ 118 °C " | |
| "ระบบเลือกใช้ค่าที่เข้มกว่าคือ 93 °C ไว้ก่อน ถ้างานจริงต้องเกิน 93 °C ต้องยืนยันกับฝ่ายเทคนิคก่อนเสนอ" | |
| ) | |
| def fingerprint(obj) -> str: | |
| return hashlib.sha256( | |
| json.dumps(obj, ensure_ascii=False, sort_keys=True, default=str).encode() | |
| ).hexdigest() | |
| def notes_from_page(doc, page: int) -> list[str]: | |
| """บรรทัดใต้หัวข้อ Important Notes ที่ขึ้นต้นด้วย '-' ติดกัน หยุดที่บรรทัดแรกที่ไม่ขึ้นต้นด้วย '-'""" | |
| lines = doc[page - 1].get_text().split("\n") | |
| try: | |
| i = next(k for k, l in enumerate(lines) if l.strip() == "Important Notes") | |
| except StopIteration: | |
| raise SystemExit(f"หน้า {page}: ไม่พบหัวข้อ Important Notes — หยุด ไม่เดา") | |
| out = [] | |
| for l in lines[i + 1:]: | |
| s = l.strip() | |
| if not s: | |
| continue | |
| if not s.startswith("-"): | |
| break | |
| out.append(s.lstrip("- ").strip()) | |
| if not out: | |
| raise SystemExit(f"หน้า {page}: อ่านหมายเหตุไม่ได้สักบรรทัด — หยุด") | |
| return out | |
| def scrub(doc: dict) -> dict: | |
| """ลบเฉพาะฟิลด์ที่ตั้งใจจะแก้ออกจากทั้งสองฝั่ง เพื่อให้ที่เหลือต้องเหมือนกันเป๊ะ""" | |
| d = copy.deepcopy(doc) | |
| for p in d.get("products", []): | |
| if p.get("belt_code") in NOTES_PAGES: | |
| p.get("specifications", {}).pop("notes", None) | |
| for v in p.get("specifications", {}).get("variants") or []: | |
| if v.get("variant_id") == UNCONFIRMED_VARIANT: | |
| v.pop("temperature_trust", None) | |
| v.pop("temperature_unconfirmed_th", None) | |
| return d | |
| def main() -> int: | |
| if len(sys.argv) < 3: | |
| print(__doc__) | |
| return 2 | |
| src, pdf = sys.argv[1], sys.argv[2] | |
| dst = sys.argv[3] if len(sys.argv) > 3 else "modutech_v30_1.json" | |
| import pymupdf | |
| doc = pymupdf.open(pdf) | |
| with open(src, encoding="utf-8") as f: | |
| data = json.load(f) | |
| shadow = copy.deepcopy(data) # ของดิบไว้เทียบ | |
| by_code = {p.get("belt_code"): p for p in data.get("products", [])} | |
| print("1) เติม specifications.notes") | |
| for code, page in NOTES_PAGES.items(): | |
| p = by_code.get(code) | |
| if p is None: | |
| raise SystemExit(f"ไม่พบรุ่น {code} ในไฟล์ — หยุด") | |
| spec = p.setdefault("specifications", {}) | |
| if spec.get("page") != page: | |
| raise SystemExit(f"{code}: ไฟล์ระบุหน้า {spec.get('page')} แต่สคริปต์ตั้งไว้ {page} — หยุด") | |
| if spec.get("notes"): | |
| raise SystemExit(f"{code}: notes ไม่ว่าง ({len(spec['notes'])} บรรทัด) — หยุด ไม่ทับของเดิม") | |
| notes = notes_from_page(doc, page) | |
| spec["notes"] = notes | |
| m = re.search(r"(?<!Non-)Standard\s*b\s?elt\s*increme\s?nts?\s*([\d,\.]+)", | |
| " | ".join(notes), re.IGNORECASE) | |
| printed = float(m.group(1).replace(",", ".").rstrip(".")) if m else None | |
| table = (spec.get("width_effective") or {}).get("increment_mm") | |
| flag = "ตรงกัน" if (printed is not None and table is not None | |
| and abs(printed - table) < 0.05) else "⚠️ ไม่ตรง" | |
| print(f" {code:<14} p{page} {len(notes)} บรรทัด · เล่ม={printed} ตาราง={table} {flag}") | |
| print("\n2) ตั้ง temperature_trust = unconfirmed") | |
| hits = 0 | |
| for p in data.get("products", []): | |
| for v in p.get("specifications", {}).get("variants") or []: | |
| if v.get("variant_id") != UNCONFIRMED_VARIANT: | |
| continue | |
| if v.get("temperature_trust") != "ok": | |
| raise SystemExit(f"{UNCONFIRMED_VARIANT}: temperature_trust เดิมคือ " | |
| f"{v.get('temperature_trust')!r} ไม่ใช่ 'ok' — หยุด") | |
| v["temperature_trust"] = "unconfirmed" | |
| v["temperature_unconfirmed_th"] = UNCONFIRMED_TH | |
| hits += 1 | |
| if hits != 1: | |
| raise SystemExit(f"เจอ variant {UNCONFIRMED_VARIANT} {hits} ตัว ต้องเป็น 1 — หยุด") | |
| print(f" {UNCONFIRMED_VARIANT} · ok → unconfirmed (ค่าตัวเลขไม่เปลี่ยน)") | |
| print("\n3) เทียบกับ shadow copy") | |
| a, b = fingerprint(scrub(shadow)), fingerprint(scrub(data)) | |
| if a != b: | |
| raise SystemExit("❌ มีอย่างอื่นเปลี่ยนนอกเหนือจากที่ประกาศไว้ — ไม่เขียนไฟล์") | |
| print(" ✅ นอกจากฟิลด์ที่ประกาศไว้ ไม่มีอะไรเปลี่ยน") | |
| print("\n4) จำนวนนับต้องเท่าเดิม") | |
| n_prod = len(data["products"]) | |
| n_var = sum(len(p.get("specifications", {}).get("variants") or []) for p in data["products"]) | |
| n_app = sum(len(a.get("applications") or []) | |
| for p in data["products"] for a in p.get("industries") or []) | |
| n_pair = sum(len(p.get("industries") or []) for p in data["products"]) | |
| print(f" สินค้า {n_prod} · คู่สายพาน-อุตสาหกรรม {n_pair} · การใช้งาน {n_app} · variant {n_var}") | |
| if (n_prod, n_pair, n_app) != (68, 211, 651): | |
| raise SystemExit("❌ จำนวนนับเปลี่ยน — ไม่เขียนไฟล์") | |
| with open(dst, "w", encoding="utf-8") as f: | |
| json.dump(data, f, ensure_ascii=False, indent=1) | |
| print(f"\nเขียน {dst} แล้ว · {src} ไม่ถูกแตะต้อง") | |
| return 0 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |