From 14b2aeff7ce16a8b66cbddb26cbbfe55e7bc3c65 Mon Sep 17 00:00:00 2001 From: Kunthawat Greethong Date: Fri, 28 Aug 2026 11:41:48 +0700 Subject: [PATCH] feat(scheduler): per-source cadence + source-health log with failure diagnosis + UI copy --- backend/app/__init__.py | 15 ++ backend/app/scheduler.py | 210 +++++++++++++++++++++++-- backend/tests/test_scheduler.py | 62 ++++++++ frontend/dist/assets/index-CUQk4rwt.js | 18 --- frontend/dist/assets/index-DOVbTpbx.js | 18 +++ frontend/dist/index.html | 2 +- frontend/src/App.vue | 70 ++++++++- 7 files changed, 363 insertions(+), 32 deletions(-) delete mode 100644 frontend/dist/assets/index-CUQk4rwt.js create mode 100644 frontend/dist/assets/index-DOVbTpbx.js diff --git a/backend/app/__init__.py b/backend/app/__init__.py index af275a0..05712af 100644 --- a/backend/app/__init__.py +++ b/backend/app/__init__.py @@ -857,6 +857,21 @@ def create_app(config: dict[str, Any] | None = None) -> Flask: store = app.extensions["backtest_store"] return jsonify({"runs": store.all()}) + @app.get("/api/v1/scheduler/sources") + def scheduler_sources(): + """Source-health log for the data scheduler (refresh cadence + failures). + + Lets the frontend show each source's last outcome and copy the failure + detail for diagnosis (e.g. a source that changed its page structure is + categorized as `structure`, a network blip as `network`). Empty when no + scheduler is wired (e.g. TESTING or a read-only host) or no tick yet. + """ + sched = app.extensions.get("data_scheduler") + if sched is None: + return jsonify({"sources": []}) + limit = int(request.args.get("limit", "200")) + return jsonify({"sources": sched._load_source_health(limit)}) + @app.post("/api/v1/backtest") def run_backtest_endpoint(): """Run a real backtest over [start, end] with capital; persist result.""" diff --git a/backend/app/scheduler.py b/backend/app/scheduler.py index d20cc37..d28e29a 100644 --- a/backend/app/scheduler.py +++ b/backend/app/scheduler.py @@ -28,13 +28,33 @@ log = logging.getLogger("set50.scheduler") # collectors returning a .to_dict()/dict, keyed by cache key # (imported lazily to avoid import cycles at module load) # `fetch_module` = the FACTORS.fetch module name this job feeds (for history). +# `frequency` = natural refresh cadence of the source. A job is only run +# once its cooldown window has elapsed — the strategy rebalances +# a few times a year, so polling slow sources hourly wastes +# resources. Values: daily | weekly | monthly | quarterly. _REFRESH_JOBS: List[dict] = [ - {"key": "bot_tourism", "label": "ท่องเที่ยว (BOT)", "module": "bot_tourism", "fn": "BotTourismSource().fetch", "fetch_module": "macro_thai"}, - {"key": "auto_credit/tourism", "label": "ยอดขายรถ (TradingEconomics)", "module": "auto_credit", "fn": "fetch_auto_credit", "fetch_module": "auto_credit"}, - {"key": "auto_npl", "label": "NPL รถยนต์ (BOT)", "module": "auto_npl", "fn": "fetch_auto_npl", "fetch_module": "auto_npl"}, - {"key": "energy_thai", "label": "โรงกลั่น TOP", "module": "energy_thai", "fn": "fetch_energy_thai", "fetch_module": "energy_thai"}, - {"key": "macro_thai", "label": "ภาพรวมประเทศไทย (BOT)", "module": "macro_thai", "fn": "fetch_macro_thai", "fetch_module": "macro_thai"}, - {"key": "bank_npl", "label": "NPL ภาคการเงิน (BOT)", "module": "bank_npl", "fn": "fetch_bank_npl", "fetch_module": "bank_npl"}, + {"key": "bot_tourism", "label": "ท่องเที่ยว (BOT)", "module": "bot_tourism", "fn": "BotTourismSource().fetch", "fetch_module": "macro_thai", "frequency": "monthly"}, + {"key": "auto_credit/tourism", "label": "ยอดขายรถ (TradingEconomics)", "module": "auto_credit", "fn": "fetch_auto_credit", "fetch_module": "auto_credit", "frequency": "monthly"}, + {"key": "auto_npl", "label": "NPL รถยนต์ (BOT)", "module": "auto_npl", "fn": "fetch_auto_npl", "fetch_module": "auto_npl", "frequency": "quarterly"}, + {"key": "energy_thai", "label": "โรงกลั่น TOP", "module": "energy_thai", "fn": "fetch_energy_thai", "fetch_module": "energy_thai", "frequency": "quarterly"}, + {"key": "macro_thai", "label": "ภาพรวมประเทศไทย (BOT)", "module": "macro_thai", "fn": "fetch_macro_thai", "fetch_module": "macro_thai", "frequency": "monthly"}, + {"key": "bank_npl", "label": "NPL ภาคการเงิน (BOT)", "module": "bank_npl", "fn": "fetch_bank_npl", "fetch_module": "bank_npl", "frequency": "quarterly"}, +] + +# Frequencies -> minimum seconds between successful refreshes of a job. +# These implement the "adjust cadence to the source" requirement. +_FREQ_SECONDS: dict[str, int] = { + "daily": 24 * 3600, + "weekly": 7 * 24 * 3600, + "monthly": 30 * 24 * 3600, + "quarterly": 91 * 24 * 3600, +} + +# Data that legitimately changes every day (or faster) is refreshed separately +# at a daily cadence rather than on the slow factor loop. +_DAILY_JOBS: List[dict] = [ + {"key": "siamchart_vintages", "label": "Siamchart SET50 snapshot (vintage)", "fn": "_record_siamchart_vintages", "frequency": "daily"}, + {"key": "price_snapshot", "label": "ราคาหุ้น SET50 (Yahoo)", "fn": "_refresh_price_snapshot", "frequency": "daily"}, ] @@ -77,23 +97,103 @@ class AppDataScheduler: log.exception("set50 scheduler refresh_all failed (will retry)") def refresh_all(self) -> list[dict]: - """Run every collector, warm the daily cache, snapshot the state, and - append each factor's value to the historical store (P4 enabler).""" + """Run each collector (respecting its natural cadence), warm the cache, + snapshot state, write vintages, and log per-source health. + + Slow sources (monthly/quarterly factors, dividends, Siamchart) are only + re-fetched once their cooldown has elapsed; only daily-changing data + (prices) runs every eligible tick. This keeps resource usage aligned + with how often the data actually changes (the strategy rebalances a few + times a year) while still front-loading an initial refresh at boot. + """ results: list[dict] = [] fetched_by_module: dict[str, dict] = {} + for job in _REFRESH_JOBS: + if not self._job_due(job): + continue res = self._run_job(job) results.append(res) - fetch_module = job.get("fetch_module") - if res.get("ok") and isinstance(res.get("value"), dict) and fetch_module: - fetched_by_module[fetch_module] = res["value"] + if res.get("ok"): + self._mark_job_run(job) + fetch_module = job.get("fetch_module") + if isinstance(res.get("value"), dict) and fetch_module: + fetched_by_module[fetch_module] = res["value"] + + # daily cadence data (Siamchart vintages + price snapshots) + for djob in _DAILY_JOBS: + if not self._job_due(djob): + continue + try: + fn = getattr(self, djob["fn"]) + fn() + self._mark_job_run(djob) + results.append({"key": djob["key"], "label": djob["label"], + "ok": True, "at": self._now()}) + except Exception as exc: # noqa: BLE001 — non-fatal + results.append({"key": djob["key"], "label": djob["label"], + "ok": False, "error": str(exc), "at": self._now()}) + self._record_history(fetched_by_module) self._record_pit_factor_vintages(fetched_by_module) - self._record_siamchart_vintages() self._maybe_refresh_dated_dividends() self._write_marker(results) + self._append_source_log(results) return results + # -- per-job cadence cooldown ------------------------------------------ + def _job_marker_path(self, job: dict) -> Path: + safe = "".join(c if (c.isalnum() or c in "._-") else "_" for c in job["key"]) + return self._snap_dir / f"job_{safe}.json" + + def _job_due(self, job: dict) -> bool: + """True if the job's cooldown (from its `frequency`) has elapsed.""" + import json + import datetime as _dt + freq = job.get("frequency") + cooldown = _FREQ_SECONDS.get(freq if isinstance(freq, str) else "daily", _FREQ_SECONDS["daily"]) + path = self._job_marker_path(job) + if not path.is_file(): + return True # never run -> run at boot + try: + data = json.loads(path.read_text(encoding="utf-8")) + last = _dt.datetime.fromisoformat(data["at"]) + elapsed = (_dt.datetime.now().astimezone() - last).total_seconds() + return elapsed >= cooldown + except (OSError, ValueError, KeyError): + return True # corrupt/missing marker -> allow retry + + def _mark_job_run(self, job: dict) -> None: + import json + try: + self._job_marker_path(job).write_text( + json.dumps({"at": self._now()}), encoding="utf-8") + except OSError: + log.exception("could not write job marker for %s", job["key"]) + + def _refresh_price_snapshot(self) -> None: + """Refresh the SET50 Yahoo price snapshot (daily cadence). + + Pulls live daily bars over a rolling ~3y window into the price snapshot + store so valuation and next-trading-day execution use fresh prices. This + is the one data type that legitimately changes every trading day, so it + runs on the daily cadence rather than the slow factor loop. Non-fatal: + on network failure the previous snapshot is retained. + """ + import datetime as _dt + from .prices import collect_price_snapshot, PriceSourceError + # rolling window: start ~3y back (enough history for momentum + next-day + # execution), end = yesterday (SET session close is the latest tradable). + today = _dt.date.today() + start = (today - _dt.timedelta(days=3 * 366)).isoformat() + end = (today - _dt.timedelta(days=1)).isoformat() + prices_dir = self.data_root / "prices" + try: + collect_price_snapshot(prices_dir, start=start, end=end) + except PriceSourceError as exc: + log.warning("set50 price snapshot refresh failed (non-fatal): %s", exc) + raise + def _record_history(self, fetched_by_module: dict[str, dict]) -> None: """Append current factor values to the historical store (append-only). @@ -279,6 +379,92 @@ class AppDataScheduler: except OSError: log.exception("could not write scheduler marker") + def _append_source_log(self, results: list[dict]) -> None: + """Append this refresh tick's per-source outcome to a durable health log + the frontend can render (with a one-click copy), and analyze failures. + + Stored at ``data/scheduler/source_health.json`` (ring buffer, newest + first). Each entry categorizes the failure (network / http / parse / + structure / auth / other) so a source that "changed its page structure" + is distinguishable from a transient network blip. + """ + import json + if not results: + return + path = self._snap_dir / "source_health.json" + try: + existing = [] + if path.is_file(): + existing = json.loads(path.read_text(encoding="utf-8")) + if not isinstance(existing, list): + existing = [] + except (OSError, ValueError): + existing = [] + entries = [] + for r in results: + category = "ok" + if not r.get("ok"): + category = self._analyze_error(r.get("error", "")) + entries.append({ + "key": r.get("key"), "label": r.get("label"), + "ok": bool(r.get("ok")), "category": category, + "at": r.get("at") or self._now(), + "detail": str(r.get("error") or "")[:500], + }) + # newest-first ring buffer, cap at 500 entries + combined = entries + existing + combined = combined[:500] + try: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(json.dumps(combined, ensure_ascii=False), encoding="utf-8") + except OSError: + log.exception("could not write source-health log") + + @staticmethod + def _analyze_error(message: str) -> str: + """Classify a failure reason so the frontend can guide diagnosis. + + Keys off the exception message/type text. Returns one of: + network, timeout, http, parse, structure, auth, other. + """ + m = (message or "").lower() + if not m: + return "other" + if any(t in m for t in ("timed out", "timeout", "timedout")): + return "timeout" + if any(t in m for t in ("no such host", "connection refused", + "name or service not known", "network is unreachable", + "connection reset", "getaddrinfo", "dns")): + return "network" + if any(t in m for t in ("http ", "status", "response code", "403", "404", + "429", "502", "503")): + return "http" + if any(t in m for t in ("json decode", "parse", "unable to find", + "regex", "no match", "value not found", + "expecting value", "jsondecodeerror")): + return "parse" + if any(t in m for t in ("structure", "schema", "changed", "column", + "field missing", "keyerror", "attributeerror")): + return "structure" + if any(t in m for t in ("auth", "login", "token", "credentials", + "unauthorized", "forbidden", "401")): + return "auth" + return "other" + + def _load_source_health(self, limit: int = 200) -> list[dict]: + """Return the most recent source-health entries (for the API/UI).""" + import json + path = self._snap_dir / "source_health.json" + if not path.is_file(): + return [] + try: + data = json.loads(path.read_text(encoding="utf-8")) + except (OSError, ValueError): + return [] + if not isinstance(data, list): + return [] + return data[:limit] + @staticmethod def _now() -> str: import datetime as _dt diff --git a/backend/tests/test_scheduler.py b/backend/tests/test_scheduler.py index ae47e7e..0055a1a 100644 --- a/backend/tests/test_scheduler.py +++ b/backend/tests/test_scheduler.py @@ -128,6 +128,68 @@ class VintageCollectionTest(unittest.TestCase): len(__import__("json").loads(manifest.read_text()).get("snapshots", {})), 1) +class CadenceAndHealthTest(unittest.TestCase): + """Per-source cadence + source-health log (user requirements).""" + + def test_job_due_respects_frequency_marker(self): + import json + snap_dir = Path(tempfile.mkdtemp()) + sched = AppDataScheduler(_FakeCache(), snap_dir, interval_seconds=99999) + job = {"key": "macro_thai", "frequency": "monthly"} + # never run -> due + self.assertTrue(sched._job_due(job)) + sched._mark_job_run(job) + # just marked -> not due again for ~30 days + self.assertFalse(sched._job_due(job)) + # age the marker back 40 days -> due again + import datetime as _dt + old = (_dt.datetime.now().astimezone() - _dt.timedelta(days=40)).isoformat(timespec="seconds") + (snap_dir / "scheduler" / "job_macro_thai.json").write_text( + json.dumps({"at": old}), encoding="utf-8") + self.assertTrue(sched._job_due(job)) + + def test_analyze_error_classifies(self): + from app.scheduler import AppDataScheduler + self.assertEqual(AppDataScheduler._analyze_error("timed out connecting"), "timeout") + self.assertEqual(AppDataScheduler._analyze_error("Connection refused to host"), "network") + self.assertEqual(AppDataScheduler._analyze_error("HTTP 404 Not Found"), "http") + self.assertEqual(AppDataScheduler._analyze_error("JSONDecodeError: expecting value"), "parse") + self.assertEqual(AppDataScheduler._analyze_error("page structure changed - KeyError 'field'"), "structure") + self.assertEqual(AppDataScheduler._analyze_error("unauthorized token expired"), "auth") + self.assertEqual(AppDataScheduler._analyze_error(""), "other") + + def test_source_health_log_written_and_readable(self): + import json + snap_dir = Path(tempfile.mkdtemp()) + sched = AppDataScheduler(_FakeCache(), snap_dir, interval_seconds=99999) + results = [ + {"key": "macro_thai", "label": "ภาพรวม (BOT)", "ok": True, "at": "2026-08-28T00:00:00+07:00"}, + {"key": "auto_npl", "label": "NPL รถ", "ok": False, + "error": "JSONDecodeError: expecting value at line 1 (structure change?)", + "at": "2026-08-28T00:01:00+07:00"}, + ] + sched._append_source_log(results) + entries = sched._load_source_health() + self.assertEqual(len(entries), 2) + by_key = {e["key"]: e for e in entries} + self.assertTrue(by_key["macro_thai"]["ok"]) + self.assertFalse(by_key["auto_npl"]["ok"]) + self.assertEqual(by_key["auto_npl"]["category"], "parse") + + def test_refresh_only_runs_due_jobs(self): + # with frequency markers set to "now", a second refresh_all in the same + # tick should skip all factor jobs but still try daily jobs. + snap_dir = Path(tempfile.mkdtemp()) + sched = AppDataScheduler(_FakeCache(), snap_dir, interval_seconds=99999) + from app.scheduler import _REFRESH_JOBS, _DAILY_JOBS + for job in _REFRESH_JOBS + _DAILY_JOBS: + sched._mark_job_run(job) + # all marked -> a refresh tick runs nothing successfully (no network) + results = sched.refresh_all() + # daily jobs that ARE collections we stubbed: none should hard-crash + self.assertIsInstance(results, list) + + class DividendCooldownTest(unittest.TestCase): def _sched(self, snap_dir, cooldown): return AppDataScheduler(_FakeCache(), snap_dir, interval_seconds=99999, diff --git a/frontend/dist/assets/index-CUQk4rwt.js b/frontend/dist/assets/index-CUQk4rwt.js deleted file mode 100644 index f030cbf..0000000 --- a/frontend/dist/assets/index-CUQk4rwt.js +++ /dev/null @@ -1,18 +0,0 @@ -(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const l of document.querySelectorAll('link[rel="modulepreload"]'))n(l);new MutationObserver(l=>{for(const i of l)if(i.type==="childList")for(const r of i.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&n(r)}).observe(document,{childList:!0,subtree:!0});function s(l){const i={};return l.integrity&&(i.integrity=l.integrity),l.referrerPolicy&&(i.referrerPolicy=l.referrerPolicy),l.crossOrigin==="use-credentials"?i.credentials="include":l.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function n(l){if(l.ep)return;l.ep=!0;const i=s(l);fetch(l.href,i)}})();/** -* @vue/shared v3.5.41 -* (c) 2018-present Yuxi (Evan) You and Vue contributors -* @license MIT -**/function bn(e){const t=Object.create(null);for(const s of e.split(","))t[s]=1;return s=>s in t}const ee={},Ft=[],qe=()=>{},yl=()=>!1,Ds=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Ns=e=>e.startsWith("onUpdate:"),be=Object.assign,yn=(e,t)=>{const s=e.indexOf(t);s>-1&&e.splice(s,1)},Ri=Object.prototype.hasOwnProperty,J=(e,t)=>Ri.call(e,t),L=Array.isArray,Dt=e=>as(e)==="[object Map]",Ht=e=>as(e)==="[object Set]",Hn=e=>as(e)==="[object Date]",j=e=>typeof e=="function",re=e=>typeof e=="string",Je=e=>typeof e=="symbol",Z=e=>e!==null&&typeof e=="object",xl=e=>(Z(e)||j(e))&&j(e.then)&&j(e.catch),wl=Object.prototype.toString,as=e=>wl.call(e),Mi=e=>as(e).slice(8,-1),Sl=e=>as(e)==="[object Object]",xn=e=>re(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Gt=bn(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Ls=e=>{const t=Object.create(null);return(s=>t[s]||(t[s]=e(s)))},Ii=/-\w/g,Ie=Ls(e=>e.replace(Ii,t=>t.slice(1).toUpperCase())),Fi=/\B([A-Z])/g,Ot=Ls(e=>e.replace(Fi,"-$1").toLowerCase()),Cl=Ls(e=>e.charAt(0).toUpperCase()+e.slice(1)),Ys=Ls(e=>e?`on${Cl(e)}`:""),Ke=(e,t)=>!Object.is(e,t),Cs=(e,...t)=>{for(let s=0;s{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:n,value:s})},js=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let Bn;const Vs=()=>Bn||(Bn=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function $s(e){if(L(e)){const t={};for(let s=0;s{if(s){const n=s.split(Ni);n.length>1&&(t[n[0].trim()]=n[1].trim())}}),t}function Q(e){let t="";if(re(e))t=e;else if(L(e))for(let s=0;sBt(s,t))}const El=e=>!!(e&&e.__v_isRef===!0),_=e=>re(e)?e:e==null?"":L(e)||Z(e)&&(e.toString===wl||!j(e.toString))?El(e)?_(e.value):JSON.stringify(e,Ol,2):String(e),Ol=(e,t)=>El(t)?Ol(e,t.value):Dt(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((s,[n,l],i)=>(s[Xs(n,i)+" =>"]=l,s),{})}:Ht(t)?{[`Set(${t.size})`]:[...t.values()].map(s=>Xs(s))}:Je(t)?Xs(t):Z(t)&&!L(t)&&!Sl(t)?String(t):t,Xs=(e,t="")=>{var s;return Je(e)?`Symbol(${(s=e.description)!=null?s:t})`:e};/** -* @vue/reactivity v3.5.41 -* (c) 2018-present Yuxi (Evan) You and Vue contributors -* @license MIT -**/let ge;class Bi{constructor(t=!1){this.detached=t,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this._warnOnRun=!0,this.__v_skip=!0,!t&&ge&&(ge.active?(this.parent=ge,this.index=(ge.scopes||(ge.scopes=[])).push(this)-1):(this._active=!1,this._warnOnRun=!1))}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,s;if(this.scopes){const n=this.scopes.slice();for(t=0,s=n.length;t0&&--this._on===0){if(ge===this)ge=this.prevScope;else{let t=ge;for(;t;){if(t.prevScope===this){t.prevScope=this.prevScope;break}t=t.prevScope}}this.prevScope=void 0}}stop(t){if(this._active){this._active=!1;let s,n;for(s=0,n=this.effects.length;s0)return;if(Xt){let t=Xt;for(Xt=void 0;t;){const s=t.next;t.next=void 0,t.flags&=-9,t=s}}let e;for(;Yt;){let t=Yt;for(Yt=void 0;t;){const s=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(n){e||(e=n)}t=s}}if(e)throw e}function Ml(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function Il(e){let t,s=e.depsTail,n=s;for(;n;){const l=n.prevDep;n.version===-1?(n===s&&(s=l),Tn(n),Ki(n)):t=n,n.dep.activeLink=n.prevActiveLink,n.prevActiveLink=void 0,n=l}e.deps=t,e.depsTail=s}function cn(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(Fl(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function Fl(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===ts)||(e.globalVersion=ts,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!cn(e))))return;e.flags|=2;const t=e.dep,s=te,n=Fe;te=e,Fe=!0;try{Ml(e);const l=e.fn(e._value);(t.version===0||Ke(l,e._value))&&(e.flags|=128,e._value=l,t.version++)}catch(l){throw t.version++,l}finally{te=s,Fe=n,Il(e),e.flags&=-3}}function Tn(e,t=!1){const{dep:s,prevSub:n,nextSub:l}=e;if(n&&(n.nextSub=l,e.prevSub=void 0),l&&(l.prevSub=n,e.nextSub=void 0),s.subs===e&&(s.subs=n,!n&&s.computed)){s.computed.flags&=-5;for(let i=s.computed.deps;i;i=i.nextDep)Tn(i,!0)}!t&&!--s.sc&&s.map&&s.map.delete(s.key)}function Ki(e){const{prevDep:t,nextDep:s}=e;t&&(t.nextDep=s,e.prevDep=void 0),s&&(s.prevDep=t,e.nextDep=void 0)}let Fe=!0;const Dl=[];function it(){Dl.push(Fe),Fe=!1}function ot(){const e=Dl.pop();Fe=e===void 0?!0:e}function Un(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const s=te;te=void 0;try{t()}finally{te=s}}}let ts=0;class Wi{constructor(t,s){this.sub=t,this.dep=s,this.version=s.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class kn{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(t){if(!te||!Fe||te===this.computed)return;let s=this.activeLink;if(s===void 0||s.sub!==te)s=this.activeLink=new Wi(te,this),te.deps?(s.prevDep=te.depsTail,te.depsTail.nextDep=s,te.depsTail=s):te.deps=te.depsTail=s,Nl(s);else if(s.version===-1&&(s.version=this.version,s.nextDep)){const n=s.nextDep;n.prevDep=s.prevDep,s.prevDep&&(s.prevDep.nextDep=n),s.prevDep=te.depsTail,s.nextDep=void 0,te.depsTail.nextDep=s,te.depsTail=s,te.deps===s&&(te.deps=n)}return s}trigger(t){this.version++,ts++,this.notify(t)}notify(t){Sn();try{for(let s=this.subs;s;s=s.prevSub)s.sub.notify()&&s.sub.dep.notify()}finally{Cn()}}}function Nl(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let n=t.deps;n;n=n.nextDep)Nl(n)}const s=e.dep.subs;s!==e&&(e.prevSub=s,s&&(s.nextSub=e)),e.dep.subs=e}}const un=new WeakMap,Tt=Symbol(""),fn=Symbol(""),ss=Symbol("");function _e(e,t,s){if(Fe&&te){let n=un.get(e);n||un.set(e,n=new Map);let l=n.get(s);l||(n.set(s,l=new kn),l.map=n,l.key=s),l.track()}}function nt(e,t,s,n,l,i){const r=un.get(e);if(!r){ts++;return}const a=u=>{u&&u.trigger()};if(Sn(),t==="clear")r.forEach(a);else{const u=L(e),h=u&&xn(s);if(u&&s==="length"){const p=Number(n);r.forEach((y,R)=>{(R==="length"||R===ss||!Je(R)&&R>=p)&&a(y)})}else switch((s!==void 0||r.has(void 0))&&a(r.get(s)),h&&a(r.get(ss)),t){case"add":u?h&&a(r.get("length")):(a(r.get(Tt)),Dt(e)&&a(r.get(fn)));break;case"delete":u||(a(r.get(Tt)),Dt(e)&&a(r.get(fn)));break;case"set":Dt(e)&&a(r.get(Tt));break}}Cn()}function Mt(e){const t=z(e);return t===e?t:(_e(t,"iterate",ss),Me(e)?t:t.map(De))}function Hs(e){return _e(e=z(e),"iterate",ss),e}function Be(e,t){return rt(e)?jt(kt(e)?De(t):t):De(t)}const qi={__proto__:null,[Symbol.iterator](){return Qs(this,Symbol.iterator,e=>Be(this,e))},concat(...e){return Mt(this).concat(...e.map(t=>L(t)?Mt(t):t))},entries(){return Qs(this,"entries",e=>(e[1]=Be(this,e[1]),e))},every(e,t){return et(this,"every",e,t,void 0,arguments)},filter(e,t){return et(this,"filter",e,t,s=>s.map(n=>Be(this,n)),arguments)},find(e,t){return et(this,"find",e,t,s=>Be(this,s),arguments)},findIndex(e,t){return et(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return et(this,"findLast",e,t,s=>Be(this,s),arguments)},findLastIndex(e,t){return et(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return et(this,"forEach",e,t,void 0,arguments)},includes(...e){return en(this,"includes",e)},indexOf(...e){return en(this,"indexOf",e)},join(e){return Mt(this).join(e)},lastIndexOf(...e){return en(this,"lastIndexOf",e)},map(e,t){return et(this,"map",e,t,void 0,arguments)},pop(){return Wt(this,"pop")},push(...e){return Wt(this,"push",e)},reduce(e,...t){return Kn(this,"reduce",e,t)},reduceRight(e,...t){return Kn(this,"reduceRight",e,t)},shift(){return Wt(this,"shift")},some(e,t){return et(this,"some",e,t,void 0,arguments)},splice(...e){return Wt(this,"splice",e)},toReversed(){return Mt(this).toReversed()},toSorted(e){return Mt(this).toSorted(e)},toSpliced(...e){return Mt(this).toSpliced(...e)},unshift(...e){return Wt(this,"unshift",e)},values(){return Qs(this,"values",e=>Be(this,e))}};function Qs(e,t,s){const n=Hs(e),l=n[t]();return n!==e&&!Me(e)&&(l._next=l.next,l.next=()=>{const i=l._next();return i.done||(i.value=s(i.value)),i}),l}const zi=Array.prototype;function et(e,t,s,n,l,i){const r=Hs(e),a=r!==e&&!Me(e),u=r[t];if(u!==zi[t]){const y=u.apply(e,i);return a?De(y):y}let h=s;r!==e&&(a?h=function(y,R){return s.call(this,Be(e,y),R,e)}:s.length>2&&(h=function(y,R){return s.call(this,y,R,e)}));const p=u.call(r,h,n);return a&&l?l(p):p}function Kn(e,t,s,n){const l=Hs(e),i=l!==e&&!Me(e);let r=s,a=!1;l!==e&&(i?(a=n.length===0,r=function(h,p,y){return a&&(a=!1,h=Be(e,h)),s.call(this,h,Be(e,p),y,e)}):s.length>3&&(r=function(h,p,y){return s.call(this,h,p,y,e)}));const u=l[t](r,...n);return a?Be(e,u):u}function en(e,t,s){const n=z(e);_e(n,"iterate",ss);const l=n[t](...s);return(l===-1||l===!1)&&An(s[0])?(s[0]=z(s[0]),n[t](...s)):l}function Wt(e,t,s=[]){it(),Sn();const n=z(e)[t].apply(e,s);return Cn(),ot(),n}const Ji=bn("__proto__,__v_isRef,__isVue"),Ll=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Je));function Gi(e){Je(e)||(e=String(e));const t=z(this);return _e(t,"has",e),t.hasOwnProperty(e)}class jl{constructor(t=!1,s=!1){this._isReadonly=t,this._isShallow=s}get(t,s,n){if(s==="__v_skip")return t.__v_skip;const l=this._isReadonly,i=this._isShallow;if(s==="__v_isReactive")return!l;if(s==="__v_isReadonly")return l;if(s==="__v_isShallow")return i;if(s==="__v_raw")return n===(l?i?io:Bl:i?Hl:$l).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(n)?t:void 0;const r=L(t);if(!l){let u;if(r&&(u=qi[s]))return u;if(s==="hasOwnProperty")return Gi}const a=Reflect.get(t,s,me(t)?t:n);if((Je(s)?Ll.has(s):Ji(s))||(l||_e(t,"get",s),i))return a;if(me(a)){const u=r&&xn(s)?a:a.value;return l&&Z(u)?pn(u):u}return Z(a)?l?pn(a):On(a):a}}class Vl extends jl{constructor(t=!1){super(!1,t)}set(t,s,n,l){let i=t[s];const r=L(t)&&xn(s);if(!this._isShallow){const h=rt(i);if(!Me(n)&&!rt(n)&&(i=z(i),n=z(n)),!r&&me(i)&&!me(n))return h||(i.value=n),!0}const a=r?Number(s)e,bs=e=>Reflect.getPrototypeOf(e);function eo(e,t,s){return function(...n){const l=this.__v_raw,i=z(l),r=Dt(i),a=e==="entries"||e===Symbol.iterator&&r,u=e==="keys"&&r,h=l[e](...n),p=s?dn:t?jt:De;return!t&&_e(i,"iterate",u?fn:Tt),be(Object.create(h),{next(){const{value:y,done:R}=h.next();return R?{value:y,done:R}:{value:a?[p(y[0]),p(y[1])]:p(y),done:R}}})}}function ys(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function to(e,t){const s={get(l){const i=this.__v_raw,r=z(i),a=z(l);e||(Ke(l,a)&&_e(r,"get",l),_e(r,"get",a));const{has:u}=bs(r),h=t?dn:e?jt:De;if(u.call(r,l))return h(i.get(l));if(u.call(r,a))return h(i.get(a));i!==r&&i.get(l)},get size(){const l=this.__v_raw;return!e&&_e(z(l),"iterate",Tt),l.size},has(l){const i=this.__v_raw,r=z(i),a=z(l);return e||(Ke(l,a)&&_e(r,"has",l),_e(r,"has",a)),l===a?i.has(l):i.has(l)||i.has(a)},forEach(l,i){const r=this,a=r.__v_raw,u=z(a),h=t?dn:e?jt:De;return!e&&_e(u,"iterate",Tt),a.forEach((p,y)=>l.call(i,h(p),h(y),r))}};return be(s,e?{add:ys("add"),set:ys("set"),delete:ys("delete"),clear:ys("clear")}:{add(l){const i=z(this),r=bs(i),a=z(l),u=!t&&!Me(l)&&!rt(l)?a:l;return r.has.call(i,u)||Ke(l,u)&&r.has.call(i,l)||Ke(a,u)&&r.has.call(i,a)||(i.add(u),nt(i,"add",u,u)),this},set(l,i){!t&&!Me(i)&&!rt(i)&&(i=z(i));const r=z(this),{has:a,get:u}=bs(r);let h=a.call(r,l);h||(l=z(l),h=a.call(r,l));const p=u.call(r,l);return r.set(l,i),h?Ke(i,p)&&nt(r,"set",l,i):nt(r,"add",l,i),this},delete(l){const i=z(this),{has:r,get:a}=bs(i);let u=r.call(i,l);u||(l=z(l),u=r.call(i,l)),a&&a.call(i,l);const h=i.delete(l);return u&&nt(i,"delete",l,void 0),h},clear(){const l=z(this),i=l.size!==0,r=l.clear();return i&&nt(l,"clear",void 0,void 0),r}}),["keys","values","entries",Symbol.iterator].forEach(l=>{s[l]=eo(l,e,t)}),s}function En(e,t){const s=to(e,t);return(n,l,i)=>l==="__v_isReactive"?!e:l==="__v_isReadonly"?e:l==="__v_raw"?n:Reflect.get(J(s,l)&&l in n?s:n,l,i)}const so={get:En(!1,!1)},no={get:En(!1,!0)},lo={get:En(!0,!1)};const $l=new WeakMap,Hl=new WeakMap,Bl=new WeakMap,io=new WeakMap;function oo(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function On(e){return rt(e)?e:Pn(e,!1,Xi,so,$l)}function ro(e){return Pn(e,!1,Qi,no,Hl)}function pn(e){return Pn(e,!0,Zi,lo,Bl)}function Pn(e,t,s,n,l){if(!Z(e)||e.__v_raw&&!(t&&e.__v_isReactive)||e.__v_skip||!Object.isExtensible(e))return e;const i=l.get(e);if(i)return i;const r=oo(Mi(e));if(r===0)return e;const a=new Proxy(e,r===2?n:s);return l.set(e,a),a}function kt(e){return rt(e)?kt(e.__v_raw):!!(e&&e.__v_isReactive)}function rt(e){return!!(e&&e.__v_isReadonly)}function Me(e){return!!(e&&e.__v_isShallow)}function An(e){return e?!!e.__v_raw:!1}function z(e){const t=e&&e.__v_raw;return t?z(t):e}function ao(e){return!J(e,"__v_skip")&&Object.isExtensible(e)&&Tl(e,"__v_skip",!0),e}const De=e=>Z(e)?On(e):e,jt=e=>Z(e)?pn(e):e;function me(e){return e?e.__v_isRef===!0:!1}function $(e){return co(e,!1)}function co(e,t){return me(e)?e:new uo(e,t)}class uo{constructor(t,s){this.dep=new kn,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=s?t:z(t),this._value=s?t:De(t),this.__v_isShallow=s}get value(){return this.dep.track(),this._value}set value(t){const s=this._rawValue,n=this.__v_isShallow||Me(t)||rt(t);t=n?t:z(t),Ke(t,s)&&(this._rawValue=t,this._value=n?t:De(t),this.dep.trigger())}}function fo(e){return me(e)?e.value:e}const po={get:(e,t,s)=>t==="__v_raw"?e:fo(Reflect.get(e,t,s)),set:(e,t,s,n)=>{const l=e[t];return me(l)&&!me(s)?(l.value=s,!0):Reflect.set(e,t,s,n)}};function Ul(e){return kt(e)?e:new Proxy(e,po)}class ho{constructor(t,s,n){this.fn=t,this.setter=s,this._value=void 0,this.dep=new kn(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=ts-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!s,this.isSSR=n}notify(){if(this.flags|=16,!(this.flags&8)&&te!==this)return Rl(this,!0),!0}get value(){const t=this.dep.track();return Fl(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function go(e,t,s=!1){let n,l;return j(e)?n=e:(n=e.get,l=e.set),new ho(n,l,s)}const xs={},Os=new WeakMap;let Ct;function vo(e,t=!1,s=Ct){if(s){let n=Os.get(s);n||Os.set(s,n=[]),n.push(e)}}function _o(e,t,s=ee){const{immediate:n,deep:l,once:i,scheduler:r,augmentJob:a,call:u}=s,h=N=>l?N:Me(N)||l===!1||l===0?lt(N,1):lt(N);let p,y,R,I,U=!1,A=!1;if(me(e)?(y=()=>e.value,U=Me(e)):kt(e)?(y=()=>h(e),U=!0):L(e)?(A=!0,U=e.some(N=>kt(N)||Me(N)),y=()=>e.map(N=>{if(me(N))return N.value;if(kt(N))return h(N);if(j(N))return u?u(N,2):N()})):j(e)?t?y=u?()=>u(e,2):e:y=()=>{if(R){it();try{R()}finally{ot()}}const N=Ct;Ct=p;try{return u?u(e,3,[I]):e(I)}finally{Ct=N}}:y=qe,t&&l){const N=y,W=l===!0?1/0:l;y=()=>lt(N(),W)}const se=Ui(),H=()=>{p.stop(),se&&se.active&&yn(se.effects,p)};if(i&&t){const N=t;t=(...W)=>{const Se=N(...W);return H(),Se}}let V=A?new Array(e.length).fill(xs):xs;const K=N=>{if(!(!(p.flags&1)||!p.dirty&&!N))if(t){const W=p.run();if(N||l||U||(A?W.some((Se,ne)=>Ke(Se,V[ne])):Ke(W,V))){R&&R();const Se=Ct;Ct=p;try{const ne=[W,V===xs?void 0:A&&V[0]===xs?[]:V,I];V=W,u?u(t,3,ne):t(...ne)}finally{Ct=Se}}}else p.run()};return a&&a(K),p=new Pl(y),p.scheduler=r?()=>r(K,!1):K,I=N=>vo(N,!1,p),R=p.onStop=()=>{const N=Os.get(p);if(N){if(u)u(N,4);else for(const W of N)W();Os.delete(p)}},t?n?K(!0):V=p.run():r?r(K.bind(null,!0),!0):p.run(),H.pause=p.pause.bind(p),H.resume=p.resume.bind(p),H.stop=H,H}function lt(e,t=1/0,s){if(t<=0||!Z(e)||e.__v_skip||(s=s||new Map,(s.get(e)||0)>=t))return e;if(s.set(e,t),t--,me(e))lt(e.value,t,s);else if(L(e))for(let n=0;n{lt(n,t,s)});else if(Sl(e)){for(const n in e)lt(e[n],t,s);for(const n of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,n)&<(e[n],t,s)}return e}/** -* @vue/runtime-core v3.5.41 -* (c) 2018-present Yuxi (Evan) You and Vue contributors -* @license MIT -**/function cs(e,t,s,n){try{return n?e(...n):e()}catch(l){Bs(l,t,s)}}function Ne(e,t,s,n){if(j(e)){const l=cs(e,t,s,n);return l&&xl(l)&&l.catch(i=>{Bs(i,t,s)}),l}if(L(e)){const l=[];for(let i=0;i>>1,l=xe[n],i=ns(l);i=ns(s)?xe.push(e):xe.splice(bo(t),0,e),e.flags|=1,ql()}}function ql(){Ps||(Ps=Kl.then(Jl))}function yo(e){if(!L(e))ht&&e.id===-1?ht.splice(It+1,0,e):e.flags&1||(Nt.push(e),e.flags|=1);else for(let t=0;tns(s)-ns(n));if(Nt.length=0,ht){for(let s=0;se.id==null?e.flags&2?-1:1/0:e.id;function Jl(e){try{for(He=0;He{n._d&&sl(-1);const i=As(t),r=Et.length;let a;try{a=e(...l)}finally{for(let u=Et.length;u>r;u--)yi();As(i),n._d&&sl(1)}return a};return n._n=!0,n._c=!0,n._d=!0,n}function xt(e,t){if(Re===null)return e;const s=zs(Re),n=e.dirs||(e.dirs=[]);for(let l=0;l1)return s&&j(t)?t.call(n&&n.proxy):t}}const So=Symbol.for("v-scx"),Co=()=>Ts(So);function tn(e,t,s){return Yl(e,t,s)}function Yl(e,t,s=ee){const{immediate:n,deep:l,flush:i,once:r}=s,a=be({},s),u=t&&n||!t&&i!=="post";let h;if(os){if(i==="sync"){const I=Co();h=I.__watcherHandles||(I.__watcherHandles=[])}else if(!u){const I=()=>{};return I.stop=qe,I.resume=qe,I.pause=qe,I}}const p=we;a.call=(I,U,A)=>Ne(I,p,U,A);let y=!1;i==="post"?a.scheduler=I=>{Te(I,p&&p.suspense)}:i!=="sync"&&(y=!0,a.scheduler=(I,U)=>{U?I():Rn(I)}),a.augmentJob=I=>{t&&(I.flags|=4),y&&(I.flags|=2,p&&(I.id=p.uid,I.i=p))};const R=_o(e,t,a);return os&&(h?h.push(R):u&&R()),R}function To(e,t,s){const n=this.proxy,l=re(e)?e.includes(".")?Xl(n,e):()=>n[e]:e.bind(n,n);let i;j(t)?i=t:(i=t.handler,s=t);const r=us(this),a=Yl(l,i.bind(n),s);return r(),a}function Xl(e,t){const s=t.split(".");return()=>{let n=e;for(let l=0;le.__isTeleport,sn=Symbol("_leaveCb");function Eo(e){let t=e[0];if(e.length>1){for(const s of e)if(s.type!==at){t=s;break}}return t}function Zl(e){if(!In(e))return Us(e.type)&&e.children?Eo(e.children):e;if(e.component)return e.component.subTree;const{shapeFlag:t,children:s}=e;if(s){if(t&16)return s[0];if(t&32&&j(s.default))return s.default()}}function Mn(e,t){if(e.shapeFlag&6&&e.component){e.transition=t;const s=e.component.subTree;Mn(Us(s.type)&&Zl(s)||s,t)}else e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Ql(e){e.ids=[e.ids[0]+e.ids[2]+++"-",0,0]}function qn(e,t){let s;return!!((s=Object.getOwnPropertyDescriptor(e,t))&&!s.configurable)}const Rs=new WeakMap;function Zt(e,t,s,n,l=!1){if(L(e)){e.forEach((A,se)=>Zt(A,t&&(L(t)?t[se]:t),s,n,l));return}if(Qt(n)&&!l){n.shapeFlag&512&&n.type.__asyncResolved&&n.component.subTree.component&&Zt(e,t,s,n.component.subTree);return}const i=n.shapeFlag&4?zs(n.component):n.el,r=l?null:i,{i:a,r:u}=e,h=t&&t.r,p=a.refs===ee?a.refs={}:a.refs,y=a.setupState,R=z(y),I=y===ee?yl:A=>qn(p,A)?!1:J(R,A),U=(A,se)=>!(se&&qn(p,se));if(h!=null&&h!==u){if(zn(t),re(h))p[h]=null,I(h)&&(y[h]=null);else if(me(h)){const A=t;U(h,A.k)&&(h.value=null),A.k&&(p[A.k]=null)}}if(j(u))cs(u,a,12,[r,p]);else{const A=re(u),se=me(u);if(A||se){const H=()=>{if(e.f){const V=A?I(u)?y[u]:p[u]:U()||!e.k?u.value:p[e.k];if(l)L(V)&&yn(V,i);else if(L(V))V.includes(i)||V.push(i);else if(A)p[u]=[i],I(u)&&(y[u]=p[u]);else{const K=[i];U(u,e.k)&&(u.value=K),e.k&&(p[e.k]=K)}}else A?(p[u]=r,I(u)&&(y[u]=r)):se&&(U(u,e.k)&&(u.value=r),e.k&&(p[e.k]=r))};if(r){const V=()=>{H(),Rs.delete(e)};V.id=-1,Rs.set(e,V),Te(V,s)}else zn(e),H()}}}function zn(e){const t=Rs.get(e);t&&(t.flags|=8,Rs.delete(e))}Vs().requestIdleCallback;Vs().cancelIdleCallback;const Qt=e=>!!e.type.__asyncLoader,In=e=>e.type.__isKeepAlive;function Oo(e,t){ei(e,"a",t)}function Po(e,t){ei(e,"da",t)}function ei(e,t,s=we){const n=e.__wdc||(e.__wdc=()=>{let l=s;for(;l;){if(l.isDeactivated)return;l=l.parent}return e()});if(Ks(t,n,s),s){let l=s.parent;for(;l&&l.parent;)In(l.parent.vnode)&&Ao(n,t,s,l),l=l.parent}}function Ao(e,t,s,n){const l=Ks(t,e,n,!0);si(()=>{yn(n[t],l)},s)}function Ks(e,t,s=we,n=!1){if(s){const l=s[e]||(s[e]=[]),i=t.__weh||(t.__weh=(...r)=>{it();const a=us(s),u=Ne(t,s,e,r);return a(),ot(),u});return n?l.unshift(i):l.push(i),i}}const ct=e=>(t,s=we)=>{(!os||e==="sp")&&Ks(e,(...n)=>t(...n),s)},Ro=ct("bm"),ti=ct("m"),Mo=ct("bu"),Io=ct("u"),Fo=ct("bum"),si=ct("um"),Do=ct("sp"),No=ct("rtg"),Lo=ct("rtc");function jo(e,t=we){Ks("ec",e,t)}const Vo=Symbol.for("v-ndc");function Ae(e,t,s,n){let l;const i=s,r=L(e);if(r||re(e)){const a=r&&kt(e);let u=!1,h=!1;a&&(u=!Me(e),h=rt(e),e=Hs(e)),l=new Array(e.length);for(let p=0,y=e.length;pt(a,u,void 0,i));else{const a=Object.keys(e);l=new Array(a.length);for(let u=0,h=a.length;ue?Ci(e)?zs(e):hn(e.parent):null,es=be(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>hn(e.parent),$root:e=>hn(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>li(e),$forceUpdate:e=>e.f||(e.f=()=>{Rn(e.update)}),$nextTick:e=>e.n||(e.n=Wl.bind(e.proxy)),$watch:e=>To.bind(e)}),nn=(e,t)=>e!==ee&&!e.__isScriptSetup&&J(e,t),$o={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:s,setupState:n,data:l,props:i,accessCache:r,type:a,appContext:u}=e;if(t[0]!=="$"){const R=r[t];if(R!==void 0)switch(R){case 1:return n[t];case 2:return l[t];case 4:return s[t];case 3:return i[t]}else{if(nn(n,t))return r[t]=1,n[t];if(l!==ee&&J(l,t))return r[t]=2,l[t];if(J(i,t))return r[t]=3,i[t];if(s!==ee&&J(s,t))return r[t]=4,s[t];gn&&(r[t]=0)}}const h=es[t];let p,y;if(h)return t==="$attrs"&&_e(e.attrs,"get",""),h(e);if((p=a.__cssModules)&&(p=p[t]))return p;if(s!==ee&&J(s,t))return r[t]=4,s[t];if(y=u.config.globalProperties,J(y,t))return y[t]},set({_:e},t,s){const{data:n,setupState:l,ctx:i}=e;return nn(l,t)?(l[t]=s,!0):n!==ee&&J(n,t)?(n[t]=s,!0):J(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(i[t]=s,!0)},has({_:{data:e,setupState:t,accessCache:s,ctx:n,appContext:l,props:i,type:r}},a){let u;return!!(s[a]||e!==ee&&a[0]!=="$"&&J(e,a)||nn(t,a)||J(i,a)||J(n,a)||J(es,a)||J(l.config.globalProperties,a)||(u=r.__cssModules)&&u[a])},defineProperty(e,t,s){return s.get!=null?e._.accessCache[t]=0:J(s,"value")&&this.set(e,t,s.value,null),Reflect.defineProperty(e,t,s)}};function Jn(e){return L(e)?e.reduce((t,s)=>(t[s]=null,t),{}):e}let gn=!0;function Ho(e){const t=li(e),s=e.proxy,n=e.ctx;gn=!1,t.beforeCreate&&Gn(t.beforeCreate,e,"bc");const{data:l,computed:i,methods:r,watch:a,provide:u,inject:h,created:p,beforeMount:y,mounted:R,beforeUpdate:I,updated:U,activated:A,deactivated:se,beforeDestroy:H,beforeUnmount:V,destroyed:K,unmounted:N,render:W,renderTracked:Se,renderTriggered:ne,errorCaptured:Ce,serverPrefetch:Pt,expose:Ge,inheritAttrs:vt,components:ut,directives:Ye,filters:ft}=t;if(h&&Bo(h,n,null),r)for(const le in r){const X=r[le];j(X)&&(n[le]=X.bind(s))}if(l){const le=l.call(s,s);Z(le)&&(e.data=On(le))}if(gn=!0,i)for(const le in i){const X=i[le],Le=j(X)?X.bind(s,s):j(X.get)?X.get.bind(s,s):qe,_t=!j(X)&&j(X.set)?X.set.bind(s):qe,je=ae({get:Le,set:_t});Object.defineProperty(n,le,{enumerable:!0,configurable:!0,get:()=>je.value,set:de=>je.value=de})}if(a)for(const le in a)ni(a[le],n,s,le);if(u){const le=j(u)?u.call(s):u;Reflect.ownKeys(le).forEach(X=>{wo(X,le[X])})}p&&Gn(p,e,"c");function fe(le,X){L(X)?X.forEach(Le=>le(Le.bind(s))):X&&le(X.bind(s))}if(fe(Ro,y),fe(ti,R),fe(Mo,I),fe(Io,U),fe(Oo,A),fe(Po,se),fe(jo,Ce),fe(Lo,Se),fe(No,ne),fe(Fo,V),fe(si,N),fe(Do,Pt),L(Ge))if(Ge.length){const le=e.exposed||(e.exposed={});Ge.forEach(X=>{Object.defineProperty(le,X,{get:()=>s[X],set:Le=>s[X]=Le,enumerable:!0})})}else e.exposed||(e.exposed={});W&&e.render===qe&&(e.render=W),vt!=null&&(e.inheritAttrs=vt),ut&&(e.components=ut),Ye&&(e.directives=Ye),Pt&&Ql(e)}function Bo(e,t,s=qe){L(e)&&(e=vn(e));for(const n in e){const l=e[n];let i;Z(l)?"default"in l?i=Ts(l.from||n,l.default,!0):i=Ts(l.from||n):i=Ts(l),me(i)?Object.defineProperty(t,n,{enumerable:!0,configurable:!0,get:()=>i.value,set:r=>i.value=r}):t[n]=i}}function Gn(e,t,s){Ne(L(e)?e.map(n=>n.bind(t.proxy)):e.bind(t.proxy),t,s)}function ni(e,t,s,n){let l=n.includes(".")?Xl(s,n):()=>s[n];if(re(e)){const i=t[e];j(i)&&tn(l,i)}else if(j(e))tn(l,e.bind(s));else if(Z(e))if(L(e))e.forEach(i=>ni(i,t,s,n));else{const i=j(e.handler)?e.handler.bind(s):t[e.handler];j(i)&&tn(l,i,e)}}function li(e){const t=e.type,{mixins:s,extends:n}=t,{mixins:l,optionsCache:i,config:{optionMergeStrategies:r}}=e.appContext,a=i.get(t);let u;return a?u=a:!l.length&&!s&&!n?u=t:(u={},l.length&&l.forEach(h=>Ms(u,h,r,!0)),Ms(u,t,r)),Z(t)&&i.set(t,u),u}function Ms(e,t,s,n=!1){const{mixins:l,extends:i}=t;i&&Ms(e,i,s,!0),l&&l.forEach(r=>Ms(e,r,s,!0));for(const r in t)if(!(n&&r==="expose")){const a=Uo[r]||s&&s[r];e[r]=a?a(e[r],t[r]):t[r]}return e}const Uo={data:Yn,props:Xn,emits:Xn,methods:zt,computed:zt,beforeCreate:ye,created:ye,beforeMount:ye,mounted:ye,beforeUpdate:ye,updated:ye,beforeDestroy:ye,beforeUnmount:ye,destroyed:ye,unmounted:ye,activated:ye,deactivated:ye,errorCaptured:ye,serverPrefetch:ye,components:zt,directives:zt,watch:Wo,provide:Yn,inject:Ko};function Yn(e,t){return t?e?function(){return be(j(e)?e.call(this,this):e,j(t)?t.call(this,this):t)}:t:e}function Ko(e,t){return zt(vn(e),vn(t))}function vn(e){if(L(e)){const t={};for(let s=0;st==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${Ie(t)}Modifiers`]||e[`${Ot(t)}Modifiers`];function Go(e,t,...s){if(e.isUnmounted)return;const n=e.vnode.props||ee;let l=s;const i=t.startsWith("update:"),r=i&&Jo(n,t.slice(7));r&&(r.trim&&(l=s.map(p=>re(p)?p.trim():p)),r.number&&(l=s.map(js)));let a,u=n[a=Ys(t)]||n[a=Ys(Ie(t))];!u&&i&&(u=n[a=Ys(Ot(t))]),u&&Ne(u,e,6,l);const h=n[a+"Once"];if(h){if(!e.emitted)e.emitted={};else if(e.emitted[a])return;e.emitted[a]=!0,Ne(h,e,6,l)}}const Yo=new WeakMap;function oi(e,t,s=!1){const n=s?Yo:t.emitsCache,l=n.get(e);if(l!==void 0)return l;const i=e.emits;let r={},a=!1;if(!j(e)){const u=h=>{const p=oi(h,t,!0);p&&(a=!0,be(r,p))};!s&&t.mixins.length&&t.mixins.forEach(u),e.extends&&u(e.extends),e.mixins&&e.mixins.forEach(u)}return!i&&!a?(Z(e)&&n.set(e,null),null):(L(i)?i.forEach(u=>r[u]=null):be(r,i),Z(e)&&n.set(e,r),r)}function Ws(e,t){return!e||!Ds(t)?!1:(t=t.slice(2),t=t==="Once"?t:t.replace(/Once$/,""),J(e,t[0].toLowerCase()+t.slice(1))||J(e,Ot(t))||J(e,t))}function Zn(e){const{type:t,vnode:s,proxy:n,withProxy:l,propsOptions:[i],slots:r,attrs:a,emit:u,render:h,renderCache:p,props:y,data:R,setupState:I,ctx:U,inheritAttrs:A}=e,se=As(e);let H,V;try{if(s.shapeFlag&4){const N=l||n,W=N;H=Ue(h.call(W,N,p,y,I,R,U)),V=a}else{const N=t;H=Ue(N.length>1?N(y,{attrs:a,slots:r,emit:u}):N(y,null)),V=t.props?a:Xo(a)}}catch(N){Et.length=0,Bs(N,e,1),H=ze(at)}let K=H;if(V&&A!==!1){const N=Object.keys(V),{shapeFlag:W}=K;N.length&&W&7&&(i&&N.some(Ns)&&(V=Zo(V,i)),K=Vt(K,V,!1,!0))}if(s.dirs&&(K=Vt(K,null,!1,!0),K.dirs=K.dirs?K.dirs.concat(s.dirs):s.dirs),s.transition){const N=Us(K.type)&&Zl(K)||K;Mn(N,s.transition)}return H=K,As(se),H}const Xo=e=>{let t;for(const s in e)(s==="class"||s==="style"||Ds(s))&&((t||(t={}))[s]=e[s]);return t},Zo=(e,t)=>{const s={};for(const n in e)(!Ns(n)||!(n.slice(9)in t))&&(s[n]=e[n]);return s};function Qo(e,t,s){const{props:n,children:l,component:i}=e,{props:r,children:a,patchFlag:u}=t,h=i.emitsOptions;if(t.dirs||t.transition)return!0;if(s&&u>=0){if(u&1024)return!0;if(u&16)return n?Qn(n,r,h):!!r;if(u&8){const p=t.dynamicProps;for(let y=0;yObject.create(ai),ui=e=>Object.getPrototypeOf(e)===ai;function tr(e,t,s,n=!1){const l={},i=ci();e.propsDefaults=Object.create(null),fi(e,t,l,i);for(const r in e.propsOptions[0])r in l||(l[r]=void 0);s?e.props=n?l:ro(l):e.type.props?e.props=l:e.props=i,e.attrs=i}function sr(e,t,s,n){const{props:l,attrs:i,vnode:{patchFlag:r}}=e,a=z(l),[u]=e.propsOptions;let h=!1;if((n||r>0)&&!(r&16)){if(r&8){const p=e.vnode.dynamicProps;for(let y=0;y{u=!0;const[R,I]=di(y,t,!0);be(r,R),I&&a.push(...I)};!s&&t.mixins.length&&t.mixins.forEach(p),e.extends&&p(e.extends),e.mixins&&e.mixins.forEach(p)}if(!i&&!u)return Z(e)&&n.set(e,Ft),Ft;if(L(i))for(let p=0;pe==="_"||e==="_ctx"||e==="$stable",Dn=e=>L(e)?e.map(Ue):[Ue(e)],lr=(e,t,s)=>{if(t._n)return t;const n=xo((...l)=>Dn(t(...l)),s);return n._c=!1,n},pi=(e,t,s)=>{const n=e._ctx;for(const l in e){if(Fn(l))continue;const i=e[l];if(j(i))t[l]=lr(l,i,n);else if(i!=null){const r=Dn(i);t[l]=()=>r}}},hi=(e,t)=>{const s=Dn(t);e.slots.default=()=>s},gi=(e,t,s)=>{for(const n in t)(s||!Fn(n))&&(e[n]=t[n])},ir=(e,t,s)=>{const n=e.slots=ci();if(e.vnode.shapeFlag&32){const l=t._;l?(gi(n,t,s),s&&Tl(n,"_",l,!0)):pi(t,n)}else t&&hi(e,t)},or=(e,t,s)=>{const{vnode:n,slots:l}=e;let i=!0,r=ee;if(n.shapeFlag&32){const a=t._;a?s&&a===1?i=!1:gi(l,t,s):(i=!t.$stable,pi(t,l)),r=t}else t&&(hi(e,t),r={default:1});if(i)for(const a in l)!Fn(a)&&r[a]==null&&delete l[a]},Te=fr;function rr(e){return ar(e)}function ar(e,t){const s=Vs();s.__VUE__=!0;const{insert:n,remove:l,patchProp:i,createElement:r,createText:a,createComment:u,setText:h,setElementText:p,parentNode:y,nextSibling:R,setScopeId:I=qe,insertStaticContent:U}=e,A=(c,d,m,C=null,S=null,x=null,k=void 0,T=null,b=!!d.dynamicChildren)=>{if(c===d)return;c&&!qt(c,d)&&(C=Xe(c),de(c,S,x,!0),c=null),d.patchFlag===-2&&(b=!1,d.dynamicChildren=null);const{type:w,ref:D,shapeFlag:P}=d;switch(w){case qs:se(c,d,m,C);break;case at:H(c,d,m,C);break;case ks:c==null&&V(d,m,C,k);break;case oe:ut(c,d,m,C,S,x,k,T,b);break;default:P&1?W(c,d,m,C,S,x,k,T,b):P&6?Ye(c,d,m,C,S,x,k,T,b):(P&64||P&128)&&w.process(c,d,m,C,S,x,k,T,b,pt)}D!=null&&S?Zt(D,c&&c.ref,x,d||c,!d):D==null&&c&&c.ref!=null&&Zt(c.ref,null,x,c,!0)},se=(c,d,m,C)=>{if(c==null)n(d.el=a(d.children),m,C);else{const S=d.el=c.el;d.children!==c.children&&h(S,d.children)}},H=(c,d,m,C)=>{c==null?n(d.el=u(d.children||""),m,C):d.el=c.el},V=(c,d,m,C)=>{[c.el,c.anchor]=U(c.children,d,m,C,c.el,c.anchor)},K=({el:c,anchor:d},m,C)=>{let S;for(;c&&c!==d;)S=R(c),n(c,m,C),c=S;n(d,m,C)},N=({el:c,anchor:d})=>{let m;for(;c&&c!==d;)m=R(c),l(c),c=m;l(d)},W=(c,d,m,C,S,x,k,T,b)=>{if(d.type==="svg"?k="svg":d.type==="math"&&(k="mathml"),c==null)Se(d,m,C,S,x,k,T,b);else{const w=c.el&&c.el._isVueCE?c.el:null;try{w&&w._beginPatch(),Pt(c,d,S,x,k,T,b)}finally{w&&w._endPatch()}}},Se=(c,d,m,C,S,x,k,T)=>{let b,w;const{props:D,shapeFlag:P,transition:F,dirs:M}=c;if(b=c.el=r(c.type,x,D&&D.is,D),P&8?p(b,c.children):P&16&&Ce(c.children,b,null,C,S,ln(c,x),k,T),M&&wt(c,null,C,"created"),ne(b,c,c.scopeId,k,C),D){for(const G in D)G!=="value"&&!Gt(G)&&i(b,G,null,D[G],x,C);"value"in D&&i(b,"value",null,D.value,x),(w=D.onVnodeBeforeMount)&&$e(w,C,c)}M&&wt(c,null,C,"beforeMount");const B=cr(S,F);B&&F.beforeEnter(b),n(b,d,m),((w=D&&D.onVnodeMounted)||B||M)&&Te(()=>{try{w&&$e(w,C,c),B&&F.enter(b),M&&wt(c,null,C,"mounted")}finally{}},S)},ne=(c,d,m,C,S)=>{if(m&&I(c,m),C)for(let x=0;x{for(let w=b;w{const T=d.el=c.el;let{patchFlag:b,dynamicChildren:w,dirs:D}=d;b|=c.patchFlag&16;const P=c.props||ee,F=d.props||ee;let M;if(m&&St(m,!1),(M=F.onVnodeBeforeUpdate)&&$e(M,m,d,c),D&&wt(d,c,m,"beforeUpdate"),m&&St(m,!0),w&&(!c.dynamicChildren||c.dynamicChildren.length!==w.length)&&(b=0,k=!1,w=null),(P.innerHTML&&F.innerHTML==null||P.textContent&&F.textContent==null)&&p(T,""),w?Ge(c.dynamicChildren,w,T,m,C,ln(d,S),x):k||X(c,d,T,null,m,C,ln(d,S),x,!1),b>0){if(b&16)vt(T,P,F,m,S);else if(b&2&&P.class!==F.class&&i(T,"class",null,F.class,S),b&4&&i(T,"style",P.style,F.style,S),b&8){const B=d.dynamicProps;for(let G=0;G{M&&$e(M,m,d,c),D&&wt(d,c,m,"updated")},C)},Ge=(c,d,m,C,S,x,k)=>{for(let T=0;T{if(d!==m){if(d!==ee)for(const x in d)!Gt(x)&&!(x in m)&&i(c,x,d[x],null,S,C);for(const x in m){if(Gt(x))continue;const k=m[x],T=d[x];k!==T&&x!=="value"&&i(c,x,T,k,S,C)}"value"in m&&i(c,"value",d.value,m.value,S)}},ut=(c,d,m,C,S,x,k,T,b)=>{const w=d.el=c?c.el:a(""),D=d.anchor=c?c.anchor:a("");let{patchFlag:P,dynamicChildren:F,slotScopeIds:M}=d;M&&(T=T?T.concat(M):M),c==null?(n(w,m,C),n(D,m,C),Ce(d.children||[],m,D,S,x,k,T,b)):P>0&&P&64&&F&&c.dynamicChildren&&c.dynamicChildren.length===F.length?(Ge(c.dynamicChildren,F,m,S,x,k,T),(d.key!=null||S&&d===S.subTree)&&vi(c,d,!0)):X(c,d,m,D,S,x,k,T,b)},Ye=(c,d,m,C,S,x,k,T,b)=>{d.slotScopeIds=T,c==null?d.shapeFlag&512?S.ctx.activate(d,m,C,k,b):ft(d,m,C,S,x,k,b):fs(c,d,b)},ft=(c,d,m,C,S,x,k)=>{const T=c.component=br(c,C,S);if(In(c)&&(T.ctx.renderer=pt),xr(T,!1,k),T.asyncDep){if(S&&S.registerDep(T,fe,k),!c.el){const b=T.subTree=ze(at);H(null,b,d,m),c.placeholder=b.el}}else fe(T,c,d,m,S,x,k)},fs=(c,d,m)=>{const C=d.component=c.component;if(Qo(c,d,m))if(C.asyncDep&&!C.asyncResolved){le(C,d,m);return}else C.next=d,C.update();else d.el=c.el,C.vnode=d},fe=(c,d,m,C,S,x,k)=>{const T=()=>{if(c.isMounted){let{next:P,bu:F,u:M,parent:B,vnode:G}=c;{const Ee=_i(c);if(Ee){P&&(P.el=G.el,le(c,P,k)),Ee.asyncDep.then(()=>{Te(()=>{c.isUnmounted||w()},S)});return}}let q=P,ie;St(c,!1),P?(P.el=G.el,le(c,P,k)):P=G,F&&Cs(F),(ie=P.props&&P.props.onVnodeBeforeUpdate)&&$e(ie,B,P,G),St(c,!0);const ce=Zn(c),pe=c.subTree;c.subTree=ce,A(pe,ce,y(pe.el),Xe(pe),c,S,x),P.el=ce.el,q===null&&er(c,ce.el),M&&Te(M,S),(ie=P.props&&P.props.onVnodeUpdated)&&Te(()=>$e(ie,B,P,G),S)}else{let P;const{el:F,props:M}=d,{bm:B,m:G,parent:q,root:ie,type:ce}=c,pe=Qt(d);St(c,!1),B&&Cs(B),!pe&&(P=M&&M.onVnodeBeforeMount)&&$e(P,q,d),St(c,!0);{ie.ce&&ie.ce._hasShadowRoot()&&ie.ce._injectChildStyle(ce,c.parent?c.parent.type:void 0);const Ee=c.subTree=Zn(c);A(null,Ee,m,C,c,S,x),d.el=Ee.el}if(G&&Te(G,S),!pe&&(P=M&&M.onVnodeMounted)){const Ee=d;Te(()=>$e(P,q,Ee),S)}(d.shapeFlag&256||q&&Qt(q.vnode)&&q.vnode.shapeFlag&256)&&c.a&&Te(c.a,S),c.isMounted=!0,d=m=C=null}};c.scope.on();const b=c.effect=new Pl(T);c.scope.off();const w=c.update=b.run.bind(b),D=c.job=b.runIfDirty.bind(b);D.i=c,D.id=c.uid,b.scheduler=()=>Rn(D),St(c,!0),w()},le=(c,d,m)=>{d.component=c;const C=c.vnode.props;c.vnode=d,c.next=null,sr(c,d.props,C,m),or(c,d.children,m),it(),Wn(c),ot()},X=(c,d,m,C,S,x,k,T,b=!1)=>{const w=c&&c.children,D=c?c.shapeFlag:0,P=d.children,{patchFlag:F,shapeFlag:M}=d;if(F>0){if(F&128){_t(w,P,m,C,S,x,k,T,b);return}else if(F&256){Le(w,P,m,C,S,x,k,T,b);return}}M&8?(D&16&&mt(w,S,x),P!==w&&p(m,P)):D&16?M&16?_t(w,P,m,C,S,x,k,T,b):mt(w,S,x,!0):(D&8&&p(m,""),M&16&&Ce(P,m,C,S,x,k,T,b))},Le=(c,d,m,C,S,x,k,T,b)=>{c=c||Ft,d=d||Ft;const w=c.length,D=d.length,P=Math.min(w,D);let F;for(F=0;FD?mt(c,S,x,!0,!1,P):Ce(d,m,C,S,x,k,T,b,P)},_t=(c,d,m,C,S,x,k,T,b)=>{let w=0;const D=d.length;let P=c.length-1,F=D-1;for(;w<=P&&w<=F;){const M=c[w],B=d[w]=b?st(d[w]):Ue(d[w]);if(qt(M,B))A(M,B,m,null,S,x,k,T,b);else break;w++}for(;w<=P&&w<=F;){const M=c[P],B=d[F]=b?st(d[F]):Ue(d[F]);if(qt(M,B))A(M,B,m,null,S,x,k,T,b);else break;P--,F--}if(w>P){if(w<=F){const M=F+1,B=MF)for(;w<=P;)de(c[w],S,x,!0),w++;else{const M=w,B=w,G=new Map;for(w=B;w<=F;w++){const ue=d[w]=b?st(d[w]):Ue(d[w]);ue.key!=null&&G.set(ue.key,w)}let q,ie=0;const ce=F-B+1;let pe=!1,Ee=0;const Ze=new Array(ce);for(w=0;w=ce){de(ue,S,x,!0);continue}let Oe;if(ue.key!=null)Oe=G.get(ue.key);else for(q=B;q<=F;q++)if(Ze[q-B]===0&&qt(ue,d[q])){Oe=q;break}Oe===void 0?de(ue,S,x,!0):(Ze[Oe-B]=w+1,Oe>=Ee?Ee=Oe:pe=!0,A(ue,d[Oe],m,null,S,x,k,T,b),ie++)}const Kt=pe?ur(Ze):Ft;for(q=Kt.length-1,w=ce-1;w>=0;w--){const ue=B+w,Oe=d[ue],hs=d[ue+1],gs=ue+1{const{el:x,type:k,transition:T,children:b,shapeFlag:w}=c;if(w&6){je(c.component.subTree,d,m,C);return}if(w&128){c.suspense.move(d,m,C);return}if(w&64){k.move(c,d,m,pt);return}if(k===oe){n(x,d,m);for(let P=0;PT.enter(x),S));else{const{leave:P,delayLeave:F,afterLeave:M}=T,B=()=>{c.ctx.isUnmounted?l(x):n(x,d,m)},G=()=>{const q=x._isLeaving||!!x[sn];x._isLeaving&&x[sn](!0),T.persisted&&!q?B():P(x,()=>{B(),M&&M()})};F?F(x,B,G):G()}else n(x,d,m)},de=(c,d,m,C=!1,S=!1)=>{const{type:x,props:k,ref:T,children:b,dynamicChildren:w,shapeFlag:D,patchFlag:P,dirs:F,cacheIndex:M,memo:B}=c;if(P===-2&&(S=!1),T!=null&&(it(),Zt(T,null,m,c,!0),ot()),M!=null&&(d.renderCache[M]=void 0),D&256){d.ctx.deactivate(c);return}const G=D&1&&F,q=!Qt(c);let ie;if(q&&(ie=k&&k.onVnodeBeforeUnmount)&&$e(ie,d,c),D&6)Ut(c.component,m,C);else{if(D&128){c.suspense.unmount(m,C);return}G&&wt(c,null,d,"beforeUnmount"),D&64?c.type.remove(c,d,m,pt,C):w&&!w.hasOnce&&(x!==oe||P>0&&P&64)?mt(w,d,m,!1,!0):(x===oe&&P&384||!S&&D&16)&&mt(b,d,m),C&&At(c)}const ce=B!=null&&M==null;(q&&(ie=k&&k.onVnodeUnmounted)||G||ce)&&Te(()=>{ie&&$e(ie,d,c),G&&wt(c,null,d,"unmounted"),ce&&(c.el=null)},m)},At=c=>{const{type:d,el:m,anchor:C,transition:S}=c;if(d===oe){ds(m,C);return}if(d===ks){N(c);return}const x=()=>{l(m),S&&!S.persisted&&S.afterLeave&&S.afterLeave()};if(c.shapeFlag&1&&S&&!S.persisted){const{leave:k,delayLeave:T}=S,b=()=>k(m,x);T?T(c.el,x,b):b()}else x()},ds=(c,d)=>{let m;for(;c!==d;)m=R(c),l(c),c=m;l(d)},Ut=(c,d,m)=>{const{bum:C,scope:S,job:x,subTree:k,um:T,m:b,a:w}=c;tl(b),tl(w),C&&Cs(C),S.stop(),x&&(x.flags|=8,de(k,c,d,m)),T&&Te(T,d),Te(()=>{c.isUnmounted=!0},d)},mt=(c,d,m,C=!1,S=!1,x=0)=>{for(let k=x;k{if(c.shapeFlag&6)return Xe(c.component.subTree);if(c.shapeFlag&128)return c.suspense.next();const d=R(c.anchor||c.el),m=d&&d[ko];return m?R(m):d};let dt=!1;const ps=(c,d,m)=>{let C;c==null?d._vnode&&(de(d._vnode,null,null,!0),C=d._vnode.component):A(d._vnode||null,c,d,null,null,null,m),d._vnode=c,dt||(dt=!0,Wn(C),zl(),dt=!1)},pt={p:A,um:de,m:je,r:At,mt:ft,mc:Ce,pc:X,pbc:Ge,n:Xe,o:e};return{render:ps,hydrate:void 0,createApp:zo(ps)}}function ln({type:e,props:t},s){return s==="svg"&&e==="foreignObject"||s==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:s}function St({effect:e,job:t},s){s?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function cr(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function vi(e,t,s=!1){const n=e.children,l=t.children;if(L(n)&&L(l))for(let i=0;i>1,e[s[a]]0&&(t[n]=s[i-1]),s[i]=n)}}for(i=s.length,r=s[i-1];i-- >0;)s[i]=r,r=t[r];return s}function _i(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:_i(t)}function tl(e){if(e)for(let t=0;te.__isSuspense;function fr(e,t){t&&t.pendingBranch?L(e)?t.effects.push(...e):t.effects.push(e):yo(e)}const oe=Symbol.for("v-fgt"),qs=Symbol.for("v-txt"),at=Symbol.for("v-cmt"),ks=Symbol.for("v-stc"),Et=[];let ke=null;function E(e=!1){Et.push(ke=e?null:[])}function yi(){Et.pop(),ke=Et[Et.length-1]||null}let ls=1;function sl(e,t=!1){ls+=e,e<0&&ke&&t&&(ke.hasOnce=!0)}function xi(e){return e.dynamicChildren=ls>0?ke||Ft:null,yi(),ls>0&&ke&&ke.push(e),e}function O(e,t,s,n,l,i){return xi(o(e,t,s,n,l,i,!0))}function dr(e,t,s,n,l){return xi(ze(e,t,s,n,l,!0))}function wi(e){return e?e.__v_isVNode===!0:!1}function qt(e,t){return e.type===t.type&&e.key===t.key}const Si=({key:e})=>e??null,Es=({ref:e,ref_key:t,ref_for:s})=>(typeof e=="number"&&(e=""+e),e!=null?re(e)||me(e)||j(e)?{i:Re,r:e,k:t,f:!!s}:e:null);function o(e,t=null,s=null,n=0,l=null,i=e===oe?0:1,r=!1,a=!1){const u={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&Si(t),ref:t&&Es(t),scopeId:Gl,slotScopeIds:null,children:s,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:i,patchFlag:n,dynamicProps:l,dynamicChildren:null,appContext:null,ctx:Re};return a?(Is(u,s),i&128&&e.normalize(u)):s&&(u.shapeFlag|=re(s)?8:16),ls>0&&!r&&ke&&(u.patchFlag>0||i&6)&&u.patchFlag!==32&&ke.push(u),u}const ze=pr;function pr(e,t=null,s=null,n=0,l=null,i=!1){if((!e||e===Vo)&&(e=at),wi(e)){const a=Vt(e,t,!0);return s&&Is(a,s),ls>0&&!i&&ke&&(a.shapeFlag&6?ke[ke.indexOf(e)]=a:ke.push(a)),a.patchFlag=-2,a}if(Tr(e)&&(e=e.__vccOpts),t){t=hr(t);let{class:a,style:u}=t;a&&!re(a)&&(t.class=Q(a)),Z(u)&&(An(u)&&!L(u)&&(u=be({},u)),t.style=$s(u))}const r=re(e)?1:bi(e)?128:Us(e)?64:Z(e)?4:j(e)?2:0;return o(e,t,s,n,l,r,i,!0)}function hr(e){return e?An(e)||ui(e)?be({},e):e:null}function Vt(e,t,s=!1,n=!1){const{props:l,ref:i,patchFlag:r,children:a,transition:u}=e,h=t?vr(l||{},t):l,p={__v_isVNode:!0,__v_skip:!0,type:e.type,props:h,key:h&&Si(h),ref:t&&t.ref?s&&i?L(i)?i.concat(Es(t)):[i,Es(t)]:Es(t):i,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:a,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==oe?r===-1?16:r|16:r,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:u,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&Vt(e.ssContent),ssFallback:e.ssFallback&&Vt(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return u&&n&&Mn(p,u.clone(p)),p}function Y(e=" ",t=0){return ze(qs,null,e,t)}function gr(e,t){const s=ze(ks,null,e);return s.staticCount=t,s}function he(e="",t=!1){return t?(E(),dr(at,null,e)):ze(at,null,e)}function Ue(e){return e==null||typeof e=="boolean"?ze(at):L(e)?ze(oe,null,e.slice()):wi(e)?st(e):ze(qs,null,String(e))}function st(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:Vt(e)}function Is(e,t){let s=0;const{shapeFlag:n}=e;if(t==null)t=null;else if(L(t))s=16;else if(typeof t=="object")if(n&65){const l=t.default;l&&(l._c&&(l._d=!1),Is(e,l()),l._c&&(l._d=!0));return}else{s=32;const l=t._;!l&&!ui(t)?t._ctx=Re:l===3&&Re&&(Re.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else if(j(t)){if(n&65){Is(e,{default:t});return}t={default:t,_ctx:Re},s=32}else t=String(t),n&64?(s=16,t=[Y(t)]):s=8;e.children=t,e.shapeFlag|=s}function vr(...e){const t={};for(let s=0;swe||Re;let Fs,is;{const e=Vs(),t=(s,n)=>{let l;return(l=e[s])||(l=e[s]=[]),l.push(n),i=>{l.length>1?l.forEach(r=>r(i)):l[0](i)}};Fs=t("__VUE_INSTANCE_SETTERS__",s=>we=s),is=t("__VUE_SSR_SETTERS__",s=>os=s)}const us=e=>{const t=we;return Fs(e),e.scope.on(),()=>{e.scope.off(),Fs(t)}},nl=()=>{we&&we.scope.off(),Fs(null)};function Ci(e){return e.vnode.shapeFlag&4}let os=!1;function xr(e,t=!1,s=!1){t&&is(t);const{props:n,children:l}=e.vnode,i=Ci(e);tr(e,n,i,t),ir(e,l,s||t);const r=i?wr(e,t):void 0;return t&&is(!1),r}function wr(e,t){const s=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,$o);const{setup:n}=s;if(n){it();const l=e.setupContext=n.length>1?Cr(e):null,i=us(e),r=cs(n,e,0,[e.props,l]),a=xl(r);if(ot(),i(),(a||e.sp)&&!Qt(e)&&Ql(e),a){if(r.then(nl,nl),t)return r.then(u=>{is(!0);try{ll(e,u,t)}finally{is(!1)}}).catch(u=>{Bs(u,e,0)});e.asyncDep=r}else ll(e,r)}else Ti(e)}function ll(e,t,s){j(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:Z(t)&&(e.setupState=Ul(t)),Ti(e)}function Ti(e,t,s){const n=e.type;e.render||(e.render=n.render||qe);{const l=us(e);it();try{Ho(e)}finally{ot(),l()}}}const Sr={get(e,t){return _e(e,"get",""),e[t]}};function Cr(e){const t=s=>{e.exposed=s||{}};return{attrs:new Proxy(e.attrs,Sr),slots:e.slots,emit:e.emit,expose:t}}function zs(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(Ul(ao(e.exposed)),{get(t,s){if(s in t)return t[s];if(s in es)return es[s](e)},has(t,s){return s in t||s in es}})):e.proxy}function Tr(e){return j(e)&&"__vccOpts"in e}const ae=(e,t)=>go(e,t,os),kr="3.5.41";/** -* @vue/runtime-dom v3.5.41 -* (c) 2018-present Yuxi (Evan) You and Vue contributors -* @license MIT -**/let mn;const il=typeof window<"u"&&window.trustedTypes;if(il)try{mn=il.createPolicy("vue",{createHTML:e=>e})}catch{}const ki=mn?e=>mn.createHTML(e):e=>e,Er="http://www.w3.org/2000/svg",Or="http://www.w3.org/1998/Math/MathML",tt=typeof document<"u"?document:null,ol=tt&&tt.createElement("template"),Pr={insert:(e,t,s)=>{t.insertBefore(e,s||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,s,n)=>{const l=t==="svg"?tt.createElementNS(Er,e):t==="mathml"?tt.createElementNS(Or,e):s?tt.createElement(e,{is:s}):tt.createElement(e);return e==="select"&&n&&n.multiple!=null&&l.setAttribute("multiple",n.multiple),l},createText:e=>tt.createTextNode(e),createComment:e=>tt.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>tt.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,s,n,l,i){const r=s?s.previousSibling:t.lastChild;if(l&&(l===i||l.nextSibling))for(;t.insertBefore(l.cloneNode(!0),s),!(l===i||!(l=l.nextSibling)););else{ol.innerHTML=ki(n==="svg"?`${e}`:n==="mathml"?`${e}`:e);const a=ol.content;if(n==="svg"||n==="mathml"){const u=a.firstChild;for(;u.firstChild;)a.appendChild(u.firstChild);a.removeChild(u)}t.insertBefore(a,s)}return[r?r.nextSibling:t.firstChild,s?s.previousSibling:t.lastChild]}},Ar=Symbol("_vtc");function Rr(e,t,s){const n=e[Ar];n&&(t=(t?[t,...n]:[...n]).join(" ")),t==null?e.removeAttribute("class"):s?e.setAttribute("class",t):e.className=t}const rl=Symbol("_vod"),Mr=Symbol("_vsh"),Ir=Symbol(""),Fr=/(?:^|;)\s*display\s*:/;function Dr(e,t,s){const n=e.style,l=re(s);let i=!1;if(s&&!l){if(t)if(re(t))for(const r of t.split(";")){const a=r.slice(0,r.indexOf(":")).trim();s[a]==null&&Jt(n,a,"")}else for(const r in t)s[r]==null&&Jt(n,r,"");for(const r in s){r==="display"&&(i=!0);const a=s[r];a!=null?Lr(e,r,!re(t)&&t?t[r]:void 0,a)||Jt(n,r,a):Jt(n,r,"")}}else if(l){if(t!==s){const r=n[Ir];r&&(s+=";"+r),n.cssText=s,i=Fr.test(s)}}else t&&e.removeAttribute("style");rl in e&&(e[rl]=i?n.display:"",e[Mr]&&(n.display="none"))}const al=/\s*!important$/;function Jt(e,t,s){if(L(s))s.forEach(n=>Jt(e,t,n));else if(s==null&&(s=""),t.startsWith("--"))e.setProperty(t,s);else{const n=Nr(e,t);al.test(s)?e.setProperty(Ot(n),s.replace(al,""),"important"):e[n]=s}}const cl=["Webkit","Moz","ms"],on={};function Nr(e,t){const s=on[t];if(s)return s;let n=Ie(t);if(n!=="filter"&&n in e)return on[t]=n;n=Cl(n);for(let l=0;lrn||(Ur.then(()=>rn=0),rn=Date.now());function Wr(e,t){const s=n=>{if(!n._vts)n._vts=Date.now();else if(n._vts<=s.attached)return;const l=s.value;if(L(l)){const i=n.stopImmediatePropagation;n.stopImmediatePropagation=()=>{i.call(n),n._stopped=!0};const r=l.slice(),a=[n];for(let u=0;ue.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,qr=(e,t,s,n,l,i)=>{const r=l==="svg";t==="class"?Rr(e,n,r):t==="style"?Dr(e,s,n):Ds(t)?Ns(t)||Vr(e,t,s,n,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):zr(e,t,n,r))?(dl(e,t,n),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&fl(e,t,n,r,i,t!=="value")):e._isVueCE&&(Jr(e,t)||e._def.__asyncLoader&&(/[A-Z]/.test(t)||!re(n)))?dl(e,Ie(t),n,i,t):(t==="true-value"?e._trueValue=n:t==="false-value"&&(e._falseValue=n),fl(e,t,n,r))};function zr(e,t,s,n){if(n)return!!(t==="innerHTML"||t==="textContent"||t in e&&hl(t)&&j(s));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="autocorrect"||t==="sandbox"&&e.tagName==="IFRAME"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const l=e.tagName;if(l==="IMG"||l==="VIDEO"||l==="CANVAS"||l==="SOURCE")return!1}return hl(t)&&re(s)?!1:t in e}function Jr(e,t){const s=e._def.props;if(!s)return!1;const n=Ie(t);return Array.isArray(s)?s.some(l=>Ie(l)===n):Object.keys(s).some(l=>Ie(l)===n)}const $t=e=>{const t=e.props["onUpdate:modelValue"]||!1;return L(t)?s=>Cs(t,s):t};function Gr(e){e.target.composing=!0}function gl(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const We=Symbol("_assign"),ws=Symbol("_initialValue");function an(e,t,s){return t&&(e=e.trim()),s&&(e=js(e)),e}const Ss={created(e,{modifiers:{lazy:t,trim:s,number:n}},l){e.parentNode&&(e.type==="text"?e[ws]=e.defaultValue.replace(/[\r\n]/g,""):e.type==="textarea"&&(e[ws]=e.defaultValue.replace(/\r\n?/g,` -`))),e[We]=$t(l);const i=n||l.props&&l.props.type==="number";gt(e,t?"change":"input",r=>{r.target.composing||e[We](an(e.value,s,i))}),(s||i)&>(e,"change",()=>{e.value=an(e.value,s,i)}),t||(gt(e,"compositionstart",Gr),gt(e,"compositionend",gl),gt(e,"change",gl))},mounted(e,{value:t,modifiers:{trim:s,number:n}}){const l=t??"",i=e[ws];delete e[ws],i!==void 0&&(e.type==="text"||e.type==="textarea")&&e.value!==i?e[We](an(e.value,s,n)):e.value=l},beforeUpdate(e,{value:t,oldValue:s,modifiers:{lazy:n,trim:l,number:i}},r){if(e[We]=$t(r),e.composing)return;const a=(i||e.type==="number")&&!/^0\d/.test(e.value)?js(e.value):e.value,u=t??"";if(a===u)return;const h=e.getRootNode();(h instanceof Document||h instanceof ShadowRoot)&&h.activeElement===e&&e.type!=="range"&&(n&&t===s||l&&e.value.trim()===u)||(e.value=u)}},vl={deep:!0,created(e,t,s){e[We]=$t(s),gt(e,"change",()=>{const n=e._modelValue,l=rs(e),i=e.checked,r=e[We];if(L(n)){const a=wn(n,l),u=a!==-1;if(i&&!u)r(n.concat(l));else if(!i&&u){const h=[...n];h.splice(a,1),r(h)}}else if(Ht(n)){const a=new Set(n);i?a.add(l):a.delete(l),r(a)}else r(Ei(e,i))})},mounted:_l,beforeUpdate(e,t,s){e[We]=$t(s),_l(e,t,s)}};function _l(e,{value:t,oldValue:s},n){e._modelValue=t;let l;if(L(t))l=wn(t,n.props.value)>-1;else if(Ht(t))l=t.has(n.props.value);else{if(t===s)return;l=Bt(t,Ei(e,!0))}e.checked!==l&&(e.checked=l)}const Yr={deep:!0,created(e,{value:t,modifiers:{number:s}},n){e._modelValue=t,gt(e,"change",()=>{const l=Array.prototype.filter.call(e.options,i=>i.selected).map(i=>s?js(rs(i)):rs(i));e[We](e.multiple?Ht(e._modelValue)?new Set(l):l:l[0]),e._assigning=!0,Wl(()=>{e._assigning=!1})}),e[We]=$t(n)},mounted(e,{value:t}){ml(e,t)},beforeUpdate(e,{value:t},s){e._modelValue=t,e[We]=$t(s)},updated(e,{value:t}){e._assigning||ml(e,t)}};function ml(e,t){const s=e.multiple,n=L(t);if(!(s&&!n&&!Ht(t))){for(let l=0,i=e.options.length;lString(h)===String(a)):r.selected=wn(t,a)>-1}else r.selected=t.has(a);else if(Bt(rs(r),t)){e.selectedIndex!==l&&(e.selectedIndex=l);return}}!s&&e.selectedIndex!==-1&&(e.selectedIndex=-1)}}function rs(e){return"_value"in e?e._value:e.value}function Ei(e,t){const s=t?"_trueValue":"_falseValue";return s in e?e[s]:t}const Xr=["ctrl","shift","alt","meta"],Zr={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>Xr.some(s=>e[`${s}Key`]&&!t.includes(s))},Qr=(e,t)=>{if(!e)return e;const s=e._withMods||(e._withMods={}),n=t.join(".");return s[n]||(s[n]=((l,...i)=>{for(let r=0;r{const t=ta().createApp(...e),{mount:s}=t;return t.mount=n=>{const l=la(n);if(!l)return;const i=t._component;!j(i)&&!i.render&&!i.template&&(i.template=l.innerHTML),l.nodeType===1&&(l.textContent="");const r=s(l,!1,na(l));return l instanceof Element&&(l.removeAttribute("v-cloak"),l.setAttribute("data-v-app","")),r},t});function na(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function la(e){return re(e)?document.querySelector(e):e}const ia={class:"app-shell"},oa={class:"content",id:"overview"},ra={class:"topbar"},aa={class:"topbar-meta"},ca={class:"as-of"},ua={key:0,class:"state-card"},fa={key:1,class:"state-card error-state"},da={class:"kpi-grid","aria-label":"Signal summary"},pa={class:"kpi-card accent-card"},ha={class:"kpi-value"},ga={class:"kpi-foot"},va={class:"long-count"},_a={class:"short-count"},ma={class:"neutral-count"},ba={class:"kpi-card"},ya={class:"kpi-value"},xa={class:"kpi-foot"},wa={class:"panel theme-panel",id:"themes"},Sa={class:"panel-header signal-header"},Ca={class:"status-tag"},Ta={class:"theme-grid"},ka={class:"theme-card-head"},Ea={class:"theme-chip"},Oa={class:"theme-label-th"},Pa={class:"theme-surprise"},Aa={class:"theme-surprise-value"},Ra={class:"theme-read"},Ma={key:0,class:"theme-read-value"},Ia={key:1,class:"theme-read-value"},Fa={key:2,class:"theme-read-value"},Da={key:3,class:"theme-read-value"},Na={key:0,class:"theme-narrative"},La={key:0,class:"macro-panel"},ja={class:"macro-chips"},Va={class:"macro-chip"},$a={class:"macro-chip"},Ha={class:"macro-chip"},Ba={class:"macro-chip"},Ua={class:"macro-chip"},Ka={class:"panel stock-panel",id:"stocks"},Wa={class:"panel-header signal-header"},qa={class:"stock-controls"},za={class:"toggle-filter"},Ja={key:0,class:"empty-research"},Ga={key:1,class:"table-wrap"},Ya={class:"factor-table"},Xa=["onClick"],Za={key:1,class:"muted-cell"},Qa={class:"combined-cell"},ec={class:"symbol-name"},tc={key:0,class:"muted-cell"},sc={class:"score-cell"},nc={key:0,class:"dividend-dot",title:"จ่ายปันผล"},lc={class:"panel lineage-panel",id:"lineage"},ic={class:"panel-header signal-header"},oc={class:"status-tag"},rc={class:"table-wrap"},ac={class:"source-table"},cc={class:"source-name"},uc={class:"muted-cell"},fc={class:"muted-cell"},dc={class:"muted-cell"},pc={class:"muted-cell"},hc={class:"panel sim-panel",id:"simulation"},gc={class:"panel-header signal-header"},vc={class:"status-tag neutral-tag"},_c={class:"sim-controls"},mc={class:"sim-field"},bc={class:"sim-field"},yc=["disabled"],xc={key:0,class:"sim-result"},wc={class:"sim-sums"},Sc={class:"sim-sum"},Cc={class:"sim-sum"},Tc={class:"sim-note"},kc={class:"sim-buckets"},Ec={class:"sim-bucket"},Oc={class:"sim-order-table"},Pc={key:0},Ac={class:"muted-cell"},Rc={class:"score-cell"},Mc={class:"score-cell"},Ic={key:1},Fc={class:"sim-bucket"},Dc={class:"sim-order-table"},Nc={key:0},Lc={class:"muted-cell"},jc={class:"score-cell"},Vc={class:"score-cell"},$c={key:1},Hc={class:"sim-bucket"},Bc={class:"sim-order-table"},Uc={key:0},Kc={class:"muted-cell"},Wc={class:"score-cell"},qc={class:"score-cell"},zc={key:1},Jc={key:1,class:"empty-research"},Gc={key:2,class:"fwd-panel"},Yc={key:0,class:"empty-research muted-cell"},Xc={key:1,class:"source-table"},Zc={class:"muted-cell"},Qc={key:0,class:"status-tag warning-tag",title:"ใช้คะแนนปัจจุบัน ไม่ใช่ PIT"},eu={class:"positive-text"},tu={class:"muted-cell"},su=["onClick"],nu=["onClick"],lu={key:2,class:"muted-cell"},iu={class:"panel backtest-panel",id:"backtest"},ou={class:"backtest-controls"},ru={class:"checkbox-label",style:{display:"flex","align-items":"center",gap:"6px"}},au=["disabled"],cu={key:0,class:"state-card warning-state"},uu={class:"muted-cell",style:{"margin-top":"4px"}},fu={class:"muted-cell",style:{"margin-top":"2px"}},du={key:1,class:"state-card error-state"},pu={key:2,class:"backtest-results"},hu={class:"bt-kpi-grid"},gu={class:"bt-kpi"},vu={class:"bt-kpi"},_u={class:"bt-kpi"},mu={class:"positive-text"},bu={class:"bt-kpi"},yu={class:"negative-text"},xu={class:"bt-kpi"},wu={class:"bt-kpi"},Su={class:"bt-kpi"},Cu={class:"bt-meta muted-cell"},Tu={key:0,class:"bt-meta"},ku={key:1,class:"bt-meta muted-cell"},Eu={key:2,class:"bt-holdings"},Ou={class:"source-table",style:{"margin-top":"6px"}},Pu={class:"muted-cell"},Au={key:3,class:"empty-research"},Ru={key:4,class:"bt-history"},Mu={class:"source-table"},Iu={key:0,class:"status-tag warning-tag",title:"ใช้คะแนนปัจจุบันย้อนหลัง ไม่ใช่ point-in-time"},Fu={class:"positive-text"},Du=["title"],Nu={class:"muted-cell"},Lu={class:"modal-card"},ju={class:"modal-head"},Vu={key:0,class:"empty-research"},$u={key:1,class:"state-card error-state"},Hu={key:2,class:"modal-body"},Bu={class:"modal-section"},Uu={key:0,class:"modal-themes"},Ku={class:"contrib-name"},Wu={key:0,class:"contrib-calc"},qu={key:1,class:"muted-cell"},zu={key:1,class:"muted-cell"},Ju={class:"modal-section"},Gu={class:"fund-grid"},Yu={class:"modal-sub"},Xu={class:"modal-section"},Zu={class:"calc-box"},Qu={class:"calc-line"},ef={class:"calc-step-head"},tf={class:"calc-step-note"},sf={key:0,class:"calc-z"},nf={class:"modal-sub"},lf={__name:"App",setup(e){const t=$(null),s=$(null),n=$(null),l=$(null),i=$(null),r=$(null),a=$(1e6),u=$(null),h=$(null),p=$(!1),y=$(""),R=$(""),I=$(1e6),U=$(!1),A=$(null),se=$([]),H=$(null),V=$(!0),K=$("backtest"),N=$(!1),W=$(null),Se=$(!1),ne=$("signal_score"),Ce=$("desc"),Pt=$({entries:[]}),Ge=$(null),vt=$(null),ut=$(!0),Ye=$(""),ft=$(""),fs=$(!1),fe=$("token"),le=$(!0),X=$(""),Le=ae(()=>{var v;return((v=l.value)==null?void 0:v.factors)??[]}),_t=ae(()=>{var v;return((v=r.value)==null?void 0:v.themes)??[]}),je=ae(()=>{var v;return((v=r.value)==null?void 0:v.sources)??[]}),de=ae(()=>{var v;return((v=r.value)==null?void 0:v.macro)??{}}),At=ae(()=>je.value.length),ds=ae(()=>{var v,f;return((f=(v=r.value)==null?void 0:v.source_summary)==null?void 0:f.factor_keys)??At.value}),Ut=ae(()=>{var v;return((v=r.value)==null?void 0:v.available)??!1}),mt=ae(()=>{var v;return((v=r.value)==null?void 0:v.board)??Le.value}),Xe=ae(()=>{const v={};for(const f of mt.value)v[f.symbol]=f;return v}),dt=ae(()=>{var f;const v=(f=t.value)==null?void 0:f.signal_summary;return{long:(v==null?void 0:v.long)??0,short:(v==null?void 0:v.short)??0,neutral:(v==null?void 0:v.neutral)??0,total:(v==null?void 0:v.total)??0}}),ps=v=>({monthly:"รายเดือน",quarterly:"รายไตรมาส",annual:"รายปี",daily:"รายวัน"})[v]||v,pt=ae(()=>{const v={};for(const f of _t.value)v[f.id]=f.label_th;return v});function Js(v){const f=Xe.value[v];return((f==null?void 0:f.themes)??[]).map(Pe=>pt.value[Pe]||Pe)}const c=ae(()=>{var v;return((v=l.value)==null?void 0:v.available)??!1}),d=ae(()=>{var v;return((v=l.value)==null?void 0:v.dividend_count)??0}),m=ae(()=>{var v;return((v=i.value)==null?void 0:v.combined_count)??0}),C=ae(()=>{let v=Le.value;return Se.value&&(v=v.filter(f=>f.is_dividend)),v});function S(v,f){var ve;return f==="signal_score"?v.signal_score??(v.signal_side==="LONG"?9999:0):f==="combined"?((ve=Xe.value[v.symbol])==null?void 0:ve.combined)??-9999:f==="symbol"?v.symbol:f==="dividend_yield"?v.dividend_yield??-1:f==="eps_growth_yoy"?v.eps_growth_yoy??-1:f==="pe"?v.pe??0:f==="eps"?v.eps??0:f==="pbv"?v.pbv??0:f==="roe"?v.roe??0:v[f]}const x=ae(()=>{const v=[...C.value],f=Ce.value==="asc"?1:-1;return v.sort((ve,Pe)=>{const Ve=S(ve,ne.value),Qe=S(Pe,ne.value);return typeof Ve=="string"?Ve.localeCompare(Qe)*f:Ve===Qe?ve.symbol.localeCompare(Pe.symbol):Ve==null?1:Qe==null?-1:(Ve-Qe)*f}),v});function k(v){ne.value===v?Ce.value=Ce.value==="asc"?"desc":"asc":(ne.value=v,Ce.value="desc")}function T(v){return ne.value!==v?"":Ce.value==="asc"?"↑":"↓"}function b(v,f=2){return Number(v??0).toFixed(f)}function w(v){return v==="dated_ledger"}function D(v){return w(v)?{label:"ตามวันจริง",cls:"status-tag",style:"background:#1a7f37;color:#fff"}:v==="dps_annual_proxy"?{label:"Proxy (ต่อหุ้น)",cls:"status-tag warning-tag"}:{label:"Proxy",cls:"status-tag warning-tag"}}function P(v){return w(v)?"ปันผลตามวันจริงจาก ledger (ex-date × จำนวนหุ้น) — กระแสเงินสดจริง":v==="dps_annual_proxy"?"ประมาณการปันผลต่อหุ้น (DPS ล่าสุด × จำนวนหุ้น) ไม่ใช่กระแสเงินสดตามวันจริง":"ประมาณจาก dividend yield ของพอร์ตสุดท้าย ไม่ใช่กระแสเงินสดปันผลจริง"}function F(v){return v?new Date(v).toLocaleString("en-GB",{day:"2-digit",month:"short",year:"numeric",hour:"2-digit",minute:"2-digit"}):"—"}async function M(v,f){const ve=await fetch(v,f);if(!ve.ok){const Pe=await ve.json().catch(()=>({}));throw new Error(Pe.error||`Request failed: ${ve.status}`)}return ve.json()}async function B(){const v=await fetch("/api/v1/backtest/tourism?min_events=12"),f=await v.json().catch(()=>({}));if(![200,409].includes(v.status))throw new Error(f.error||`Request failed: ${v.status}`);return f}async function G(){const v=await fetch("/api/v1/research/tourism/latest");if(v.status===404)return null;const f=await v.json().catch(()=>({}));if(!v.ok)throw new Error(f.error||`Request failed: ${v.status}`);return f}const q=ae(()=>{var v;return((v=W.value)==null?void 0:v.orders)??[]}),ie=ae(()=>{var v;return((v=W.value)==null?void 0:v.invested)??0}),ce=ae(()=>{var v;return((v=W.value)==null?void 0:v.unallocated_cash)??0}),pe=v=>q.value.filter(f=>f.bucket===v);async function Ee(){N.value=!0,W.value=null;try{K.value==="forward"?(W.value=await M("/api/v1/forward",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({capital:Number(a.value),use_pit:!1})}),await ue()):W.value=await M("/api/v1/simulation",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({capital:Number(a.value),mode:"backtest"})})}catch(v){ft.value=v.message}finally{N.value=!1}}const Ze=$([]),Kt=$(!1);async function ue(){Kt.value=!0;try{const v=await M("/api/v1/forward");Ze.value=v.runs??[]}catch(v){ft.value=v.message}finally{Kt.value=!1}}async function Oe(v){try{await M(`/api/v1/forward/${v}/mark`,{method:"POST"}),await ue()}catch(f){ft.value=f.message}}async function hs(v){try{await M(`/api/v1/forward/${v}/mature`,{method:"POST"}),await ue()}catch(f){ft.value=f.message}}async function gs(){ut.value=!0,Ye.value="";try{const[v,f,ve,Pe,Ve,Qe,vs,yt,_s,ms]=await Promise.all([M("/api/v1/dashboard/summary"),M("/api/v1/factors/tourism/observations"),M("/api/v1/signals"),M("/api/v1/factors"),M("/api/v1/themes"),M("/api/v1/dashboard"),M("/api/v1/paper/ledger"),M("/api/v1/auth/paper",{credentials:"include"}),B(),G()]);t.value=v,s.value=f,n.value=ve,l.value=Pe,i.value=Ve,r.value=Qe,Pt.value=vs,fs.value=!!yt.authenticated,fe.value=yt.mode||"token",le.value=yt.enabled!==!1,X.value=yt.warning||"",Ge.value=_s,vt.value=ms,await ue()}catch(v){Ye.value=v.message}finally{ut.value=!1}}async function Oi(v){u.value=v,h.value=null,p.value=!0;try{h.value=await M(`/api/v1/symbols/${v}`)}catch(f){h.value={error:f.message,symbol:v}}finally{p.value=!1}}function Nn(){u.value=null,h.value=null}async function Pi(){try{const v=await M("/api/v1/backtest/readiness");H.value=v,!y.value&&v.recommended_start&&(y.value=v.recommended_start),!R.value&&v.recommended_end&&(R.value=v.recommended_end)}catch{H.value=null}}async function Ai(){U.value=!0,A.value=null;try{A.value=await M("/api/v1/backtest/run",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({start:y.value,end:R.value,capital:Number(I.value),use_ledger:V.value})}),await Ln()}catch(v){A.value={error:v.message}}finally{U.value=!1}}async function Ln(){try{se.value=(await M("/api/v1/backtest/run")).runs||[]}catch{se.value=[]}}const bt=v=>v!=null?v>=0?"positive-text":"negative-text":"";return ti(async()=>{await gs(),await Promise.all([Ln(),Pi()])}),(v,f)=>{var ve,Pe,Ve,Qe,vs,yt,_s,ms,jn,Vn,$n;return E(),O("div",ia,[f[80]||(f[80]=gr('',1)),o("main",oa,[o("header",ra,[f[17]||(f[17]=o("div",null,[o("div",{class:"eyebrow"},"Alternative data · SET50"),o("h1",null,"SET50 Signal Lab"),o("p",{class:"subtitle"},"ภาพรวม alternative factors ไทย ไปจนถึงสัญญาณลงทุนที่อธิบายได้ — research + paper only")],-1)),o("div",aa,[o("div",{class:Q(["freshness-pill",Ut.value?"pill-live":"pill-fixture"])},[f[16]||(f[16]=o("span",{class:"freshness-dot"},null,-1)),Y(_(Ut.value?"ข้อมูลจริงจากแหล่งไทย":"ข้อมูลจำลอง (fixture)"),1)],2),o("div",ca,"ข้อมูล "+_(((ve=t.value)==null?void 0:ve.as_of)||"—"),1)])]),ut.value?(E(),O("div",ua,"กำลังโหลดข้อมูล…")):Ye.value?(E(),O("div",fa,_(Ye.value),1)):(E(),O(oe,{key:2},[o("section",da,[o("article",pa,[f[20]||(f[20]=o("div",{class:"kpi-label"},"สัญญาณที่ใช้งาน",-1)),o("div",ha,_(dt.value.long),1),o("div",ga,[o("span",va,_(dt.value.long)+" ซื้อ",1),f[18]||(f[18]=Y(" · ",-1)),o("span",_a,_(dt.value.short)+" ขาย",1),f[19]||(f[19]=Y(" · ",-1)),o("span",ma,_(dt.value.neutral)+" เป็นกลาง",1)])]),o("article",ba,[f[21]||(f[21]=o("div",{class:"kpi-label"},"แหล่งข้อมูลที่ใช้",-1)),o("div",ya,_(ds.value)+" ปัจจัย · "+_(At.value)+" แหล่ง",1),o("div",xa,"ข้อมูลจริงจากแหล่งไทย "+_(Ut.value?"(จริง)":"—"),1)])]),o("section",wa,[o("div",Sa,[f[22]||(f[22]=o("div",null,[o("div",{class:"section-kicker"},"ธีม"),o("h2",null,"ธีม (Themes)"),o("p",{class:"panel-subtitle"},"ภาพรวม alternative factors ของไทย — แต่ละธีมมีความถี่ข้อมูลต่างกัน (monthly / quarterly) ดังนั้นอย่าเทียบเป็นจุดเวลาเดียวกัน.")],-1)),o("span",Ca,"รวม "+_(m.value)+" symbols",1)]),o("div",Ta,[(E(!0),O(oe,null,Ae(_t.value,g=>(E(),O("article",{key:g.id,class:"theme-card"},[o("div",ka,[o("span",Ea,_(ps(g.frequency)),1),o("span",Oa,_(g.label_th),1)]),o("div",Pa,[f[23]||(f[23]=o("span",{class:"theme-surprise-label"},"ความต่าง (surprise)",-1)),o("span",Aa,_(g.surprise!=null?b(g.surprise,2)+"σ":"—"),1)]),o("div",Ra,[g.id==="auto_credit"&&g.read.new_car_sales_yoy!=null?(E(),O("div",Ma,_(b(g.read.new_car_sales_yoy))+"% YoY ยอดขายรถ",1)):g.id==="auto_credit"&&g.read.auto_npl_pct!=null?(E(),O("div",Ia,"NPL "+_(b(g.read.auto_npl_pct))+"%",1)):g.id==="refining_energy"&&(g.read.quarterly||g.read.net_profit)?(E(),O("div",Fa,"กำไรสุทธิ TOP (รายไตรมาส)")):g.id==="tourism"?(E(),O("div",Da,"signal tourism "+_(g.surprise!=null?b(g.surprise,2):"—")+"σ",1)):he("",!0)]),g.narrative?(E(),O("div",Na,_(g.narrative),1)):he("",!0)]))),128))]),Object.keys(de.value).length?(E(),O("div",La,[f[29]||(f[29]=o("div",{class:"section-kicker"},"ภาพรวมประเทศไทย",-1)),o("div",ja,[o("span",Va,[f[24]||(f[24]=Y("การบริโภคภาคเอกชน ",-1)),o("strong",null,_(de.value.private_consumption_yoy)+"%",1)]),o("span",$a,[f[25]||(f[25]=Y("การลงทุนเอกชน ",-1)),o("strong",null,_(de.value.private_investment_yoy)+"%",1)]),o("span",Ha,[f[26]||(f[26]=Y("เงินเฟ้อ ",-1)),o("strong",null,_(de.value.headline_inflation_yoy)+"%",1)]),o("span",Ba,[f[27]||(f[27]=Y("การว่างงาน ",-1)),o("strong",null,_(de.value.unemployment_pct)+"%",1)]),o("span",Ua,[f[28]||(f[28]=Y("นักท่องเที่ยว YTD ",-1)),o("strong",null,_(de.value.tourists_ytd_mn)+" ล้าน",1)])])])):he("",!0)]),o("section",Ka,[o("div",Wa,[f[30]||(f[30]=o("div",null,[o("div",{class:"section-kicker"},"ตารางหุ้น"),o("h2",null,"ตารางหุ้น"),o("p",{class:"panel-subtitle"},[Y("ตารางเดียวรวมทุกธีม — สัญญาณ + คะแนนรวม (60% ธีม / 40% พื้นฐาน) + มูลค่าพื้นฐานจาก Siamchart. เรียงได้โดยคลิกหัวตาราง; เปิด "),o("em",null,"เฉพาะหุ้นปันผล"),Y(" เพื่อกรองหุ้นที่จ่ายปันผล.")])],-1)),o("div",qa,[o("label",za,[xt(o("input",{type:"checkbox","onUpdate:modelValue":f[0]||(f[0]=g=>Se.value=g)},null,512),[[vl,Se.value]]),o("span",null,"เฉพาะหุ้นปันผล ("+_(d.value)+")",1)]),o("span",{class:Q(["status-tag",c.value?"":"warning-tag"])},_(c.value?"Siamchart ใช้งานได้":"ไม่มี factor"),3)])]),c.value?(E(),O("div",Ga,[o("table",Ya,[o("thead",null,[o("tr",null,[o("th",{class:Q(["sortable",{active:ne.value==="signal_score"}]),onClick:f[1]||(f[1]=g=>k("signal_score"))},"สัญญาณ "+_(T("signal_score")),3),o("th",{class:Q(["sortable",{active:ne.value==="combined"}]),onClick:f[2]||(f[2]=g=>k("combined")),title:"60% ธีม + 40% พื้นฐาน"},"คะแนนรวม (60/40) "+_(T("combined")),3),o("th",{class:Q(["sortable",{active:ne.value==="symbol"}]),onClick:f[3]||(f[3]=g=>k("symbol"))},"หุ้น "+_(T("symbol")),3),f[32]||(f[32]=o("th",null,"ธีม",-1)),o("th",{class:Q(["sortable",{active:ne.value==="pe"}]),onClick:f[4]||(f[4]=g=>k("pe"))},"P/E "+_(T("pe")),3),o("th",{class:Q(["sortable",{active:ne.value==="eps"}]),onClick:f[5]||(f[5]=g=>k("eps"))},"EPS "+_(T("eps")),3),o("th",{class:Q(["sortable",{active:ne.value==="eps_growth_yoy"}]),onClick:f[6]||(f[6]=g=>k("eps_growth_yoy"))},"EPS YoY "+_(T("eps_growth_yoy")),3),o("th",{class:Q(["sortable",{active:ne.value==="dividend_yield"}]),onClick:f[7]||(f[7]=g=>k("dividend_yield"))},"ปันผล % "+_(T("dividend_yield")),3),o("th",{class:Q(["sortable",{active:ne.value==="pbv"}]),onClick:f[8]||(f[8]=g=>k("pbv"))},"P/BV "+_(T("pbv")),3),o("th",{class:Q(["sortable",{active:ne.value==="roe"}]),onClick:f[9]||(f[9]=g=>k("roe"))},"ROE "+_(T("roe")),3)])]),o("tbody",null,[(E(!0),O(oe,null,Ae(x.value,g=>{var Rt;return E(),O("tr",{key:g.symbol,class:"clickable-row",onClick:Gs=>Oi(g.symbol)},[o("td",null,[g.signal_side?(E(),O("span",{key:0,class:Q(["side-pill",g.signal_side.toLowerCase()])},_(g.signal_side),3)):(E(),O("span",Za,"—"))]),o("td",Qa,_(((Rt=Xe.value[g.symbol])==null?void 0:Rt.combined)!=null?b(Xe.value[g.symbol].combined):"—"),1),o("td",null,[o("strong",ec,_(g.symbol),1)]),o("td",null,[(E(!0),O(oe,null,Ae(Js(g.symbol),Gs=>(E(),O("span",{key:Gs,class:"theme-tag"},_(Gs),1))),128)),Js(g.symbol).length?he("",!0):(E(),O("span",tc,"—"))]),o("td",sc,_(g.pe!=null?b(g.pe):"—"),1),o("td",null,_(g.eps!=null?b(g.eps):"—"),1),o("td",{class:Q(g.eps_growth_yoy>=0?"positive-text":"negative-text")},_(g.eps_growth_yoy!=null?(g.eps_growth_yoy>=0?"+":"")+b(g.eps_growth_yoy)+"%":"—"),3),o("td",{class:Q(g.dividend_yield>=0?"positive-text":"")},[Y(_(g.dividend_yield!=null?b(g.dividend_yield)+"%":"—"),1),g.is_dividend?(E(),O("span",nc,"●")):he("",!0)],2),o("td",null,_(g.pbv!=null?b(g.pbv):"—"),1),o("td",{class:Q(g.roe>=0?"positive-text":"negative-text")},_(g.roe!=null?b(g.roe)+"%":"—"),3)],8,Xa)}),128))])])])):(E(),O("div",Ja,[...f[31]||(f[31]=[Y("Siamchart snapshot ไม่อยู่บน disk. รัน ",-1),o("code",null,"collect_siamchart.py --group SET50 --with-info",-1),Y(" เพื่อเก็บข้อมูล.",-1)])]))]),o("section",lc,[o("div",ic,[f[33]||(f[33]=o("div",null,[o("div",{class:"section-kicker"},"ที่มาของข้อมูล"),o("h2",null,"แหล่งข้อมูลทั้งหมด"),o("p",{class:"panel-subtitle"},"รายการแหล่งข้อมูลจริงที่ใช้ — ดึงมาเมื่อใด และข้อมูลชุดไหน ข้อมูลทั้งหมดจากแหล่งไทย.")],-1)),o("span",oc,_(ds.value)+" ปัจจัย · "+_(At.value)+" แหล่ง",1)]),o("div",rc,[o("table",ac,[f[34]||(f[34]=o("thead",null,[o("tr",null,[o("th",null,"ข้อมูล"),o("th",null,"แหล่ง"),o("th",null,"ช่วงข้อมูล"),o("th",null,"ความถี่"),o("th",null,"อัปเดตครั้งต่อไป"),o("th",null,"อัปเดตล่าสุด")])],-1)),o("tbody",null,[(E(!0),O(oe,null,Ae(je.value,(g,Rt)=>(E(),O("tr",{key:Rt},[o("td",null,_(g.จาก||g.ขอบเขต),1),o("td",cc,_(g.แหล่ง),1),o("td",uc,_(g.ข้อมูล),1),o("td",fc,_(g.ความถี่||"—"),1),o("td",dc,_(g.อัปเดตครั้งต่อไป?F(g.อัปเดตครั้งต่อไป):"—"),1),o("td",pc,_(g.dึงมาเมื่อ?F(g.dึงมาเมื่อ):"—"),1)]))),128))])])])]),o("section",hc,[o("div",gc,[f[35]||(f[35]=o("div",null,[o("div",{class:"section-kicker"},"การจำลองการลงทุน"),o("h2",null,"จัดสรรทุน (Simulation)"),o("p",{class:"panel-subtitle"},"กรอกทุน และระบบจัดสรรตามสัดส่วน 50 / 20 / 30 — หุ้นที่ทำกำไรได้มากสุดแล้วจ่ายปันผล, หุ้นทำกำไรแต่ไม่ปันผล, และหุ้นปันผลสูงสุด (ไม่ซ้ำ) — ขั้นต่ำ 100 หุ้นต่อตัว.")],-1)),o("span",vc,_(W.value?"ใช้ได้":"รอใส่ทุน"),1)]),o("div",_c,[o("div",mc,[f[36]||(f[36]=o("label",null,"ทุน (บาท)",-1)),xt(o("input",{"onUpdate:modelValue":f[10]||(f[10]=g=>a.value=g),type:"number",min:"1000",step:"1000"},null,512),[[Ss,a.value]])]),o("div",bc,[f[38]||(f[38]=o("label",null,"โหมด",-1)),xt(o("select",{"onUpdate:modelValue":f[11]||(f[11]=g=>K.value=g)},[...f[37]||(f[37]=[o("option",{value:"backtest"},"Backtest",-1),o("option",{value:"forward"},"Forward test",-1)])],512),[[Yr,K.value]])]),o("button",{class:"primary-button",disabled:N.value,onClick:Ee},_(N.value?"กำลังคำนวณ…":"คำนวณการจัดสรร"),9,yc)]),W.value?(E(),O("div",xc,[o("div",wc,[o("div",Sc,[f[39]||(f[39]=o("span",null,"ลงทุนรวม",-1)),o("strong",null,_(b(ie.value,0))+" บาท",1)]),o("div",Cc,[f[40]||(f[40]=o("span",null,"เงินสดเหลือ",-1)),o("strong",null,_(b(ce.value,0))+" บาท",1)])]),o("div",Tc,_(W.value.data_note),1),o("div",kc,[o("div",Ec,[f[42]||(f[42]=o("div",{class:"sim-bucket-head"},[o("span",{class:"sim-bucket-tag b1"},"50%"),o("strong",null,"ทำกำไร + จ่ายปันผล")],-1)),o("table",Oc,[pe(1).length?(E(),O("tbody",Pc,[(E(!0),O(oe,null,Ae(pe(1),g=>(E(),O("tr",{key:"b1"+g.symbol},[o("td",null,_(g.symbol),1),o("td",Ac,"qty "+_(g.qty),1),o("td",Rc,"@ "+_(b(g.price)),1),o("td",Mc,_(b(g.notional,0)),1)]))),128))])):(E(),O("tbody",Ic,[...f[41]||(f[41]=[o("tr",null,[o("td",{class:"muted-cell"},"ไม่มีหุ้นที่เข้าเกณฑ์")],-1)])]))])]),o("div",Fc,[f[44]||(f[44]=o("div",{class:"sim-bucket-head"},[o("span",{class:"sim-bucket-tag b2"},"20%"),o("strong",null,"ทำกำไร ไม่ปันผล")],-1)),o("table",Dc,[pe(2).length?(E(),O("tbody",Nc,[(E(!0),O(oe,null,Ae(pe(2),g=>(E(),O("tr",{key:"b2"+g.symbol},[o("td",null,_(g.symbol),1),o("td",Lc,"qty "+_(g.qty),1),o("td",jc,"@ "+_(b(g.price)),1),o("td",Vc,_(b(g.notional,0)),1)]))),128))])):(E(),O("tbody",$c,[...f[43]||(f[43]=[o("tr",null,[o("td",{class:"muted-cell"},"ไม่มีหุ้นที่เข้าเกณฑ์")],-1)])]))])]),o("div",Hc,[f[46]||(f[46]=o("div",{class:"sim-bucket-head"},[o("span",{class:"sim-bucket-tag b3"},"30%"),o("strong",null,"ปันผลสูงสุด (ไม่ซ้ำ)")],-1)),o("table",Bc,[pe(3).length?(E(),O("tbody",Uc,[(E(!0),O(oe,null,Ae(pe(3),g=>(E(),O("tr",{key:"b3"+g.symbol},[o("td",null,_(g.symbol),1),o("td",Kc,"qty "+_(g.qty),1),o("td",Wc,"@ "+_(b(g.price)),1),o("td",qc,_(b(g.notional,0)),1)]))),128))])):(E(),O("tbody",zc,[...f[45]||(f[45]=[o("tr",null,[o("td",{class:"muted-cell"},"ไม่มีหุ้นที่เข้าเกณฑ์")],-1)])]))])])])])):he("",!0),W.value?he("",!0):(E(),O("div",Jc,"กด 'คำนวณการจัดสรร' เพื่อดูว่า 50/20/30 จัดสรรทุนของคุณไปที่หุ้นไหนบ้าง")),K.value==="forward"?(E(),O("div",Gc,[f[48]||(f[48]=o("div",{class:"section-kicker"},"Forward Test (Paper) — สัญญาณถูกตรึง ณ เวลาสร้าง",-1)),f[49]||(f[49]=o("p",{class:"panel-subtitle"},"สร้าง forward run → สัญญาณ (คะแนน) ถูก freeze ทันทีที่สร้าง แล้ว execute ด้วยราคาหลัง freeze. กด Mark ตามราคาล่าสุด, Mature เพื่อปิด run. เป็น Paper เท่านั้น.",-1)),Ze.value.length===0?(E(),O("div",Yc,"ยังไม่มี forward run — กด 'คำนวณการจัดสรร' ข้างบนเพื่อสร้าง")):(E(),O("table",Xc,[f[47]||(f[47]=o("thead",null,[o("tr",null,[o("th",null,"#"),o("th",null,"สถานะ"),o("th",null,"ทุน"),o("th",null,"ลงทุน"),o("th",null,"ถือ"),o("th",null,"ผลตอบแทน"),o("th",null,"ตรวจ")])],-1)),o("tbody",null,[(E(!0),O(oe,null,Ae(Ze.value.slice().reverse(),g=>(E(),O("tr",{key:g.id},[o("td",Zc,_(g.id.slice(0,12)),1),o("td",null,[o("span",{class:Q(["status-tag",g.status==="matured"?"warning-tag":g.status==="frozen"?"neutral-tag":"warning-tag"])},_(g.status),3),g.non_pit?(E(),O("span",Qc,"non-PIT")):he("",!0)]),o("td",null,_(b(g.capital,0)),1),o("td",eu,_(b(g.invested,0)),1),o("td",tu,_(Object.keys(g.holdings||{}).join(", ")||"—"),1),o("td",{class:Q(bt(g.net_return))},_(g.net_return!=null?(g.net_return*100).toFixed(2)+"%":"—"),3),o("td",null,[g.status!=="matured"?(E(),O("button",{key:0,class:"primary-btn",style:{padding:"2px 8px","margin-right":"4px"},onClick:Rt=>Oe(g.id)},"Mark",8,su)):he("",!0),g.status!=="matured"?(E(),O("button",{key:1,class:"primary-btn",style:{padding:"2px 8px"},onClick:Rt=>hs(g.id)},"Mature",8,nu)):(E(),O("span",lu,"ปิดแล้ว"))])]))),128))])]))])):he("",!0)]),o("section",iu,[f[66]||(f[66]=o("div",{class:"panel-header signal-header"},[o("div",null,[o("div",{class:"section-kicker"},"การย้อนทดสอบ"),o("h2",null,"Backtest (ย้อนทดสอบ)"),o("p",{class:"panel-subtitle"},"กำหนดช่วงวัน แล้วระบบจัดสรร 50/20/30 ณ วันที่เริ่ม ลงทุน และปรับพอร์ตตามข้อมูลที่เผยแพร่ใหม่ (event-driven) จนถึงวันสิ้นสุด — สรุปกำไร/ขาดทุนจากราคา + เงินปันผล. มีค่าธรรมเนียม 0.3% ต่อรายการ และปันผลเข้าบัญชีใน 30 วันหลัง ex-date.")])],-1)),o("div",ou,[o("label",null,[f[50]||(f[50]=Y("ตั้งแต่ ",-1)),xt(o("input",{type:"date","onUpdate:modelValue":f[12]||(f[12]=g=>y.value=g)},null,512),[[Ss,y.value]])]),o("label",null,[f[51]||(f[51]=Y("ถึง ",-1)),xt(o("input",{type:"date","onUpdate:modelValue":f[13]||(f[13]=g=>R.value=g)},null,512),[[Ss,R.value]])]),o("label",null,[f[52]||(f[52]=Y("ทุน ",-1)),xt(o("input",{type:"number","onUpdate:modelValue":f[14]||(f[14]=g=>I.value=g),step:"100000"},null,512),[[Ss,I.value,void 0,{number:!0}]])]),o("label",ru,[xt(o("input",{type:"checkbox","onUpdate:modelValue":f[15]||(f[15]=g=>V.value=g)},null,512),[[vl,V.value]]),f[53]||(f[53]=Y(" ใช้ ledger ปันผลตามวันที่จริง ",-1))]),o("button",{class:"primary-btn",disabled:U.value||H.value&&!H.value.ready,onClick:Ai},_(U.value?"กำลังย้อนทดสอบ…":"รัน Backtest"),9,au)]),H.value&&!H.value.ready?(E(),O("div",cu,[f[54]||(f[54]=o("strong",null,"ยังรันย้อนทดสอบแบบ strict PIT ไม่ได้ — ขาดข้อมูล coverage:",-1)),o("div",uu,_((H.value.missing||[]).slice(0,8).join(", "))+_((H.value.missing||[]).length>8?"…":""),1),o("div",fu,"วันเริ่มที่แนะนำ: "+_(H.value.recommended_start||"—")+" · วันสิ้นสุด: "+_(H.value.recommended_end||"—"),1)])):he("",!0),(Pe=A.value)!=null&&Pe.error?(E(),O("div",du,_(A.value.error),1)):A.value&&!A.value.error?(E(),O("div",pu,[o("div",hu,[o("div",gu,[f[55]||(f[55]=o("span",null,"กำไรจากราคา (realized)",-1)),o("strong",{class:Q(bt(A.value.realized_trading_pnl))},_(b(A.value.realized_trading_pnl))+" บาท",3)]),o("div",vu,[f[56]||(f[56]=o("span",null,"กำไรจากราคา (unrealized)",-1)),o("strong",{class:Q(bt(A.value.unrealized_trading_pnl))},_(b(A.value.unrealized_trading_pnl))+" บาท",3)]),o("div",_u,[f[57]||(f[57]=o("span",null,"เงินปันผลที่ได้รับ",-1)),o("strong",mu,_(b(A.value.dividend_cash_received))+" บาท",1)]),o("div",bu,[f[58]||(f[58]=o("span",null,"ค่าธรรมเนียม (0.3%)",-1)),o("strong",yu,"–"+_(b(A.value.transaction_costs))+" บาท",1)]),o("div",xu,[f[59]||(f[59]=o("span",null,"เงินปันผลค้างรับ",-1)),o("strong",null,_(b(A.value.dividend_receivable))+" บาท",1)]),o("div",wu,[f[60]||(f[60]=o("span",null,"มูลค่าสุดท้าย (equity)",-1)),o("strong",null,_(b(A.value.final_equity))+" บาท",1)]),o("div",Su,[f[61]||(f[61]=o("span",null,"ผลตอบแทนสุทธิ",-1)),o("strong",{class:Q(bt(A.value.net_return))},_((A.value.net_return*100).toFixed(2))+"%",3)])]),o("div",Cu,"Rebalances: "+_(A.value.rebalances)+" · ปันผลตาม: "+_(A.value.dividend_timing)+" · ช่วง "+_(A.value.start)+" → "+_(A.value.end),1),A.value.leakage_guard?(E(),O("div",Tu,"✅ strict PIT (leakage guard active)")):(E(),O("div",ku,"คำเตือน: ไม่ได้พิสูจน์ point-in-time (non-PIT)")),A.value.holdings&&A.value.holdings.length?(E(),O("div",Eu,[f[63]||(f[63]=o("strong",null,"พอร์ตสุดท้าย:",-1)),o("table",Ou,[f[62]||(f[62]=o("thead",null,[o("tr",null,[o("th",null,"หุ้น"),o("th",null,"จำนวน"),o("th",null,"ต้นทุนเฉลี่ย"),o("th",null,"ราคาล่าสุด"),o("th",null,"มูลค่า"),o("th",null,"กำไร unrealized")])],-1)),o("tbody",null,[(E(!0),O(oe,null,Ae(A.value.holdings,g=>(E(),O("tr",{key:g.symbol},[o("td",Pu,_(g.symbol),1),o("td",null,_(g.qty),1),o("td",null,_(b(g.average_cost,2)),1),o("td",null,_(b(g.last_price,2)),1),o("td",null,_(b(g.market_value)),1),o("td",{class:Q(bt(g.unrealized_pnl))},_(b(g.unrealized_pnl)),3)]))),128))])])])):he("",!0)])):(E(),O("div",Au,"กำหนดช่วงวันแล้วกด 'รัน Backtest' เพื่อดูผล (กำไร/ขาดทุนจากราคา + ปันผล)")),se.value.length?(E(),O("div",Ru,[f[65]||(f[65]=o("div",{class:"section-kicker"},"ประวัติการย้อนทดสอบ",-1)),o("table",Mu,[f[64]||(f[64]=o("thead",null,[o("tr",null,[o("th",null,"#"),o("th",null,"ช่วง"),o("th",null,"ทุน"),o("th",null,"กำไรราคา"),o("th",null,"ปันผล"),o("th",null,"ผลตอบแทน"),o("th",null,"รันเมื่อ")])],-1)),o("tbody",null,[(E(!0),O(oe,null,Ae(se.value.slice().reverse(),g=>(E(),O("tr",{key:g.id},[o("td",null,_(g.id),1),o("td",null,[Y(_(g.start)+" → "+_(g.end)+" ",1),g.leakage_guard===!1?(E(),O("span",Iu,"descriptive non-PIT")):he("",!0)]),o("td",null,_(b(g.capital)),1),o("td",{class:Q(bt(g.price_pnl))},_(b(g.price_pnl)),3),o("td",Fu,[Y(_(b(g.dividend_income)),1),o("span",{class:Q(["status-tag",D(g.dividend_method).cls]),style:$s([D(g.dividend_method).style||void 0,{"margin-left":"4px"}]),title:P(g.dividend_method)},_(D(g.dividend_method).label),15,Du)]),o("td",{class:Q(bt(g.net_return))},_((g.net_return*100).toFixed(2))+"%",3),o("td",Nu,_(g.ran_at?F(g.ran_at):"—"),1)]))),128))])])])):he("",!0)])],64))]),u.value?(E(),O("div",{key:0,class:"modal-overlay",onClick:Qr(Nn,["self"])},[o("div",Lu,[o("div",ju,[o("div",null,[f[67]||(f[67]=o("div",{class:"modal-kicker"},"การวิเคราะห์รายหุ้น",-1)),o("h3",null,_(u.value),1)]),o("button",{class:"modal-close",onClick:Nn},"✕")]),p.value?(E(),O("div",Vu,"กำลังโหลดการวิเคราะห์…")):(Ve=h.value)!=null&&Ve.error?(E(),O("div",$u,_(h.value.error),1)):h.value?(E(),O("div",Hu,[o("div",Bu,[f[71]||(f[71]=o("div",{class:"modal-section-title"},"ธีมที่เกี่ยวข้อง (คะแนนต่อธีม)",-1)),(Qe=h.value.themes)!=null&&Qe.length?(E(),O("div",Uu,[(E(!0),O(oe,null,Ae(h.value.theme_contributions,g=>(E(),O("div",{key:g.theme,class:"contrib-line"},[o("span",Ku,_(g.label_th||pt.value[g.theme]||g.theme),1),g.surprise!=null?(E(),O("span",Wu,[o("em",null,_(b(g.surprise))+"σ",1),f[68]||(f[68]=Y(" × คุณภาพ ",-1)),o("em",null,_(g.quality),1),f[69]||(f[69]=Y(" = ",-1)),o("strong",null,_(b(g.theme_score))+"σ",1)])):(E(),O("strong",qu,"ยังไม่มีข้อมูล"))]))),128)),f[70]||(f[70]=o("div",{class:"modal-sub"},"คะแนนธีม = ค่าเฉลี่ยของ (surprise × คุณภาพหุ้น) ที่หุ้นนี้อยู่ใน",-1))])):(E(),O("div",zu,"หุ้นนี้ยังไม่ได้จัดอยู่ในธีมใด (จะอัปเดตเมื่อเพิ่มธีม)"))]),o("div",Ju,[f[77]||(f[77]=o("div",{class:"modal-section-title"},"มูลค่าพื้นฐาน (Siamchart)",-1)),o("div",Gu,[o("span",null,[f[72]||(f[72]=Y("P/E ",-1)),o("strong",null,_(((vs=h.value.fundamentals)==null?void 0:vs.pe)??"—"),1)]),o("span",null,[f[73]||(f[73]=Y("EPS ",-1)),o("strong",null,_(((yt=h.value.fundamentals)==null?void 0:yt.eps)??"—"),1)]),o("span",null,[f[74]||(f[74]=Y("P/BV ",-1)),o("strong",null,_(((_s=h.value.fundamentals)==null?void 0:_s.pbv)??"—"),1)]),o("span",null,[f[75]||(f[75]=Y("ROE ",-1)),o("strong",null,_(((ms=h.value.fundamentals)==null?void 0:ms.roe)??"—"),1)]),o("span",null,[f[76]||(f[76]=Y("ปันผล ",-1)),o("strong",null,_((jn=h.value.fundamentals)!=null&&jn.is_dividend?"จ่าย":"—"),1)])]),o("div",Yu,"ภาพรวม: "+_(h.value.company_name||u.value),1)]),o("div",Xu,[f[79]||(f[79]=o("div",{class:"modal-section-title"},"ขั้นตอนการคำนวณคะแนนรวม",-1)),o("div",Zu,[o("div",Qu,_(h.value.combined_formula),1),(E(!0),O(oe,null,Ae(h.value.combined_calc,g=>(E(),O("div",{key:g.label,class:"calc-step"},[o("div",ef,[o("span",null,_(g.label),1),o("strong",null,_(b(g.value))+" × "+_(g.weight),1)]),o("div",tf,_(g.note),1)]))),128)),h.value.siamchart_z_note?(E(),O("div",sf,[Y(" คะแนนพื้นฐานได้จาก z-score: z = (ค่า"+_(h.value.siamchart_z_note.raw_i)+" − ค่าเฉลี่ย "+_(h.value.siamchart_z_note.population_mean)+") / ค่าเบี่ยงเบน "+_(h.value.siamchart_z_note.population_stdev),1),f[78]||(f[78]=o("br",null,null,-1)),Y("เทียบกับ "+_(h.value.siamchart_z_note.universe_size)+" หุ้นใน SET50 ",1)])):he("",!0)]),o("div",nf,"ราคาล่าสุด: "+_(((Vn=h.value.price)==null?void 0:Vn.latest)!=null?b(h.value.price.latest):"—")+" ("+_((($n=h.value.price)==null?void 0:$n.date)||"—")+")",1)])])):he("",!0)])])):he("",!0)])}}};sa(lf).mount("#app"); diff --git a/frontend/dist/assets/index-DOVbTpbx.js b/frontend/dist/assets/index-DOVbTpbx.js new file mode 100644 index 0000000..7828009 --- /dev/null +++ b/frontend/dist/assets/index-DOVbTpbx.js @@ -0,0 +1,18 @@ +(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const l of document.querySelectorAll('link[rel="modulepreload"]'))n(l);new MutationObserver(l=>{for(const i of l)if(i.type==="childList")for(const r of i.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&n(r)}).observe(document,{childList:!0,subtree:!0});function s(l){const i={};return l.integrity&&(i.integrity=l.integrity),l.referrerPolicy&&(i.referrerPolicy=l.referrerPolicy),l.crossOrigin==="use-credentials"?i.credentials="include":l.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function n(l){if(l.ep)return;l.ep=!0;const i=s(l);fetch(l.href,i)}})();/** +* @vue/shared v3.5.41 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function bn(e){const t=Object.create(null);for(const s of e.split(","))t[s]=1;return s=>s in t}const ee={},Dt=[],Ge=()=>{},xl=()=>!1,$s=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Ls=e=>e.startsWith("onUpdate:"),_e=Object.assign,yn=(e,t)=>{const s=e.indexOf(t);s>-1&&e.splice(s,1)},Li=Object.prototype.hasOwnProperty,Y=(e,t)=>Li.call(e,t),L=Array.isArray,$t=e=>cs(e)==="[object Map]",Bt=e=>cs(e)==="[object Set]",Bn=e=>cs(e)==="[object Date]",j=e=>typeof e=="function",re=e=>typeof e=="string",Xe=e=>typeof e=="symbol",Z=e=>e!==null&&typeof e=="object",wl=e=>(Z(e)||j(e))&&j(e.then)&&j(e.catch),Sl=Object.prototype.toString,cs=e=>Sl.call(e),Ni=e=>cs(e).slice(8,-1),Cl=e=>cs(e)==="[object Object]",xn=e=>re(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Yt=bn(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Ns=e=>{const t=Object.create(null);return(s=>t[s]||(t[s]=e(s)))},ji=/-\w/g,Fe=Ns(e=>e.replace(ji,t=>t.slice(1).toUpperCase())),Vi=/\B([A-Z])/g,Rt=Ns(e=>e.replace(Vi,"-$1").toLowerCase()),kl=Ns(e=>e.charAt(0).toUpperCase()+e.slice(1)),Ys=Ns(e=>e?`on${kl(e)}`:""),ze=(e,t)=>!Object.is(e,t),ks=(e,...t)=>{for(let s=0;s{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:n,value:s})},js=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let Kn;const Vs=()=>Kn||(Kn=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Hs(e){if(L(e)){const t={};for(let s=0;s{if(s){const n=s.split(Bi);n.length>1&&(t[n[0].trim()]=n[1].trim())}}),t}function Q(e){let t="";if(re(e))t=e;else if(L(e))for(let s=0;sKt(s,t))}const Ol=e=>!!(e&&e.__v_isRef===!0),_=e=>re(e)?e:e==null?"":L(e)||Z(e)&&(e.toString===Sl||!j(e.toString))?Ol(e)?_(e.value):JSON.stringify(e,Pl,2):String(e),Pl=(e,t)=>Ol(t)?Pl(e,t.value):$t(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((s,[n,l],i)=>(s[Xs(n,i)+" =>"]=l,s),{})}:Bt(t)?{[`Set(${t.size})`]:[...t.values()].map(s=>Xs(s))}:Xe(t)?Xs(t):Z(t)&&!L(t)&&!Cl(t)?String(t):t,Xs=(e,t="")=>{var s;return Xe(e)?`Symbol(${(s=e.description)!=null?s:t})`:e};/** +* @vue/reactivity v3.5.41 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let pe;class Ji{constructor(t=!1){this.detached=t,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this._warnOnRun=!0,this.__v_skip=!0,!t&&pe&&(pe.active?(this.parent=pe,this.index=(pe.scopes||(pe.scopes=[])).push(this)-1):(this._active=!1,this._warnOnRun=!1))}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,s;if(this.scopes){const n=this.scopes.slice();for(t=0,s=n.length;t0&&--this._on===0){if(pe===this)pe=this.prevScope;else{let t=pe;for(;t;){if(t.prevScope===this){t.prevScope=this.prevScope;break}t=t.prevScope}}this.prevScope=void 0}}stop(t){if(this._active){this._active=!1;let s,n;for(s=0,n=this.effects.length;s0)return;if(Zt){let t=Zt;for(Zt=void 0;t;){const s=t.next;t.next=void 0,t.flags&=-9,t=s}}let e;for(;Xt;){let t=Xt;for(Xt=void 0;t;){const s=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(n){e||(e=n)}t=s}}if(e)throw e}function Il(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function Fl(e){let t,s=e.depsTail,n=s;for(;n;){const l=n.prevDep;n.version===-1?(n===s&&(s=l),kn(n),Yi(n)):t=n,n.dep.activeLink=n.prevActiveLink,n.prevActiveLink=void 0,n=l}e.deps=t,e.depsTail=s}function cn(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(Dl(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function Dl(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===ss)||(e.globalVersion=ss,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!cn(e))))return;e.flags|=2;const t=e.dep,s=te,n=De;te=e,De=!0;try{Il(e);const l=e.fn(e._value);(t.version===0||ze(l,e._value))&&(e.flags|=128,e._value=l,t.version++)}catch(l){throw t.version++,l}finally{te=s,De=n,Fl(e),e.flags&=-3}}function kn(e,t=!1){const{dep:s,prevSub:n,nextSub:l}=e;if(n&&(n.nextSub=l,e.prevSub=void 0),l&&(l.prevSub=n,e.nextSub=void 0),s.subs===e&&(s.subs=n,!n&&s.computed)){s.computed.flags&=-5;for(let i=s.computed.deps;i;i=i.nextDep)kn(i,!0)}!t&&!--s.sc&&s.map&&s.map.delete(s.key)}function Yi(e){const{prevDep:t,nextDep:s}=e;t&&(t.nextDep=s,e.prevDep=void 0),s&&(s.prevDep=t,e.nextDep=void 0)}let De=!0;const $l=[];function ot(){$l.push(De),De=!1}function rt(){const e=$l.pop();De=e===void 0?!0:e}function Un(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const s=te;te=void 0;try{t()}finally{te=s}}}let ss=0;class Xi{constructor(t,s){this.sub=t,this.dep=s,this.version=s.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class Tn{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(t){if(!te||!De||te===this.computed)return;let s=this.activeLink;if(s===void 0||s.sub!==te)s=this.activeLink=new Xi(te,this),te.deps?(s.prevDep=te.depsTail,te.depsTail.nextDep=s,te.depsTail=s):te.deps=te.depsTail=s,Ll(s);else if(s.version===-1&&(s.version=this.version,s.nextDep)){const n=s.nextDep;n.prevDep=s.prevDep,s.prevDep&&(s.prevDep.nextDep=n),s.prevDep=te.depsTail,s.nextDep=void 0,te.depsTail.nextDep=s,te.depsTail=s,te.deps===s&&(te.deps=n)}return s}trigger(t){this.version++,ss++,this.notify(t)}notify(t){Sn();try{for(let s=this.subs;s;s=s.prevSub)s.sub.notify()&&s.sub.dep.notify()}finally{Cn()}}}function Ll(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let n=t.deps;n;n=n.nextDep)Ll(n)}const s=e.dep.subs;s!==e&&(e.prevSub=s,s&&(s.nextSub=e)),e.dep.subs=e}}const un=new WeakMap,Ot=Symbol(""),fn=Symbol(""),ns=Symbol("");function ge(e,t,s){if(De&&te){let n=un.get(e);n||un.set(e,n=new Map);let l=n.get(s);l||(n.set(s,l=new Tn),l.map=n,l.key=s),l.track()}}function lt(e,t,s,n,l,i){const r=un.get(e);if(!r){ss++;return}const a=u=>{u&&u.trigger()};if(Sn(),t==="clear")r.forEach(a);else{const u=L(e),g=u&&xn(s);if(u&&s==="length"){const h=Number(n);r.forEach((b,M)=>{(M==="length"||M===ns||!Xe(M)&&M>=h)&&a(b)})}else switch((s!==void 0||r.has(void 0))&&a(r.get(s)),g&&a(r.get(ns)),t){case"add":u?g&&a(r.get("length")):(a(r.get(Ot)),$t(e)&&a(r.get(fn)));break;case"delete":u||(a(r.get(Ot)),$t(e)&&a(r.get(fn)));break;case"set":$t(e)&&a(r.get(Ot));break}}Cn()}function It(e){const t=G(e);return t===e?t:(ge(t,"iterate",ns),Ie(e)?t:t.map($e))}function Bs(e){return ge(e=G(e),"iterate",ns),e}function We(e,t){return at(e)?jt(Pt(e)?$e(t):t):$e(t)}const Zi={__proto__:null,[Symbol.iterator](){return Qs(this,Symbol.iterator,e=>We(this,e))},concat(...e){return It(this).concat(...e.map(t=>L(t)?It(t):t))},entries(){return Qs(this,"entries",e=>(e[1]=We(this,e[1]),e))},every(e,t){return tt(this,"every",e,t,void 0,arguments)},filter(e,t){return tt(this,"filter",e,t,s=>s.map(n=>We(this,n)),arguments)},find(e,t){return tt(this,"find",e,t,s=>We(this,s),arguments)},findIndex(e,t){return tt(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return tt(this,"findLast",e,t,s=>We(this,s),arguments)},findLastIndex(e,t){return tt(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return tt(this,"forEach",e,t,void 0,arguments)},includes(...e){return en(this,"includes",e)},indexOf(...e){return en(this,"indexOf",e)},join(e){return It(this).join(e)},lastIndexOf(...e){return en(this,"lastIndexOf",e)},map(e,t){return tt(this,"map",e,t,void 0,arguments)},pop(){return qt(this,"pop")},push(...e){return qt(this,"push",e)},reduce(e,...t){return Wn(this,"reduce",e,t)},reduceRight(e,...t){return Wn(this,"reduceRight",e,t)},shift(){return qt(this,"shift")},some(e,t){return tt(this,"some",e,t,void 0,arguments)},splice(...e){return qt(this,"splice",e)},toReversed(){return It(this).toReversed()},toSorted(e){return It(this).toSorted(e)},toSpliced(...e){return It(this).toSpliced(...e)},unshift(...e){return qt(this,"unshift",e)},values(){return Qs(this,"values",e=>We(this,e))}};function Qs(e,t,s){const n=Bs(e),l=n[t]();return n!==e&&!Ie(e)&&(l._next=l.next,l.next=()=>{const i=l._next();return i.done||(i.value=s(i.value)),i}),l}const Qi=Array.prototype;function tt(e,t,s,n,l,i){const r=Bs(e),a=r!==e&&!Ie(e),u=r[t];if(u!==Qi[t]){const b=u.apply(e,i);return a?$e(b):b}let g=s;r!==e&&(a?g=function(b,M){return s.call(this,We(e,b),M,e)}:s.length>2&&(g=function(b,M){return s.call(this,b,M,e)}));const h=u.call(r,g,n);return a&&l?l(h):h}function Wn(e,t,s,n){const l=Bs(e),i=l!==e&&!Ie(e);let r=s,a=!1;l!==e&&(i?(a=n.length===0,r=function(g,h,b){return a&&(a=!1,g=We(e,g)),s.call(this,g,We(e,h),b,e)}):s.length>3&&(r=function(g,h,b){return s.call(this,g,h,b,e)}));const u=l[t](r,...n);return a?We(e,u):u}function en(e,t,s){const n=G(e);ge(n,"iterate",ns);const l=n[t](...s);return(l===-1||l===!1)&&An(s[0])?(s[0]=G(s[0]),n[t](...s)):l}function qt(e,t,s=[]){ot(),Sn();const n=G(e)[t].apply(e,s);return Cn(),rt(),n}const eo=bn("__proto__,__v_isRef,__isVue"),Nl=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Xe));function to(e){Xe(e)||(e=String(e));const t=G(this);return ge(t,"has",e),t.hasOwnProperty(e)}class jl{constructor(t=!1,s=!1){this._isReadonly=t,this._isShallow=s}get(t,s,n){if(s==="__v_skip")return t.__v_skip;const l=this._isReadonly,i=this._isShallow;if(s==="__v_isReactive")return!l;if(s==="__v_isReadonly")return l;if(s==="__v_isShallow")return i;if(s==="__v_raw")return n===(l?i?fo:Kl:i?Bl:Hl).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(n)?t:void 0;const r=L(t);if(!l){let u;if(r&&(u=Zi[s]))return u;if(s==="hasOwnProperty")return to}const a=Reflect.get(t,s,ve(t)?t:n);if((Xe(s)?Nl.has(s):eo(s))||(l||ge(t,"get",s),i))return a;if(ve(a)){const u=r&&xn(s)?a:a.value;return l&&Z(u)?pn(u):u}return Z(a)?l?pn(a):On(a):a}}class Vl extends jl{constructor(t=!1){super(!1,t)}set(t,s,n,l){let i=t[s];const r=L(t)&&xn(s);if(!this._isShallow){const g=at(i);if(!Ie(n)&&!at(n)&&(i=G(i),n=G(n)),!r&&ve(i)&&!ve(n))return g||(i.value=n),!0}const a=r?Number(s)e,ys=e=>Reflect.getPrototypeOf(e);function oo(e,t,s){return function(...n){const l=this.__v_raw,i=G(l),r=$t(i),a=e==="entries"||e===Symbol.iterator&&r,u=e==="keys"&&r,g=l[e](...n),h=s?dn:t?jt:$e;return!t&&ge(i,"iterate",u?fn:Ot),_e(Object.create(g),{next(){const{value:b,done:M}=g.next();return M?{value:b,done:M}:{value:a?[h(b[0]),h(b[1])]:h(b),done:M}}})}}function xs(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function ro(e,t){const s={get(l){const i=this.__v_raw,r=G(i),a=G(l);e||(ze(l,a)&&ge(r,"get",l),ge(r,"get",a));const{has:u}=ys(r),g=t?dn:e?jt:$e;if(u.call(r,l))return g(i.get(l));if(u.call(r,a))return g(i.get(a));i!==r&&i.get(l)},get size(){const l=this.__v_raw;return!e&&ge(G(l),"iterate",Ot),l.size},has(l){const i=this.__v_raw,r=G(i),a=G(l);return e||(ze(l,a)&&ge(r,"has",l),ge(r,"has",a)),l===a?i.has(l):i.has(l)||i.has(a)},forEach(l,i){const r=this,a=r.__v_raw,u=G(a),g=t?dn:e?jt:$e;return!e&&ge(u,"iterate",Ot),a.forEach((h,b)=>l.call(i,g(h),g(b),r))}};return _e(s,e?{add:xs("add"),set:xs("set"),delete:xs("delete"),clear:xs("clear")}:{add(l){const i=G(this),r=ys(i),a=G(l),u=!t&&!Ie(l)&&!at(l)?a:l;return r.has.call(i,u)||ze(l,u)&&r.has.call(i,l)||ze(a,u)&&r.has.call(i,a)||(i.add(u),lt(i,"add",u,u)),this},set(l,i){!t&&!Ie(i)&&!at(i)&&(i=G(i));const r=G(this),{has:a,get:u}=ys(r);let g=a.call(r,l);g||(l=G(l),g=a.call(r,l));const h=u.call(r,l);return r.set(l,i),g?ze(i,h)&<(r,"set",l,i):lt(r,"add",l,i),this},delete(l){const i=G(this),{has:r,get:a}=ys(i);let u=r.call(i,l);u||(l=G(l),u=r.call(i,l)),a&&a.call(i,l);const g=i.delete(l);return u&<(i,"delete",l,void 0),g},clear(){const l=G(this),i=l.size!==0,r=l.clear();return i&<(l,"clear",void 0,void 0),r}}),["keys","values","entries",Symbol.iterator].forEach(l=>{s[l]=oo(l,e,t)}),s}function En(e,t){const s=ro(e,t);return(n,l,i)=>l==="__v_isReactive"?!e:l==="__v_isReadonly"?e:l==="__v_raw"?n:Reflect.get(Y(s,l)&&l in n?s:n,l,i)}const ao={get:En(!1,!1)},co={get:En(!1,!0)},uo={get:En(!0,!1)};const Hl=new WeakMap,Bl=new WeakMap,Kl=new WeakMap,fo=new WeakMap;function po(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function On(e){return at(e)?e:Pn(e,!1,no,ao,Hl)}function ho(e){return Pn(e,!1,io,co,Bl)}function pn(e){return Pn(e,!0,lo,uo,Kl)}function Pn(e,t,s,n,l){if(!Z(e)||e.__v_raw&&!(t&&e.__v_isReactive)||e.__v_skip||!Object.isExtensible(e))return e;const i=l.get(e);if(i)return i;const r=po(Ni(e));if(r===0)return e;const a=new Proxy(e,r===2?n:s);return l.set(e,a),a}function Pt(e){return at(e)?Pt(e.__v_raw):!!(e&&e.__v_isReactive)}function at(e){return!!(e&&e.__v_isReadonly)}function Ie(e){return!!(e&&e.__v_isShallow)}function An(e){return e?!!e.__v_raw:!1}function G(e){const t=e&&e.__v_raw;return t?G(t):e}function go(e){return!Y(e,"__v_skip")&&Object.isExtensible(e)&&Tl(e,"__v_skip",!0),e}const $e=e=>Z(e)?On(e):e,jt=e=>Z(e)?pn(e):e;function ve(e){return e?e.__v_isRef===!0:!1}function H(e){return vo(e,!1)}function vo(e,t){return ve(e)?e:new _o(e,t)}class _o{constructor(t,s){this.dep=new Tn,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=s?t:G(t),this._value=s?t:$e(t),this.__v_isShallow=s}get value(){return this.dep.track(),this._value}set value(t){const s=this._rawValue,n=this.__v_isShallow||Ie(t)||at(t);t=n?t:G(t),ze(t,s)&&(this._rawValue=t,this._value=n?t:$e(t),this.dep.trigger())}}function mo(e){return ve(e)?e.value:e}const bo={get:(e,t,s)=>t==="__v_raw"?e:mo(Reflect.get(e,t,s)),set:(e,t,s,n)=>{const l=e[t];return ve(l)&&!ve(s)?(l.value=s,!0):Reflect.set(e,t,s,n)}};function Ul(e){return Pt(e)?e:new Proxy(e,bo)}class yo{constructor(t,s,n){this.fn=t,this.setter=s,this._value=void 0,this.dep=new Tn(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=ss-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!s,this.isSSR=n}notify(){if(this.flags|=16,!(this.flags&8)&&te!==this)return Ml(this,!0),!0}get value(){const t=this.dep.track();return Dl(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function xo(e,t,s=!1){let n,l;return j(e)?n=e:(n=e.get,l=e.set),new yo(n,l,s)}const ws={},Ps=new WeakMap;let Et;function wo(e,t=!1,s=Et){if(s){let n=Ps.get(s);n||Ps.set(s,n=[]),n.push(e)}}function So(e,t,s=ee){const{immediate:n,deep:l,once:i,scheduler:r,augmentJob:a,call:u}=s,g=D=>l?D:Ie(D)||l===!1||l===0?it(D,1):it(D);let h,b,M,I,U=!1,R=!1;if(ve(e)?(b=()=>e.value,U=Ie(e)):Pt(e)?(b=()=>g(e),U=!0):L(e)?(R=!0,U=e.some(D=>Pt(D)||Ie(D)),b=()=>e.map(D=>{if(ve(D))return D.value;if(Pt(D))return g(D);if(j(D))return u?u(D,2):D()})):j(e)?t?b=u?()=>u(e,2):e:b=()=>{if(M){ot();try{M()}finally{rt()}}const D=Et;Et=h;try{return u?u(e,3,[I]):e(I)}finally{Et=D}}:b=Ge,t&&l){const D=b,z=l===!0?1/0:l;b=()=>it(D(),z)}const se=Gi(),K=()=>{h.stop(),se&&se.active&&yn(se.effects,h)};if(i&&t){const D=t;t=(...z)=>{const we=D(...z);return K(),we}}let B=R?new Array(e.length).fill(ws):ws;const W=D=>{if(!(!(h.flags&1)||!h.dirty&&!D))if(t){const z=h.run();if(D||l||U||(R?z.some((we,ne)=>ze(we,B[ne])):ze(z,B))){M&&M();const we=Et;Et=h;try{const ne=[z,B===ws?void 0:R&&B[0]===ws?[]:B,I];B=z,u?u(t,3,ne):t(...ne)}finally{Et=we}}}else h.run()};return a&&a(W),h=new Al(b),h.scheduler=r?()=>r(W,!1):W,I=D=>wo(D,!1,h),M=h.onStop=()=>{const D=Ps.get(h);if(D){if(u)u(D,4);else for(const z of D)z();Ps.delete(h)}},t?n?W(!0):B=h.run():r?r(W.bind(null,!0),!0):h.run(),K.pause=h.pause.bind(h),K.resume=h.resume.bind(h),K.stop=K,K}function it(e,t=1/0,s){if(t<=0||!Z(e)||e.__v_skip||(s=s||new Map,(s.get(e)||0)>=t))return e;if(s.set(e,t),t--,ve(e))it(e.value,t,s);else if(L(e))for(let n=0;n{it(n,t,s)});else if(Cl(e)){for(const n in e)it(e[n],t,s);for(const n of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,n)&&it(e[n],t,s)}return e}/** +* @vue/runtime-core v3.5.41 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function us(e,t,s,n){try{return n?e(...n):e()}catch(l){Ks(l,t,s)}}function Le(e,t,s,n){if(j(e)){const l=us(e,t,s,n);return l&&wl(l)&&l.catch(i=>{Ks(i,t,s)}),l}if(L(e)){const l=[];for(let i=0;i>>1,l=ye[n],i=ls(l);i=ls(s)?ye.push(e):ye.splice(ko(t),0,e),e.flags|=1,zl()}}function zl(){As||(As=Wl.then(Gl))}function To(e){if(!L(e))vt&&e.id===-1?vt.splice(Ft+1,0,e):e.flags&1||(Lt.push(e),e.flags|=1);else for(let t=0;tls(s)-ls(n));if(Lt.length=0,vt){for(let s=0;se.id==null?e.flags&2?-1:1/0:e.id;function Gl(e){try{for(Ue=0;Ue{n._d&&nl(-1);const i=Rs(t),r=At.length;let a;try{a=e(...l)}finally{for(let u=At.length;u>r;u--)xi();Rs(i),n._d&&nl(1)}return a};return n._n=!0,n._c=!0,n._d=!0,n}function Ct(e,t){if(Me===null)return e;const s=Js(Me),n=e.dirs||(e.dirs=[]);for(let l=0;l1)return s&&j(t)?t.call(n&&n.proxy):t}}const Po=Symbol.for("v-scx"),Ao=()=>Ts(Po);function tn(e,t,s){return Xl(e,t,s)}function Xl(e,t,s=ee){const{immediate:n,deep:l,flush:i,once:r}=s,a=_e({},s),u=t&&n||!t&&i!=="post";let g;if(rs){if(i==="sync"){const I=Ao();g=I.__watcherHandles||(I.__watcherHandles=[])}else if(!u){const I=()=>{};return I.stop=Ge,I.resume=Ge,I.pause=Ge,I}}const h=xe;a.call=(I,U,R)=>Le(I,h,U,R);let b=!1;i==="post"?a.scheduler=I=>{Ce(I,h&&h.suspense)}:i!=="sync"&&(b=!0,a.scheduler=(I,U)=>{U?I():Rn(I)}),a.augmentJob=I=>{t&&(I.flags|=4),b&&(I.flags|=2,h&&(I.id=h.uid,I.i=h))};const M=So(e,t,a);return rs&&(g?g.push(M):u&&M()),M}function Ro(e,t,s){const n=this.proxy,l=re(e)?e.includes(".")?Zl(n,e):()=>n[e]:e.bind(n,n);let i;j(t)?i=t:(i=t.handler,s=t);const r=fs(this),a=Xl(l,i.bind(n),s);return r(),a}function Zl(e,t){const s=t.split(".");return()=>{let n=e;for(let l=0;le.__isTeleport,sn=Symbol("_leaveCb");function Io(e){let t=e[0];if(e.length>1){for(const s of e)if(s.type!==ct){t=s;break}}return t}function Ql(e){if(!In(e))return Us(e.type)&&e.children?Io(e.children):e;if(e.component)return e.component.subTree;const{shapeFlag:t,children:s}=e;if(s){if(t&16)return s[0];if(t&32&&j(s.default))return s.default()}}function Mn(e,t){if(e.shapeFlag&6&&e.component){e.transition=t;const s=e.component.subTree;Mn(Us(s.type)&&Ql(s)||s,t)}else e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function ei(e){e.ids=[e.ids[0]+e.ids[2]+++"-",0,0]}function zn(e,t){let s;return!!((s=Object.getOwnPropertyDescriptor(e,t))&&!s.configurable)}const Ms=new WeakMap;function Qt(e,t,s,n,l=!1){if(L(e)){e.forEach((R,se)=>Qt(R,t&&(L(t)?t[se]:t),s,n,l));return}if(es(n)&&!l){n.shapeFlag&512&&n.type.__asyncResolved&&n.component.subTree.component&&Qt(e,t,s,n.component.subTree);return}const i=n.shapeFlag&4?Js(n.component):n.el,r=l?null:i,{i:a,r:u}=e,g=t&&t.r,h=a.refs===ee?a.refs={}:a.refs,b=a.setupState,M=G(b),I=b===ee?xl:R=>zn(h,R)?!1:Y(M,R),U=(R,se)=>!(se&&zn(h,se));if(g!=null&&g!==u){if(Jn(t),re(g))h[g]=null,I(g)&&(b[g]=null);else if(ve(g)){const R=t;U(g,R.k)&&(g.value=null),R.k&&(h[R.k]=null)}}if(j(u))us(u,a,12,[r,h]);else{const R=re(u),se=ve(u);if(R||se){const K=()=>{if(e.f){const B=R?I(u)?b[u]:h[u]:U()||!e.k?u.value:h[e.k];if(l)L(B)&&yn(B,i);else if(L(B))B.includes(i)||B.push(i);else if(R)h[u]=[i],I(u)&&(b[u]=h[u]);else{const W=[i];U(u,e.k)&&(u.value=W),e.k&&(h[e.k]=W)}}else R?(h[u]=r,I(u)&&(b[u]=r)):se&&(U(u,e.k)&&(u.value=r),e.k&&(h[e.k]=r))};if(r){const B=()=>{K(),Ms.delete(e)};B.id=-1,Ms.set(e,B),Ce(B,s)}else Jn(e),K()}}}function Jn(e){const t=Ms.get(e);t&&(t.flags|=8,Ms.delete(e))}Vs().requestIdleCallback;Vs().cancelIdleCallback;const es=e=>!!e.type.__asyncLoader,In=e=>e.type.__isKeepAlive;function Fo(e,t){ti(e,"a",t)}function Do(e,t){ti(e,"da",t)}function ti(e,t,s=xe){const n=e.__wdc||(e.__wdc=()=>{let l=s;for(;l;){if(l.isDeactivated)return;l=l.parent}return e()});if(Ws(t,n,s),s){let l=s.parent;for(;l&&l.parent;)In(l.parent.vnode)&&$o(n,t,s,l),l=l.parent}}function $o(e,t,s,n){const l=Ws(t,e,n,!0);ni(()=>{yn(n[t],l)},s)}function Ws(e,t,s=xe,n=!1){if(s){const l=s[e]||(s[e]=[]),i=t.__weh||(t.__weh=(...r)=>{ot();const a=fs(s),u=Le(t,s,e,r);return a(),rt(),u});return n?l.unshift(i):l.push(i),i}}const ut=e=>(t,s=xe)=>{(!rs||e==="sp")&&Ws(e,(...n)=>t(...n),s)},Lo=ut("bm"),si=ut("m"),No=ut("bu"),jo=ut("u"),Vo=ut("bum"),ni=ut("um"),Ho=ut("sp"),Bo=ut("rtg"),Ko=ut("rtc");function Uo(e,t=xe){Ws("ec",e,t)}const Wo=Symbol.for("v-ndc");function Te(e,t,s,n){let l;const i=s,r=L(e);if(r||re(e)){const a=r&&Pt(e);let u=!1,g=!1;a&&(u=!Ie(e),g=at(e),e=Bs(e)),l=new Array(e.length);for(let h=0,b=e.length;ht(a,u,void 0,i));else{const a=Object.keys(e);l=new Array(a.length);for(let u=0,g=a.length;ue?ki(e)?Js(e):hn(e.parent):null,ts=_e(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>hn(e.parent),$root:e=>hn(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>ii(e),$forceUpdate:e=>e.f||(e.f=()=>{Rn(e.update)}),$nextTick:e=>e.n||(e.n=ql.bind(e.proxy)),$watch:e=>Ro.bind(e)}),nn=(e,t)=>e!==ee&&!e.__isScriptSetup&&Y(e,t),qo={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:s,setupState:n,data:l,props:i,accessCache:r,type:a,appContext:u}=e;if(t[0]!=="$"){const M=r[t];if(M!==void 0)switch(M){case 1:return n[t];case 2:return l[t];case 4:return s[t];case 3:return i[t]}else{if(nn(n,t))return r[t]=1,n[t];if(l!==ee&&Y(l,t))return r[t]=2,l[t];if(Y(i,t))return r[t]=3,i[t];if(s!==ee&&Y(s,t))return r[t]=4,s[t];gn&&(r[t]=0)}}const g=ts[t];let h,b;if(g)return t==="$attrs"&&ge(e.attrs,"get",""),g(e);if((h=a.__cssModules)&&(h=h[t]))return h;if(s!==ee&&Y(s,t))return r[t]=4,s[t];if(b=u.config.globalProperties,Y(b,t))return b[t]},set({_:e},t,s){const{data:n,setupState:l,ctx:i}=e;return nn(l,t)?(l[t]=s,!0):n!==ee&&Y(n,t)?(n[t]=s,!0):Y(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(i[t]=s,!0)},has({_:{data:e,setupState:t,accessCache:s,ctx:n,appContext:l,props:i,type:r}},a){let u;return!!(s[a]||e!==ee&&a[0]!=="$"&&Y(e,a)||nn(t,a)||Y(i,a)||Y(n,a)||Y(ts,a)||Y(l.config.globalProperties,a)||(u=r.__cssModules)&&u[a])},defineProperty(e,t,s){return s.get!=null?e._.accessCache[t]=0:Y(s,"value")&&this.set(e,t,s.value,null),Reflect.defineProperty(e,t,s)}};function Gn(e){return L(e)?e.reduce((t,s)=>(t[s]=null,t),{}):e}let gn=!0;function zo(e){const t=ii(e),s=e.proxy,n=e.ctx;gn=!1,t.beforeCreate&&Yn(t.beforeCreate,e,"bc");const{data:l,computed:i,methods:r,watch:a,provide:u,inject:g,created:h,beforeMount:b,mounted:M,beforeUpdate:I,updated:U,activated:R,deactivated:se,beforeDestroy:K,beforeUnmount:B,destroyed:W,unmounted:D,render:z,renderTracked:we,renderTriggered:ne,errorCaptured:Se,serverPrefetch:Mt,expose:Ze,inheritAttrs:mt,components:ft,directives:Qe,filters:Ne}=t;if(g&&Jo(g,n,null),r)for(const le in r){const X=r[le];j(X)&&(n[le]=X.bind(s))}if(l){const le=l.call(s,s);Z(le)&&(e.data=On(le))}if(gn=!0,i)for(const le in i){const X=i[le],je=j(X)?X.bind(s,s):j(X.get)?X.get.bind(s,s):Ge,bt=!j(X)&&j(X.set)?X.set.bind(s):Ge,Ve=ae({get:je,set:bt});Object.defineProperty(n,le,{enumerable:!0,configurable:!0,get:()=>Ve.value,set:me=>Ve.value=me})}if(a)for(const le in a)li(a[le],n,s,le);if(u){const le=j(u)?u.call(s):u;Reflect.ownKeys(le).forEach(X=>{Oo(X,le[X])})}h&&Yn(h,e,"c");function fe(le,X){L(X)?X.forEach(je=>le(je.bind(s))):X&&le(X.bind(s))}if(fe(Lo,b),fe(si,M),fe(No,I),fe(jo,U),fe(Fo,R),fe(Do,se),fe(Uo,Se),fe(Ko,we),fe(Bo,ne),fe(Vo,B),fe(ni,D),fe(Ho,Mt),L(Ze))if(Ze.length){const le=e.exposed||(e.exposed={});Ze.forEach(X=>{Object.defineProperty(le,X,{get:()=>s[X],set:je=>s[X]=je,enumerable:!0})})}else e.exposed||(e.exposed={});z&&e.render===Ge&&(e.render=z),mt!=null&&(e.inheritAttrs=mt),ft&&(e.components=ft),Qe&&(e.directives=Qe),Mt&&ei(e)}function Jo(e,t,s=Ge){L(e)&&(e=vn(e));for(const n in e){const l=e[n];let i;Z(l)?"default"in l?i=Ts(l.from||n,l.default,!0):i=Ts(l.from||n):i=Ts(l),ve(i)?Object.defineProperty(t,n,{enumerable:!0,configurable:!0,get:()=>i.value,set:r=>i.value=r}):t[n]=i}}function Yn(e,t,s){Le(L(e)?e.map(n=>n.bind(t.proxy)):e.bind(t.proxy),t,s)}function li(e,t,s,n){let l=n.includes(".")?Zl(s,n):()=>s[n];if(re(e)){const i=t[e];j(i)&&tn(l,i)}else if(j(e))tn(l,e.bind(s));else if(Z(e))if(L(e))e.forEach(i=>li(i,t,s,n));else{const i=j(e.handler)?e.handler.bind(s):t[e.handler];j(i)&&tn(l,i,e)}}function ii(e){const t=e.type,{mixins:s,extends:n}=t,{mixins:l,optionsCache:i,config:{optionMergeStrategies:r}}=e.appContext,a=i.get(t);let u;return a?u=a:!l.length&&!s&&!n?u=t:(u={},l.length&&l.forEach(g=>Is(u,g,r,!0)),Is(u,t,r)),Z(t)&&i.set(t,u),u}function Is(e,t,s,n=!1){const{mixins:l,extends:i}=t;i&&Is(e,i,s,!0),l&&l.forEach(r=>Is(e,r,s,!0));for(const r in t)if(!(n&&r==="expose")){const a=Go[r]||s&&s[r];e[r]=a?a(e[r],t[r]):t[r]}return e}const Go={data:Xn,props:Zn,emits:Zn,methods:Jt,computed:Jt,beforeCreate:be,created:be,beforeMount:be,mounted:be,beforeUpdate:be,updated:be,beforeDestroy:be,beforeUnmount:be,destroyed:be,unmounted:be,activated:be,deactivated:be,errorCaptured:be,serverPrefetch:be,components:Jt,directives:Jt,watch:Xo,provide:Xn,inject:Yo};function Xn(e,t){return t?e?function(){return _e(j(e)?e.call(this,this):e,j(t)?t.call(this,this):t)}:t:e}function Yo(e,t){return Jt(vn(e),vn(t))}function vn(e){if(L(e)){const t={};for(let s=0;st==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${Fe(t)}Modifiers`]||e[`${Rt(t)}Modifiers`];function tr(e,t,...s){if(e.isUnmounted)return;const n=e.vnode.props||ee;let l=s;const i=t.startsWith("update:"),r=i&&er(n,t.slice(7));r&&(r.trim&&(l=s.map(h=>re(h)?h.trim():h)),r.number&&(l=s.map(js)));let a,u=n[a=Ys(t)]||n[a=Ys(Fe(t))];!u&&i&&(u=n[a=Ys(Rt(t))]),u&&Le(u,e,6,l);const g=n[a+"Once"];if(g){if(!e.emitted)e.emitted={};else if(e.emitted[a])return;e.emitted[a]=!0,Le(g,e,6,l)}}const sr=new WeakMap;function ri(e,t,s=!1){const n=s?sr:t.emitsCache,l=n.get(e);if(l!==void 0)return l;const i=e.emits;let r={},a=!1;if(!j(e)){const u=g=>{const h=ri(g,t,!0);h&&(a=!0,_e(r,h))};!s&&t.mixins.length&&t.mixins.forEach(u),e.extends&&u(e.extends),e.mixins&&e.mixins.forEach(u)}return!i&&!a?(Z(e)&&n.set(e,null),null):(L(i)?i.forEach(u=>r[u]=null):_e(r,i),Z(e)&&n.set(e,r),r)}function qs(e,t){return!e||!$s(t)?!1:(t=t.slice(2),t=t==="Once"?t:t.replace(/Once$/,""),Y(e,t[0].toLowerCase()+t.slice(1))||Y(e,Rt(t))||Y(e,t))}function Qn(e){const{type:t,vnode:s,proxy:n,withProxy:l,propsOptions:[i],slots:r,attrs:a,emit:u,render:g,renderCache:h,props:b,data:M,setupState:I,ctx:U,inheritAttrs:R}=e,se=Rs(e);let K,B;try{if(s.shapeFlag&4){const D=l||n,z=D;K=qe(g.call(z,D,h,b,I,M,U)),B=a}else{const D=t;K=qe(D.length>1?D(b,{attrs:a,slots:r,emit:u}):D(b,null)),B=t.props?a:nr(a)}}catch(D){At.length=0,Ks(D,e,1),K=Ye(ct)}let W=K;if(B&&R!==!1){const D=Object.keys(B),{shapeFlag:z}=W;D.length&&z&7&&(i&&D.some(Ls)&&(B=lr(B,i)),W=Vt(W,B,!1,!0))}if(s.dirs&&(W=Vt(W,null,!1,!0),W.dirs=W.dirs?W.dirs.concat(s.dirs):s.dirs),s.transition){const D=Us(W.type)&&Ql(W)||W;Mn(D,s.transition)}return K=W,Rs(se),K}const nr=e=>{let t;for(const s in e)(s==="class"||s==="style"||$s(s))&&((t||(t={}))[s]=e[s]);return t},lr=(e,t)=>{const s={};for(const n in e)(!Ls(n)||!(n.slice(9)in t))&&(s[n]=e[n]);return s};function ir(e,t,s){const{props:n,children:l,component:i}=e,{props:r,children:a,patchFlag:u}=t,g=i.emitsOptions;if(t.dirs||t.transition)return!0;if(s&&u>=0){if(u&1024)return!0;if(u&16)return n?el(n,r,g):!!r;if(u&8){const h=t.dynamicProps;for(let b=0;bObject.create(ci),fi=e=>Object.getPrototypeOf(e)===ci;function rr(e,t,s,n=!1){const l={},i=ui();e.propsDefaults=Object.create(null),di(e,t,l,i);for(const r in e.propsOptions[0])r in l||(l[r]=void 0);s?e.props=n?l:ho(l):e.type.props?e.props=l:e.props=i,e.attrs=i}function ar(e,t,s,n){const{props:l,attrs:i,vnode:{patchFlag:r}}=e,a=G(l),[u]=e.propsOptions;let g=!1;if((n||r>0)&&!(r&16)){if(r&8){const h=e.vnode.dynamicProps;for(let b=0;b{u=!0;const[M,I]=pi(b,t,!0);_e(r,M),I&&a.push(...I)};!s&&t.mixins.length&&t.mixins.forEach(h),e.extends&&h(e.extends),e.mixins&&e.mixins.forEach(h)}if(!i&&!u)return Z(e)&&n.set(e,Dt),Dt;if(L(i))for(let h=0;he==="_"||e==="_ctx"||e==="$stable",Dn=e=>L(e)?e.map(qe):[qe(e)],ur=(e,t,s)=>{if(t._n)return t;const n=Eo((...l)=>Dn(t(...l)),s);return n._c=!1,n},hi=(e,t,s)=>{const n=e._ctx;for(const l in e){if(Fn(l))continue;const i=e[l];if(j(i))t[l]=ur(l,i,n);else if(i!=null){const r=Dn(i);t[l]=()=>r}}},gi=(e,t)=>{const s=Dn(t);e.slots.default=()=>s},vi=(e,t,s)=>{for(const n in t)(s||!Fn(n))&&(e[n]=t[n])},fr=(e,t,s)=>{const n=e.slots=ui();if(e.vnode.shapeFlag&32){const l=t._;l?(vi(n,t,s),s&&Tl(n,"_",l,!0)):hi(t,n)}else t&&gi(e,t)},dr=(e,t,s)=>{const{vnode:n,slots:l}=e;let i=!0,r=ee;if(n.shapeFlag&32){const a=t._;a?s&&a===1?i=!1:vi(l,t,s):(i=!t.$stable,hi(t,l)),r=t}else t&&(gi(e,t),r={default:1});if(i)for(const a in l)!Fn(a)&&r[a]==null&&delete l[a]},Ce=_r;function pr(e){return hr(e)}function hr(e,t){const s=Vs();s.__VUE__=!0;const{insert:n,remove:l,patchProp:i,createElement:r,createText:a,createComment:u,setText:g,setElementText:h,parentNode:b,nextSibling:M,setScopeId:I=Ge,insertStaticContent:U}=e,R=(c,d,m,S=null,w=null,x=null,P=void 0,O=null,C=!!d.dynamicChildren)=>{if(c===d)return;c&&!zt(c,d)&&(S=ht(c),me(c,w,x,!0),c=null),d.patchFlag===-2&&(C=!1,d.dynamicChildren=null);const{type:y,ref:k,shapeFlag:A}=d;switch(y){case zs:se(c,d,m,S);break;case ct:K(c,d,m,S);break;case Es:c==null&&B(d,m,S,P);break;case ie:ft(c,d,m,S,w,x,P,O,C);break;default:A&1?z(c,d,m,S,w,x,P,O,C):A&6?Qe(c,d,m,S,w,x,P,O,C):(A&64||A&128)&&y.process(c,d,m,S,w,x,P,O,C,He)}k!=null&&w?Qt(k,c&&c.ref,x,d||c,!d):k==null&&c&&c.ref!=null&&Qt(c.ref,null,x,c,!0)},se=(c,d,m,S)=>{if(c==null)n(d.el=a(d.children),m,S);else{const w=d.el=c.el;d.children!==c.children&&g(w,d.children)}},K=(c,d,m,S)=>{c==null?n(d.el=u(d.children||""),m,S):d.el=c.el},B=(c,d,m,S)=>{[c.el,c.anchor]=U(c.children,d,m,S,c.el,c.anchor)},W=({el:c,anchor:d},m,S)=>{let w;for(;c&&c!==d;)w=M(c),n(c,m,S),c=w;n(d,m,S)},D=({el:c,anchor:d})=>{let m;for(;c&&c!==d;)m=M(c),l(c),c=m;l(d)},z=(c,d,m,S,w,x,P,O,C)=>{if(d.type==="svg"?P="svg":d.type==="math"&&(P="mathml"),c==null)we(d,m,S,w,x,P,O,C);else{const y=c.el&&c.el._isVueCE?c.el:null;try{y&&y._beginPatch(),Mt(c,d,w,x,P,O,C)}finally{y&&y._endPatch()}}},we=(c,d,m,S,w,x,P,O)=>{let C,y;const{props:k,shapeFlag:A,transition:F,dirs:$}=c;if(C=c.el=r(c.type,x,k&&k.is,k),A&8?h(C,c.children):A&16&&Se(c.children,C,null,S,w,ln(c,x),P,O),$&&kt(c,null,S,"created"),ne(C,c,c.scopeId,P,S),k){for(const N in k)N!=="value"&&!Yt(N)&&i(C,N,null,k[N],x,S);"value"in k&&i(C,"value",null,k.value,x),(y=k.onVnodeBeforeMount)&&Ke(y,S,c)}$&&kt(c,null,S,"beforeMount");const V=gr(w,F);V&&F.beforeEnter(C),n(C,d,m),((y=k&&k.onVnodeMounted)||V||$)&&Ce(()=>{try{y&&Ke(y,S,c),V&&F.enter(C),$&&kt(c,null,S,"mounted")}finally{}},w)},ne=(c,d,m,S,w)=>{if(m&&I(c,m),S)for(let x=0;x{for(let y=C;y{const O=d.el=c.el;let{patchFlag:C,dynamicChildren:y,dirs:k}=d;C|=c.patchFlag&16;const A=c.props||ee,F=d.props||ee;let $;if(m&&Tt(m,!1),($=F.onVnodeBeforeUpdate)&&Ke($,m,d,c),k&&kt(d,c,m,"beforeUpdate"),m&&Tt(m,!0),y&&(!c.dynamicChildren||c.dynamicChildren.length!==y.length)&&(C=0,P=!1,y=null),(A.innerHTML&&F.innerHTML==null||A.textContent&&F.textContent==null)&&h(O,""),y?Ze(c.dynamicChildren,y,O,m,S,ln(d,w),x):P||X(c,d,O,null,m,S,ln(d,w),x,!1),C>0){if(C&16)mt(O,A,F,m,w);else if(C&2&&A.class!==F.class&&i(O,"class",null,F.class,w),C&4&&i(O,"style",A.style,F.style,w),C&8){const V=d.dynamicProps;for(let N=0;N{$&&Ke($,m,d,c),k&&kt(d,c,m,"updated")},S)},Ze=(c,d,m,S,w,x,P)=>{for(let O=0;O{if(d!==m){if(d!==ee)for(const x in d)!Yt(x)&&!(x in m)&&i(c,x,d[x],null,w,S);for(const x in m){if(Yt(x))continue;const P=m[x],O=d[x];P!==O&&x!=="value"&&i(c,x,O,P,w,S)}"value"in m&&i(c,"value",d.value,m.value,w)}},ft=(c,d,m,S,w,x,P,O,C)=>{const y=d.el=c?c.el:a(""),k=d.anchor=c?c.anchor:a("");let{patchFlag:A,dynamicChildren:F,slotScopeIds:$}=d;$&&(O=O?O.concat($):$),c==null?(n(y,m,S),n(k,m,S),Se(d.children||[],m,k,w,x,P,O,C)):A>0&&A&64&&F&&c.dynamicChildren&&c.dynamicChildren.length===F.length?(Ze(c.dynamicChildren,F,m,w,x,P,O),(d.key!=null||w&&d===w.subTree)&&_i(c,d,!0)):X(c,d,m,k,w,x,P,O,C)},Qe=(c,d,m,S,w,x,P,O,C)=>{d.slotScopeIds=O,c==null?d.shapeFlag&512?w.ctx.activate(d,m,S,P,C):Ne(d,m,S,w,x,P,C):ds(c,d,C)},Ne=(c,d,m,S,w,x,P)=>{const O=c.component=kr(c,S,w);if(In(c)&&(O.ctx.renderer=He),Er(O,!1,P),O.asyncDep){if(w&&w.registerDep(O,fe,P),!c.el){const C=O.subTree=Ye(ct);K(null,C,d,m),c.placeholder=C.el}}else fe(O,c,d,m,w,x,P)},ds=(c,d,m)=>{const S=d.component=c.component;if(ir(c,d,m))if(S.asyncDep&&!S.asyncResolved){le(S,d,m);return}else S.next=d,S.update();else d.el=c.el,S.vnode=d},fe=(c,d,m,S,w,x,P)=>{const O=()=>{if(c.isMounted){let{next:A,bu:F,u:$,parent:V,vnode:N}=c;{const Pe=mi(c);if(Pe){A&&(A.el=N.el,le(c,A,P)),Pe.asyncDep.then(()=>{Ce(()=>{c.isUnmounted||y()},w)});return}}let J=A,oe;Tt(c,!1),A?(A.el=N.el,le(c,A,P)):A=N,F&&ks(F),(oe=A.props&&A.props.onVnodeBeforeUpdate)&&Ke(oe,V,A,N),Tt(c,!0);const ce=Qn(c),Oe=c.subTree;c.subTree=ce,R(Oe,ce,b(Oe.el),ht(Oe),c,w,x),A.el=ce.el,J===null&&or(c,ce.el),$&&Ce($,w),(oe=A.props&&A.props.onVnodeUpdated)&&Ce(()=>Ke(oe,V,A,N),w)}else{let A;const{el:F,props:$}=d,{bm:V,m:N,parent:J,root:oe,type:ce}=c,Oe=es(d);Tt(c,!1),V&&ks(V),!Oe&&(A=$&&$.onVnodeBeforeMount)&&Ke(A,J,d),Tt(c,!0);{oe.ce&&oe.ce._hasShadowRoot()&&oe.ce._injectChildStyle(ce,c.parent?c.parent.type:void 0);const Pe=c.subTree=Qn(c);R(null,Pe,m,S,c,w,x),d.el=Pe.el}if(N&&Ce(N,w),!Oe&&(A=$&&$.onVnodeMounted)){const Pe=d;Ce(()=>Ke(A,J,Pe),w)}(d.shapeFlag&256||J&&es(J.vnode)&&J.vnode.shapeFlag&256)&&c.a&&Ce(c.a,w),c.isMounted=!0,d=m=S=null}};c.scope.on();const C=c.effect=new Al(O);c.scope.off();const y=c.update=C.run.bind(C),k=c.job=C.runIfDirty.bind(C);k.i=c,k.id=c.uid,C.scheduler=()=>Rn(k),Tt(c,!0),y()},le=(c,d,m)=>{d.component=c;const S=c.vnode.props;c.vnode=d,c.next=null,ar(c,d.props,S,m),dr(c,d.children,m),ot(),qn(c),rt()},X=(c,d,m,S,w,x,P,O,C=!1)=>{const y=c&&c.children,k=c?c.shapeFlag:0,A=d.children,{patchFlag:F,shapeFlag:$}=d;if(F>0){if(F&128){bt(y,A,m,S,w,x,P,O,C);return}else if(F&256){je(y,A,m,S,w,x,P,O,C);return}}$&8?(k&16&&pt(y,w,x),A!==y&&h(m,A)):k&16?$&16?bt(y,A,m,S,w,x,P,O,C):pt(y,w,x,!0):(k&8&&h(m,""),$&16&&Se(A,m,S,w,x,P,O,C))},je=(c,d,m,S,w,x,P,O,C)=>{c=c||Dt,d=d||Dt;const y=c.length,k=d.length,A=Math.min(y,k);let F;for(F=0;Fk?pt(c,w,x,!0,!1,A):Se(d,m,S,w,x,P,O,C,A)},bt=(c,d,m,S,w,x,P,O,C)=>{let y=0;const k=d.length;let A=c.length-1,F=k-1;for(;y<=A&&y<=F;){const $=c[y],V=d[y]=C?nt(d[y]):qe(d[y]);if(zt($,V))R($,V,m,null,w,x,P,O,C);else break;y++}for(;y<=A&&y<=F;){const $=c[A],V=d[F]=C?nt(d[F]):qe(d[F]);if(zt($,V))R($,V,m,null,w,x,P,O,C);else break;A--,F--}if(y>A){if(y<=F){const $=F+1,V=$F)for(;y<=A;)me(c[y],w,x,!0),y++;else{const $=y,V=y,N=new Map;for(y=V;y<=F;y++){const de=d[y]=C?nt(d[y]):qe(d[y]);de.key!=null&&N.set(de.key,y)}let J,oe=0;const ce=F-V+1;let Oe=!1,Pe=0;const Ae=new Array(ce);for(y=0;y=ce){me(de,w,x,!0);continue}let ke;if(de.key!=null)ke=N.get(de.key);else for(J=V;J<=F;J++)if(Ae[J-V]===0&&zt(de,d[J])){ke=J;break}ke===void 0?me(de,w,x,!0):(Ae[ke-V]=y+1,ke>=Pe?Pe=ke:Oe=!0,R(de,d[ke],m,null,w,x,P,O,C),oe++)}const hs=Oe?vr(Ae):Dt;for(J=hs.length-1,y=ce-1;y>=0;y--){const de=V+y,ke=d[de],xt=d[de+1],gs=de+1{const{el:x,type:P,transition:O,children:C,shapeFlag:y}=c;if(y&6){Ve(c.component.subTree,d,m,S);return}if(y&128){c.suspense.move(d,m,S);return}if(y&64){P.move(c,d,m,He);return}if(P===ie){n(x,d,m);for(let A=0;AO.enter(x),w));else{const{leave:A,delayLeave:F,afterLeave:$}=O,V=()=>{c.ctx.isUnmounted?l(x):n(x,d,m)},N=()=>{const J=x._isLeaving||!!x[sn];x._isLeaving&&x[sn](!0),O.persisted&&!J?V():A(x,()=>{V(),$&&$()})};F?F(x,V,N):N()}else n(x,d,m)},me=(c,d,m,S=!1,w=!1)=>{const{type:x,props:P,ref:O,children:C,dynamicChildren:y,shapeFlag:k,patchFlag:A,dirs:F,cacheIndex:$,memo:V}=c;if(A===-2&&(w=!1),O!=null&&(ot(),Qt(O,null,m,c,!0),rt()),$!=null&&(d.renderCache[$]=void 0),k&256){d.ctx.deactivate(c);return}const N=k&1&&F,J=!es(c);let oe;if(J&&(oe=P&&P.onVnodeBeforeUnmount)&&Ke(oe,d,c),k&6)Ut(c.component,m,S);else{if(k&128){c.suspense.unmount(m,S);return}N&&kt(c,null,d,"beforeUnmount"),k&64?c.type.remove(c,d,m,He,S):y&&!y.hasOnce&&(x!==ie||A>0&&A&64)?pt(y,d,m,!1,!0):(x===ie&&A&384||!w&&k&16)&&pt(C,d,m),S&&ps(c)}const ce=V!=null&&$==null;(J&&(oe=P&&P.onVnodeUnmounted)||N||ce)&&Ce(()=>{oe&&Ke(oe,d,c),N&&kt(c,null,d,"unmounted"),ce&&(c.el=null)},m)},ps=c=>{const{type:d,el:m,anchor:S,transition:w}=c;if(d===ie){dt(m,S);return}if(d===Es){D(c);return}const x=()=>{l(m),w&&!w.persisted&&w.afterLeave&&w.afterLeave()};if(c.shapeFlag&1&&w&&!w.persisted){const{leave:P,delayLeave:O}=w,C=()=>P(m,x);O?O(c.el,x,C):C()}else x()},dt=(c,d)=>{let m;for(;c!==d;)m=M(c),l(c),c=m;l(d)},Ut=(c,d,m)=>{const{bum:S,scope:w,job:x,subTree:P,um:O,m:C,a:y}=c;sl(C),sl(y),S&&ks(S),w.stop(),x&&(x.flags|=8,me(P,c,d,m)),O&&Ce(O,d),Ce(()=>{c.isUnmounted=!0},d)},pt=(c,d,m,S=!1,w=!1,x=0)=>{for(let P=x;P{if(c.shapeFlag&6)return ht(c.component.subTree);if(c.shapeFlag&128)return c.suspense.next();const d=M(c.anchor||c.el),m=d&&d[Mo];return m?M(m):d};let Wt=!1;const yt=(c,d,m)=>{let S;c==null?d._vnode&&(me(d._vnode,null,null,!0),S=d._vnode.component):R(d._vnode||null,c,d,null,null,null,m),d._vnode=c,Wt||(Wt=!0,qn(S),Jl(),Wt=!1)},He={p:R,um:me,m:Ve,r:ps,mt:Ne,mc:Se,pc:X,pbc:Ze,n:ht,o:e};return{render:yt,hydrate:void 0,createApp:Qo(yt)}}function ln({type:e,props:t},s){return s==="svg"&&e==="foreignObject"||s==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:s}function Tt({effect:e,job:t},s){s?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function gr(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function _i(e,t,s=!1){const n=e.children,l=t.children;if(L(n)&&L(l))for(let i=0;i>1,e[s[a]]0&&(t[n]=s[i-1]),s[i]=n)}}for(i=s.length,r=s[i-1];i-- >0;)s[i]=r,r=t[r];return s}function mi(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:mi(t)}function sl(e){if(e)for(let t=0;te.__isSuspense;function _r(e,t){t&&t.pendingBranch?L(e)?t.effects.push(...e):t.effects.push(e):To(e)}const ie=Symbol.for("v-fgt"),zs=Symbol.for("v-txt"),ct=Symbol.for("v-cmt"),Es=Symbol.for("v-stc"),At=[];let Ee=null;function T(e=!1){At.push(Ee=e?null:[])}function xi(){At.pop(),Ee=At[At.length-1]||null}let is=1;function nl(e,t=!1){is+=e,e<0&&Ee&&t&&(Ee.hasOnce=!0)}function wi(e){return e.dynamicChildren=is>0?Ee||Dt:null,xi(),is>0&&Ee&&Ee.push(e),e}function E(e,t,s,n,l,i){return wi(o(e,t,s,n,l,i,!0))}function mr(e,t,s,n,l){return wi(Ye(e,t,s,n,l,!0))}function Si(e){return e?e.__v_isVNode===!0:!1}function zt(e,t){return e.type===t.type&&e.key===t.key}const Ci=({key:e})=>e??null,Os=({ref:e,ref_key:t,ref_for:s})=>(typeof e=="number"&&(e=""+e),e!=null?re(e)||ve(e)||j(e)?{i:Me,r:e,k:t,f:!!s}:e:null);function o(e,t=null,s=null,n=0,l=null,i=e===ie?0:1,r=!1,a=!1){const u={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&Ci(t),ref:t&&Os(t),scopeId:Yl,slotScopeIds:null,children:s,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:i,patchFlag:n,dynamicProps:l,dynamicChildren:null,appContext:null,ctx:Me};return a?(Fs(u,s),i&128&&e.normalize(u)):s&&(u.shapeFlag|=re(s)?8:16),is>0&&!r&&Ee&&(u.patchFlag>0||i&6)&&u.patchFlag!==32&&Ee.push(u),u}const Ye=br;function br(e,t=null,s=null,n=0,l=null,i=!1){if((!e||e===Wo)&&(e=ct),Si(e)){const a=Vt(e,t,!0);return s&&Fs(a,s),is>0&&!i&&Ee&&(a.shapeFlag&6?Ee[Ee.indexOf(e)]=a:Ee.push(a)),a.patchFlag=-2,a}if(Rr(e)&&(e=e.__vccOpts),t){t=yr(t);let{class:a,style:u}=t;a&&!re(a)&&(t.class=Q(a)),Z(u)&&(An(u)&&!L(u)&&(u=_e({},u)),t.style=Hs(u))}const r=re(e)?1:yi(e)?128:Us(e)?64:Z(e)?4:j(e)?2:0;return o(e,t,s,n,l,r,i,!0)}function yr(e){return e?An(e)||fi(e)?_e({},e):e:null}function Vt(e,t,s=!1,n=!1){const{props:l,ref:i,patchFlag:r,children:a,transition:u}=e,g=t?wr(l||{},t):l,h={__v_isVNode:!0,__v_skip:!0,type:e.type,props:g,key:g&&Ci(g),ref:t&&t.ref?s&&i?L(i)?i.concat(Os(t)):[i,Os(t)]:Os(t):i,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:a,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==ie?r===-1?16:r|16:r,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:u,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&Vt(e.ssContent),ssFallback:e.ssFallback&&Vt(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return u&&n&&Mn(h,u.clone(h)),h}function q(e=" ",t=0){return Ye(zs,null,e,t)}function xr(e,t){const s=Ye(Es,null,e);return s.staticCount=t,s}function ue(e="",t=!1){return t?(T(),mr(ct,null,e)):Ye(ct,null,e)}function qe(e){return e==null||typeof e=="boolean"?Ye(ct):L(e)?Ye(ie,null,e.slice()):Si(e)?nt(e):Ye(zs,null,String(e))}function nt(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:Vt(e)}function Fs(e,t){let s=0;const{shapeFlag:n}=e;if(t==null)t=null;else if(L(t))s=16;else if(typeof t=="object")if(n&65){const l=t.default;l&&(l._c&&(l._d=!1),Fs(e,l()),l._c&&(l._d=!0));return}else{s=32;const l=t._;!l&&!fi(t)?t._ctx=Me:l===3&&Me&&(Me.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else if(j(t)){if(n&65){Fs(e,{default:t});return}t={default:t,_ctx:Me},s=32}else t=String(t),n&64?(s=16,t=[q(t)]):s=8;e.children=t,e.shapeFlag|=s}function wr(...e){const t={};for(let s=0;sxe||Me;let Ds,os;{const e=Vs(),t=(s,n)=>{let l;return(l=e[s])||(l=e[s]=[]),l.push(n),i=>{l.length>1?l.forEach(r=>r(i)):l[0](i)}};Ds=t("__VUE_INSTANCE_SETTERS__",s=>xe=s),os=t("__VUE_SSR_SETTERS__",s=>rs=s)}const fs=e=>{const t=xe;return Ds(e),e.scope.on(),()=>{e.scope.off(),Ds(t)}},ll=()=>{xe&&xe.scope.off(),Ds(null)};function ki(e){return e.vnode.shapeFlag&4}let rs=!1;function Er(e,t=!1,s=!1){t&&os(t);const{props:n,children:l}=e.vnode,i=ki(e);rr(e,n,i,t),fr(e,l,s||t);const r=i?Or(e,t):void 0;return t&&os(!1),r}function Or(e,t){const s=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,qo);const{setup:n}=s;if(n){ot();const l=e.setupContext=n.length>1?Ar(e):null,i=fs(e),r=us(n,e,0,[e.props,l]),a=wl(r);if(rt(),i(),(a||e.sp)&&!es(e)&&ei(e),a){if(r.then(ll,ll),t)return r.then(u=>{os(!0);try{il(e,u,t)}finally{os(!1)}}).catch(u=>{Ks(u,e,0)});e.asyncDep=r}else il(e,r)}else Ti(e)}function il(e,t,s){j(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:Z(t)&&(e.setupState=Ul(t)),Ti(e)}function Ti(e,t,s){const n=e.type;e.render||(e.render=n.render||Ge);{const l=fs(e);ot();try{zo(e)}finally{rt(),l()}}}const Pr={get(e,t){return ge(e,"get",""),e[t]}};function Ar(e){const t=s=>{e.exposed=s||{}};return{attrs:new Proxy(e.attrs,Pr),slots:e.slots,emit:e.emit,expose:t}}function Js(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(Ul(go(e.exposed)),{get(t,s){if(s in t)return t[s];if(s in ts)return ts[s](e)},has(t,s){return s in t||s in ts}})):e.proxy}function Rr(e){return j(e)&&"__vccOpts"in e}const ae=(e,t)=>xo(e,t,rs),Mr="3.5.41";/** +* @vue/runtime-dom v3.5.41 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let mn;const ol=typeof window<"u"&&window.trustedTypes;if(ol)try{mn=ol.createPolicy("vue",{createHTML:e=>e})}catch{}const Ei=mn?e=>mn.createHTML(e):e=>e,Ir="http://www.w3.org/2000/svg",Fr="http://www.w3.org/1998/Math/MathML",st=typeof document<"u"?document:null,rl=st&&st.createElement("template"),Dr={insert:(e,t,s)=>{t.insertBefore(e,s||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,s,n)=>{const l=t==="svg"?st.createElementNS(Ir,e):t==="mathml"?st.createElementNS(Fr,e):s?st.createElement(e,{is:s}):st.createElement(e);return e==="select"&&n&&n.multiple!=null&&l.setAttribute("multiple",n.multiple),l},createText:e=>st.createTextNode(e),createComment:e=>st.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>st.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,s,n,l,i){const r=s?s.previousSibling:t.lastChild;if(l&&(l===i||l.nextSibling))for(;t.insertBefore(l.cloneNode(!0),s),!(l===i||!(l=l.nextSibling)););else{rl.innerHTML=Ei(n==="svg"?`${e}`:n==="mathml"?`${e}`:e);const a=rl.content;if(n==="svg"||n==="mathml"){const u=a.firstChild;for(;u.firstChild;)a.appendChild(u.firstChild);a.removeChild(u)}t.insertBefore(a,s)}return[r?r.nextSibling:t.firstChild,s?s.previousSibling:t.lastChild]}},$r=Symbol("_vtc");function Lr(e,t,s){const n=e[$r];n&&(t=(t?[t,...n]:[...n]).join(" ")),t==null?e.removeAttribute("class"):s?e.setAttribute("class",t):e.className=t}const al=Symbol("_vod"),Nr=Symbol("_vsh"),jr=Symbol(""),Vr=/(?:^|;)\s*display\s*:/;function Hr(e,t,s){const n=e.style,l=re(s);let i=!1;if(s&&!l){if(t)if(re(t))for(const r of t.split(";")){const a=r.slice(0,r.indexOf(":")).trim();s[a]==null&&Gt(n,a,"")}else for(const r in t)s[r]==null&&Gt(n,r,"");for(const r in s){r==="display"&&(i=!0);const a=s[r];a!=null?Kr(e,r,!re(t)&&t?t[r]:void 0,a)||Gt(n,r,a):Gt(n,r,"")}}else if(l){if(t!==s){const r=n[jr];r&&(s+=";"+r),n.cssText=s,i=Vr.test(s)}}else t&&e.removeAttribute("style");al in e&&(e[al]=i?n.display:"",e[Nr]&&(n.display="none"))}const cl=/\s*!important$/;function Gt(e,t,s){if(L(s))s.forEach(n=>Gt(e,t,n));else if(s==null&&(s=""),t.startsWith("--"))e.setProperty(t,s);else{const n=Br(e,t);cl.test(s)?e.setProperty(Rt(n),s.replace(cl,""),"important"):e[n]=s}}const ul=["Webkit","Moz","ms"],on={};function Br(e,t){const s=on[t];if(s)return s;let n=Fe(t);if(n!=="filter"&&n in e)return on[t]=n;n=kl(n);for(let l=0;lrn||(Gr.then(()=>rn=0),rn=Date.now());function Xr(e,t){const s=n=>{if(!n._vts)n._vts=Date.now();else if(n._vts<=s.attached)return;const l=s.value;if(L(l)){const i=n.stopImmediatePropagation;n.stopImmediatePropagation=()=>{i.call(n),n._stopped=!0};const r=l.slice(),a=[n];for(let u=0;ue.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,Zr=(e,t,s,n,l,i)=>{const r=l==="svg";t==="class"?Lr(e,n,r):t==="style"?Hr(e,s,n):$s(t)?Ls(t)||Wr(e,t,s,n,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Qr(e,t,n,r))?(pl(e,t,n),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&dl(e,t,n,r,i,t!=="value")):e._isVueCE&&(ea(e,t)||e._def.__asyncLoader&&(/[A-Z]/.test(t)||!re(n)))?pl(e,Fe(t),n,i,t):(t==="true-value"?e._trueValue=n:t==="false-value"&&(e._falseValue=n),dl(e,t,n,r))};function Qr(e,t,s,n){if(n)return!!(t==="innerHTML"||t==="textContent"||t in e&&gl(t)&&j(s));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="autocorrect"||t==="sandbox"&&e.tagName==="IFRAME"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const l=e.tagName;if(l==="IMG"||l==="VIDEO"||l==="CANVAS"||l==="SOURCE")return!1}return gl(t)&&re(s)?!1:t in e}function ea(e,t){const s=e._def.props;if(!s)return!1;const n=Fe(t);return Array.isArray(s)?s.some(l=>Fe(l)===n):Object.keys(s).some(l=>Fe(l)===n)}const Ht=e=>{const t=e.props["onUpdate:modelValue"]||!1;return L(t)?s=>ks(t,s):t};function ta(e){e.target.composing=!0}function vl(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const Je=Symbol("_assign"),Ss=Symbol("_initialValue");function an(e,t,s){return t&&(e=e.trim()),s&&(e=js(e)),e}const Cs={created(e,{modifiers:{lazy:t,trim:s,number:n}},l){e.parentNode&&(e.type==="text"?e[Ss]=e.defaultValue.replace(/[\r\n]/g,""):e.type==="textarea"&&(e[Ss]=e.defaultValue.replace(/\r\n?/g,` +`))),e[Je]=Ht(l);const i=n||l.props&&l.props.type==="number";_t(e,t?"change":"input",r=>{r.target.composing||e[Je](an(e.value,s,i))}),(s||i)&&_t(e,"change",()=>{e.value=an(e.value,s,i)}),t||(_t(e,"compositionstart",ta),_t(e,"compositionend",vl),_t(e,"change",vl))},mounted(e,{value:t,modifiers:{trim:s,number:n}}){const l=t??"",i=e[Ss];delete e[Ss],i!==void 0&&(e.type==="text"||e.type==="textarea")&&e.value!==i?e[Je](an(e.value,s,n)):e.value=l},beforeUpdate(e,{value:t,oldValue:s,modifiers:{lazy:n,trim:l,number:i}},r){if(e[Je]=Ht(r),e.composing)return;const a=(i||e.type==="number")&&!/^0\d/.test(e.value)?js(e.value):e.value,u=t??"";if(a===u)return;const g=e.getRootNode();(g instanceof Document||g instanceof ShadowRoot)&&g.activeElement===e&&e.type!=="range"&&(n&&t===s||l&&e.value.trim()===u)||(e.value=u)}},_l={deep:!0,created(e,t,s){e[Je]=Ht(s),_t(e,"change",()=>{const n=e._modelValue,l=as(e),i=e.checked,r=e[Je];if(L(n)){const a=wn(n,l),u=a!==-1;if(i&&!u)r(n.concat(l));else if(!i&&u){const g=[...n];g.splice(a,1),r(g)}}else if(Bt(n)){const a=new Set(n);i?a.add(l):a.delete(l),r(a)}else r(Oi(e,i))})},mounted:ml,beforeUpdate(e,t,s){e[Je]=Ht(s),ml(e,t,s)}};function ml(e,{value:t,oldValue:s},n){e._modelValue=t;let l;if(L(t))l=wn(t,n.props.value)>-1;else if(Bt(t))l=t.has(n.props.value);else{if(t===s)return;l=Kt(t,Oi(e,!0))}e.checked!==l&&(e.checked=l)}const sa={deep:!0,created(e,{value:t,modifiers:{number:s}},n){e._modelValue=t,_t(e,"change",()=>{const l=Array.prototype.filter.call(e.options,i=>i.selected).map(i=>s?js(as(i)):as(i));e[Je](e.multiple?Bt(e._modelValue)?new Set(l):l:l[0]),e._assigning=!0,ql(()=>{e._assigning=!1})}),e[Je]=Ht(n)},mounted(e,{value:t}){bl(e,t)},beforeUpdate(e,{value:t},s){e._modelValue=t,e[Je]=Ht(s)},updated(e,{value:t}){e._assigning||bl(e,t)}};function bl(e,t){const s=e.multiple,n=L(t);if(!(s&&!n&&!Bt(t))){for(let l=0,i=e.options.length;lString(g)===String(a)):r.selected=wn(t,a)>-1}else r.selected=t.has(a);else if(Kt(as(r),t)){e.selectedIndex!==l&&(e.selectedIndex=l);return}}!s&&e.selectedIndex!==-1&&(e.selectedIndex=-1)}}function as(e){return"_value"in e?e._value:e.value}function Oi(e,t){const s=t?"_trueValue":"_falseValue";return s in e?e[s]:t}const na=["ctrl","shift","alt","meta"],la={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>na.some(s=>e[`${s}Key`]&&!t.includes(s))},ia=(e,t)=>{if(!e)return e;const s=e._withMods||(e._withMods={}),n=t.join(".");return s[n]||(s[n]=((l,...i)=>{for(let r=0;r{const t=ra().createApp(...e),{mount:s}=t;return t.mount=n=>{const l=ua(n);if(!l)return;const i=t._component;!j(i)&&!i.render&&!i.template&&(i.template=l.innerHTML),l.nodeType===1&&(l.textContent="");const r=s(l,!1,ca(l));return l instanceof Element&&(l.removeAttribute("v-cloak"),l.setAttribute("data-v-app","")),r},t});function ca(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function ua(e){return re(e)?document.querySelector(e):e}const fa={class:"app-shell"},da={class:"content",id:"overview"},pa={class:"topbar"},ha={class:"topbar-meta"},ga={class:"as-of"},va={key:0,class:"state-card"},_a={key:1,class:"state-card error-state"},ma={class:"kpi-grid","aria-label":"Signal summary"},ba={class:"kpi-card accent-card"},ya={class:"kpi-value"},xa={class:"kpi-foot"},wa={class:"long-count"},Sa={class:"short-count"},Ca={class:"neutral-count"},ka={class:"kpi-card"},Ta={class:"kpi-value"},Ea={class:"kpi-foot"},Oa={class:"panel theme-panel",id:"themes"},Pa={class:"panel-header signal-header"},Aa={class:"status-tag"},Ra={class:"theme-grid"},Ma={class:"theme-card-head"},Ia={class:"theme-chip"},Fa={class:"theme-label-th"},Da={class:"theme-surprise"},$a={class:"theme-surprise-value"},La={class:"theme-read"},Na={key:0,class:"theme-read-value"},ja={key:1,class:"theme-read-value"},Va={key:2,class:"theme-read-value"},Ha={key:3,class:"theme-read-value"},Ba={key:0,class:"theme-narrative"},Ka={key:0,class:"macro-panel"},Ua={class:"macro-chips"},Wa={class:"macro-chip"},qa={class:"macro-chip"},za={class:"macro-chip"},Ja={class:"macro-chip"},Ga={class:"macro-chip"},Ya={class:"panel stock-panel",id:"stocks"},Xa={class:"panel-header signal-header"},Za={class:"stock-controls"},Qa={class:"toggle-filter"},ec={key:0,class:"empty-research"},tc={key:1,class:"table-wrap"},sc={class:"factor-table"},nc=["onClick"],lc={key:1,class:"muted-cell"},ic={class:"combined-cell"},oc={class:"symbol-name"},rc={key:0,class:"muted-cell"},ac={class:"score-cell"},cc={key:0,class:"dividend-dot",title:"จ่ายปันผล"},uc={class:"panel lineage-panel",id:"lineage"},fc={class:"panel-header signal-header"},dc={class:"status-tag"},pc={class:"table-wrap"},hc={class:"source-table"},gc={class:"source-name"},vc={class:"muted-cell"},_c={class:"muted-cell"},mc={class:"muted-cell"},bc={class:"muted-cell"},yc={class:"panel health-panel",id:"health"},xc={key:0,class:"empty-research muted-cell"},wc={key:1},Sc={class:"source-table"},Cc={class:"source-name"},kc={class:"muted-cell",style:{"font-size":"11px"}},Tc={key:0,class:"status-tag",style:{background:"#1a7f37",color:"#fff"}},Ec={key:1,class:"status-tag warning-tag"},Oc={key:0,class:"muted-cell",style:{"font-size":"11px","word-break":"break-word"}},Pc={class:"muted-cell"},Ac=["onClick"],Rc={class:"panel sim-panel",id:"simulation"},Mc={class:"panel-header signal-header"},Ic={class:"status-tag neutral-tag"},Fc={class:"sim-controls"},Dc={class:"sim-field"},$c={class:"sim-field"},Lc=["disabled"],Nc={key:0,class:"sim-result"},jc={class:"sim-sums"},Vc={class:"sim-sum"},Hc={class:"sim-sum"},Bc={class:"sim-note"},Kc={class:"sim-buckets"},Uc={class:"sim-bucket"},Wc={class:"sim-order-table"},qc={key:0},zc={class:"muted-cell"},Jc={class:"score-cell"},Gc={class:"score-cell"},Yc={key:1},Xc={class:"sim-bucket"},Zc={class:"sim-order-table"},Qc={key:0},eu={class:"muted-cell"},tu={class:"score-cell"},su={class:"score-cell"},nu={key:1},lu={class:"sim-bucket"},iu={class:"sim-order-table"},ou={key:0},ru={class:"muted-cell"},au={class:"score-cell"},cu={class:"score-cell"},uu={key:1},fu={key:1,class:"empty-research"},du={key:2,class:"fwd-panel"},pu={key:0,class:"empty-research muted-cell"},hu={key:1,class:"source-table"},gu={class:"muted-cell"},vu={key:0,class:"status-tag warning-tag",title:"ใช้คะแนนปัจจุบัน ไม่ใช่ PIT"},_u={class:"positive-text"},mu={class:"muted-cell"},bu=["onClick"],yu=["onClick"],xu={key:2,class:"muted-cell"},wu={class:"panel backtest-panel",id:"backtest"},Su={class:"backtest-controls"},Cu={class:"checkbox-label",style:{display:"flex","align-items":"center",gap:"6px"}},ku=["disabled"],Tu={key:0,class:"state-card warning-state"},Eu={class:"muted-cell",style:{"margin-top":"4px"}},Ou={class:"muted-cell",style:{"margin-top":"2px"}},Pu={key:1,class:"state-card error-state"},Au={key:2,class:"backtest-results"},Ru={class:"bt-kpi-grid"},Mu={class:"bt-kpi"},Iu={class:"bt-kpi"},Fu={class:"bt-kpi"},Du={class:"positive-text"},$u={class:"bt-kpi"},Lu={class:"negative-text"},Nu={class:"bt-kpi"},ju={class:"bt-kpi"},Vu={class:"bt-kpi"},Hu={class:"bt-meta muted-cell"},Bu={key:0,class:"bt-meta"},Ku={key:1,class:"bt-meta muted-cell"},Uu={key:2,class:"bt-holdings"},Wu={class:"source-table",style:{"margin-top":"6px"}},qu={class:"muted-cell"},zu={key:3,class:"empty-research"},Ju={key:4,class:"bt-history"},Gu={class:"source-table"},Yu={key:0,class:"status-tag warning-tag",title:"ใช้คะแนนปัจจุบันย้อนหลัง ไม่ใช่ point-in-time"},Xu={class:"positive-text"},Zu=["title"],Qu={class:"muted-cell"},ef={class:"modal-card"},tf={class:"modal-head"},sf={key:0,class:"empty-research"},nf={key:1,class:"state-card error-state"},lf={key:2,class:"modal-body"},of={class:"modal-section"},rf={key:0,class:"modal-themes"},af={class:"contrib-name"},cf={key:0,class:"contrib-calc"},uf={key:1,class:"muted-cell"},ff={key:1,class:"muted-cell"},df={class:"modal-section"},pf={class:"fund-grid"},hf={class:"modal-sub"},gf={class:"modal-section"},vf={class:"calc-box"},_f={class:"calc-line"},mf={class:"calc-step-head"},bf={class:"calc-step-note"},yf={key:0,class:"calc-z"},xf={class:"modal-sub"},wf={__name:"App",setup(e){const t=H(null),s=H(null),n=H(null),l=H(null),i=H(null),r=H(null),a=H(1e6),u=H(null),g=H(null),h=H(!1),b=H(""),M=H(""),I=H(1e6),U=H(!1),R=H(null),se=H([]),K=H(null),B=H(!0),W=H("backtest"),D=H(!1),z=H(null),we=H(!1),ne=H("signal_score"),Se=H("desc"),Mt=H({entries:[]}),Ze=H(null),mt=H(null),ft=H(!0),Qe=H(""),Ne=H(""),ds=H(!1),fe=H("token"),le=H(!0),X=H(""),je=ae(()=>{var v;return((v=l.value)==null?void 0:v.factors)??[]}),bt=ae(()=>{var v;return((v=r.value)==null?void 0:v.themes)??[]}),Ve=ae(()=>{var v;return((v=r.value)==null?void 0:v.sources)??[]}),me=H([]),ps=H(!1),dt=ae(()=>{var v;return((v=r.value)==null?void 0:v.macro)??{}}),Ut=ae(()=>Ve.value.length),pt=ae(()=>{var v,f;return((f=(v=r.value)==null?void 0:v.source_summary)==null?void 0:f.factor_keys)??Ut.value}),ht=ae(()=>{var v;return((v=r.value)==null?void 0:v.available)??!1}),Wt=ae(()=>{var v;return((v=r.value)==null?void 0:v.board)??je.value}),yt=ae(()=>{const v={};for(const f of Wt.value)v[f.symbol]=f;return v}),He=ae(()=>{var f;const v=(f=t.value)==null?void 0:f.signal_summary;return{long:(v==null?void 0:v.long)??0,short:(v==null?void 0:v.short)??0,neutral:(v==null?void 0:v.neutral)??0,total:(v==null?void 0:v.total)??0}}),$n=v=>({monthly:"รายเดือน",quarterly:"รายไตรมาส",annual:"รายปี",daily:"รายวัน"})[v]||v,c=ae(()=>{const v={};for(const f of bt.value)v[f.id]=f.label_th;return v});function d(v){const f=yt.value[v];return((f==null?void 0:f.themes)??[]).map(Re=>c.value[Re]||Re)}const m=ae(()=>{var v;return((v=l.value)==null?void 0:v.available)??!1}),S=ae(()=>{var v;return((v=l.value)==null?void 0:v.dividend_count)??0}),w=ae(()=>{var v;return((v=i.value)==null?void 0:v.combined_count)??0}),x=ae(()=>{let v=je.value;return we.value&&(v=v.filter(f=>f.is_dividend)),v});function P(v,f){var he;return f==="signal_score"?v.signal_score??(v.signal_side==="LONG"?9999:0):f==="combined"?((he=yt.value[v.symbol])==null?void 0:he.combined)??-9999:f==="symbol"?v.symbol:f==="dividend_yield"?v.dividend_yield??-1:f==="eps_growth_yoy"?v.eps_growth_yoy??-1:f==="pe"?v.pe??0:f==="eps"?v.eps??0:f==="pbv"?v.pbv??0:f==="roe"?v.roe??0:v[f]}const O=ae(()=>{const v=[...x.value],f=Se.value==="asc"?1:-1;return v.sort((he,Re)=>{const Be=P(he,ne.value),et=P(Re,ne.value);return typeof Be=="string"?Be.localeCompare(et)*f:Be===et?he.symbol.localeCompare(Re.symbol):Be==null?1:et==null?-1:(Be-et)*f}),v});function C(v){ne.value===v?Se.value=Se.value==="asc"?"desc":"asc":(ne.value=v,Se.value="desc")}function y(v){return ne.value!==v?"":Se.value==="asc"?"↑":"↓"}function k(v,f=2){return Number(v??0).toFixed(f)}function A(v){return v==="dated_ledger"}function F(v){return A(v)?{label:"ตามวันจริง",cls:"status-tag",style:"background:#1a7f37;color:#fff"}:v==="dps_annual_proxy"?{label:"Proxy (ต่อหุ้น)",cls:"status-tag warning-tag"}:{label:"Proxy",cls:"status-tag warning-tag"}}function $(v){return A(v)?"ปันผลตามวันจริงจาก ledger (ex-date × จำนวนหุ้น) — กระแสเงินสดจริง":v==="dps_annual_proxy"?"ประมาณการปันผลต่อหุ้น (DPS ล่าสุด × จำนวนหุ้น) ไม่ใช่กระแสเงินสดตามวันจริง":"ประมาณจาก dividend yield ของพอร์ตสุดท้าย ไม่ใช่กระแสเงินสดปันผลจริง"}function V(v){return v?new Date(v).toLocaleString("en-GB",{day:"2-digit",month:"short",year:"numeric",hour:"2-digit",minute:"2-digit"}):"—"}async function N(v,f){const he=await fetch(v,f);if(!he.ok){const Re=await he.json().catch(()=>({}));throw new Error(Re.error||`Request failed: ${he.status}`)}return he.json()}async function J(){const v=await fetch("/api/v1/backtest/tourism?min_events=12"),f=await v.json().catch(()=>({}));if(![200,409].includes(v.status))throw new Error(f.error||`Request failed: ${v.status}`);return f}async function oe(){const v=await fetch("/api/v1/research/tourism/latest");if(v.status===404)return null;const f=await v.json().catch(()=>({}));if(!v.ok)throw new Error(f.error||`Request failed: ${v.status}`);return f}const ce=ae(()=>{var v;return((v=z.value)==null?void 0:v.orders)??[]}),Oe=ae(()=>{var v;return((v=z.value)==null?void 0:v.invested)??0}),Pe=ae(()=>{var v;return((v=z.value)==null?void 0:v.unallocated_cash)??0}),Ae=v=>ce.value.filter(f=>f.bucket===v);async function hs(){D.value=!0,z.value=null;try{W.value==="forward"?(z.value=await N("/api/v1/forward",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({capital:Number(a.value),use_pit:!1})}),await xt()):z.value=await N("/api/v1/simulation",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({capital:Number(a.value),mode:"backtest"})})}catch(v){Ne.value=v.message}finally{D.value=!1}}const de=H([]),ke=H(!1);async function xt(){ke.value=!0;try{const v=await N("/api/v1/forward");de.value=v.runs??[]}catch(v){Ne.value=v.message}finally{ke.value=!1}}async function gs(v){try{await N(`/api/v1/forward/${v}/mark`,{method:"POST"}),await xt()}catch(f){Ne.value=f.message}}async function Pi(v){try{await N(`/api/v1/forward/${v}/mature`,{method:"POST"}),await xt()}catch(f){Ne.value=f.message}}async function Ai(){ft.value=!0,Qe.value="";try{const[v,f,he,Re,Be,et,vs,St,_s,ms]=await Promise.all([N("/api/v1/dashboard/summary"),N("/api/v1/factors/tourism/observations"),N("/api/v1/signals"),N("/api/v1/factors"),N("/api/v1/themes"),N("/api/v1/dashboard"),N("/api/v1/paper/ledger"),N("/api/v1/auth/paper",{credentials:"include"}),J(),oe()]);t.value=v,s.value=f,n.value=he,l.value=Re,i.value=Be,r.value=et,Mt.value=vs,ds.value=!!St.authenticated,fe.value=St.mode||"token",le.value=St.enabled!==!1,X.value=St.warning||"",Ze.value=_s,mt.value=ms,await xt()}catch(v){Qe.value=v.message}finally{ft.value=!1}}async function Ri(v){u.value=v,g.value=null,h.value=!0;try{g.value=await N(`/api/v1/symbols/${v}`)}catch(f){g.value={error:f.message,symbol:v}}finally{h.value=!1}}function Ln(){u.value=null,g.value=null}async function Mi(){try{const v=await N("/api/v1/backtest/readiness");K.value=v,!b.value&&v.recommended_start&&(b.value=v.recommended_start),!M.value&&v.recommended_end&&(M.value=v.recommended_end)}catch{K.value=null}}async function Ii(){try{const v=await N("/api/v1/scheduler/sources");me.value=v.sources||[]}catch{me.value=[]}ps.value=!0}const Gs=v=>({ok:"ปกติ",network:"เครือข่ายขัดข้อง",timeout:"หมดเวลา",http:"HTTP error",parse:"รูปแบบข้อมูลผิด",structure:"หน้าเว็บเปลี่ยนโครงสร้าง",auth:"สิทธิ์/ยืนยันตัวตน",other:"อื่น ๆ"})[v]||v;async function Fi(v){const f=`[${v.at}] ${v.label} (${v.key}) — ${v.ok?"OK":"FAIL: "+Gs(v.category)} ${v.detail?"| "+v.detail:""}`;try{await navigator.clipboard.writeText(f),Ne.value=`คัดลอกสาเหตุของ ${v.key} แล้ว`}catch{Ne.value=f}}function Di(v){return v.ok?"":` (สาเหตุน่าจะ: ${Gs(v.category)})`}async function $i(){U.value=!0,R.value=null;try{R.value=await N("/api/v1/backtest/run",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({start:b.value,end:M.value,capital:Number(I.value),use_ledger:B.value})}),await Nn()}catch(v){R.value={error:v.message}}finally{U.value=!1}}async function Nn(){try{se.value=(await N("/api/v1/backtest/run")).runs||[]}catch{se.value=[]}}const wt=v=>v!=null?v>=0?"positive-text":"negative-text":"";return si(async()=>{await Ai(),await Promise.all([Nn(),Mi(),Ii()])}),(v,f)=>{var he,Re,Be,et,vs,St,_s,ms,jn,Vn,Hn;return T(),E("div",fa,[f[82]||(f[82]=xr('',1)),o("main",da,[o("header",pa,[f[17]||(f[17]=o("div",null,[o("div",{class:"eyebrow"},"Alternative data · SET50"),o("h1",null,"SET50 Signal Lab"),o("p",{class:"subtitle"},"ภาพรวม alternative factors ไทย ไปจนถึงสัญญาณลงทุนที่อธิบายได้ — research + paper only")],-1)),o("div",ha,[o("div",{class:Q(["freshness-pill",ht.value?"pill-live":"pill-fixture"])},[f[16]||(f[16]=o("span",{class:"freshness-dot"},null,-1)),q(_(ht.value?"ข้อมูลจริงจากแหล่งไทย":"ข้อมูลจำลอง (fixture)"),1)],2),o("div",ga,"ข้อมูล "+_(((he=t.value)==null?void 0:he.as_of)||"—"),1)])]),ft.value?(T(),E("div",va,"กำลังโหลดข้อมูล…")):Qe.value?(T(),E("div",_a,_(Qe.value),1)):(T(),E(ie,{key:2},[o("section",ma,[o("article",ba,[f[20]||(f[20]=o("div",{class:"kpi-label"},"สัญญาณที่ใช้งาน",-1)),o("div",ya,_(He.value.long),1),o("div",xa,[o("span",wa,_(He.value.long)+" ซื้อ",1),f[18]||(f[18]=q(" · ",-1)),o("span",Sa,_(He.value.short)+" ขาย",1),f[19]||(f[19]=q(" · ",-1)),o("span",Ca,_(He.value.neutral)+" เป็นกลาง",1)])]),o("article",ka,[f[21]||(f[21]=o("div",{class:"kpi-label"},"แหล่งข้อมูลที่ใช้",-1)),o("div",Ta,_(pt.value)+" ปัจจัย · "+_(Ut.value)+" แหล่ง",1),o("div",Ea,"ข้อมูลจริงจากแหล่งไทย "+_(ht.value?"(จริง)":"—"),1)])]),o("section",Oa,[o("div",Pa,[f[22]||(f[22]=o("div",null,[o("div",{class:"section-kicker"},"ธีม"),o("h2",null,"ธีม (Themes)"),o("p",{class:"panel-subtitle"},"ภาพรวม alternative factors ของไทย — แต่ละธีมมีความถี่ข้อมูลต่างกัน (monthly / quarterly) ดังนั้นอย่าเทียบเป็นจุดเวลาเดียวกัน.")],-1)),o("span",Aa,"รวม "+_(w.value)+" symbols",1)]),o("div",Ra,[(T(!0),E(ie,null,Te(bt.value,p=>(T(),E("article",{key:p.id,class:"theme-card"},[o("div",Ma,[o("span",Ia,_($n(p.frequency)),1),o("span",Fa,_(p.label_th),1)]),o("div",Da,[f[23]||(f[23]=o("span",{class:"theme-surprise-label"},"ความต่าง (surprise)",-1)),o("span",$a,_(p.surprise!=null?k(p.surprise,2)+"σ":"—"),1)]),o("div",La,[p.id==="auto_credit"&&p.read.new_car_sales_yoy!=null?(T(),E("div",Na,_(k(p.read.new_car_sales_yoy))+"% YoY ยอดขายรถ",1)):p.id==="auto_credit"&&p.read.auto_npl_pct!=null?(T(),E("div",ja,"NPL "+_(k(p.read.auto_npl_pct))+"%",1)):p.id==="refining_energy"&&(p.read.quarterly||p.read.net_profit)?(T(),E("div",Va,"กำไรสุทธิ TOP (รายไตรมาส)")):p.id==="tourism"?(T(),E("div",Ha,"signal tourism "+_(p.surprise!=null?k(p.surprise,2):"—")+"σ",1)):ue("",!0)]),p.narrative?(T(),E("div",Ba,_(p.narrative),1)):ue("",!0)]))),128))]),Object.keys(dt.value).length?(T(),E("div",Ka,[f[29]||(f[29]=o("div",{class:"section-kicker"},"ภาพรวมประเทศไทย",-1)),o("div",Ua,[o("span",Wa,[f[24]||(f[24]=q("การบริโภคภาคเอกชน ",-1)),o("strong",null,_(dt.value.private_consumption_yoy)+"%",1)]),o("span",qa,[f[25]||(f[25]=q("การลงทุนเอกชน ",-1)),o("strong",null,_(dt.value.private_investment_yoy)+"%",1)]),o("span",za,[f[26]||(f[26]=q("เงินเฟ้อ ",-1)),o("strong",null,_(dt.value.headline_inflation_yoy)+"%",1)]),o("span",Ja,[f[27]||(f[27]=q("การว่างงาน ",-1)),o("strong",null,_(dt.value.unemployment_pct)+"%",1)]),o("span",Ga,[f[28]||(f[28]=q("นักท่องเที่ยว YTD ",-1)),o("strong",null,_(dt.value.tourists_ytd_mn)+" ล้าน",1)])])])):ue("",!0)]),o("section",Ya,[o("div",Xa,[f[30]||(f[30]=o("div",null,[o("div",{class:"section-kicker"},"ตารางหุ้น"),o("h2",null,"ตารางหุ้น"),o("p",{class:"panel-subtitle"},[q("ตารางเดียวรวมทุกธีม — สัญญาณ + คะแนนรวม (60% ธีม / 40% พื้นฐาน) + มูลค่าพื้นฐานจาก Siamchart. เรียงได้โดยคลิกหัวตาราง; เปิด "),o("em",null,"เฉพาะหุ้นปันผล"),q(" เพื่อกรองหุ้นที่จ่ายปันผล.")])],-1)),o("div",Za,[o("label",Qa,[Ct(o("input",{type:"checkbox","onUpdate:modelValue":f[0]||(f[0]=p=>we.value=p)},null,512),[[_l,we.value]]),o("span",null,"เฉพาะหุ้นปันผล ("+_(S.value)+")",1)]),o("span",{class:Q(["status-tag",m.value?"":"warning-tag"])},_(m.value?"Siamchart ใช้งานได้":"ไม่มี factor"),3)])]),m.value?(T(),E("div",tc,[o("table",sc,[o("thead",null,[o("tr",null,[o("th",{class:Q(["sortable",{active:ne.value==="signal_score"}]),onClick:f[1]||(f[1]=p=>C("signal_score"))},"สัญญาณ "+_(y("signal_score")),3),o("th",{class:Q(["sortable",{active:ne.value==="combined"}]),onClick:f[2]||(f[2]=p=>C("combined")),title:"60% ธีม + 40% พื้นฐาน"},"คะแนนรวม (60/40) "+_(y("combined")),3),o("th",{class:Q(["sortable",{active:ne.value==="symbol"}]),onClick:f[3]||(f[3]=p=>C("symbol"))},"หุ้น "+_(y("symbol")),3),f[32]||(f[32]=o("th",null,"ธีม",-1)),o("th",{class:Q(["sortable",{active:ne.value==="pe"}]),onClick:f[4]||(f[4]=p=>C("pe"))},"P/E "+_(y("pe")),3),o("th",{class:Q(["sortable",{active:ne.value==="eps"}]),onClick:f[5]||(f[5]=p=>C("eps"))},"EPS "+_(y("eps")),3),o("th",{class:Q(["sortable",{active:ne.value==="eps_growth_yoy"}]),onClick:f[6]||(f[6]=p=>C("eps_growth_yoy"))},"EPS YoY "+_(y("eps_growth_yoy")),3),o("th",{class:Q(["sortable",{active:ne.value==="dividend_yield"}]),onClick:f[7]||(f[7]=p=>C("dividend_yield"))},"ปันผล % "+_(y("dividend_yield")),3),o("th",{class:Q(["sortable",{active:ne.value==="pbv"}]),onClick:f[8]||(f[8]=p=>C("pbv"))},"P/BV "+_(y("pbv")),3),o("th",{class:Q(["sortable",{active:ne.value==="roe"}]),onClick:f[9]||(f[9]=p=>C("roe"))},"ROE "+_(y("roe")),3)])]),o("tbody",null,[(T(!0),E(ie,null,Te(O.value,p=>{var gt;return T(),E("tr",{key:p.symbol,class:"clickable-row",onClick:bs=>Ri(p.symbol)},[o("td",null,[p.signal_side?(T(),E("span",{key:0,class:Q(["side-pill",p.signal_side.toLowerCase()])},_(p.signal_side),3)):(T(),E("span",lc,"—"))]),o("td",ic,_(((gt=yt.value[p.symbol])==null?void 0:gt.combined)!=null?k(yt.value[p.symbol].combined):"—"),1),o("td",null,[o("strong",oc,_(p.symbol),1)]),o("td",null,[(T(!0),E(ie,null,Te(d(p.symbol),bs=>(T(),E("span",{key:bs,class:"theme-tag"},_(bs),1))),128)),d(p.symbol).length?ue("",!0):(T(),E("span",rc,"—"))]),o("td",ac,_(p.pe!=null?k(p.pe):"—"),1),o("td",null,_(p.eps!=null?k(p.eps):"—"),1),o("td",{class:Q(p.eps_growth_yoy>=0?"positive-text":"negative-text")},_(p.eps_growth_yoy!=null?(p.eps_growth_yoy>=0?"+":"")+k(p.eps_growth_yoy)+"%":"—"),3),o("td",{class:Q(p.dividend_yield>=0?"positive-text":"")},[q(_(p.dividend_yield!=null?k(p.dividend_yield)+"%":"—"),1),p.is_dividend?(T(),E("span",cc,"●")):ue("",!0)],2),o("td",null,_(p.pbv!=null?k(p.pbv):"—"),1),o("td",{class:Q(p.roe>=0?"positive-text":"negative-text")},_(p.roe!=null?k(p.roe)+"%":"—"),3)],8,nc)}),128))])])])):(T(),E("div",ec,[...f[31]||(f[31]=[q("Siamchart snapshot ไม่อยู่บน disk. รัน ",-1),o("code",null,"collect_siamchart.py --group SET50 --with-info",-1),q(" เพื่อเก็บข้อมูล.",-1)])]))]),o("section",uc,[o("div",fc,[f[33]||(f[33]=o("div",null,[o("div",{class:"section-kicker"},"ที่มาของข้อมูล"),o("h2",null,"แหล่งข้อมูลทั้งหมด"),o("p",{class:"panel-subtitle"},"รายการแหล่งข้อมูลจริงที่ใช้ — ดึงมาเมื่อใด และข้อมูลชุดไหน ข้อมูลทั้งหมดจากแหล่งไทย.")],-1)),o("span",dc,_(pt.value)+" ปัจจัย · "+_(Ut.value)+" แหล่ง",1)]),o("div",pc,[o("table",hc,[f[34]||(f[34]=o("thead",null,[o("tr",null,[o("th",null,"ข้อมูล"),o("th",null,"แหล่ง"),o("th",null,"ช่วงข้อมูล"),o("th",null,"ความถี่"),o("th",null,"อัปเดตครั้งต่อไป"),o("th",null,"อัปเดตล่าสุด")])],-1)),o("tbody",null,[(T(!0),E(ie,null,Te(Ve.value,(p,gt)=>(T(),E("tr",{key:gt},[o("td",null,_(p.จาก||p.ขอบเขต),1),o("td",gc,_(p.แหล่ง),1),o("td",vc,_(p.ข้อมูล),1),o("td",_c,_(p.ความถี่||"—"),1),o("td",mc,_(p.อัปเดตครั้งต่อไป?V(p.อัปเดตครั้งต่อไป):"—"),1),o("td",bc,_(p.dึงมาเมื่อ?V(p.dึงมาเมื่อ):"—"),1)]))),128))])])])]),o("section",yc,[f[36]||(f[36]=o("div",{class:"panel-header signal-header"},[o("div",null,[o("div",{class:"section-kicker"},"สถานะการดึงข้อมูล"),o("h2",null,"Log — สถานะแหล่งข้อมูล"),o("p",{class:"panel-subtitle"},'ผลการดึงข้อมูลครั้งล่าสุดของแต่ละแหล่ง โดยระบบวิเคราะห์สาเหตุให้อัตโนมัติ (เครือข่าย / หมดเวลา / หน้าเว็บเปลี่ยนโครงสร้าง / รูปแบบข้อมูล เป็นต้น) — กดปุ่ม "คัดลอก" เพื่อ copy สาเหตุไปแจ้ง/ตรวจสอบได้ทันที.')])],-1)),me.value.length===0?(T(),E("div",xc,"ยังไม่มี log — รอรอบ refresh ถัดไป (ปกติ ~ทุกวันสำหรับราคา, ~รายเดือน/ไตรมาสสำหรับปัจจัย).")):(T(),E("div",wc,[o("table",Sc,[f[35]||(f[35]=o("thead",null,[o("tr",null,[o("th",null,"แหล่ง"),o("th",null,"ผลลัพธ์"),o("th",null,"สาเหตุ"),o("th",null,"เวลา"),o("th")])],-1)),o("tbody",null,[(T(!0),E(ie,null,Te(me.value.slice(0,20),(p,gt)=>(T(),E("tr",{key:gt},[o("td",Cc,[q(_(p.label),1),o("div",kc,_(p.key),1)]),o("td",null,[p.ok?(T(),E("span",Tc,"OK")):(T(),E("span",Ec,"FAIL"))]),o("td",null,[p.ok?(T(),E(ie,{key:0},[q("—")],64)):(T(),E(ie,{key:1},[o("div",null,_(Gs(p.category))+_(Di(p)),1),p.detail?(T(),E("div",Oc,_(p.detail.slice(0,160)),1)):ue("",!0)],64))]),o("td",Pc,_(p.at?V(p.at):"—"),1),o("td",null,[p.ok?ue("",!0):(T(),E("button",{key:0,class:"primary-btn",style:{padding:"2px 8px"},onClick:bs=>Fi(p)},"คัดลอกสาเหตุ",8,Ac))])]))),128))])])]))]),o("section",Rc,[o("div",Mc,[f[37]||(f[37]=o("div",null,[o("div",{class:"section-kicker"},"การจำลองการลงทุน"),o("h2",null,"จัดสรรทุน (Simulation)"),o("p",{class:"panel-subtitle"},"กรอกทุน และระบบจัดสรรตามสัดส่วน 50 / 20 / 30 — หุ้นที่ทำกำไรได้มากสุดแล้วจ่ายปันผล, หุ้นทำกำไรแต่ไม่ปันผล, และหุ้นปันผลสูงสุด (ไม่ซ้ำ) — ขั้นต่ำ 100 หุ้นต่อตัว.")],-1)),o("span",Ic,_(z.value?"ใช้ได้":"รอใส่ทุน"),1)]),o("div",Fc,[o("div",Dc,[f[38]||(f[38]=o("label",null,"ทุน (บาท)",-1)),Ct(o("input",{"onUpdate:modelValue":f[10]||(f[10]=p=>a.value=p),type:"number",min:"1000",step:"1000"},null,512),[[Cs,a.value]])]),o("div",$c,[f[40]||(f[40]=o("label",null,"โหมด",-1)),Ct(o("select",{"onUpdate:modelValue":f[11]||(f[11]=p=>W.value=p)},[...f[39]||(f[39]=[o("option",{value:"backtest"},"Backtest",-1),o("option",{value:"forward"},"Forward test",-1)])],512),[[sa,W.value]])]),o("button",{class:"primary-button",disabled:D.value,onClick:hs},_(D.value?"กำลังคำนวณ…":"คำนวณการจัดสรร"),9,Lc)]),z.value?(T(),E("div",Nc,[o("div",jc,[o("div",Vc,[f[41]||(f[41]=o("span",null,"ลงทุนรวม",-1)),o("strong",null,_(k(Oe.value,0))+" บาท",1)]),o("div",Hc,[f[42]||(f[42]=o("span",null,"เงินสดเหลือ",-1)),o("strong",null,_(k(Pe.value,0))+" บาท",1)])]),o("div",Bc,_(z.value.data_note),1),o("div",Kc,[o("div",Uc,[f[44]||(f[44]=o("div",{class:"sim-bucket-head"},[o("span",{class:"sim-bucket-tag b1"},"50%"),o("strong",null,"ทำกำไร + จ่ายปันผล")],-1)),o("table",Wc,[Ae(1).length?(T(),E("tbody",qc,[(T(!0),E(ie,null,Te(Ae(1),p=>(T(),E("tr",{key:"b1"+p.symbol},[o("td",null,_(p.symbol),1),o("td",zc,"qty "+_(p.qty),1),o("td",Jc,"@ "+_(k(p.price)),1),o("td",Gc,_(k(p.notional,0)),1)]))),128))])):(T(),E("tbody",Yc,[...f[43]||(f[43]=[o("tr",null,[o("td",{class:"muted-cell"},"ไม่มีหุ้นที่เข้าเกณฑ์")],-1)])]))])]),o("div",Xc,[f[46]||(f[46]=o("div",{class:"sim-bucket-head"},[o("span",{class:"sim-bucket-tag b2"},"20%"),o("strong",null,"ทำกำไร ไม่ปันผล")],-1)),o("table",Zc,[Ae(2).length?(T(),E("tbody",Qc,[(T(!0),E(ie,null,Te(Ae(2),p=>(T(),E("tr",{key:"b2"+p.symbol},[o("td",null,_(p.symbol),1),o("td",eu,"qty "+_(p.qty),1),o("td",tu,"@ "+_(k(p.price)),1),o("td",su,_(k(p.notional,0)),1)]))),128))])):(T(),E("tbody",nu,[...f[45]||(f[45]=[o("tr",null,[o("td",{class:"muted-cell"},"ไม่มีหุ้นที่เข้าเกณฑ์")],-1)])]))])]),o("div",lu,[f[48]||(f[48]=o("div",{class:"sim-bucket-head"},[o("span",{class:"sim-bucket-tag b3"},"30%"),o("strong",null,"ปันผลสูงสุด (ไม่ซ้ำ)")],-1)),o("table",iu,[Ae(3).length?(T(),E("tbody",ou,[(T(!0),E(ie,null,Te(Ae(3),p=>(T(),E("tr",{key:"b3"+p.symbol},[o("td",null,_(p.symbol),1),o("td",ru,"qty "+_(p.qty),1),o("td",au,"@ "+_(k(p.price)),1),o("td",cu,_(k(p.notional,0)),1)]))),128))])):(T(),E("tbody",uu,[...f[47]||(f[47]=[o("tr",null,[o("td",{class:"muted-cell"},"ไม่มีหุ้นที่เข้าเกณฑ์")],-1)])]))])])])])):ue("",!0),z.value?ue("",!0):(T(),E("div",fu,"กด 'คำนวณการจัดสรร' เพื่อดูว่า 50/20/30 จัดสรรทุนของคุณไปที่หุ้นไหนบ้าง")),W.value==="forward"?(T(),E("div",du,[f[50]||(f[50]=o("div",{class:"section-kicker"},"Forward Test (Paper) — สัญญาณถูกตรึง ณ เวลาสร้าง",-1)),f[51]||(f[51]=o("p",{class:"panel-subtitle"},"สร้าง forward run → สัญญาณ (คะแนน) ถูก freeze ทันทีที่สร้าง แล้ว execute ด้วยราคาหลัง freeze. กด Mark ตามราคาล่าสุด, Mature เพื่อปิด run. เป็น Paper เท่านั้น.",-1)),de.value.length===0?(T(),E("div",pu,"ยังไม่มี forward run — กด 'คำนวณการจัดสรร' ข้างบนเพื่อสร้าง")):(T(),E("table",hu,[f[49]||(f[49]=o("thead",null,[o("tr",null,[o("th",null,"#"),o("th",null,"สถานะ"),o("th",null,"ทุน"),o("th",null,"ลงทุน"),o("th",null,"ถือ"),o("th",null,"ผลตอบแทน"),o("th",null,"ตรวจ")])],-1)),o("tbody",null,[(T(!0),E(ie,null,Te(de.value.slice().reverse(),p=>(T(),E("tr",{key:p.id},[o("td",gu,_(p.id.slice(0,12)),1),o("td",null,[o("span",{class:Q(["status-tag",p.status==="matured"?"warning-tag":p.status==="frozen"?"neutral-tag":"warning-tag"])},_(p.status),3),p.non_pit?(T(),E("span",vu,"non-PIT")):ue("",!0)]),o("td",null,_(k(p.capital,0)),1),o("td",_u,_(k(p.invested,0)),1),o("td",mu,_(Object.keys(p.holdings||{}).join(", ")||"—"),1),o("td",{class:Q(wt(p.net_return))},_(p.net_return!=null?(p.net_return*100).toFixed(2)+"%":"—"),3),o("td",null,[p.status!=="matured"?(T(),E("button",{key:0,class:"primary-btn",style:{padding:"2px 8px","margin-right":"4px"},onClick:gt=>gs(p.id)},"Mark",8,bu)):ue("",!0),p.status!=="matured"?(T(),E("button",{key:1,class:"primary-btn",style:{padding:"2px 8px"},onClick:gt=>Pi(p.id)},"Mature",8,yu)):(T(),E("span",xu,"ปิดแล้ว"))])]))),128))])]))])):ue("",!0)]),o("section",wu,[f[68]||(f[68]=o("div",{class:"panel-header signal-header"},[o("div",null,[o("div",{class:"section-kicker"},"การย้อนทดสอบ"),o("h2",null,"Backtest (ย้อนทดสอบ)"),o("p",{class:"panel-subtitle"},"กำหนดช่วงวัน แล้วระบบจัดสรร 50/20/30 ณ วันที่เริ่ม ลงทุน และปรับพอร์ตตามข้อมูลที่เผยแพร่ใหม่ (event-driven) จนถึงวันสิ้นสุด — สรุปกำไร/ขาดทุนจากราคา + เงินปันผล. มีค่าธรรมเนียม 0.3% ต่อรายการ และปันผลเข้าบัญชีใน 30 วันหลัง ex-date.")])],-1)),o("div",Su,[o("label",null,[f[52]||(f[52]=q("ตั้งแต่ ",-1)),Ct(o("input",{type:"date","onUpdate:modelValue":f[12]||(f[12]=p=>b.value=p)},null,512),[[Cs,b.value]])]),o("label",null,[f[53]||(f[53]=q("ถึง ",-1)),Ct(o("input",{type:"date","onUpdate:modelValue":f[13]||(f[13]=p=>M.value=p)},null,512),[[Cs,M.value]])]),o("label",null,[f[54]||(f[54]=q("ทุน ",-1)),Ct(o("input",{type:"number","onUpdate:modelValue":f[14]||(f[14]=p=>I.value=p),step:"100000"},null,512),[[Cs,I.value,void 0,{number:!0}]])]),o("label",Cu,[Ct(o("input",{type:"checkbox","onUpdate:modelValue":f[15]||(f[15]=p=>B.value=p)},null,512),[[_l,B.value]]),f[55]||(f[55]=q(" ใช้ ledger ปันผลตามวันที่จริง ",-1))]),o("button",{class:"primary-btn",disabled:U.value||K.value&&!K.value.ready,onClick:$i},_(U.value?"กำลังย้อนทดสอบ…":"รัน Backtest"),9,ku)]),K.value&&!K.value.ready?(T(),E("div",Tu,[f[56]||(f[56]=o("strong",null,"ยังรันย้อนทดสอบแบบ strict PIT ไม่ได้ — ขาดข้อมูล coverage:",-1)),o("div",Eu,_((K.value.missing||[]).slice(0,8).join(", "))+_((K.value.missing||[]).length>8?"…":""),1),o("div",Ou,"วันเริ่มที่แนะนำ: "+_(K.value.recommended_start||"—")+" · วันสิ้นสุด: "+_(K.value.recommended_end||"—"),1)])):ue("",!0),(Re=R.value)!=null&&Re.error?(T(),E("div",Pu,_(R.value.error),1)):R.value&&!R.value.error?(T(),E("div",Au,[o("div",Ru,[o("div",Mu,[f[57]||(f[57]=o("span",null,"กำไรจากราคา (realized)",-1)),o("strong",{class:Q(wt(R.value.realized_trading_pnl))},_(k(R.value.realized_trading_pnl))+" บาท",3)]),o("div",Iu,[f[58]||(f[58]=o("span",null,"กำไรจากราคา (unrealized)",-1)),o("strong",{class:Q(wt(R.value.unrealized_trading_pnl))},_(k(R.value.unrealized_trading_pnl))+" บาท",3)]),o("div",Fu,[f[59]||(f[59]=o("span",null,"เงินปันผลที่ได้รับ",-1)),o("strong",Du,_(k(R.value.dividend_cash_received))+" บาท",1)]),o("div",$u,[f[60]||(f[60]=o("span",null,"ค่าธรรมเนียม (0.3%)",-1)),o("strong",Lu,"–"+_(k(R.value.transaction_costs))+" บาท",1)]),o("div",Nu,[f[61]||(f[61]=o("span",null,"เงินปันผลค้างรับ",-1)),o("strong",null,_(k(R.value.dividend_receivable))+" บาท",1)]),o("div",ju,[f[62]||(f[62]=o("span",null,"มูลค่าสุดท้าย (equity)",-1)),o("strong",null,_(k(R.value.final_equity))+" บาท",1)]),o("div",Vu,[f[63]||(f[63]=o("span",null,"ผลตอบแทนสุทธิ",-1)),o("strong",{class:Q(wt(R.value.net_return))},_((R.value.net_return*100).toFixed(2))+"%",3)])]),o("div",Hu,"Rebalances: "+_(R.value.rebalances)+" · ปันผลตาม: "+_(R.value.dividend_timing)+" · ช่วง "+_(R.value.start)+" → "+_(R.value.end),1),R.value.leakage_guard?(T(),E("div",Bu,"✅ strict PIT (leakage guard active)")):(T(),E("div",Ku,"คำเตือน: ไม่ได้พิสูจน์ point-in-time (non-PIT)")),R.value.holdings&&R.value.holdings.length?(T(),E("div",Uu,[f[65]||(f[65]=o("strong",null,"พอร์ตสุดท้าย:",-1)),o("table",Wu,[f[64]||(f[64]=o("thead",null,[o("tr",null,[o("th",null,"หุ้น"),o("th",null,"จำนวน"),o("th",null,"ต้นทุนเฉลี่ย"),o("th",null,"ราคาล่าสุด"),o("th",null,"มูลค่า"),o("th",null,"กำไร unrealized")])],-1)),o("tbody",null,[(T(!0),E(ie,null,Te(R.value.holdings,p=>(T(),E("tr",{key:p.symbol},[o("td",qu,_(p.symbol),1),o("td",null,_(p.qty),1),o("td",null,_(k(p.average_cost,2)),1),o("td",null,_(k(p.last_price,2)),1),o("td",null,_(k(p.market_value)),1),o("td",{class:Q(wt(p.unrealized_pnl))},_(k(p.unrealized_pnl)),3)]))),128))])])])):ue("",!0)])):(T(),E("div",zu,"กำหนดช่วงวันแล้วกด 'รัน Backtest' เพื่อดูผล (กำไร/ขาดทุนจากราคา + ปันผล)")),se.value.length?(T(),E("div",Ju,[f[67]||(f[67]=o("div",{class:"section-kicker"},"ประวัติการย้อนทดสอบ",-1)),o("table",Gu,[f[66]||(f[66]=o("thead",null,[o("tr",null,[o("th",null,"#"),o("th",null,"ช่วง"),o("th",null,"ทุน"),o("th",null,"กำไรราคา"),o("th",null,"ปันผล"),o("th",null,"ผลตอบแทน"),o("th",null,"รันเมื่อ")])],-1)),o("tbody",null,[(T(!0),E(ie,null,Te(se.value.slice().reverse(),p=>(T(),E("tr",{key:p.id},[o("td",null,_(p.id),1),o("td",null,[q(_(p.start)+" → "+_(p.end)+" ",1),p.leakage_guard===!1?(T(),E("span",Yu,"descriptive non-PIT")):ue("",!0)]),o("td",null,_(k(p.capital)),1),o("td",{class:Q(wt(p.price_pnl))},_(k(p.price_pnl)),3),o("td",Xu,[q(_(k(p.dividend_income)),1),o("span",{class:Q(["status-tag",F(p.dividend_method).cls]),style:Hs([F(p.dividend_method).style||void 0,{"margin-left":"4px"}]),title:$(p.dividend_method)},_(F(p.dividend_method).label),15,Zu)]),o("td",{class:Q(wt(p.net_return))},_((p.net_return*100).toFixed(2))+"%",3),o("td",Qu,_(p.ran_at?V(p.ran_at):"—"),1)]))),128))])])])):ue("",!0)])],64))]),u.value?(T(),E("div",{key:0,class:"modal-overlay",onClick:ia(Ln,["self"])},[o("div",ef,[o("div",tf,[o("div",null,[f[69]||(f[69]=o("div",{class:"modal-kicker"},"การวิเคราะห์รายหุ้น",-1)),o("h3",null,_(u.value),1)]),o("button",{class:"modal-close",onClick:Ln},"✕")]),h.value?(T(),E("div",sf,"กำลังโหลดการวิเคราะห์…")):(Be=g.value)!=null&&Be.error?(T(),E("div",nf,_(g.value.error),1)):g.value?(T(),E("div",lf,[o("div",of,[f[73]||(f[73]=o("div",{class:"modal-section-title"},"ธีมที่เกี่ยวข้อง (คะแนนต่อธีม)",-1)),(et=g.value.themes)!=null&&et.length?(T(),E("div",rf,[(T(!0),E(ie,null,Te(g.value.theme_contributions,p=>(T(),E("div",{key:p.theme,class:"contrib-line"},[o("span",af,_(p.label_th||c.value[p.theme]||p.theme),1),p.surprise!=null?(T(),E("span",cf,[o("em",null,_(k(p.surprise))+"σ",1),f[70]||(f[70]=q(" × คุณภาพ ",-1)),o("em",null,_(p.quality),1),f[71]||(f[71]=q(" = ",-1)),o("strong",null,_(k(p.theme_score))+"σ",1)])):(T(),E("strong",uf,"ยังไม่มีข้อมูล"))]))),128)),f[72]||(f[72]=o("div",{class:"modal-sub"},"คะแนนธีม = ค่าเฉลี่ยของ (surprise × คุณภาพหุ้น) ที่หุ้นนี้อยู่ใน",-1))])):(T(),E("div",ff,"หุ้นนี้ยังไม่ได้จัดอยู่ในธีมใด (จะอัปเดตเมื่อเพิ่มธีม)"))]),o("div",df,[f[79]||(f[79]=o("div",{class:"modal-section-title"},"มูลค่าพื้นฐาน (Siamchart)",-1)),o("div",pf,[o("span",null,[f[74]||(f[74]=q("P/E ",-1)),o("strong",null,_(((vs=g.value.fundamentals)==null?void 0:vs.pe)??"—"),1)]),o("span",null,[f[75]||(f[75]=q("EPS ",-1)),o("strong",null,_(((St=g.value.fundamentals)==null?void 0:St.eps)??"—"),1)]),o("span",null,[f[76]||(f[76]=q("P/BV ",-1)),o("strong",null,_(((_s=g.value.fundamentals)==null?void 0:_s.pbv)??"—"),1)]),o("span",null,[f[77]||(f[77]=q("ROE ",-1)),o("strong",null,_(((ms=g.value.fundamentals)==null?void 0:ms.roe)??"—"),1)]),o("span",null,[f[78]||(f[78]=q("ปันผล ",-1)),o("strong",null,_((jn=g.value.fundamentals)!=null&&jn.is_dividend?"จ่าย":"—"),1)])]),o("div",hf,"ภาพรวม: "+_(g.value.company_name||u.value),1)]),o("div",gf,[f[81]||(f[81]=o("div",{class:"modal-section-title"},"ขั้นตอนการคำนวณคะแนนรวม",-1)),o("div",vf,[o("div",_f,_(g.value.combined_formula),1),(T(!0),E(ie,null,Te(g.value.combined_calc,p=>(T(),E("div",{key:p.label,class:"calc-step"},[o("div",mf,[o("span",null,_(p.label),1),o("strong",null,_(k(p.value))+" × "+_(p.weight),1)]),o("div",bf,_(p.note),1)]))),128)),g.value.siamchart_z_note?(T(),E("div",yf,[q(" คะแนนพื้นฐานได้จาก z-score: z = (ค่า"+_(g.value.siamchart_z_note.raw_i)+" − ค่าเฉลี่ย "+_(g.value.siamchart_z_note.population_mean)+") / ค่าเบี่ยงเบน "+_(g.value.siamchart_z_note.population_stdev),1),f[80]||(f[80]=o("br",null,null,-1)),q("เทียบกับ "+_(g.value.siamchart_z_note.universe_size)+" หุ้นใน SET50 ",1)])):ue("",!0)]),o("div",xf,"ราคาล่าสุด: "+_(((Vn=g.value.price)==null?void 0:Vn.latest)!=null?k(g.value.price.latest):"—")+" ("+_(((Hn=g.value.price)==null?void 0:Hn.date)||"—")+")",1)])])):ue("",!0)])])):ue("",!0)])}}};aa(wf).mount("#app"); diff --git a/frontend/dist/index.html b/frontend/dist/index.html index 5514a77..15f27e3 100644 --- a/frontend/dist/index.html +++ b/frontend/dist/index.html @@ -5,7 +5,7 @@ SET50 Signal Lab - + diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 036a4d6..52fce80 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -53,6 +53,9 @@ const factorRows = computed(() => factorData.value?.factors ?? []) // real multi-theme dashboard (3 themes + macro + sources) const dashboardThemes = computed(() => dashData.value?.themes ?? []) const dashboardSources = computed(() => dashData.value?.sources ?? []) +// data scheduler source-health log (refresh cadence + failure diagnosis) +const sourceHealth = ref([]) +const sourceHealthLoaded = ref(false) const dashboardMacro = computed(() => dashData.value?.macro ?? {}) const sourceCount = computed(() => dashboardSources.value.length) const factorCount = computed(() => dashData.value?.source_summary?.factor_keys ?? sourceCount.value) @@ -403,6 +406,34 @@ async function loadBacktestReadiness() { } catch { btReadiness.value = null } } +async function loadSourceHealth() { + try { + const body = await fetchJson('/api/v1/scheduler/sources') + sourceHealth.value = body.sources || [] + } catch { sourceHealth.value = [] } + sourceHealthLoaded.value = true +} + +const healthCategoryLabel = (cat) => ({ + ok: 'ปกติ', network: 'เครือข่ายขัดข้อง', timeout: 'หมดเวลา', + http: 'HTTP error', parse: 'รูปแบบข้อมูลผิด', structure: 'หน้าเว็บเปลี่ยนโครงสร้าง', + auth: 'สิทธิ์/ยืนยันตัวตน', other: 'อื่น ๆ', +})[cat] || cat + +async function copyHealthLine(entry) { + const line = `[${entry.at}] ${entry.label} (${entry.key}) — ${entry.ok ? 'OK' : 'FAIL: ' + healthCategoryLabel(entry.category)} ${entry.detail ? '| ' + entry.detail : ''}` + try { + await navigator.clipboard.writeText(line) + notice.value = `คัดลอกสาเหตุของ ${entry.key} แล้ว` + } catch { + notice.value = line // fallback: show raw text as a notice + } +} + +function appendHealthRationale(entry) { + return entry.ok ? '' : ` (สาเหตุน่าจะ: ${healthCategoryLabel(entry.category)})` +} + async function runBacktest() { btLoading.value = true btResult.value = null @@ -489,7 +520,7 @@ async function recordPaperEntry() { } } -onMounted(async () => { await loadDashboard(); await Promise.all([loadBacktestRuns(), loadBacktestReadiness()]) }) +onMounted(async () => { await loadDashboard(); await Promise.all([loadBacktestRuns(), loadBacktestReadiness(), loadSourceHealth()]) })