@things-factory/headless-twin 10.0.19 โ 10.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-server/engine/canonical-ingest.d.ts +10 -1
- package/dist-server/engine/canonical-ingest.js +110 -33
- package/dist-server/engine/canonical-ingest.js.map +1 -1
- package/dist-server/engine/event-time.d.ts +25 -0
- package/dist-server/engine/event-time.js +98 -0
- package/dist-server/engine/event-time.js.map +1 -0
- package/dist-server/engine/index.d.ts +2 -0
- package/dist-server/engine/index.js +23 -0
- package/dist-server/engine/index.js.map +1 -1
- package/dist-server/engine/ingest-dedupe.d.ts +18 -6
- package/dist-server/engine/ingest-dedupe.js +201 -15
- package/dist-server/engine/ingest-dedupe.js.map +1 -1
- package/dist-server/engine/ingest-health.d.ts +60 -1
- package/dist-server/engine/ingest-health.js +43 -8
- package/dist-server/engine/ingest-health.js.map +1 -1
- package/dist-server/engine/kpi-fold.d.ts +19 -0
- package/dist-server/engine/kpi-fold.js +4 -1
- package/dist-server/engine/kpi-fold.js.map +1 -1
- package/dist-server/engine/kpi-query.js +23 -3
- package/dist-server/engine/kpi-query.js.map +1 -1
- package/dist-server/engine/oee-accumulator.d.ts +35 -2
- package/dist-server/engine/oee-accumulator.js +56 -4
- package/dist-server/engine/oee-accumulator.js.map +1 -1
- package/dist-server/engine/twin-engine.d.ts +72 -3
- package/dist-server/engine/twin-engine.js +118 -5
- package/dist-server/engine/twin-engine.js.map +1 -1
- package/dist-server/index.js +21 -0
- package/dist-server/index.js.map +1 -1
- package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.d.ts +5 -0
- package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.js +66 -0
- package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.js.map +1 -0
- package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.d.ts +5 -0
- package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.js +79 -0
- package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.js.map +1 -0
- package/dist-server/migrations/index.js +5 -1
- package/dist-server/migrations/index.js.map +1 -1
- package/dist-server/routes.js +12 -20
- package/dist-server/routes.js.map +1 -1
- package/dist-server/service/actuation/actuation-advisor.d.ts +60 -0
- package/dist-server/service/actuation/actuation-advisor.js +53 -0
- package/dist-server/service/actuation/actuation-advisor.js.map +1 -0
- package/dist-server/service/actuation/actuation-outcome.d.ts +52 -0
- package/dist-server/service/actuation/actuation-outcome.js +34 -0
- package/dist-server/service/actuation/actuation-outcome.js.map +1 -0
- package/dist-server/service/actuation/actuation-rule-resolver.d.ts +19 -0
- package/dist-server/service/actuation/actuation-rule-resolver.js +161 -0
- package/dist-server/service/actuation/actuation-rule-resolver.js.map +1 -0
- package/dist-server/service/actuation/actuation-rule.d.ts +55 -0
- package/dist-server/service/actuation/actuation-rule.js +130 -0
- package/dist-server/service/actuation/actuation-rule.js.map +1 -0
- package/dist-server/service/actuation/approval-gateway.d.ts +20 -0
- package/dist-server/service/actuation/approval-gateway.js +14 -0
- package/dist-server/service/actuation/approval-gateway.js.map +1 -0
- package/dist-server/service/actuation/catch-up-effects.d.ts +16 -0
- package/dist-server/service/actuation/catch-up-effects.js +120 -0
- package/dist-server/service/actuation/catch-up-effects.js.map +1 -0
- package/dist-server/service/actuation/command-dispatcher.d.ts +206 -8
- package/dist-server/service/actuation/command-dispatcher.js +191 -14
- package/dist-server/service/actuation/command-dispatcher.js.map +1 -1
- package/dist-server/service/actuation/command-store.d.ts +10 -2
- package/dist-server/service/actuation/command-store.js +168 -5
- package/dist-server/service/actuation/command-store.js.map +1 -1
- package/dist-server/service/actuation/dispatch-after-approval.d.ts +11 -0
- package/dist-server/service/actuation/dispatch-after-approval.js +73 -0
- package/dist-server/service/actuation/dispatch-after-approval.js.map +1 -0
- package/dist-server/service/actuation/effect-match.d.ts +53 -0
- package/dist-server/service/actuation/effect-match.js +65 -0
- package/dist-server/service/actuation/effect-match.js.map +1 -0
- package/dist-server/service/actuation/index.d.ts +21 -2
- package/dist-server/service/actuation/index.js +21 -2
- package/dist-server/service/actuation/index.js.map +1 -1
- package/dist-server/service/actuation/retry-plan.d.ts +63 -0
- package/dist-server/service/actuation/retry-plan.js +99 -0
- package/dist-server/service/actuation/retry-plan.js.map +1 -0
- package/dist-server/service/actuation/rule-evaluate.d.ts +127 -0
- package/dist-server/service/actuation/rule-evaluate.js +205 -0
- package/dist-server/service/actuation/rule-evaluate.js.map +1 -0
- package/dist-server/service/actuation/rule-loop.d.ts +5 -0
- package/dist-server/service/actuation/rule-loop.js +156 -0
- package/dist-server/service/actuation/rule-loop.js.map +1 -0
- package/dist-server/service/actuation/rule-runner.d.ts +52 -0
- package/dist-server/service/actuation/rule-runner.js +135 -0
- package/dist-server/service/actuation/rule-runner.js.map +1 -0
- package/dist-server/service/actuation/rule-wiring.d.ts +24 -0
- package/dist-server/service/actuation/rule-wiring.js +80 -0
- package/dist-server/service/actuation/rule-wiring.js.map +1 -0
- package/dist-server/service/actuation/settle-effects.d.ts +21 -0
- package/dist-server/service/actuation/settle-effects.js +101 -0
- package/dist-server/service/actuation/settle-effects.js.map +1 -0
- package/dist-server/service/actuation/sweep-dispatch.d.ts +37 -0
- package/dist-server/service/actuation/sweep-dispatch.js +125 -0
- package/dist-server/service/actuation/sweep-dispatch.js.map +1 -0
- package/dist-server/service/actuation/twin-command-resolver.d.ts +120 -0
- package/dist-server/service/actuation/twin-command-resolver.js +406 -0
- package/dist-server/service/actuation/twin-command-resolver.js.map +1 -0
- package/dist-server/service/actuation/twin-command.d.ts +81 -0
- package/dist-server/service/actuation/twin-command.js +60 -0
- package/dist-server/service/actuation/twin-command.js.map +1 -1
- package/dist-server/service/actuation/twin-now.d.ts +41 -0
- package/dist-server/service/actuation/twin-now.js +65 -0
- package/dist-server/service/actuation/twin-now.js.map +1 -0
- package/dist-server/service/index.d.ts +5 -2
- package/dist-server/service/index.js +8 -0
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/reference/actuation-routing.d.ts +60 -0
- package/dist-server/service/reference/actuation-routing.js +126 -0
- package/dist-server/service/reference/actuation-routing.js.map +1 -0
- package/dist-server/service/reference/actuation-target.d.ts +65 -0
- package/dist-server/service/reference/actuation-target.js +94 -0
- package/dist-server/service/reference/actuation-target.js.map +1 -0
- package/dist-server/service/reference/connection-portability-resolver.d.ts +29 -0
- package/dist-server/service/reference/connection-portability-resolver.js +181 -0
- package/dist-server/service/reference/connection-portability-resolver.js.map +1 -0
- package/dist-server/service/reference/connection-portability.d.ts +138 -0
- package/dist-server/service/reference/connection-portability.js +230 -0
- package/dist-server/service/reference/connection-portability.js.map +1 -0
- package/dist-server/service/reference/fill-cadence.d.ts +17 -0
- package/dist-server/service/reference/fill-cadence.js +31 -0
- package/dist-server/service/reference/fill-cadence.js.map +1 -0
- package/dist-server/service/reference/fill-dedupe.d.ts +16 -0
- package/dist-server/service/reference/fill-dedupe.js +63 -0
- package/dist-server/service/reference/fill-dedupe.js.map +1 -0
- package/dist-server/service/reference/fill-loop.d.ts +35 -0
- package/dist-server/service/reference/fill-loop.js +187 -0
- package/dist-server/service/reference/fill-loop.js.map +1 -0
- package/dist-server/service/reference/fill-span.d.ts +10 -0
- package/dist-server/service/reference/fill-span.js +37 -0
- package/dist-server/service/reference/fill-span.js.map +1 -0
- package/dist-server/service/reference/hook-contract.d.ts +88 -4
- package/dist-server/service/reference/hook-contract.js +105 -4
- package/dist-server/service/reference/hook-contract.js.map +1 -1
- package/dist-server/service/reference/hook-rejected.d.ts +25 -0
- package/dist-server/service/reference/hook-rejected.js +48 -0
- package/dist-server/service/reference/hook-rejected.js.map +1 -0
- package/dist-server/service/reference/index.d.ts +4 -1
- package/dist-server/service/reference/index.js +5 -1
- package/dist-server/service/reference/index.js.map +1 -1
- package/dist-server/service/reference/live-cadence.d.ts +68 -0
- package/dist-server/service/reference/live-cadence.js +44 -0
- package/dist-server/service/reference/live-cadence.js.map +1 -0
- package/dist-server/service/reference/live-feed-lease.d.ts +15 -0
- package/dist-server/service/reference/live-feed-lease.js +56 -0
- package/dist-server/service/reference/live-feed-lease.js.map +1 -0
- package/dist-server/service/reference/live-ingest.d.ts +21 -0
- package/dist-server/service/reference/live-ingest.js +66 -0
- package/dist-server/service/reference/live-ingest.js.map +1 -0
- package/dist-server/service/reference/reference-adapter.d.ts +291 -2
- package/dist-server/service/reference/reference-adapter.js +19 -1
- package/dist-server/service/reference/reference-adapter.js.map +1 -1
- package/dist-server/service/reference/reference-fill-run.d.ts +50 -0
- package/dist-server/service/reference/reference-fill-run.js +142 -0
- package/dist-server/service/reference/reference-fill-run.js.map +1 -0
- package/dist-server/service/reference/reference-fill.d.ts +90 -0
- package/dist-server/service/reference/reference-fill.js +141 -0
- package/dist-server/service/reference/reference-fill.js.map +1 -0
- package/dist-server/service/reference/reference-hook.d.ts +22 -0
- package/dist-server/service/reference/reference-hook.js +135 -55
- package/dist-server/service/reference/reference-hook.js.map +1 -1
- package/dist-server/service/reference/reference-link-groups.d.ts +10 -0
- package/dist-server/service/reference/reference-link-groups.js +15 -0
- package/dist-server/service/reference/reference-link-groups.js.map +1 -0
- package/dist-server/service/reference/reference-links.d.ts +14 -0
- package/dist-server/service/reference/reference-links.js +73 -0
- package/dist-server/service/reference/reference-links.js.map +1 -0
- package/dist-server/service/reference/reference-live.d.ts +1 -0
- package/dist-server/service/reference/reference-live.js +32 -6
- package/dist-server/service/reference/reference-live.js.map +1 -1
- package/dist-server/service/reference/reference-master.d.ts +56 -2
- package/dist-server/service/reference/reference-master.js +33 -3
- package/dist-server/service/reference/reference-master.js.map +1 -1
- package/dist-server/service/reference/reference-resolver.d.ts +27 -0
- package/dist-server/service/reference/reference-resolver.js +79 -1
- package/dist-server/service/reference/reference-resolver.js.map +1 -1
- package/dist-server/service/twin-event/twin-event-keys.d.ts +31 -3
- package/dist-server/service/twin-event/twin-event-keys.js +36 -4
- package/dist-server/service/twin-event/twin-event-keys.js.map +1 -1
- package/dist-server/service/twin-event/twin-event.d.ts +1 -0
- package/dist-server/service/twin-event/twin-event.js +11 -2
- package/dist-server/service/twin-event/twin-event.js.map +1 -1
- package/dist-server/service/twin-model/choose-recipe.d.ts +15 -0
- package/dist-server/service/twin-model/choose-recipe.js +33 -0
- package/dist-server/service/twin-model/choose-recipe.js.map +1 -0
- package/dist-server/service/twin-model/external-resolver.d.ts +76 -0
- package/dist-server/service/twin-model/external-resolver.js +109 -0
- package/dist-server/service/twin-model/external-resolver.js.map +1 -0
- package/dist-server/service/twin-model/project-structure.js +16 -3
- package/dist-server/service/twin-model/project-structure.js.map +1 -1
- package/dist-server/service/twin-model/twin-equipment.d.ts +17 -0
- package/dist-server/service/twin-model/twin-equipment.js +10 -0
- package/dist-server/service/twin-model/twin-equipment.js.map +1 -1
- package/dist-server/service/twin-model/twin-lineage-query.js +75 -1
- package/dist-server/service/twin-model/twin-lineage-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-item-query.js +94 -5
- package/dist-server/service/twin-model/twin-model-item-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-tree-query.js.map +1 -1
- package/dist-server/service/twin-space/twin-space.d.ts +29 -0
- package/dist-server/service/twin-space/twin-space.js +13 -0
- package/dist-server/service/twin-space/twin-space.js.map +1 -1
- package/dist-server/service/twin-subject/event-subjects.d.ts +3 -1
- package/dist-server/service/twin-subject/event-subjects.js +8 -1
- package/dist-server/service/twin-subject/event-subjects.js.map +1 -1
- package/dist-shared/entity-delta.js +1 -1
- package/dist-shared/entity-delta.js.map +1 -1
- package/package.json +7 -7
- package/server/engine/canonical-ingest.ts +119 -33
- package/server/engine/event-time.ts +96 -0
- package/server/engine/index.ts +20 -0
- package/server/engine/ingest-dedupe.ts +203 -27
- package/server/engine/ingest-health.ts +91 -6
- package/server/engine/kpi-fold.ts +24 -1
- package/server/engine/kpi-query.ts +23 -4
- package/server/engine/oee-accumulator.ts +80 -8
- package/server/engine/twin-engine.ts +119 -5
- package/server/index.ts +23 -0
- package/server/migrations/1786600000000-RenameOperatoMesAdapterType.ts +66 -0
- package/server/migrations/1786700000000-AddDispatchRetryColumns.ts +82 -0
- package/server/migrations/index.ts +5 -1
- package/server/routes.ts +12 -24
- package/server/service/actuation/actuation-advisor.ts +124 -0
- package/server/service/actuation/actuation-outcome.ts +97 -0
- package/server/service/actuation/actuation-rule-resolver.ts +147 -0
- package/server/service/actuation/actuation-rule.ts +139 -0
- package/server/service/actuation/approval-gateway.ts +44 -0
- package/server/service/actuation/catch-up-effects.ts +152 -0
- package/server/service/actuation/command-dispatcher.ts +401 -20
- package/server/service/actuation/command-store.ts +182 -8
- package/server/service/actuation/dispatch-after-approval.ts +71 -0
- package/server/service/actuation/effect-match.ts +124 -0
- package/server/service/actuation/index.ts +21 -2
- package/server/service/actuation/retry-plan.ts +145 -0
- package/server/service/actuation/rule-evaluate.ts +352 -0
- package/server/service/actuation/rule-loop.ts +160 -0
- package/server/service/actuation/rule-runner.ts +216 -0
- package/server/service/actuation/rule-wiring.ts +84 -0
- package/server/service/actuation/settle-effects.ts +115 -0
- package/server/service/actuation/sweep-dispatch.ts +179 -0
- package/server/service/actuation/twin-command-resolver.ts +387 -0
- package/server/service/actuation/twin-command.ts +128 -1
- package/server/service/actuation/twin-now.ts +97 -0
- package/server/service/index.ts +9 -1
- package/server/service/reference/actuation-routing.ts +165 -0
- package/server/service/reference/actuation-target.ts +163 -0
- package/server/service/reference/connection-portability-resolver.ts +171 -0
- package/server/service/reference/connection-portability.ts +285 -0
- package/server/service/reference/fill-cadence.ts +29 -0
- package/server/service/reference/fill-dedupe.ts +66 -0
- package/server/service/reference/fill-loop.ts +153 -0
- package/server/service/reference/fill-span.ts +31 -0
- package/server/service/reference/hook-contract.ts +185 -5
- package/server/service/reference/hook-rejected.ts +53 -0
- package/server/service/reference/index.ts +5 -1
- package/server/service/reference/live-cadence.ts +129 -0
- package/server/service/reference/live-feed-lease.ts +56 -0
- package/server/service/reference/live-ingest.ts +94 -0
- package/server/service/reference/reference-adapter.ts +327 -5
- package/server/service/reference/reference-fill-run.ts +165 -0
- package/server/service/reference/reference-fill.ts +223 -0
- package/server/service/reference/reference-hook.ts +162 -56
- package/server/service/reference/reference-link-groups.ts +21 -0
- package/server/service/reference/reference-links.ts +77 -0
- package/server/service/reference/reference-live.ts +30 -5
- package/server/service/reference/reference-master.ts +90 -5
- package/server/service/reference/reference-resolver.ts +77 -2
- package/server/service/twin-event/twin-event-keys.ts +37 -4
- package/server/service/twin-event/twin-event.ts +18 -1
- package/server/service/twin-model/choose-recipe.ts +31 -0
- package/server/service/twin-model/external-resolver.ts +161 -0
- package/server/service/twin-model/project-structure.ts +16 -3
- package/server/service/twin-model/twin-equipment.ts +22 -0
- package/server/service/twin-model/twin-lineage-query.ts +82 -1
- package/server/service/twin-model/twin-model-item-query.ts +95 -4
- package/server/service/twin-model/twin-model-tree-query.ts +1 -1
- package/server/service/twin-space/twin-space.ts +39 -0
- package/server/service/twin-subject/event-subjects.ts +8 -1
- package/shared/entity-delta.ts +1 -1
- package/test/ack-shape-alignment.test.ts +97 -0
- package/test/actuation-approval-door.test.ts +421 -0
- package/test/actuation-dispatch.test.ts +16 -3
- package/test/actuation-effect.test.ts +162 -0
- package/test/actuation-outcome.test.ts +152 -0
- package/test/actuation-rule-runner.test.ts +281 -0
- package/test/actuation-rule.test.ts +266 -0
- package/test/actuation-seam.test.ts +249 -0
- package/test/actuation-settle.test.ts +164 -0
- package/test/actuation-target.test.ts +145 -0
- package/test/canonical-ingest-vocabularies.test.ts +49 -2
- package/test/capability-mapping.test.ts +1 -1
- package/test/choose-recipe.test.ts +117 -0
- package/test/command-store-writes-columns.test.ts +126 -0
- package/test/connection-portability-doors.test.ts +87 -0
- package/test/connector-capability-declaration.test.ts +54 -4
- package/test/declaration-reaches-model.test.ts +43 -0
- package/test/dedupe-transformation.test.ts +112 -0
- package/test/entity-delta.test.ts +1 -1
- package/test/event-subjects.test.ts +2 -1
- package/test/external-resolver.test.ts +171 -0
- package/test/fill-dedupe.test.ts +59 -0
- package/test/fill-loop.test.ts +35 -0
- package/test/first-envelope.test.ts +153 -0
- package/test/fold-shift-dst.test.ts +110 -0
- package/test/home-in-area.test.ts +90 -0
- package/test/hook-rejected-shape.test.ts +86 -0
- package/test/hook-response-sum.test.ts +193 -0
- package/test/hook-sequence.test.ts +1 -1
- package/test/ingest-dedupe.test.ts +56 -0
- package/test/ingest-expected-quiet.test.ts +111 -0
- package/test/ingest-idempotent.test.ts +79 -0
- package/test/ingest-reconcile-four-ways.test.ts +97 -0
- package/test/ingest-rules-header.test.ts +100 -0
- package/test/ingest-window-rolls-unobserved.test.ts +72 -0
- package/test/intake-mapping-parity.test.ts +175 -0
- package/test/live-cadence.test.ts +170 -0
- package/test/live-feed-lease.test.ts +63 -0
- package/test/live-mirror-parity.test.ts +1 -1
- package/test/oee-accumulator.test.ts +3 -3
- package/test/oee-site-calendar.test.ts +146 -0
- package/test/order-and-transaction-split.test.ts +107 -0
- package/test/reference-fill.test.ts +235 -0
- package/test/reference-hook.test.ts +1 -1
- package/test/reference-links.test.ts +56 -0
- package/test/retry-plan.test.ts +139 -0
- package/test/sweep-dispatch.test.ts +191 -0
- package/test/twin-event-keys.test.ts +20 -6
- package/test/twin-model-item-db.test.ts +6 -6
- package/test/twin-model-tree-db.test.ts +6 -6
- package/tsconfig.shared.tsbuildinfo +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kpi-fold.js","sourceRoot":"","sources":["../../server/engine/kpi-fold.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * ์
๋ฌด KPI ํด๋ โ **์ด๋ฒคํธ ์ ๋์ ๊ณ์ฐํด** ์๊ฐ์ฐฝ ์งํ๋ฅผ ๋ง๋ ๋ค(์์).\n *\n * โโ ์ ํ์ํ๊ฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ง๊ธ ํธ์์ด ๋ตํ ์ ์๋ ๊ฒ์ \"์ด ์๊ฐ์ ๊ฐ\"(์ ์ 92%)๊ณผ \"์ธํ๋ผ ๋ถํ\"(์ด๋น ์ด๋ฒคํธ ์)๋ฟ์ด๋ค.\n * ์ด์์ด ๋ฌป๋ ๊ฒ์ ๋ค๋ฅด๋ค โ **์ง๋ ํ ์๊ฐ์ ๋ช ๊ฑด ์ฒ๋ฆฌํ๋, ํ ๊ฑด์ ์ผ๋ง๋ ๊ฑธ๋ฆฌ๋, ์์์ ์ผ๋ง๋\n * ์ผํ๋.** ๊ทธ ๊ฐ์ด ์์ผ๋ฉด AI ๋ \"์ ์ 92%\" ๋ ๋งํด๋ \"๋ชฉํ๋ณด๋ค ๋์๊ฐ\" ๋ ๋ตํ ์ ์๋ค.\n *\n * โโ ์๋ฃ๋ ์ด๋ฏธ ์๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ๋(`TwinEvent`)์ `task.status`ยท`order.status`ยท`equipment.status` ์ ์ด๊ฐ `eventTime`(ISO)๊ณผ ํจ๊ป\n * append-only ๋ก ์์ธ๋ค. ๊ทธ๋์ ์ ๊ณ์ธก์ ์ฌ์ ํ์๊ฐ ์๋ค โ **๊ณ์ฐ๋ง ํ๋ฉด ๋๋ค.**\n * ๊ฐ์ ๋ชจ์์ ์ ๋ก๊ฐ ์ด ํด๋์ ์๋ค(`oee-accumulator.ts` โ equipment ์ ์ด๋ฅผ ๊ณ์ฐํด OEE ์นด์ดํฐ ์์ฐ).\n *\n * โโ ์ด ํ์ผ์ด ํ์ง ์๋ ๊ฒ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ยท ๋ชฉํ์ ๋น๊ตํ์ง ์๋๋ค. \"95% ๋ชฉํ ๋๋น\" ๋ ๋ชฉํ๋ฅผ ์ ์ฅํ๋ ๋ณ๊ฐ ์ธต(๊ฒฝ์ KPI)์ ๋ชซ์ด๊ณ ,\n * ์ด ์ธต์ **์ฌ์ค๋ง** ์์ฐํ๋ค. ๋ ์ธต์ ์์ผ๋ฉด ๋ชฉํ๋ฅผ ์ ์ํ์ง ์์ ํ์ฅ์ ์ฌ์ค์กฐ์ฐจ ๋ชป ๋ณธ๋ค.\n * ยท ์ฒด๋ฅ์๊ฐ(dwell)์ ์์ง ๋ด์ง ์๋๋ค. ๋ฌผ๊ฑด์ด ๋
ธ๋์ ๋จธ๋ฌธ ์๊ฐ์ item ๋จ์ ์ด๋ฒคํธ(epcis.*)๋ฅผ\n * ์ง์ง์ด์ผ ํ๊ณ , ๊ทธ ์ง๋ง์ถค ๊ท์น์ด ๋๋ฉ์ธ๋ง๋ค ๋ค๋ฅด๋ค. **์๋ ๊ฒ์ 0 ์ผ๋ก ๊พธ๋ฏธ์ง ์๋๋ค.**\n * ยท DBยท์ปค๋์ ๋ชจ๋ฅธ๋ค. ์
๋ ฅ์ ํ๋ฒํ ๋ฐฐ์ด์ด๊ณ ์ถ๋ ฅ์ ํ๋ฒํ ๊ฐ์ฒด๋ค(ํ
์คํธ๊ฐ ๊ฐ์ธ๋ค).\n */\n\n/*\n * ์ง๋ง์ถค์ **์ปค๋์ด ์์ ํ๋ค**(`foldTaskRecords`). ์๋ฃ๋ ์์
๋น ํ๋ยท๋์ค ๊ฒ์ด ์ฌ์ค, ์ฐฉ์๋ ์ฒ์ ๊ฒ,\n * ์ข
๋ฅยท์ค๋๋ ์ด๋ ์ ์ด์์๋ โ ๊ทธ ๊ท์น์ ์ปค๋ ์ํ ๊ธฐ๊ณ์์ ๋์ค๋ ์ง์์ด๋ค. ์ฌ๊ธฐ์ ๋ค์ ์ ์๋๋\n * ๊ณต์ ํ์๋ผ์ธ๊ณผ **๋ค๋ฅธ ๋ต**์ ๋๋ค(์ฌ์ ์ก๋ ์๋ฃ๋ฅผ ๋ ๊ฑด์ผ๋ก ์ธ์ด ์ฒ๋ฆฌ๋ยท์ ์ ๊ฐ ๋ถํ๋ ค์ก๋ค).\n * ์ด ํ์ผ์ ์ด์ \"๊ณ์ฐํ ๊ธฐ๋ก โ ์ฐฝ ์งํ\" ๋ง ํ๋ค.\n */\nimport { attributeEnergy, electricityCost, energyIntensity, energyOfWindows, foldTaskRecords, type ElectricityCost, type TariffDeclaration, type TaskFacets } from '@operato/twin-kernel'\nimport { type WorkCalendarEntry } from '@operato/ops-contract'\nimport { ENERGY_EVENT, isOrderTerminal, activeShiftAt } from '@operato/ops-contract'\n\n/** ์ ๋ ํ ์ค โ ํ์ํ ๊ฒ๋ง(์ํฐํฐยทtypeorm ๋น์์กด). */\nexport interface KpiEvent {\n eventType?: string\n /** ISO ์๊ฐ. ํ์ฑ ๋ถ๊ฐํ๋ฉด ๊ทธ ์ค์ ๋ฒ๋ฆฐ๋ค(์๋ฆฌ์ง ์๊ณ 0 ์ผ๋ก ์ธ์ง ์๋๋ค). */\n eventTime?: string\n payload?: any\n}\n\nexport interface KpiWindow {\n /** ์ฐฝ์ ์์ยท๋(epoch ms). ์๋ฃ ์๊ฐ์ด ์ด ์์ ๋ ๊ฒ๋ง ์ฑ๊ณผ๋ก ์ผ๋ค. */\n fromMs: number\n toMs: number\n}\n\nexport interface DurationStats {\n /** ์ง์ด ๋ง์ ๊ณ์ฐ๋ ๊ฑด์. */\n count: number\n /**\n * ํ์ ๊ผฌ๋ฆฌ โ **๋ถํฌ๋ฅผ ์์ชฝ์์ ๊ณ์ฐํ์งํ๊ธฐ ์ํด** ๋ธ๋ค.\n * p50ยทp90 ๋ง ์์ผ๋ฉด ์๋์ชฝ ํผ์ง์ ์์ชฝ์์ ๊ฑฐ์ธ์ฒ๋ผ ๋ฒ ๊ปด ์ธ ์๋ฐ์ ์๋ค(๋ฐ๋ช
). ๊ด์ธก์ด ๋งํ๊ฒ ํ๋ค.\n */\n p10Ms: number\n p50Ms: number\n p90Ms: number\n avgMs: number\n}\n\n/**\n * ๊ด์ ์ถ โ **๊ฐ์ ์ฌ์ค์ ๋ค๋ฅธ ๊ฐ์ผ๋ก** ๋ณธ๋ค.\n *\n * ๊ณ ์ ๋ ํ ๋ ์ฆ(์์๋ณ)๋ง ๋ผ ์ ์์ผ๋ฉด ์ฌ์ฉ์๊ฐ \"๊ตฌ์ญ๋ณ๋ก๋?\" ์ด๋ผ๊ณ ๋ฌผ์ด๋ ๋ต์ด ์๋ค. ์ฌ์ค ๊ณ์ฐ์ด\n * ์ถ์ ๋ชป ๋ด๋ฉด AI ๋ ๋ชป ๋ธ๋ค โ ๊ทธ๋์ ์ถ์ ๊ณ์ฐ ์ธต์ ๋ฅ๋ ฅ์ด์ด์ผ ํ๋ค.\n *\n * resource ์์๋ณ(๋๊ฐ ํ๋) taskKind ์์
์ข
๋ฅ๋ณ(๋ฌด์์ ํ๋)\n * location ๋์ฐฉ ์ง์ ๋ณ(์ด๋์) order ์ค๋๋ณ(๋ฌด์์ ์ํด)\n * area ๊ตฌ์ญ๋ณ โ ๋
ธ๋โ๊ตฌ์ญ ์ง๋๊ฐ ํ์ํ๋ค(์ด๋ฒคํธ์ ์๋ค. ํธ์ถ๋ถ๊ฐ ์ค๋ค)\n * shift ๊ต๋๋ณ(์ธ์ ) โ ์๋ฃ ์๊ฐ + ํ์ฅ์ ์๊ฐ ๊ธฐ์ค์์ **๊ณ์ฐํ๋ค**(์ด๋ฒคํธ์ ์๋ค)\n */\nexport type KpiGroupBy = 'resource' | 'taskKind' | 'location' | 'order' | 'area' | 'shift'\n\nexport interface KpiGroup {\n /** ์ถ์ ๊ฐ(์์ idยท์์
์ข
๋ฅยท๋
ธ๋ idยท์ค๋ idยท๊ตฌ์ญ id). ๊ฐ์ด ์๋ ๊ธฐ๋ก์ 'unknown'. */\n key: string\n /** ์ด ์ถ์์ ์๋ฃ๋ ๊ฑด์. */\n tasks: number\n leadTime: DurationStats\n workTime: DurationStats\n waitTime: DurationStats\n /** ์ด ์ถ์ ๋ถ์ด ์๋ ์๊ฐ์ ํฉ(์์ ์ถ์์ ํนํ ์๋ฏธ ์๋ค). */\n busyMs: number\n /**\n * **ํ์ง ํ์ ์ด ์์๋ ๊ฑด์๋ง** ์ผ๋ค (2026-08-19).\n *\n * ํ์ ์ด ์๋ ์์
(์ด๋ยท์ฒด๋ฅยท์ค๊ฐ ์คํ
์ด์
)์ ์ด๋ ์ชฝ์๋ ์ธ์ง ์๋๋ค โ ๋ชจ๋ฆ์ ์ํ์ผ๋ก ์ธ๋ฉด ์ํ๋ฅ ์ด\n * ์๋ฆฌ์ง ์๊ณ 100% ๋ก ์ฌ๋ผ๊ฐ๋ค. ๊ทธ๋์ `good + scrap` ์ `tasks` ๋ณด๋ค ์์ ์ ์๊ณ , ๊ทธ๊ฒ์ด ์ ์์ด๋ค.\n *\n * ํ์ ์ด ํ๋๋ ์์ผ๋ฉด **ํ๋๋ฅผ ๋ง๋ค์ง ์๋๋ค**(0/0 ์ ใ์ํ๋ฅ 0%ใ๋ก ์ฝํ๊ฒ ๋์ง ์๋๋ค).\n */\n quality?: { good: number; scrap: number }\n}\n\nexport interface KpiResult {\n window: { fromMs: number; toMs: number }\n /** ์ฐฝ ์์ **์๋ฃ๋** ๊ฑด์ โ ์ฑ๊ณผ๋ ์๋ฃ ์์ ์ผ๋ก ์ผ๋ค(์์ ์์ ์ผ๋ก ์ธ๋ฉด ์งํ ์ค์ธ ๊ฒ์ด ์์ธ๋ค). */\n throughput: { tasks: number; orders: number }\n /**\n * ์๋์ง โ **์ด ์ฐฝ์ ์ ๋ ฅ๋๊ณผ ์๋จ์.** ์๋์ง ํธ์์ด ์์ผ๋ฉด `undefined`(0 ์ด ์๋๋ค).\n *\n * โโ ์ KPI ํด๋ ์์ ์๋ (2026-08-14, ยง10 7๋จ๊ณ) โโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์๋จ์๋ ๋ถ์(์ ๋ ฅ๋)์ ๋ถ๋ชจ(์ฐ์ถ)๋ฅผ **๊ฐ์ ์ฐฝ**์์ ๋๋ ๊ฐ์ด๋ค. ์ง์๋ฅผ ๋ฐ๋ก ๋๋ฉด ๋ ์ฐฝ์ ๋ง์ถ๋\n * ์ผ์ด ์๋น์ฒ์ ๋ชซ์ด ๋๊ณ , ์ด๊ธ๋ ๋ ์ฌ์ค์ ๋๋ ์ซ์๋ ์๋ฌด๊ฒ๋ ๋ปํ์ง ์๋๋ค(์ปค๋์ ๊ท์น์ด ๊ทธ๊ฒ์\n * ๊ฑฐ์ ํ๋ค). ๊ฐ์ ํด๋ ์์ ๋๋ฉด ์ฐฝ์ด ํ๋๋ฟ์ด๋ผ ์ด๊ธ๋ ์ ์๋ค.\n *\n * ๋ถ์๋ **์ ๋์ ๊ตฌ๊ฐ ๋ง๊ฐ ์ฌ๊ฑด**์์ ์จ๋ค(`energy.demand.window`) โ ์ปค๋ ์ํ๊ฐ ์๋๋ผ ์ ๋์ด๋ฏ๋ก\n * ๋ฉ์ถ ํธ์ยท๊ณผ๊ฑฐ ๊ตฌ๊ฐ์๋ ๋ตํ ์ ์๋ค.\n */\n energy?: {\n /** ์ด ์ฐฝ์ ์ ๋ ฅ๋. ์
์ ์๋ ๊ตฌ๊ฐ์ด ์์ผ๋ฉด `undefined`. */\n kWh?: number\n /**\n * ์ด ์ฐฝ์ **์ต๋์์**(kW)์ ๊ทธ๊ฒ์ด ๋ ๊ตฌ๊ฐ์ ์์.\n *\n * ์ ๋ ฅ๋๊ณผ ๋ค๋ฅธ ์ง๋ฌธ์ด๋ค: ์ ๋ ฅ๋์ ์๊ธ์ ์ฌ์ฉ๋ ๋ถ๋ถ์ด๊ณ , ์ต๋์์๋ **๊ธฐ๋ณธ์๊ธ**๊ณผ ๊ณ์ฝ ์๋ฐ์\n * ์ ํ๋ค. ํ๊ท ์ผ๋ก ๊ฐ์ํ ์ ์์ด์ ์ปค๋์ด ๊ตฌ๊ฐ์ ์ต๋๋ค ์ค ๊ฐ์ฅ ํฐ ๊ฐ์ ๋ฐ๋ก ๋ธ๋ค.\n */\n peakKW?: number\n peakStartMs?: number\n /**\n * ๊ทธ ํผํฌ ๊ตฌ๊ฐ์์ **์ค๋น๊ฐ ๋์ด๋น๊ธด** ์ต๋(๋ฐ์ ยท๋ฐฉ์ ์ฐจ๊ฐ ์ )์ ๊ทธ ์ฐจ์ด(๊น์ธ ์).\n *\n * ์๊ธ์ ๊ณํต ์์(`peakKW`)๋ก ๋งค๊ฒจ์ง์ง๋ง, ใ๋ฌด์์ด ๊ทธ ์์๋ฅผ ๋ง๋ค์๋ใ์ ใ๋ฌด์์ด ๋์ด๋๋ใ๋\n * ์ด ๋ ์์ ๊ฐ๊ฒฉ์ด ๋ตํ๋ค. ๋ฐ์ ยท์ถ์ ์ ์ ์ธํ์ง ์์ ํ์ฅ์์๋ ์๋ค(์ฐจ๊ฐํ ๊ฒ์ด ์๋ค).\n */\n peakGrossKW?: number\n shavedKW?: number\n /**\n * ์ด ์ฐฝ์ **๋ฐ์ ๋** โ ์ปค๋์ด ๋ง๊ฐํ ๊ธฐ๊ฐ ์ฌ์ค(`energy.generation.period`)์์ ์จ๋ค.\n *\n * ๋ถํ(`kWh`)์ ๋ํ์ง ์๋๋ค: ๋ฐ์ ์ ์ค๋น๊ฐ ๋ง๋ ์์ด๊ณ ๋ถํ๋ ๊ณ๋ ์ง์ ์ ์ง๋ ์์ด๋ค. ๋ ์๋ฅผ\n * ๋ํ๋ฉด ์ด๋ ์ชฝ๋ ์๋ ์ซ์๊ฐ ๋๋ค.\n *\n * ์ฑ๊ณผ์งํ(ISO 50001 EnPI)์ ํ์๊ด ์ฑ๋ฅ๋น๊ฐ ์ด ๊ฐ์ ๋ถ์๋ก ์ด๋ค. ๋ฐ์ ์ฌ์ค์ด ์์ผ๋ฉด `undefined`\n * ๋ค(0 ์ด ์๋๋ค โ ใ๋ฐ์ ์ด ์๋คใ์ ใ๋ฐ์ ์ค๋น๊ฐ ์๋คใ๋ ๋ค๋ฅด๋ค).\n */\n generated?: {\n /** ์ฐฝ์ ์จ์ ํ ๋ ๊ธฐ๊ฐ๋ค์ ํฉ(kWh). */\n kWh: number\n /** ์ผ ๊ธฐ๊ฐ ์. */\n counted: number\n /**\n * ๊ทธ์ค **๊ด์ธก์ด ๊ธฐ๊ฐ์ ๋ค ๋ฎ์ง ๋ชปํ** ๊ธฐ๊ฐ ์.\n *\n * ์ปค๋์ด ๊ธฐ๊ฐ๋ง๋ค ๊ด์ธก ๊ตฌ๊ฐ์ ํจ๊ป ๋ธ๋ค. ๋ง์ง๋ง ํ๋ณธ์ด ๊ธฐ๊ฐ ๋๋ณด๋ค ์ด๋ฅด๋ฉด ๊ทธ๋งํผ ์ฌ์ง ์์\n * ๊ฒ์ด๊ณ , ๊ทธ ์๋ฅผ ๊ฐ์ถ๋ฉด ํ๋ฉด์ด ๋ ์ฐ ํฉ์ ์จ์ ํ ํฉ์ผ๋ก ๋งํ๋ค.\n */\n partial: number\n /** ์ค๋น๋ณ ๋ชซ โ ์ด๊ฒ์ **์ธก์ **์ด๋ค(๋ฐฐ๋ถ์ด ์๋๋ค). ๊ฐ ์ค๋น์ ์ ์ฐ์์ ์๋ค. */\n byEquipment: { id: string; kWh: number }[]\n /**\n * **์ด ์ฐฝ์ ๋ค ๋ค์ด์ค์ง ์์ ๋ํ์ง ๋ชปํ ๊ธฐ๊ฐ** โ ์กฐ์ฉํ ๋ฒ๋ฆฌ์ง ์๋๋ค.\n *\n * ๋ํ๋ ๊ฒ์ ์ฐฝ์ ์จ์ ํ ๋ ๊ธฐ๊ฐ๋ฟ์ด๋ค(๊ฑธ์น ๊ธฐ๊ฐ์ ๋ํ๋ฉด ๋ค๋ฅธ ๋ ๊ฐ์ด ์ด ์ฐฝ์ ๊ฐ์ธ ์ฒํ๋ค).\n * ๊ทธ๋ฐ๋ฐ ํ๋ฃจ ๋จ์ ๊ธฐ๊ฐ์ ใ์ง๊ธ๋ถํฐ 24์๊ฐ ์ ใ ์ฐฝ์ ์จ์ ํ ๋๋ ์ผ์ด ๊ฑฐ์ ์๋ค โ ์ฐฝ์ด ํ๋ฎ์์\n * ์์ํ๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋์ ์ด์ ๋ฐ์ ๋์ด ์ ๋์ ๋ฉ์ฉกํ ์๋๋ฐ ํ๋ฉด์ด ๋น์๊ณ , ์ฌ์ฉ์๋ ๊ทธ๊ฒ์\n * ใ๋ฐ์ ๋์ด ์๋คใ๋ก ์ฝ์๋ค(2026-08-30 ์ค์ธก).\n *\n * ์ด ๊ฐ์ด ์์ผ๋ฉด ํ๋ฉด์ **ใ์ด ๊ตฌ๊ฐ์ ๋ค ๋ค์ด์ค์ง ์์ ๊ธฐ๊ฐ์ด ์๋คใ**๋ฅผ ๋งํด์ผ ํ๋ค.\n */\n notCounted?: { periods: number; kWh: number; earliestStart: string; latestEnd: string }\n /**\n * ์ด์ฉ๋ฅ โ ๋ง๋ ์ รท (์ ๊ฒฉ ร ๊ทธ ๊ธฐ๊ฐ์ ์๊ฐ).\n *\n * **์ด๋ ์ ๊ฒฉ์ผ๋ก ๋๋ด๋์ง๋ฅผ ํจ๊ป ๋ธ๋ค.** ๋ณํ๊ธฐ๋ฅผ ๋ ๋ฐ์ ์ ์ง๋ฅ ์ ๊ฒฉ์ด ๊ต๋ฅ๋ณด๋ค ํฌ๊ณ ,\n * ์ง๋ฅ๋ก ๋๋ ๋ณด์ฌ ์ฃผ๋ ์์คํ
์ด ์ค์ ๋ก ์๋ค. ๋ฐํ์ง ์์ผ๋ฉด ๋ ํ๋ฉด์ ์๊ฐ ๋ ๋ฐฐ ๋ฌ๋ผ๋\n * ์ ๋ค๋ฅธ์ง ๋งํ ์ ์๋ค.\n *\n * ์ฐฝ ์ ์ฒด๊ฐ ์๋๋ผ **์ผ ๊ธฐ๊ฐ๋ค์ ๊ธธ์ด**๋ก ๋๋๋ค โ ํ๋ฃจ์น ํ๋๋ง ์ผ 24์๊ฐ ์ฐฝ์์ ์ฐฝ ๊ธธ์ด๋ก\n * ๋๋๋ฉด ๊ทธ ํ๋ฃจ๊ฐ ์ฐฝ ์ ์ฒด์ ๊ฑธ์ณ ์์๋ ๊ฒ์ฒ๋ผ ์์์ง๋ค.\n */\n capacityFactor?: { value: number; ratedKW: number; basis: 'ac' | 'dc'; from: 'equipment' | 'location'; hours: number }\n /**\n * ๋ธ ๊ฒ์ ๊ฐ โ ๊ธฐ๊ฐ๋ง๋ค ๊ทธ๋์ ๋จ๊ฐ๋ก ๋งค๊ธด๋ค.\n *\n * **๋ชจ๋ ๊ธฐ๊ฐ์ ๋จ๊ฐ๊ฐ ์์ ๋๋ง** ๊ธ์ก์ ๋ง๋ ๋ค. ์ผ๋ถ๋ง ๋งค๊ธฐ๊ณ ๋ํ๋ฉด ๊ทธ ํฉ์ด ์ฐฝ ์ ์ฒด์ ๊ฐ์ธ\n * ์ฒํ๋ค โ ๋ชป ๋งค๊ธด ๊ธฐ๊ฐ ์๋ฅผ ํจ๊ป ๋ธ๋ค.\n */\n revenue?: { amount: number; currency: string; priced: number; unpriced: number }\n }\n /**\n * `kWh` ๊ฐ ์ด๋ ํ๊ณ์์ ์๋.\n *\n * 'demand-window' ์ฐ๋ฆฌ๊ฐ ํ๋ณธ์์ ๋ง๊ฐํ ๊ตฌ๊ฐ (๊ณ๋์ด ์ค๋ ํ์ฅ)\n * 'usage-period' ๋ฐ์์ ๋ง๊ฐ๋์ด ์จ ๊ตฌ๊ฐ (๊ณ๋ ํ๋ณธ์ด ์๋ ํ์ฅ)\n *\n * ๋์ ๋ํ์ง ์๋๋ค โ ๊ฐ์ ์ ๊ธฐ๋ฅผ ๋ ๋ฒ ์ผ๋ค. ๋ ๋ค ์์ผ๋ฉด ๊ณ๋ ์ชฝ์ ์ฐ๊ณ ๊ทธ ์ฌ์ค์ ๋ธ๋ค.\n */\n kWhBasis?: 'demand-window' | 'usage-period'\n /**\n * ๊ธฐ๋ณธ์๊ธ์ ๋งค๊ธด **์๊ธ์ ์ฉ์ ๋ ฅ๊ณผ ๊ทธ ๊ทผ๊ฑฐ**.\n *\n * ์ด ๊ฐ์ ๋งค๋ฌ ๋ค์ ์ ํด์ง๋ค. ์ ์ธ์ ๋ฐ์ ๋๋ฉด ์ฌ๋์ด ๊ฐฑ์ ํด์ผ ํ๊ณ , ์ ํ๋ฉด ๋ก์ ๊ฐ์ผ๋ก\n * ๊ธฐ๋ณธ์๊ธ์ด ์กฐ์ฉํ ํ๋ฆฐ๋ค. ๊ทธ๋์ **์ฒญ๊ตฌ์๊ฐ ๋จผ์ ๋ค** โ ์๋ณธ์ด ๋งค์ผ ์ค์ด ๋ณด๋ธ๋ค.\n *\n * 'bill' ์ด ์ฐฝ์ ๋ฎ๋ ์ฒญ๊ตฌ์๊ฐ ๋งํ ๊ฐ\n * 'carried-forward' ๊ฐ์ฅ ์ต๊ทผ ์ฒญ๊ตฌ์์ ๊ฐ์ ์ด์ด ์ด๋ค(์๊ธ ์ ๋๊ฐ ์ค์ ๋ก ๊ทธ๋ ๊ฒ ๊ตฐ๋ค)\n * 'declaration' ์ฒญ๊ตฌ๊ฐ ์ค์ง ์๋ ํ์ฅ โ ๋ชจ๋ธ์ ์ ์ธ\n *\n * `declaredKW` ์ ๋ค๋ฅด๋ฉด **์ ์ธ์ด ๋ก์๋ค**(`stale`). ๊ทธ ์ฌ์ค์ ๊ฐ์ถ๋ฉด ์๋ฌด๋ ๋ค์ ์ฝ์ง ์๋๋ค.\n */\n billingDemand?: {\n kW: number\n from: 'tariff-basis' | 'bill' | 'carried-forward' | 'declaration'\n declaredKW?: number\n stale?: boolean\n /**\n * ์ด ์ฐฝ์์ ๊ด์ธกํ ์ต๊ณ ์์๊ฐ ๊ทธ ๊ธฐ์ค์ ๋์๋ค โ **๋ค์ ์ฃผ๊ธฐ์ ๊ธฐ๋ณธ์๊ธ์ด ์ค๋ฅธ๋ค.**\n *\n * ๊ณ์ฝ ์ด๊ณผ์ ๋ค๋ฅธ ๊ฐ์ด๋ค. ๊ณ์ฝ ์ด๊ณผ๋ ์ง๊ธ ์ค์ด๋ฉด ๋๊ณ , ์ด๊ฒ์ ์ด๋ฏธ ์ ํด์ง ๊ฒฐ๊ณผ๋ค.\n *\n * `observedTo` ๋ ์ด ์ต๊ณ ๊ฐ์ด ์ธ์ ๊น์ง์ ๊ฒ์ธ์ง๋ค. ์ต๊ณ ์์๋ ๊ตฌ๊ฐ์ด ๋ง๊ฐ๋์ด์ผ ์ค๋ฏ๋ก\n * ๋์ ๊ฒ์ ๋ค๋ฆ๊ฒ ์๋ค โ ๊ทธ ํ๊ณ๋ฅผ ํ๋ฉด์ด ๋งํ ์ ์์ด์ผ ํ๋ค.\n */\n exceeded?: { peakKW: number; overKW: number; observedTo: string }\n }\n /**\n * ๋ฐ์์ ๋ง๊ฐ๋์ด ์จ ์ฌ์ฉ ๊ตฌ๊ฐ โ ๊ณ๋ ํ๋ณธ์ด ์๋ ํ์ฅ์ ์ ์ผํ ๊ทผ๊ฑฐ๋ค.\n *\n * `basis` ๋ณ ๊ฑด์๋ฅผ ํจ๊ป ๋ธ๋ค: ๊ฐ์ kWh ๋ผ๋ ๊ณ๋๊ธฐ๊ฐ ์ฐ ๊ฒ๊ณผ ๊ณต๊ธ์ ํ๋ฉด์์ ๊ธ์ด์จ ๊ฒ์ ๋ฌด๊ฒ๊ฐ\n * ๋ค๋ฅด๊ณ , ์ค์ ๋ก ๊ธ์ด์จ ๊ฐ์ด ๋ง๊ฐ์ ธ ์๋ ๊ฒ์ ๋ณธ ์ ์ด ์๋ค.\n */\n usage?: {\n kWh: number\n counted: number\n /** ๊ตฌ๊ฐ๋ง๋ค ์ ๋จ๊ฐ๋ก ๋งค๊ธด ์ฌ์ฉ๋ ์๊ธ โ ๋ชจ๋ ๊ตฌ๊ฐ์ด ๋จ๊ฐ๋ฅผ ์ค์์ ๋๋ง. */\n charge?: number\n currency?: string\n /** ๋จ๊ฐ๊ฐ ์์ด ์๊ธ์ ๋งค๊ธฐ์ง ๋ชปํ ๊ตฌ๊ฐ ์ โ ์กฐ์ฉํ ๋นผ์ง ์๋๋ค. */\n unpriced: number\n byBasis: { basis: string; counted: number }[]\n }\n /**\n * ์ด ์ฐฝ์ ์จ์ ํ ๋ **์ฒญ๊ตฌ์** โ ๊ณต๊ธ์๊ฐ ํ์ ํ ๊ธ์ก.\n *\n * ์ฐ๋ฆฌ ๊ณ์ฐ์ ๋ฎ์ง ์๋๋ค. ์ฐฝ์ด ์ฒญ๊ตฌ ์ฃผ๊ธฐ์ ์ ํํ ๊ฐ์ ๋๋ง ๊ฒฌ์ค ์ ์์ผ๋ฏ๋ก ๊ทธ ์ฌ์ค์\n * `matchesWindow` ๋ก ํจ๊ป ๋ธ๋ค โ ๋ค๋ฅธ ์ฐฝ์ ๋ ์๋ฅผ ๋นผ๋ฉด ๊ทธ ์ฐจ์ด๋ ์๋ฌด๊ฒ๋ ๋ปํ์ง ์๋๋ค.\n */\n bill?: {\n from: string\n to: string\n total?: number\n energyCharge?: number\n demandCharge?: number\n currency?: string\n billingDemandKW?: number\n matchesWindow: boolean\n /**\n * ์ฐฝ์ด ๊ฐ์ ๋, **์ฐ๋ฆฌ ๊ณ์ฐ์์ ์ฒญ๊ตฌ์ก์ ๋บ ๊ฐ** โ 0 ์ด ์๋๋ฉด ์ฐ๋ฆฌ ๊ณ์ฐ์ด ํ๋ ธ๋ค๋ ๋ป์ด๋ค.\n *\n * ํญ๋ชฉ๋ณ๋ก๋ ๋ธ๋ค(2026-08-29). ์ด์ก๋ง ๊ฒฌ์ฃผ๋ฉด ์๋ณธ์ด ์ด์ก์ ์ฃผ์ง ์๋ ์ฒญ๊ตฌ์์์๋ ๋น๊ต๊ฐ\n * ์์ ๋์ค์ง ์๋๋ค โ ์ค์ ๋ก ์ฒซ ์ฒญ๊ตฌ์์ ๊ธฐ๋ณธ์๊ธ๋ง ์์๋ค. ์์ชฝ์ ์๋ ํญ๋ชฉ๋ง ๊ฒฌ์ค๋ค.\n */\n diff?: { total?: number; demandCharge?: number; energyCharge?: number }\n }\n /** ํ์์ ๊ทผ๊ฑฐ โ ๊ตฌ๊ฐ ํ๊ท ๋ถํ ร ๊ธธ์ด(`mean-kw`). */\n basis: string\n /** ์ผ ๊ตฌ๊ฐ ์ ยท ๋ชป ์ผ ๊ตฌ๊ฐ ์(๊ณ์ธก์ด ๋๊ธด ๊ตฌ๊ฐ) โ ์๋ฆฌ์ง ์๊ณ ์๋ฅด์ง ์๋๋ค. */\n counted: number\n skipped: number\n /** ์๋ฃ ์ค๋๋น ์ ๋ ฅ๋ โ ๋ตํ ์ ์์ผ๋ฉด `null` ๊ณผ ์ด์ . */\n intensity: { value: number | null; unit?: string; reason?: string }\n /**\n * ๋ฐฐ์ ๊ณํต์ **์๋ฆฌ๋ณ ๋ชซ** โ ใ์ด ๋ถ๊ธฐ๊ฐ ์ผ๋ง ์ผ๋ใ.\n *\n * โโ ์ด๊ฒ์ ์ธก์ ์ด ์๋๋ผ ๋ฐฐ๋ถ์ด๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ๋์ ์๋ ์๋์ง ์ฌ์ค์ **ํ์ฅ ์ด๋ ํ ์ค**์ด๋ค(๋ฟ๋ฆฌ ๊ณ๋๊ธฐ ํฉ). ๊ณ๋๊ธฐ๋ณ ๊ตฌ๊ฐ ์ฌ์ค์ด ์์ผ๋ฏ๋ก\n * ์๋ฆฌ๋ณ ๋ชซ์ **๋๋ ๊ฒ**์ด๊ณ , ๋ฌด์์ผ๋ก ๋๋ด๋์ง(`weightKind`)๋ฅผ ๊ฐ๊ณผ ํจ๊ป ๋ธ๋ค. ๊ทผ๊ฑฐ๋ฅผ ๊ฐ์ถ๋ฉด\n * ๋๋ ์ซ์๊ฐ ์ฐ ์ซ์์ ๊ฐ์ ๋ฌด๊ฒ๋ก ์ฝํ๋ค โ CBAMยทESG ๋ณด๊ณ ์์ ์ฒซ ์ง๋ฌธ์ ๊นจ์ง๋ ์ง์ ์ด๋ค.\n *\n * ๊ฐ์ค์น๋ **์์
๊ฐ๋์๊ฐ**์ด๋ค. ์ ๊ฒฉ(kW)์ผ๋ก ๋๋์ง ์๋๋ค: ์๋ฎฌ ํธ์์ ์ด๋ถํ๊ฐ ์ ๊ฒฉ์ ํฉ์ผ๋ก\n * ํ์๋๋ฏ๋ก, ๊ทธ ์ด๋์ ๋ค์ ์ ๊ฒฉ์ผ๋ก ๋๋๋ฉด ๋ฃ์ ๊ฐ์ด ๊ทธ๋๋ก ๋์ค๋ ๋์ด๋ฐ๋ณต์ด ๋๋ค.\n *\n * ๊ทธ๋์ ์ด ๊ฐ์๋ **๊ฐ์ ์ด ํ๋ ์ค๋ ค ์๋ค**: ์ ๊ธฐ๊ฐ ๊ฐ๋์๊ฐ์ ๋น๋กํ๋ค. ๊ณต์กฐยท์กฐ๋ช
์ฒ๋ผ ๊ณต์ ์\n * ๋ถ์ง ์๋ ๋ถํ๋ ๊ทธ ๋น์จ์ ์์ธ๋ค โ ํ๋ฉด์ด ๊ทธ ๋ฌธ์ฅ์ ํจ๊ป ๋งํด์ผ ํ๋ค.\n */\n byFeeder?: {\n /** ์๋ฆฌ(๋ถ๊ธฐยท์์ ) id. ์๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋ ์์์ `unknown` ์ผ๋ก ๋ชจ์ธ๋ค(์๋ฆฌ์ง ์๊ณ ๋ฒ๋ฆฌ์ง ์๋๋ค). */\n key: string\n kWh: number\n /**\n * ์ด ๋ชซ์ ๊ทผ๊ฑฐ โ **์ปค๋์ด ์ ํ๋ค.**\n *\n * ์ ์ธ๋ ๋ถํ๊ฐ ์ฌ๋ฟ์ด๋ฉด ๋ฐฐ๋ถ(`apportioned`)์ด๋ค. ์ ์ธ๋ ๋ถํ๊ฐ **ํ๋๋ฟ์ธ** ํ์ฅ์์๋ ์ปค๋์ด\n * ใ๊ทธ ๊ณ๋๊ธฐ๋ ๊ทธ๊ฒ๋ง ์ฐ๋คใ๊ณ ์ฝ์ด `measured` ๋ฅผ ๋ธ๋ค โ ๋ชจ๋ธ์ด ๊ทธ๋ ๊ฒ ๋งํ์ผ๋ฏ๋ก ๊ทธ๊ฒ๋ ์ฌ์ค์ด๋ค.\n * ์ฐ๋ฆฌ๊ฐ ์ด๋ ์ชฝ์ผ๋ก๋ ๋์ธ์ฐ์ง ์๋๋ค.\n */\n basis: 'apportioned' | 'measured'\n /**\n * ๋ฌด์์ผ๋ก ๋๋ด๋ โ **๋ฐฐ๋ถ์ผ ๋๋ง** ์๋ค.\n *\n * ๋ถ๊ธฐ๋ง๋ค ๊ณ๋๊ธฐ๊ฐ ์๋ ํ์ฅ์์๋ ๋๋์ง ์๋๋ค(๊ทธ ๊ฐ์ด ๊ณง ๊ณ๋์ด๋ค). ๊ทธ๋ ์ด ์นธ์\n * `runtimeMs` ๋ก ์ฑ์ฐ๋ฉด ใ๊ฐ๋์๊ฐ์ผ๋ก ๋๋ด๋คใ๋ ์๋ ์ฌ์ค์ ๋งํ๊ฒ ๋๋ค.\n */\n weightKind?: 'runtimeMs'\n /** ์ด ์๋ฆฌ์ ๋ชซ์ด ์ ์ฒด์ ์ผ๋ง์๋ โ ๋ฐฐ๋ถ์ผ ๋๋ง. */\n weightShare?: number\n /**\n * **ํผํฌ๊ฐ ์ฐํ ์๊ฐ** ์ด ๋ถ๊ธฐ๊ฐ ์ผ๋ง์๋(kW) โ ์๊ธ์ด ๊ฑธ๋ฆฐ ์๋ค.\n *\n * ์ฐฝ์ ํ๊ท ์ด๋ ํฉ์ด ์๋๋ค: ์ต๋์์๋ฅผ ๋ธ ๊ตฌ๊ฐ์ ๊ทธ ์๊ฐ ๊ฐ์ด๋ค(๋ค๋ฅธ ์๊ฐ์ ์์ผ๋ฉด ใ์ด๋ ๋ถ๊ธฐ๋ฅผ\n * ๊น์์ผ ํผํฌ๊ฐ ๋ด๋ ค๊ฐ๋ใ์ ๋ต์ด ํ๋ ค์ง๋ค). ๊ทธ ๊ตฌ๊ฐ์ ์ด ๋ถ๊ธฐ์ ํ๋ณธ์ด ์์์ผ๋ฉด **์๋ค**.\n */\n peakKW?: number\n }[]\n /**\n * ๋๋์ง ๋ชปํ ์๊ณผ ๊ทธ ์ด์ โ **์๋ฆฌ์ง ์๊ณ 0 ์ผ๋ก ๋ง๋ค์ง ์๋๋ค.**\n * `no-weights` = ๊ทธ ์ฐฝ์ ๋์๊ฐ ์์์ด ์๋ค(๊ฐ๋์๊ฐ์ด ์ ๋ถ 0). ๊ทธ๋ฌ๋ฉด ์ด๋์ ๊ทธ๋๋ก ๋จ๋๋ค.\n */\n unattributedKWh?: number\n /**\n * ์ ๋๋์ง ๋ชปํ๋(์ปค๋ ์ฝ๋) โ `no-weights`(๊ฐ๋์๊ฐ์ด ์ ๋ถ 0) ยท `no-consumers`(๋ฎ๋ ๋์ ๋ฏธ์ ์ธ) ยท\n * `not-submetered`(๋ฟ๋ฆฌ์์ ์ฌ์์ผ๋ ํ์ ๊ณ๋์ด ๋ฎ์ง ์๋ ๋ถ๋ถ โ ๊ฒฐ์์ด ์๋๋ผ ๊ณ๋ ๋ฒ์์ ์ฌ์ค).\n */\n unattributedReason?: string\n /**\n * ๋ถ๊ธฐ ๊ณ๋์ ํฉ์ด ๋ฟ๋ฆฌ ๊ณ๋๋ณด๋ค **ํฐ** ์ โ ๋ ๊ณ๋๊ธฐ์ ํ๊ณ๊ฐ ๋ค๋ฅด๋ค๋ ์ฌ์ค์ด๋ค.\n *\n * ๊ฐ์ ๊น์ ๋ง์ถ์ง ์๋๋ค: ๊ทธ๊ฒ์ ๊ณ๋์ ์ฐ๋ฆฌ๊ฐ ๊ณ ์ณ ์ฐ๋ ์ผ์ด๊ณ , ์ด๋ ์ชฝ์ด ๋ง๋์ง๋ ํ์ฅ์ด ์๋ค.\n */\n submeterExcessKWh?: number\n /**\n * ๋ฐฐ๋ถ์์ **๋น ์ง ์์ ์** โ ๊ทธ ์ฐฝ์ ๊ฐ๋ ๊ธฐ๋ก์ด ์๋ ์ค๋น๋ค. 0kWh ๋ฅผ ์ฃผ์ง ์๋ ๋์ ๋ช ๋๊ฐ\n * ๋น ์ก๋์ง ์ผ๋ค(๋๊ธฐ์ ๋ ฅ์ด ์๋ ์ค๋น์์ 0 ์ ๊ณง ๊ฑฐ์ง์ด๋ค).\n */\n excludedResources?: number\n /**\n * ์ด ์ฐฝ์ ์ ๊ธฐ์๊ธ โ **์ฒญ๊ตฌ์๊ฐ ์๋๋ค.** ๊ณ์ฐ๊ณผ ๊ทธ ํ๊ณ(TOUยท๋์นซยท์ต์์ฒญ๊ตฌ์ก ๋ฏธ๋ชจ๋ธ)๋ ์ปค๋\n * (`electricityCost`)์ด ๊ฐ๊ณ ์ฌ๊ธฐ์๋ ๋๋ฅธ๋ค. ๋จ๊ฐ๊ฐ ์์ผ๋ฉด `reason: 'no-tariff'` ๋ก ์จ๋ค.\n */\n cost?: ElectricityCost\n }\n /** ๋ฆฌ๋ํ์ โ ์์ฑ(created)์์ ์๋ฃ๊น์ง. ์ฌ์ฉ์๊ฐ ์ฒด๊ฐํ๋ ์์ ์๊ฐ. */\n leadTime: DurationStats\n /** ์์
์๊ฐ โ ์ฐฉ์(in-progress)์์ ์๋ฃ๊น์ง. ๋๊ธฐ๋ฅผ ๋บ ์ค์์
. */\n workTime: DurationStats\n /** ๋๊ธฐ์๊ฐ โ ์์ฑ์์ ์ฐฉ์๊น์ง. ์์์ด ๋ถ์กฑํ๋ฉด ์ฌ๊ธฐ๊ฐ ๋์ด๋๋ค. */\n waitTime: DurationStats\n /** ์์๋ณ ์ ์ โ ์์
์ ๋ถ์ด ์๋ ์๊ฐ์ ํฉ๊ณผ ์ฐฝ ๋๋น ๋น์จ(์์
์ผ๋ก ์ค๋ช
๋๋ ๋ถ๋ถ๋ง). */\n utilization: { resourceId: string; busyMs: number; ratio: number }[]\n /**\n * **์
์์ ๋น ์ง ๊ฒ** โ ์๋ฃ๋ ์ฐฝ ์์ด์ง๋ง ์์ ์ด๋ฒคํธ๋ฅผ ๋ชป ์ฐพ์ ๊ฑด์.\n * ์กฐํ ๊ตฌ๊ฐ์ด ์งง์ ์์์ด ์๋ ธ๊ฑฐ๋ ์ ๋์ด ์ ์ค๋ ๊ฒฝ์ฐ๋ค. ์ด ๊ฐ์ ์จ๊ธฐ๋ฉด ํ๊ท ์ด ์๋ฆฌ์ง ์๊ณ ๊ฑฐ์ง์ด ๋๋ค.\n */\n unpaired: { leadTime: number; workTime: number }\n /**\n * **์๋ฃ๋ก ์ธ์ง ์์ ์ค๋ ์ํ ๋ฑ๋ง์ ์ธ๊ตฌ์กฐ์ฌ** โ ๋ฑ๋ง โ ์ฐฝ ์์์ ๊ทธ ๋ฑ๋ง๋ก ๋ณธ ๊ฑด์.\n *\n * ใ๋ชป ์ฝ์๋คใ๊ฐ **์๋๋ค.** `picking` ์ฒ๋ผ ์๋ฃ๊ฐ ์๋ ๋ฑ๋ง์ด ์ฌ๊ธฐ ์ค๋ ๊ฒ์ ์ ์์ด๋ค. ์ด ๊ฐ์\n * ํ์ ์ด ์๋๋ผ **์ฌ๋ฃ**๋ค: ์๋ฃ๊ฐ 0 ์ธ๋ฐ ์ฌ๊ธฐ `{ finished: 2780 }` ์ด ์์ผ๋ฉด ์์ธ์ด ๊ณง ๋ณด์ธ๋ค.\n *\n * โโ ์ ํ์ํ๊ฐ, ๊ทธ๋ฆฌ๊ณ ๋ฌด์์ ๋์ฒด๊ฐ ์๋๊ฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ด ํด๋๋ ์๋ฃ๋ฅผ **๋์์ด ๋ชฉ๋ก**์ผ๋ก ํ์ ํ๋ค(`completed`ยท`fulfilled`ยท`done`ยท`finished`). ๊ทธ ๋ฐฉ์์\n * ์๋ณธ์ ๋ฑ๋ง์์ ๋ป์ **์ถ๋ก **ํ๋ ๊ฒ์ด๊ณ , ์ด ์ ์ฅ์๊ฐ ๋ค๋ฅธ ์๋ฆฌ์์ ๊ฑฐ์ ํ๋ ๊ทธ๊ฒ์ด๋ค\n * (ใ์ ์ธ์ด ์์ผ๋ฉด ๋ณํ์ด์ง๋ง ์์ผ๋ฉด ๋ฐ๋ช
์ด๋คใ).\n *\n * ์ค์ ๋ก ๊ทธ ๋๊ฐ๋ฅผ ์น๋ ๋ค: `finished` ๊ฐ ๋ชฉ๋ก์ ์์ด ์ฒซ ์ค ์์คํ
์ ์๋ฃ ์ค๋๊ฐ ์ ๋ถ 0 ์ด์๋ค.\n * ๊ทธ๋ฐ๋ฐ **๋น ์๋ฆฌ๋ ์ด ๋ชฉ๋ก์ด ์๋๋ผ ์ปค๋ฅํฐ์๋ค** โ ๊ทธ ์ปค๋ฅํฐ์ ์ํ ํ(`WORK_ORDER_STATE`)๊ฐ\n * ์ ์๋ผ ์์ผ๋ฉด์ ์ค๋ ๊ฒฝ๋ก์์ ์ฐ์ด์ง ์์๊ณ (๋กํธ ๊ฒฝ๋ก๋ ์ผ๋ค), ์๋ณธ ๋ฑ๋ง์ด ๊ทธ๋๋ก ํ๋ ๋ค.\n * ๋ชฉ๋ก์ `finished` ๋ฅผ ๋ํ ๊ฒ์ ๊ทธ ์ฌ์ค์ ๊ฐ๋ฆฐ ๋๋นต์ด์๋ค.\n *\n * **์ ์์ ์ปค๋ฅํฐ๊ฐ ์๊ธฐ ํ๋ก ์ฎ๊ธฐ๊ณ , ์ฎ๊ธธ ์ ์๋ ๋ฑ๋ง์ ์ธ๊ณ ๋ฃ์ง ์๋ ๊ฒ์ด๋ค**(์ฌ๊ณ ์ฒ๋ถ์ด ์ด๋ฏธ\n * ๊ทธ ๊ท์จ๋ก ์ ๋ค: ใํํํ ๊ธธ์ด ์๋ ๊ฒ์ ๋ฃ์ง ์๋๋คใ). ๊ทธ๋ฌ๋ฉด ์ด ํด๋๋ ์ถ๋ก ํ์ง ์์๋ ๋๋ค.\n *\n * ๊ทธ๋ฌ๋ฏ๋ก ์ด ๊ฐ์ **๋์์ด ๋ชฉ๋ก์ ๋๋ฆฌ๋ ๊ทผ๊ฑฐ๊ฐ ์๋๋ค.** ๋ชฉ๋ก์ ์ปค๋ฅํฐ๋ค์ด ์ฎ๊ธฐ๊ธฐ ์์ํ๋ฉด\n * ๋ซํ ์ดํ๋ก ์ขํ์ผ ํ๊ณ , ๊ทธ๋๊น์ง ์ด ๊ฐ์ด ์ด๊ธ๋จ์ ๋งํด ์ค๋ค. ์์๊ฐ ์ค์ํ๋ค โ ๋ชฉ๋ก์ ๋จผ์ \n * ์ขํ๋ฉด ์์ง ์ฎ๊ธฐ์ง ์๋ ์๋ณธ์ ์๋ฃ๊ฐ ๊ทธ ์๊ฐ 0 ์ด ๋๋ค.\n *\n * ์ํ๋ฅผ ๋งํ์ง ์์ ์ฌ๊ฑด์ ์ฌ๊ธฐ ์ค์ง ์๋๋ค. ๊ทธ๊ฒ์ ใ๋ชจ๋ฅด๋ ๋ฑ๋งใ์ด ์๋๋ผ ๋ค๋ฅธ ๊ฒฐํจ์ด๊ณ \n * (์ ์
๋ฌธ์ด ์ํ๋ฅผ ํ์๋ก ๋ฐ๋๋ค) ๊ทธ ์ง๋จ์ ๊ทธ ๋ฌธ์ ๋ชซ์ด๋ค.\n */\n orderStatusNotCounted: Record<string, number>\n /**\n * ์๋นํ ์ด๋ฒคํธ ์ โ **๋๊ฒจ๋ฐ์ ๋ฐฐ์ด ์ ์ฒด**(์ฐฝ ์ lookback ํฌํจ). ์ง๋จ์ฉ์ด๋ค.\n *\n * \"์ธก์ ๋ ๊ธฐ๋ก์ด ์๋๊ฐ\" ์ ํ๋จ์๋ ์ฐ์ง ๋ง ๊ฒ โ ํธ์ถ๋ถ๋ ์ฐฝ๋ณด๋ค ์๊น์ง ์ฝ์ด ๋๊ธฐ๋ฏ๋ก(์๋ฃ๋ ์์
์\n * ์์์ด ์ฐฝ ๋ฐ์ผ ์ ์๋ค) ์ฐฝ ์์ด ๋น์ด ์์ด๋ ์ด ๊ฐ์ 0 ์ด ์๋๋ค. ๊ทธ ํ๋จ์ `eventsInWindow` ๋ก ํ๋ค.\n */\n eventsSeen: number\n /**\n * **์ฐฝ ์์** ๋ค์ด์จ ์ด๋ฒคํธ ์ โ \"์ด ๊ตฌ๊ฐ์ ์ธก์ ํ ๊ธฐ๋ก์ด ์์๋๊ฐ\" ์ ์ ๋ต.\n *\n * ์ด๊ฒ์ด 0 ์ด๋ฉด \"์ฒ๋ฆฌ๋ 0\" ์ด ์๋๋ผ **\"๊ธฐ๋ก์ด ์๋ค\"** ๋ค. ๋ ์ํฉ์ ์์ผ๋ฉด ์ฌ์ฉ์๊ฐ ์๋ชป๋ ๊ฒฐ๋ก ์\n * ๋ธ๋ค(์ ๊ตฌ๊ฐ์ ๊ธฐ๋ก๋ง ์ฝ์ด ๋๊ณ \"0๊ฑด ์ฒ๋ฆฌ\" ๋ผ๊ณ ๋งํ๋ ์ผ์ด ์ค์ ๋ก ๊ฐ๋ฅํ๋ค).\n */\n eventsInWindow: number\n /** ์์ฒญํ ๊ด์ ์ผ๋ก ์ชผ๊ฐ ๊ฐ(์์ฒญํ์ ๋๋ง). */\n groups?: { by: KpiGroupBy; items: KpiGroup[]; truncated?: number; truncatedTasks?: number }\n}\n\n/**\n * ์ฐฝ์ ์ ๋ ฅ๋์ **๋ฐฐ์ ๊ณํต์ ์๋ฆฌ๋ณ๋ก ๋๋๋ค** โ ๊ทผ๊ฑฐ๋ฅผ ํจ๊ป.\n *\n * โโ ์ ์ปค๋ ํจ์๋ฅผ ์ฐ๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ใ๋๋ ๊ทผ๊ฑฐ๊ฐ ์์ผ๋ฉด ๋๋์ง ์๋๋คใยทใํฉ์ ๋ณด์กด๋๋คใยทใ๋ชซ์ด 0 ์ด๋ฉด 0kWh ๋ฅผ ์ฃผ์ง ์๋๋คใ๋ ๊ท์น์ด\n * ์ปค๋์ `attributeEnergy` ์ ์ด๋ฏธ ์๋ค. ์ฌ๊ธฐ์ ๋ค์ ์ฐ๋ฉด ๋ ๋ฒ์ด ๋๊ณ , ๊ทธ๋๋ถํฐ ๋ ํ๋ฉด์ด ๋ค๋ฅธ ํฉ์\n * ๋งํ๋ค. ์ด ํจ์๊ฐ ํ๋ ์ผ์ **์ฌ๋ฃ๋ฅผ ๋ชจ์ ๋๊ธฐ๊ณ ๋ต์ ์๋ฆฌ๋ณ๋ก ๋ฌถ๋ ๊ฒ**๋ฟ์ด๋ค.\n *\n * โโ ๊ฐ์ค์น๋ ๊ฐ๋์๊ฐ์ด๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ๊ฒฉ(kW)์ผ๋ก ๋๋์ง ์๋๋ค: ์๋ฎฌ ํธ์์ ์ด๋ถํ๊ฐ ์ ๊ฒฉ์ ํฉ์์ ํ์๋๋ฏ๋ก ๊ทธ ์ด๋์ ๋ค์ ์ ๊ฒฉ์ผ๋ก\n * ๋๋๋ฉด ๋ฃ์ ๊ฐ์ด ๊ทธ๋๋ก ๋์จ๋ค(์ ์ ๋ณด 0์ ๋์ด๋ฐ๋ณต). ๊ฐ๋์๊ฐ์ **์ ๋์ด ๊ด์ธกํ ์ฌ์ค**์ด๋ค.\n *\n * ์๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋ ์์์ `unknown` ์ผ๋ก ๋ชจ์ธ๋ค โ ๋นผ๋ฉด ํฉ์ด ์ค๊ณ , ์๋ฌด ์๋ฆฌ์ ๋ฃ์ผ๋ฉด ๊ฑฐ์ง์ด ๋๋ค.\n */\nfunction feederShares(\n kWh: number | undefined,\n utilization: { resourceId: string; busyMs: number }[],\n resourceFeeder?: Record<string, string>\n): Partial<NonNullable<KpiResult['energy']>> {\n /* ์ ์ธ์ด ์์ผ๋ฉด ๋ถํดํ์ง ์๋๋ค โ ์๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋ ์ฑ ๋๋ ์ซ์๋ ์๋ฌด ๊ฒ์ ๋ชซ๋ ์๋๋ค. */\n if (!resourceFeeder || !Object.keys(resourceFeeder).length) return {}\n if (kWh === undefined || !(kWh > 0)) return {}\n\n /*\n * โโ ํ์ด **๋ฌด์์ ๋ฎ๋์ง ์ฌ์ค๋๋ก** ๋งํ๋ค (2026-08-17) โโโโโโโโโโโโโโโโโโโโ\n *\n * ์ฒ์์๋ ใ๊ทธ ์ฐฝ์ ๋์๊ฐ ์์ใ๋ง ๋ฎ๋๋ค๊ณ ๋๊ฒผ๋ค. ๊ทธ๋ฌ์ ๋์๊ฐ ์์์ด ํ๋์ธ ์ฐฝ์์ ์ปค๋์ด\n * ๊ทธ๊ฒ์ **`measured`(์ ์ฉ ๊ณ๋)** ๋ก ํ์ ํ๋ค โ ์ปค๋์ ๊ท์น์ ์ณ๋ค(ใ๋ฎ๋ ์๋น์ฒ๊ฐ ํ๋๋ฉด ๊ทธ\n * ๊ณ๋๊ธฐ๋ ๊ทธ๊ฒ๋ง ์ฐ๋ค๋ ์ ์ธ์ด๋คใ). ํ๋ฆฐ ๊ฒ์ ๋ด ์ ์ธ์ด์๋ค: ํ์ฅ ๊ณ๋๊ธฐ๋ ๋์๊ฐ ๊ฒ๋ง ์ฌ์ง ์๋๋ค.\n *\n * ๊ทธ๋์ **์ ์ธ๋ ๋ถํ ์ ๋ถ**๋ฅผ ๋ฎ๋๋ค๊ณ ๋งํ๋ค(`resourceFeeder` ์ ํค๊ฐ ๊ณง ๊ทธ ์ ์ธ์ด๋ค).\n * ๊ทธ๋ฌ๋ฉด ๊ทธ ์ฐฝ์ ๋์ง ์์ ์ค๋น๋ ๋ชซ 0 ์ผ๋ก **๋ฐฐ๋ถ์์ ๋น ์ง๊ณ ๊ทธ ์๊ฐ ๋ณด๊ณ ๋๋ค** โ 0kWh ๋ฅผ ์ฃผ๋\n * ๋์ ใ์ด ์ค๋น๋ ์ด ์ฐฝ์ ๊ฐ๋ ๊ธฐ๋ก์ด ์๋คใ๋ฅผ ๋งํ๋ ์ชฝ์ด๋ค.\n */\n /*\n * ๋ฎ๋ ๋์์ **์ ์ธ๋ ๋ถํ โช ๊ทธ ์ฐฝ์ ๋์๊ฐ ์์**์ด๋ค.\n *\n * ์ ์ธ๋ง ์ฐ๋ฉด, ๋์๋๋ฐ ์ ๊ธฐ ๊ณํต์ ์ ์ธ๋์ง ์์ ์ค๋น์ ๋ชซ์ด ๋๋จธ์ง ์ค๋น์ ์นํ๋ค โ ๊ทธ ์ค๋น๊ฐ\n * ์ ์ด ์ ๊ธฐ๋ฅผ ์ด ๊ฒ์ผ๋ก ๋ง๋ ๋ค. ๋์๊ฐ ๊ฒ๋ง ์ฐ๋ฉด, ์ ์ธ๋์ง๋ง ์ฐ ์ค๋น๊ฐ ์ฌ๋ผ์ ธ ใ์ด ์ฐฝ์ ์ ๋์๋คใ๋ฅผ\n * ๋งํ ์ ์๋ค. ๋์ ํฉํด์ผ ๋ ์ฌ์ค์ด ๋ค ๋จ๋๋ค(์๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋ ๋ชซ์ `unknown` ์ผ๋ก ๋ชจ์ธ๋ค).\n */\n const busyOf = new Map(utilization.map(u => [u.resourceId, u.busyMs]))\n const ids = new Set<string>([...Object.keys(resourceFeeder), ...busyOf.keys()])\n const consumers = [...ids].map(id => ({ id, weight: busyOf.get(id) ?? 0 }))\n if (!consumers.length) return {}\n\n const r = attributeEnergy({\n pools: [{ meterId: 'site', kWh, consumerIds: consumers.map(c => c.id) }],\n consumers,\n weightKind: 'runtimeMs'\n })\n\n const byKey = new Map<string, { kWh: number; weightShare: number; apportioned: boolean }>()\n for (const sh of r.shares) {\n /* ์๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋ฉด `unknown` โ ๊ทธ ๋ชซ์ด ์๋ค๋ ์ฌ์ค์ ๋จ๊ธฐ๊ณ , ์ด๋์ ๊ฒ์ธ์ง๋ ์ง์ด๋ด์ง ์๋๋ค. */\n const key = resourceFeeder[sh.consumerId] ?? 'unknown'\n const cur = byKey.get(key) ?? { kWh: 0, weightShare: 0, apportioned: false }\n cur.kWh += sh.kWh\n cur.weightShare += sh.weightShare ?? 0\n /* **๊ทผ๊ฑฐ๋ ์ปค๋์ด ์ ํ๋ค.** ์ฌ๊ธฐ์ ๋์ธ์ฐ์ผ๋ฉด ์ปค๋์ด ใ์๋คใ๊ณ ํ ๊ฒ์ ใ๋๋ด๋คใ๊ณ ๋ฐ๊ฟ ๋งํ๊ฑฐ๋\n ๊ทธ ๋ฐ๋๊ฐ ๋๋ค. ์์ด๋ฉด ์ฝํ ์ชฝ(๋ฐฐ๋ถ)์ผ๋ก ์ ๋๋ค โ ๊ฐํ ์ฃผ์ฅ์ ์ฌ๋ ค ์ก์ง ์๋๋ค. */\n if (sh.basis === 'apportioned') cur.apportioned = true\n byKey.set(key, cur)\n }\n\n const byFeeder = [...byKey.entries()]\n .map(([key, v]) => ({\n key,\n kWh: v.kWh,\n basis: (v.apportioned ? 'apportioned' : 'measured') as 'apportioned' | 'measured',\n weightKind: 'runtimeMs' as const,\n weightShare: v.weightShare\n }))\n .sort((a, b) => b.kWh - a.kWh)\n\n const un = r.unattributed.reduce((sum, u) => sum + u.kWh, 0)\n return {\n ...(byFeeder.length ? { byFeeder } : {}),\n ...(un > 0 ? { unattributedKWh: un, unattributedReason: r.unattributed[0]?.reason } : {}),\n ...(r.excluded.length ? { excludedResources: r.excluded.length } : {})\n }\n}\n\n/**\n * ๋ถ๊ธฐ๋ณ ์ ๋ ฅ๋์ **๊ณ๋์ผ๋ก** ์ฝ๋๋ค โ ๊ณ๋์ด ์์ผ๋ฉด ๋ฐฐ๋ถํ์ง ์๋๋ค.\n *\n * โโ ์ ํ์ํ๋ (2026-08-18) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ค ๊ฒ์ดํธ์จ์ด๋ ๋ถ๊ธฐ๋ง๋ค ๊ณ๋๊ธฐ๋ฅผ ๋ณด๋ธ๋ค. ๊ทธ๋ฐ๋ฐ ํ๋ฉด์ ใ๋๋์ง ๋ชปํจใ์ผ๋ก ๋ตํ๊ณ ์์๋ค โ ์ฌ๊ธฐ์\n * ๊ฐ๋์๊ฐ ๋ฐฐ๋ถ ๊ฒฝ๋ก๋ง ์์๊ธฐ ๋๋ฌธ์ด๋ค. ๊ณ๋์ด ์๋๋ฐ ๋ฐฐ๋ถ์ผ๋ก ๋งํ๋ฉด **๊ทผ๊ฑฐ๋ฅผ ์ค์ ๋ณด๋ค ์ฝํ๊ฒ** ๋ณด๊ณ ํ๋\n * ๊ฒ์ด๊ณ , ๊ทธ ์์ ์ธ์ด SEU ํ๋จ์ด ๋ฌด๊ฑฐ์ด ๊ฐ์ ๋์น๋ค. ๋ฏธ๋ฌ ํธ์์๋ ์ค๋น ๊ฐ๋ ๊ธฐ๋ก์กฐ์ฐจ ์์ด์\n * (์์ฒ์ด ๊ณ๋๋ง ์ค๋ค) ๊ทธ ๊ฒฝ๋ก๋ก๋ ๋ถ๊ธฐ๋ณ ๊ฐ์ด ์์ํ ๋์ค์ง ์์๋ค.\n *\n * ๊ฐ์ ์ถ์ฒ๋ ์ปค๋์ด ๊ตฌ๊ฐ ๋ง๊ฐ ์ฌ์ค์ ์ค์ด ์ฃผ๋ **์ง์ ๋ณ ๋ชซ**์ด๋ค(์ ์ฐ์ ๋บ์
). ํ๋ณธ์ ์ง์ ์ฝ์ง ์๋\n * ์ด์ ๋ ์กฐํ ์ํ์ด๋ค โ ๊ณ์ธก์ ์ด๋น ์ฌ๋ฌ ๊ฑด์ด๋ผ ํ๋ณธ์ผ๋ก๋ ์ฐฝ์ ์ฑ์ฐ๊ธฐ ์ ์ ์ํ์ ๊ฑธ๋ฆฐ๋ค.\n *\n * ๋๋จธ์ง(๋ฟ๋ฆฌ โ ๋ถ๊ธฐ ํฉ)๋ **๋ฒ๋ฆฌ์ง๋ ์น์ง๋ ์๋๋ค**: ์์ ์ง๊ฒฐ ๋ถํยท์์คยท๊ณ๋๋์ง ์์ ํ๋ก๊ฐ ๊ทธ\n * ์ฐจ์ด์ด๋ฏ๋ก, ์ด๋ ๋ถ๊ธฐ์ ์น์ผ๋ฉด ๊ทธ ๋ถ๊ธฐ๊ฐ ์ฐ์ง ์์ ์ ๊ธฐ๋ฅผ ์ด ๊ฒ์ผ๋ก ๋ง๋ ๋ค. ์ปค๋์ `remainder` ํ๋ก\n * ๋๊ฒจ ใํ์ ๊ณ๋์ด ๋ฎ์ง ์๋๋คใ๋ก ๋จ๊ธด๋ค.\n *\n * ๋ถ๊ธฐ ๊ณ๋ ํฉ์ด ๋ฟ๋ฆฌ๋ณด๋ค ํฌ๋ฉด(ํ๊ณ๊ฐ ๋ค๋ฅธ ๋ ๊ณ๋๊ธฐ) **๊ทธ ์ฌ์ค์ ๋ธ๋ค** โ ๊ฐ์ ๊น์ ๋ง์ถ๋ฉด ๊ณ๋์\n * ์ฐ๋ฆฌ๊ฐ ๊ณ ์ณ ์ฐ๋ ๊ฒ์ด๋ค.\n */\n/**\n * ์ฐฝ์ **๋ฐ์ ๋** โ ์ปค๋์ด ๋ง๊ฐํ ๊ธฐ๊ฐ ์ฌ์ค์ ํฉํ๋ค.\n *\n * โโ ์ ํฉ์ด ์ ๋ถ์ธ๊ฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๊ธฐ๊ฐ ๋ฐ์ ๋์ ์ปค๋์ด ์ด๋ฏธ ํ์ ํ ์ฌ์ค์ด๋ค(์ ์ฐ์ ์ข
๋ฅ๋ง๋ค ๋ค๋ฅธ ๊ท์น์ผ๋ก ์ป๋๋ค). ์ฌ๊ธฐ์ ๋ค์\n * ๊ณ์ฐํ๋ฉด ๊ท์น์ด ๋ ๋ฒ์ด ๋๊ณ , ๊ทธ๋๋ถํฐ ๋ ํ๋ฉด์ด ๋ค๋ฅธ ๋ฐ์ ๋์ ๋งํ๋ค. ์ด ํจ์๊ฐ ํ๋ ์ผ์\n * **์ฐฝ์ ๋ ๊ฒ์ ๊ณ ๋ฅด๊ณ , ์ค๋น๋ณ๋ก ๋ฌถ๊ณ , ๊ทผ๊ฑฐ๊ฐ ์ผ๋ง๋ ๋ฎ์๋์ง ์ธ๋ ๊ฒ**์ด๋ค.\n *\n * โโ ๊ฑธ์น ๊ธฐ๊ฐ์ ์ธ์ง ์๋๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๊ตฌ๊ฐ ๋ง๊ฐ๊ณผ ๊ฐ์ ๊ท์น์ด๋ค. ํ๋ฃจ์ ์ ๋ฐ์ด ์ฐฝ์ ๋ค์๋ค๊ณ ์ ๋ฐ์ ์ธ๋ฉด ๊ทธ๊ฒ์ ๊ด์ธก์ด ์๋๋ผ ์ฐ๋ฆฌ๊ฐ ๋๋\n * ๊ฐ์ด๊ณ , ํฉ์ด ์ฐฝ์ ๋๋๋ค.\n *\n * โโ ๋ ๋ฎ์ธ ๊ธฐ๊ฐ์ ์ผ๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๊ธฐ๊ฐ์ ๋์ด ์์ ์ธ๋ฐ ๋ง์ง๋ง ํ๋ณธ์ด ์ ๋
์ด์์ผ๋ฉด ๊ทธ ์ฌ์ด๋ ์ฌ์ง ์์ ๊ฒ์ด๋ค. ๊ทธ ์๋ฅผ ํจ๊ป ๋ด์ผ ํ๋ฉด์ด\n * ใ์ด ํฉ์ ์ด๋งํผ ๋ ์ฐ ๊ฒใ์ด๋ผ๊ณ ๋งํ ์ ์๋ค. ์ผ๋ง๋ ์ด๊ธ๋๋ฉด ๋ฌธ์ ์ธ์ง๋ ํ์ฅ์ด ์ ํ๋ค.\n */\nfunction generatedOfPeriods(\n periods: readonly {\n equipmentId: string\n kWh: number\n startMs: number\n endMs: number\n observedFromMs: number\n observedToMs: number\n }[],\n range: { startMs: number; endMs: number },\n /** ์ด์ฉ๋ฅ ์ ๋ถ๋ชจ โ ์์ผ๋ฉด ์ด์ฉ๋ฅ ์ ๋ด์ง ์๋๋ค(0 ์ด๋ ์ง์์ ๋ง๋ค์ง ์๋๋ค). */\n rated?: { kW: number; basis: 'ac' | 'dc'; from: 'equipment' | 'location' },\n /** ๊ธฐ๊ฐ๋ง๋ค ์ ์ฉํ ๋จ๊ฐ โ ๊ธฐ๊ฐ์ ๋ฎ๋ ๊ฒ์ ์ด๋ค. ์์ผ๋ฉด ๊ธ์ก์ ๋ง๋ค์ง ์๋๋ค. */\n prices?: readonly { startMs: number; endMs: number; unitPrice: number; currency: string }[]\n): Partial<NonNullable<KpiResult['energy']>> {\n const inside = periods.filter(g => g.startMs >= range.startMs && g.endMs <= range.endMs)\n\n /*\n * โโ **๊ฑธ์น ๊ธฐ๊ฐ์ ์กฐ์ฉํ ๋ฒ๋ฆฌ์ง ์๋๋ค** (2026-08-30) โโโโโโโโโโโโโโโโโโโโโโ\n *\n * ๋ํ๋ ๊ฒ์ ์ฐฝ์ **์จ์ ํ ๋ค์ด์จ ๊ธฐ๊ฐ**๋ฟ์ด๋ค. ๊ทธ๊ฒ์ด ๋ง๋ ์
์ด๋ค โ ๊ฑธ์น ๊ธฐ๊ฐ์ ๋ํ๋ฉด ๋ค๋ฅธ ๋ ์\n * ๊ฐ์ด ์ด ์ฐฝ์ ๊ฐ์ธ ์ฒํ๋ค.\n *\n * ๊ทธ๋ฐ๋ฐ ๋ฒ๋ฆฐ ๊ฒ์ ๋งํ์ง ์์๋ค. ํ๋ฃจ ๋จ์ ๊ธฐ๊ฐ์ ใ์ง๊ธ๋ถํฐ 24์๊ฐ ์ ใ ์ฐฝ์ ์จ์ ํ ๋ค์ด์ค๋ ์ผ์ด\n * ๊ฑฐ์ ์๋ค(์ฐฝ์ด ํ๋ฎ์์ ์์ํ๋ฏ๋ก). ๊ทธ๋์ ์ด์ ๋ฐ์ ๋์ด ์ ๋์ ๋ฉ์ฉกํ ์๋๋ฐ ํ๋ฉด์ด ๋น์๊ณ ,\n * ์ฌ์ฉ์๋ ๊ทธ๊ฒ์ **ใ๋ฐ์ ๋์ด ์๋คใ**๋ก ์ฝ์๋ค. ์ค์ธก์ผ๋ก ๊ทธ ์ผ์ด ๋ฌ๋ค.\n *\n * ์ด์ ๊ฑธ์น ๊ฒ์ ์ธ์ด ํจ๊ป ๋ธ๋ค. ํ๋ฉด์ด ใ์ด ์ฐฝ์ ๋ค ๋ค์ด์ค์ง ์์ ๊ธฐ๊ฐ์ด ์๋คใ๋ฅผ ๋งํ ์ ์๋ค.\n */\n const straddling = periods.filter(\n g => !(g.startMs >= range.startMs && g.endMs <= range.endMs) && g.endMs > range.startMs && g.startMs < range.endMs\n )\n const notCounted = straddling.length\n ? {\n periods: straddling.length,\n kWh: straddling.reduce((a, g) => a + g.kWh, 0),\n earliestStart: new Date(Math.min(...straddling.map(g => g.startMs))).toISOString(),\n latestEnd: new Date(Math.max(...straddling.map(g => g.endMs))).toISOString()\n }\n : undefined\n\n if (!inside.length) {\n /* ์จ์ ํ ๋ค์ด์จ ๊ฒ์ด ์๋ค โ ๊ทธ๋๋ ๊ฑธ์น ๊ฒ์ด ์์ผ๋ฉด ๊ทธ ์ฌ์ค์ ๋ธ๋ค(๋น ๊ฐ๊ณผ ใ์์ใ์ ๋ค๋ฅด๋ค). */\n return notCounted ? { generated: { kWh: 0, counted: 0, partial: 0, byEquipment: [], notCounted } } : {}\n }\n\n const byEquipment = new Map<string, number>()\n let partial = 0\n for (const g of inside) {\n byEquipment.set(g.equipmentId, (byEquipment.get(g.equipmentId) ?? 0) + g.kWh)\n const coveredFrom = Number.isFinite(g.observedFromMs) ? g.observedFromMs <= g.startMs : false\n const coveredTo = Number.isFinite(g.observedToMs) ? g.observedToMs >= g.endMs : false\n if (!coveredFrom || !coveredTo) partial++\n }\n\n const kWh = inside.reduce((a, g) => a + g.kWh, 0)\n /*\n * ์ด์ฉ๋ฅ ์ ๋ถ๋ชจ๋ **์ผ ๊ธฐ๊ฐ๋ค์ ๊ธธ์ด**๋ค. ์ฐฝ ๊ธธ์ด๋ก ๋๋๋ฉด, ํ๋ฃจ์น ํ๋๋ง ์ผ 24์๊ฐ ์ฐฝ์์ ๊ทธ ํ๋ฃจ๊ฐ\n * ์ฐฝ ์ ์ฒด์ ๊ฑธ์ณ ์์๋ ๊ฒ์ฒ๋ผ ์์์ง๋ค.\n */\n const hours = inside.reduce((a, g) => a + (g.endMs - g.startMs) / 3_600_000, 0)\n const capacityFactor =\n rated && rated.kW > 0 && hours > 0\n ? { value: kWh / (rated.kW * hours), ratedKW: rated.kW, basis: rated.basis, from: rated.from, hours }\n : undefined\n\n /*\n * ๋ธ ๊ฒ์ ๊ฐ โ ๊ธฐ๊ฐ๋ง๋ค **๊ทธ ๊ธฐ๊ฐ์ ๋ฎ๋ ๋จ๊ฐ**๋ก ๋งค๊ธด๋ค. ๊ฑธ์น ๋จ๊ฐ๋ ์ฐ์ง ์๋๋ค: ํ๋ฃจ ๋จ๊ฐ๋ก\n * ์ดํ์น๋ฅผ ๋งค๊ธฐ๋ฉด ๊ทธ ์ ๋ฐ์ ๋ค๋ฅธ ๋ ์ ๊ฐ์ด ๋๋ค.\n *\n * ๋ชจ๋ ๊ธฐ๊ฐ์ ๋จ๊ฐ๊ฐ ์์ ๋๋ง ๊ธ์ก์ ๋ง๋ ๋ค. ์ผ๋ถ๋ง ๋งค๊ธฐ๊ณ ๋ํ๋ฉด ๊ทธ ํฉ์ด ์ฐฝ ์ ์ฒด์ ๊ฐ์ธ ์ฒํ๋ค.\n */\n let amount = 0\n let priced = 0\n let currency: string | undefined\n for (const g of inside) {\n const p = (prices ?? []).find(x => x.startMs <= g.startMs && x.endMs >= g.endMs)\n if (!p) continue\n amount += g.kWh * p.unitPrice\n priced++\n currency = currency ?? p.currency\n }\n const unpriced = inside.length - priced\n const revenue = priced > 0 && unpriced === 0 && currency ? { amount, currency, priced, unpriced } : undefined\n\n return {\n generated: {\n kWh,\n counted: inside.length,\n partial,\n byEquipment: [...byEquipment.entries()]\n .map(([id, kWh]) => ({ id, kWh }))\n .sort((a, b) => b.kWh - a.kWh),\n ...(capacityFactor ? { capacityFactor } : {}),\n ...(revenue ? { revenue } : {}),\n /* ์ด ์ฐฝ์ ๋ค ๋ค์ด์ค์ง ์์ ๋ํ์ง ๋ชปํ ๊ธฐ๊ฐ โ ์์ผ๋ฉด ํ๋ฉด์ด ๊ทธ๊ฒ์ ๋งํ๋ค. */\n ...(notCounted ? { notCounted } : {})\n }\n }\n}\n\n/**\n * ๋ฐ์์ ๋ง๊ฐ๋์ด ์จ ์ฌ์ฉ ๊ตฌ๊ฐ์ ํฉํ๋ค โ **๊ตฌ๊ฐ ๋ง๊ฐ๊ณผ ๋ํ์ง ์๋๋ค.**\n *\n * ๋ ํ๊ณ๊ฐ ๊ฐ์ ์ ๊ธฐ๋ฅผ ๋งํ๋ค. ๋ํ๋ฉด ๋ ๋ฒ ์ธ๊ณ , ๋ ๋ค ์๋ ํ์ฅ์์๋ ๊ณ๋ ์ชฝ์ด ๊ฐํ ๊ทผ๊ฑฐ์ด๋ฏ๋ก\n * ๊ทธ์ชฝ์ ์ด๋ค. ์ฌ๊ธฐ์๋ ์ด์ชฝ ๋ชซ๋ง ๊ณ์ฐํ๊ณ , ๋ฌด์์ ์ธ์ง๋ ๋ถ๋ฅด๋ ์ชฝ์ด ์ ํ๋ค.\n *\n * ๋จ๊ฐ๋ **๋ชจ๋ ๊ตฌ๊ฐ์ด ์ค์์ ๋๋ง** ์๊ธ์ ๋ง๋ ๋ค. ์ผ๋ถ๋ง ์ค์๋๋ฐ ์๋ ๊ฒ๋ง ๋ํ๋ฉด ๊ทธ ํฉ์ด ์ฐฝ์\n * ์๊ธ์ธ ์ฒํ๋ค โ ๋ชป ๋งค๊ธด ๊ตฌ๊ฐ ์๋ฅผ ํจ๊ป ๋ธ๋ค.\n */\nfunction usageOfPeriods(\n periods: readonly { meterId: string; kWh: number; startMs: number; endMs: number; unitPrice: number; currency?: string; basis: string }[],\n range: { startMs: number; endMs: number }\n): NonNullable<KpiResult['energy']>['usage'] | undefined {\n const inside = periods.filter(u => u.startMs >= range.startMs && u.endMs <= range.endMs)\n if (!inside.length) return undefined\n\n const byBasis = new Map<string, number>()\n let kWh = 0\n let charge = 0\n let unpriced = 0\n let currency: string | undefined\n for (const u of inside) {\n kWh += u.kWh\n byBasis.set(u.basis, (byBasis.get(u.basis) ?? 0) + 1)\n if (Number.isFinite(u.unitPrice)) {\n charge += u.kWh * u.unitPrice\n if (!currency) currency = u.currency\n } else unpriced++\n }\n\n return {\n kWh,\n counted: inside.length,\n ...(unpriced === 0 && currency ? { charge, currency } : {}),\n unpriced,\n byBasis: [...byBasis.entries()].map(([basis, counted]) => ({ basis, counted })).sort((a, b) => b.counted - a.counted)\n }\n}\n\n/**\n * **์๊ธ์ ์ฉ์ ๋ ฅ์ ๊ณ ๋ฅธ๋ค โ ์ฒญ๊ตฌ์๊ฐ ๋จผ์ ๋ค.**\n *\n * ์์์ ๋ป์ด ์๋ค. ์ฒญ๊ตฌ์๋ ๊ทธ ๊ธฐ๊ฐ์ ์ค์ ๋ก ๋งค๊ฒจ์ง ๊ฐ์ด๊ณ , ์ ์ธ์ ์ฌ๋์ด ์ฎ๊ฒจ ์ ์ ๊ฐ์ด๋ค.\n * ๊ทธ ๊ฐ์ด ๋งค๋ฌ ๋ฐ๋๋ฏ๋ก ์ฎ๊ฒจ ์ ์ ๊ฒ์ ๊ณง ๋ก๋๋ค.\n */\nfunction billingDemandOf(\n billsInWindow: readonly { endMs: number; billingDemandKW: number }[],\n tariffBasis: { billingDemandKW?: number } | undefined,\n lastBill: { billingDemandKW?: number } | undefined,\n declaredKW: number | undefined,\n /** ์ด ์ฐฝ์์ ๊ด์ธกํ ์ต๊ณ ์์์ ๊ทธ ๊ฐ์ด ์ธ์ ๊น์ง์ ๊ฒ์ธ์ง โ ์ฌ์ฉ ๊ตฌ๊ฐ์ `maxKW` ์์ ์จ๋ค. */\n observedPeak?: { kW: number; toMs: number }\n): NonNullable<KpiResult['energy']>['billingDemand'] | undefined {\n const declared = Number.isFinite(Number(declaredKW)) ? Number(declaredKW) : undefined\n const withValue = billsInWindow.filter(b => Number.isFinite(b.billingDemandKW))\n const fromBill = withValue.length ? withValue.reduce((a, x) => (x.endMs > a.endMs ? x : a)).billingDemandKW : undefined\n const carried = Number.isFinite(Number(lastBill?.billingDemandKW)) ? Number(lastBill?.billingDemandKW) : undefined\n /* ์ด ์ฃผ๊ธฐ์ ์ ์ฉ๋๋ ๊ธฐ์ค์ด ๊ฐ์ฅ ๋จผ์ ๋ค โ ์ฒญ๊ตฌ์๋ ๋๋ ๊ธฐ๊ฐ์ ๊ฒ์ด๋ค. */\n const fromBasis = Number.isFinite(Number(tariffBasis?.billingDemandKW)) ? Number(tariffBasis?.billingDemandKW) : undefined\n\n const picked =\n fromBasis !== undefined\n ? { kW: fromBasis, from: 'tariff-basis' as const }\n : fromBill !== undefined\n ? { kW: fromBill, from: 'bill' as const }\n : carried !== undefined\n ? { kW: carried, from: 'carried-forward' as const }\n : declared !== undefined\n ? { kW: declared, from: 'declaration' as const }\n : undefined\n if (!picked) return undefined\n\n /* ์ ์ธ์ด ์๋๋ฐ ์ฒญ๊ตฌ์์ ๋ค๋ฅด๋ฉด ๊ทธ ์ฌ์ค์ ๋ธ๋ค โ ๋ก์ ์ ์ธ์ ์ค์ค๋ก ๋งํด์ผ ํ๋ค. */\n const stale = picked.from !== 'declaration' && declared !== undefined && declared !== picked.kW\n const exceeded =\n observedPeak && observedPeak.kW > picked.kW\n ? {\n peakKW: observedPeak.kW,\n overKW: observedPeak.kW - picked.kW,\n observedTo: new Date(observedPeak.toMs).toISOString()\n }\n : undefined\n\n return {\n ...picked,\n ...(declared !== undefined ? { declaredKW: declared } : {}),\n ...(stale ? { stale: true } : {}),\n ...(exceeded ? { exceeded } : {})\n }\n}\n\n/**\n * ์ฐฝ์ ์จ์ ํ ๋ ์ฒญ๊ตฌ์ ํ๋ โ ๊ฐ์ฅ ๋ฆ๊ฒ ๋๋ ๊ฒ.\n *\n * **์ฐฝ์ด ์ฒญ๊ตฌ ์ฃผ๊ธฐ์ ๊ฐ์ ๋๋ง ๊ฒฌ์ค๋ค.** ํ ๋ฌ ์ฒญ๊ตฌ์๋ฅผ ํ๋ฃจ ์ฐฝ์ ๊ฐ๊ณผ ๋นผ๋ฉด ๊ทธ ์ฐจ์ด๋ ์๋ฌด๊ฒ๋ ๋ปํ์ง\n * ์๋๋ค. ๊ทธ๋์ ๊ฐ์์ง๋ฅผ ๊ฐ๊ณผ ํจ๊ป ๋ธ๋ค.\n */\nfunction billOfWindow(\n bills: readonly {\n from: string\n to: string\n startMs: number\n endMs: number\n total: number\n energyCharge: number\n demandCharge: number\n currency?: string\n billingDemandKW: number\n }[],\n range: { startMs: number; endMs: number },\n ours?: { total?: number; demandCharge?: number; energyCharge?: number }\n): NonNullable<KpiResult['energy']>['bill'] | undefined {\n const inside = bills.filter(b => b.startMs >= range.startMs && b.endMs <= range.endMs)\n if (!inside.length) return undefined\n const b = inside.reduce((a, x) => (x.endMs > a.endMs ? x : a))\n const matchesWindow = b.startMs === range.startMs && b.endMs === range.endMs\n /* ์์ชฝ์ ์๋ ํญ๋ชฉ๋ง ๊ฒฌ์ค๋ค โ ํ์ชฝ์ด ์๋ ๊ฒ์ 0 ์ผ๋ก ๋๋ฉด ๊ทธ ์ฐจ์ด๊ฐ ํต์งธ๋ก ์ด๊ธ๋จ์ฒ๋ผ ๋ณด์ธ๋ค. */\n const gap = (mine: unknown, billed: number): number | undefined =>\n Number.isFinite(Number(mine)) && Number.isFinite(billed) ? Number(mine) - billed : undefined\n const diff = matchesWindow\n ? {\n ...(gap(ours?.total, b.total) !== undefined ? { total: gap(ours?.total, b.total) as number } : {}),\n ...(gap(ours?.demandCharge, b.demandCharge) !== undefined\n ? { demandCharge: gap(ours?.demandCharge, b.demandCharge) as number }\n : {}),\n ...(gap(ours?.energyCharge, b.energyCharge) !== undefined\n ? { energyCharge: gap(ours?.energyCharge, b.energyCharge) as number }\n : {})\n }\n : {}\n return {\n from: b.from,\n to: b.to,\n ...(Number.isFinite(b.total) ? { total: b.total } : {}),\n ...(Number.isFinite(b.energyCharge) ? { energyCharge: b.energyCharge } : {}),\n ...(Number.isFinite(b.demandCharge) ? { demandCharge: b.demandCharge } : {}),\n ...(b.currency ? { currency: b.currency } : {}),\n ...(Number.isFinite(b.billingDemandKW) ? { billingDemandKW: b.billingDemandKW } : {}),\n matchesWindow,\n ...(Object.keys(diff).length ? { diff } : {})\n }\n}\n\nfunction measuredFeeders(\n windows: readonly {\n startMs: number\n endMs: number\n maxKW?: number\n points: { id: string; kWh: number; root: boolean }[]\n pointsAtPeak?: { id: string; kW: number }[]\n }[],\n range: { startMs: number; endMs: number },\n totalKWh: number | undefined,\n meterFeeder?: Record<string, string>\n): Partial<NonNullable<KpiResult['energy']>> | undefined {\n if (!meterFeeder || !Object.keys(meterFeeder).length) return undefined\n if (totalKWh === undefined || !(totalKWh > 0)) return undefined\n\n /* ์ฐฝ์ ์จ์ ํ ๋ ๊ตฌ๊ฐ๋ง โ ์ ์ฒด ์ ๋ ฅ๋๊ณผ ๊ฐ์ ๊ท์น์ด์ด์ผ ๋ชซ๊ณผ ํฉ์ด ๊ฐ์ ์ฐฝ์ ๋งํ๋ค. */\n const byFeederKWh = new Map<string, number>()\n let sawPoints = false\n for (const w of windows) {\n if (!(w.startMs >= range.startMs && w.endMs <= range.endMs)) continue\n for (const p of w.points ?? []) {\n const feeder = meterFeeder[p.id]\n if (!feeder) continue // ๋ฟ๋ฆฌ ๊ณ๋๊ธฐยท๋ชจ๋ฅด๋ ์ง์ โ ๋ถ๊ธฐ์ ๋ชซ์ด ์๋๋ค\n sawPoints = true\n byFeederKWh.set(feeder, (byFeederKWh.get(feeder) ?? 0) + p.kWh)\n }\n }\n if (!sawPoints) return undefined // ๊ณ๋์ด ์์ผ๋ฉด ์ด ๊ฒฝ๋ก๋ฅผ ์ฐ์ง ์๋๋ค(๋ฐฐ๋ถ์ผ๋ก ๋์๊ฐ๋ค)\n\n const feeders = [...byFeederKWh.entries()].filter(([, kWh]) => kWh > 0)\n if (!feeders.length) return undefined\n const submetered = feeders.reduce((sum, [, kWh]) => sum + kWh, 0)\n const remainder = totalKWh - submetered\n\n const r = attributeEnergy({\n pools: [\n ...feeders.map(([feeder, kWh]) => ({ meterId: `${feeder}:meter`, kWh, consumerIds: [feeder] })),\n ...(remainder > 0 ? [{ meterId: 'root:remainder', kWh: remainder, consumerIds: [], remainder: true }] : [])\n ],\n consumers: feeders.map(([feeder]) => ({ id: feeder }))\n })\n\n /*\n * โโ ํผํฌ๋ฅผ ๋ง๋ ๋ถ๊ธฐ (2026-08-18) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n *\n * ์๊ธ์ kW ๋ก ๋งค๊ฒจ์ง๋ฏ๋ก ใ์ด๋ ๋ถ๊ธฐ๋ฅผ ๊น์์ผ ํผํฌ๊ฐ ๋ด๋ ค๊ฐ๋ใ๊ฐ ์ค๋ฌด์ ์ง๋ฌธ์ด๋ค. ๊ทธ ๋ต์ **ํผํฌ๊ฐ\n * ์ฐํ ๊ตฌ๊ฐ์ ๊ทธ ์๊ฐ** ๊ฐ์ด๊ณ , ์ฐฝ ์์ ์ฌ๋ฌ ๊ตฌ๊ฐ์ ๋ํ๊ฑฐ๋ ํ๊ท ํ๋ฉด ๋ป์ด ์ฌ๋ผ์ง๋ค(๋ค๋ฅธ ์๊ฐ์ ๊ฐ์\n * ์๋ ๊ฒ์ด๋ค). ๊ทธ๋์ **์ต๋์์๋ฅผ ๋ธ ๊ตฌ๊ฐ ํ๋**๋ง ๊ณจ๋ผ ๊ทธ ์๊ฐ์ ์ง์ ๊ฐ์ ์ด๋ค.\n */\n const peakWindow = windows\n .filter(w => w.startMs >= range.startMs && w.endMs <= range.endMs && Number.isFinite(Number(w.maxKW)))\n .reduce<(typeof windows)[number] | undefined>((best, w) => (!best || Number(w.maxKW) > Number(best.maxKW) ? w : best), undefined)\n const peakOf = new Map<string, number>()\n for (const p of peakWindow?.pointsAtPeak ?? []) {\n const feeder = meterFeeder[p.id]\n if (!feeder) continue // ๋ฟ๋ฆฌ ๊ณ๋๊ธฐยท๋ชจ๋ฅด๋ ์ง์ โ ๋ถ๊ธฐ์ ๋ชซ์ด ์๋๋ค\n peakOf.set(feeder, (peakOf.get(feeder) ?? 0) + p.kW)\n }\n\n const byFeeder = r.shares\n .map(sh => ({\n key: sh.consumerId,\n kWh: sh.kWh,\n basis: sh.basis,\n weightKind: undefined,\n weightShare: undefined,\n /* ํผํฌ ์๊ฐ์ ๊ฐ์ด ์์ผ๋ฉด ๋ง๋ค์ง ์๋๋ค โ ๊ทธ ๊ตฌ๊ฐ์ ์ด ๋ถ๊ธฐ์ ํ๋ณธ์ด ์์๋ค๋ ๋ป์ด๋ค. */\n ...(peakOf.has(sh.consumerId) ? { peakKW: peakOf.get(sh.consumerId) } : {})\n }))\n .sort((a, b) => b.kWh - a.kWh) as NonNullable<KpiResult['energy']>['byFeeder']\n\n const un = r.unattributed.reduce((sum, u) => sum + u.kWh, 0)\n return {\n ...(byFeeder?.length ? { byFeeder } : {}),\n ...(un > 0 ? { unattributedKWh: un, unattributedReason: r.unattributed[0]?.reason } : {}),\n /* ๋ถ๊ธฐ ํฉ์ด ๋ฟ๋ฆฌ๋ฅผ ๋์๋ค โ ๋ ๊ณ๋๊ธฐ์ ํ๊ณ๊ฐ ๋ค๋ฅด๋ค๋ ์ฌ์ค์ด๋ค(๊น์ ๋ง์ถ์ง ์๋๋ค). */\n ...(remainder < 0 ? { submeterExcessKWh: -remainder } : {})\n }\n}\n\n/** ํด๋ ์ต์
โ ๊ด์ ์ถ๊ณผ, ๊ทธ ์ถ์ ๋ง๋ค๊ธฐ ์ํด ์ด๋ฒคํธ ๋ฐ์์ ์์ผ ํ๋ ์ง๋. */\n/*\n * โโ ๊ฐ์ ์ฌ์ค์ด ๋ ๋ฒ ์์ด๋ ํ ๋ฒ๋ง ์ผ๋ค (2026-08-30) โโโโโโโโโโโโโโโโโโโโโโ\n *\n * ๋ง๊ฐ๋ ๊ตฌ๊ฐ ์ฌ์ค์ ์ ์ฒด์ฑ์ด ๋ด์ฉ์ ์๋ค(์ปค๋ 0.7.81). ๊ทธ๋ฐ๋ฐ ์ ๋์ ์ด๋ฏธ ์ฌ๋ฌ ๋ฒ ์ ํ ๊ฒ์ด ์๋ค โ\n * ์ฐ๋ ์๋ฆฌ์์ ๋ง๊ธฐ ์ ์ ๋ค์ด๊ฐ ๊ฒ๋ค์ด๋ค(์ค์ธก: ์ด๋ ๋ ์ ๋ฐ์ ๋จ๊ฐ๊ฐ ์ธ ๋ฒ).\n *\n * ์ง๋ ๊ธฐ๋ก์ ์ง์ฐ์ง ์๋๋ค โ ์ ๋์ ์ผ์ด๋ ์ผ์ ๊ธฐ๋ก์ด๋ค. ๋์ **์ฝ์ ๋ ํ ๋ฒ๋ง ์ผ๋ค.**\n * ๊ทธ๋ฌ์ง ์์ผ๋ฉด ๊ทธ ๊ตฌ๊ฐ์ ์์ตยท์ฌ์ฉ๋์ด ๊ทธ ํ์๋งํผ ์ธ์ด์ง๋ค.\n */\nfunction onceById<T extends { payload?: any }>(rows: readonly T[]): T[] {\n const seen = new Set<string>()\n return rows.filter(r => {\n const id = (r as any)?.payload?.eventId\n if (typeof id !== 'string' || !id) return true\n if (seen.has(id)) return false\n seen.add(id)\n return true\n })\n}\n\nexport interface KpiFoldOptions {\n groupBy?: KpiGroupBy\n /**\n * ์ด ํธ์์ด ์ด์ด๋ฐ๊ณ ์๋ **๋ง์ง๋ง ์ฒญ๊ตฌ์** โ ์๊ธ์ ์ฉ์ ๋ ฅ์ ์ฐ์ ๊ทผ๊ฑฐ(ยง`billingDemandOf`).\n *\n * ์ฐฝ ๋ฐ์ ์ฒญ๊ตฌ์๋ ์ ๋ ์กฐํ์ ๊ฑธ๋ฆฌ์ง ์๋๋ค. ๊ทธ๋ฐ๋ฐ ๊ทธ ๊ฐ์ ์ด ์ฐฝ์๋ ์ ์ฉ๋๋ฏ๋ก ํธ์ถ๋ถ๊ฐ\n * ์ปค๋ ์ํ์์ ์ฝ์ด ๋๊ธด๋ค.\n */\n lastBill?: { to: string; billingDemandKW?: number }\n /**\n * ์ด ํธ์์ด ์ด์ด๋ฐ๊ณ ์๋ **์๊ธ ๊ธฐ์ค** โ ์ด ์ฃผ๊ธฐ์ ์ ์ฉ๋๋ ๊ฐ(ยง`ENERGY_EVENT.tariffBasis`).\n *\n * ์ฒญ๊ตฌ์๋ณด๋ค ๋จผ์ ๋ค. ์ฒญ๊ตฌ์๋ ๋๋ ๊ธฐ๊ฐ์ ์ ์ฐ์ด๋ผ ์ด๋ฒ ์ฃผ๊ธฐ์ ๊ธฐ์ค์ ๋งํ์ง ์๋๋ค.\n */\n tariffBasis?: { from: string; billingDemandKW?: number }\n /**\n * ์ด ํธ์์ **๋ฐ์ ์ ๊ฒฉ**๊ณผ ๊ทธ ๊ทผ๊ฑฐ โ ์ด์ฉ๋ฅ ์ ๋ถ๋ชจ(ยง ์ปค๋ `generationRated`).\n *\n * ๋ชจ๋ธ์ ์ ์ธ์์ ์ค๋ฏ๋ก ํธ์ถ๋ถ๊ฐ ์ฝ์ด ๋๊ธด๋ค. ํด๋๋ ์ ๋๋ง ๋ณธ๋ค.\n */\n generationRated?: { kW: number; basis: 'ac' | 'dc'; from: 'equipment' | 'location' }\n /**\n * ์ด ํธ์์ด ์ด์ด๋ฐ๊ณ ์๋ **๋ฐ์ ๋จ๊ฐ** โ ์ฐฝ ๋ฐ์ ๋จ๊ฐ๋ ์ด ์ฐฝ์ ์ ์ฉ๋ ์ ์๋ค.\n *\n * ์ฐฝ ์์ ๋จ๊ฐ ์ฌ์ค์ด ๋จผ์ ๋ค. ์ด๊ฒ์ ๊ทธ ์ฐฝ์ ๋จ๊ฐ๊ฐ ์์ ๋ ์ด๋ค.\n */\n generationPrice?: { from: string; to: string; unitPrice: number; currency: string }\n /**\n * ๋
ธ๋ โ ๊ตฌ์ญ ์ง๋. **์ด๋ฒคํธ์๋ ๊ตฌ์ญ์ด ์๋ค**(๋
ธ๋๊น์ง๋ง ์๋ค) โ ์ค๋
์ทยท๋ง์คํฐ๊ฐ ์๋ ๊ฐ์ด๋ผ\n * ํธ์ถ๋ถ๊ฐ ๋๊ธด๋ค. ์์ผ๋ฉด ๊ตฌ์ญ ์ถ์ 'unknown' ์ผ๋ก ๋ชจ์ธ๋ค(์๋ฆฌ์ง ์๊ณ ๋ค๋ฅธ ์ถ์ผ๋ก ๋ฐ๊พธ์ง ์๋๋ค).\n */\n locationArea?: Record<string, string>\n /**\n * ์์ โ **๋ฐฐ์ ๊ณํต์ ์๋ฆฌ**(๋ถ๊ธฐยท์์ ) ์ง๋.\n *\n * โโ ์ ๋ฐ์์ ์ค๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ด๋ฒคํธ์๋ ์ ๊ธฐ ๊ณํต์ด ์๋ค. ใ์ด ์ค๋น๊ฐ ์ด๋ ๋ถ๊ธฐ์์ ๋จน๋๊ฐใ๋ ์๋์ง ํธ์์ ๋ชจ๋ธ์ด ์๋\n * ์ ์ธ์ด๊ณ (์ค๋น ํ๋์ ์ฌ์ค ๋ โ ๊ณต์ฅ์์๋ ์์, ์ ๊ธฐ์์๋ ๋ถํ), ๊ทธ ์ ์ธ์ ์ฝ๋ ๊ฒ์ ํธ์ถ๋ถ์ ์ผ์ด๋ค.\n *\n * ์์ผ๋ฉด ๋ถ๊ธฐ ๋ถํด๋ฅผ **ํ์ง ์๋๋ค** โ ์๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋ ์ฑ ๋๋๋ฉด ๊ทธ ์ซ์๋ ์๋ฌด ๊ฒ์ ๋ชซ๋ ์๋๋ค.\n */\n resourceFeeder?: Record<string, string>\n /**\n * **๊ณ๋ ์ง์ โ ๊ทธ๊ฒ์ด ์ฌ๋ ๋ถ๊ธฐ** ์ง๋.\n *\n * ์์ผ๋ฉด ๋ถ๊ธฐ๋ณ ์ ๋ ฅ๋์ ๊ณ๋์ผ๋ก ์ฝ๋๋ค(๋ฐฐ๋ถ๋ณด๋ค ๊ฐํ ๊ทผ๊ฑฐ). ์ด ์ง๋๋ ๋ชจ๋ธ์ ์ ์ธ์์ ์ค๊ณ \n * (๊ณ๋๊ธฐ์ ์๋ฆฌ), ๊ทธ๊ฒ์ ์ฝ๋ ๊ฒ์ ํธ์ถ๋ถ์ ์ผ์ด๋ค โ ํด๋๋ ์ ๋๋ง ๋ณธ๋ค.\n */\n meterFeeder?: Record<string, string>\n /**\n * ์ ์ธ๋ **์ ๊ธฐ์๊ธ ๋จ๊ฐ** โ ์๋ฅผ ๊ธ์ก์ผ๋ก ๋ฐ๊พธ๋ ์ ์ผํ ์
๋ ฅ.\n *\n * ์ด๋ฒคํธ์๋ ์๊ธ์ด ์๋ค. ๋จ๊ฐ๋ ํ์ฅ์ ๊ณ์ฝ์ด๊ณ (์๋์ง ํธ์ ๋ชจ๋ธ์ ์์ ์๋ฆฌ์ ์ ์ธํ๋ค), ๊ทธ๊ฒ์\n * ์ฝ๋ ๊ฒ์ ํธ์ถ๋ถ์ ์ผ์ด๋ค. ์์ผ๋ฉด ๊ธ์ก์ ๋ง๋ค์ง ์๋๋ค โ ์ง์ํ ๋จ๊ฐ๋ก ๋ธ ๊ธ์ก์ ์ซ์๊ฐ ์๋ค๋\n * ๊ฒ๋ง์ผ๋ก ์ฌ๋์ ๊ฒฐ์ ์ผ๋ก ๋ฐ์ด๋ถ์ธ๋ค.\n */\n tariff?: TariffDeclaration\n /**\n * ๊ต๋ ์ ์ธ โ **์ด๋ฒคํธ์๋ ๊ต๋๊ฐ ์๋ค**(์๊ฐ๋ง ์๋ค). ํ์ฅ ๋ง์คํฐ๊ฐ ์๋ ๊ฐ์ด๋ผ ํธ์ถ๋ถ๊ฐ ๋๊ธด๋ค.\n * ์์ผ๋ฉด ๊ต๋ ์ถ์ 'unknown' ์ผ๋ก ๋ชจ์ธ๋ค(๋ค๋ฅธ ์ถ์ผ๋ก ์๋ฆฌ์ง ์๊ณ ๋ฐ๊พธ์ง ์๋๋ค).\n */\n shifts?: WorkCalendarEntry[]\n /**\n * ํ์ฅ์ ์๊ฐ ๊ธฐ์ค(๋ถ) โ ๊ต๋ ์ถ์ด `HH:MM` ์ ์ด๋ ๊ธฐ์ค์ผ๋ก ์ฝ์์ง. **๊ณต๊ฐ์ด ๊ฐ๋ ๊ฐ**์ด๋ค\n * (ํ
๋ํธ๊ฐ ์๋๋ค: ํ ํ
๋ํธ๊ฐ ๋ค๋ฅธ ์๊ฐ๋์ ๊ณต์ฅ์ ํจ๊ป ๊ฐ์ง ์ ์๋ค). ์์ผ๋ฉด UTC.\n */\n utcOffsetMinutes?: number\n /**\n * ์ถ์ ์ํ(๊ธฐ๋ณธ 20). ๋์น๋ฉด ์๋ผ๋ด๊ณ **์๋ฆฐ ์ถ์ ์์ ๊ทธ ์์ ๊ฑด์๋ฅผ ํจ๊ป ์๋ฆฐ๋ค**.\n *\n * ์ถ์ ์๋ง ์๋ฆฌ๋ฉด ๋ถ์กฑํ๋ค โ \"๊ทธ ์ธ 89๊ฐ\" ๋ก๋ ๊ทธ๊ฒ์ด 3๊ฑด์ธ์ง 300๊ฑด์ธ์ง ๋ชจ๋ฅธ๋ค. ๋ณด์ฌ์ค ์ถ์ด ์ ๋ถ์ธ\n * ๊ฒ์ฒ๋ผ ์ฝํ๋ฉด ์ฌ์ฉ์๊ฐ ๊ผฌ๋ฆฌ๋ฅผ ๋์น๋ค.\n */\n groupLimit?: number\n}\n\n/* โโ ๊ด์ ์ถ์ ์ฌ๋ฃ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ถ์ ๊ฐ์ ์ด๋ฒคํธ payload ์ ์ด๋ฏธ ๋ค์ด ์๋ค(`TaskStatusDelta`: kindยทorderIdยทfromNodeยทtoNodeยท\n * resourceRef). ์ ๊ณ์ธก์ ์ฌ์ ํ์๊ฐ ์๋ค โ **์ด๋ฏธ ์์ธ ์ ๋์ ๋ค๋ฅด๊ฒ ๋ฌถ๊ธฐ๋ง** ํ๋ค.\n */\n/** ์ฐฝ ์์ ์๋ฃ๋ ํ ๊ฑด์ ๊ธฐ๋ก โ ํต๊ณ์ ์๋ฃ์ด์ ๊ด์ ์ถ์ ์๋ฃ. */\ninterface CompletionRecord {\n taskId: string\n at: number\n facets: TaskFacets\n leadMs?: number\n workMs?: number\n waitMs?: number\n}\n\n/** ์ด ๊ธฐ๋ก์ด ์์ฒญํ ์ถ์์ ์ด๋ ๊ฐ์ ์ํ๋๊ฐ. ๊ฐ์ด ์์ผ๋ฉด 'unknown'(์๋ฆฌ์ง ์๊ณ ๋ฒ๋ฆฌ์ง ์๋๋ค). */\nfunction facetKey(rec: CompletionRecord, options: KpiFoldOptions): string {\n const f = rec.facets\n switch (options.groupBy) {\n case 'resource':\n return f.resource ?? 'unknown'\n case 'taskKind':\n return f.kind ?? 'unknown'\n case 'location':\n return f.location ?? 'unknown'\n case 'order':\n return f.order ?? 'unknown'\n case 'area':\n /* ๊ตฌ์ญ์ ์ด๋ฒคํธ ๋ฐ์ ์ง์์ด๋ค โ ์ง๋๊ฐ ์์ผ๋ฉด ์๋ค๊ณ ๋งํ๋ค(๋
ธ๋ id ๋ก ๋์ฒดํ๋ฉด ์ฌ์ฉ์๊ฐ\n * ๊ทธ๊ฒ์ ๊ตฌ์ญ์ผ๋ก ์คํดํ๋ค). */\n return (f.location && options.locationArea?.[f.location]) ?? 'unknown'\n case 'shift':\n /*\n * ๊ต๋๋ **์ ๋์ ์ฐํ ์์ง ์๋ค โ ๊ณ์ฐํ๋ค.**\n *\n * ์ด๋ฒคํธ์ ๊ต๋ ์ด๋ฆ์ ์คํฌํํ๋ฉด ๋ ๊ฐ์ง๊ฐ ๋ฌด๋์ง๋ค: โ ๊ฐ์ ์ฌ์ค์ด ๋ ๊ณณ์ ์๊ธฐ๊ณ ,\n * โก ๋์ค์ ๊ต๋ ์๊ฐ์ ๊ณ ์น๋ฉด **๊ณผ๊ฑฐ๊ฐ ์ ๊ตฌ๋ถ์ผ๋ก ๊ตณ์ด** ๋ค์ ์
์ ์๋ค. ๊ต๋๋\n * `์๋ฃ ์๊ฐ + ํ์ฅ์ ์๊ฐ ๊ธฐ์ค + ๊ต๋ ์ ์ธ`์์ ๋์ค๋ ์์ ํ์์ด๋ฏ๋ก ์ฌ๊ธฐ์ ๋ธ๋ค โ\n * ๋ผ์ด๋ธยทํ์คํ ๋ฆฌยท์์ธก์ด **์ปค๋๊ณผ ๊ฐ์ ํจ์**(`activeShiftOf`)๋ฅผ ์ด๋ค.\n *\n * ์ ์ธ์ด ์์ผ๋ฉด 'unknown' ์ด๋ค. ๊ต๋๋ฅผ ๋๋ ๋์ง ์์ ํ์ฅ์ ์ด๋ฆ์ ์ง์ด๋ด์ง ์๋๋ค.\n */\n if (!options.shifts?.length) return 'unknown'\n /* ์๊ฐ๊น์ง ๋๊ธด๋ค โ **ํด์ผ์ ์ผ์ด๋ ์ผ์ ์ด๋ ๊ต๋์๋ ์ํ์ง ์๋๋ค.** ๋ํ์ด๋ง ๋ณด๋ฉด ๊ทธ๋ ์์ง๋\n ์์ ๊ต๋์ ์ง๊ณ๋ผ, ๊ต๋๋ณ ์ฑ๊ณผ๊ฐ ์๋ฆฌ์ง ์๊ณ ๊ฑฐ์ง์ด ๋๋ค. */\n return activeShiftAt(options.shifts, rec.at, options.utcOffsetMinutes) ?? 'unknown'\n default:\n return 'unknown'\n }\n}\n\n/**\n * ์ด ์ถ์ ํ์ง โ **ํ์ ์ด ์์๋ ๊ฒ๋ง** ์ผ๋ค(์์ผ๋ฉด ํ๋๋ฅผ ๋ง๋ค์ง ์๋๋ค).\n *\n * ์ํ๋ฅ ์ ์ด๋ ฅ์ด ์ฌ๊ธฐ์ ๋์จ๋ค: ์ปค๋์ด ์์
์๋ฃ์ ๊ฒฐ๊ณผ๋ฅผ ์ ๊ณ (`TaskStatusDelta.outcome`), ํด๋๊ฐ ์ถ์ผ๋ก\n * ๋ค๊ณ (`TaskFacets.outcome`), ์ฌ๊ธฐ์ ์ข
๋ฅ๋ณ๋ก ์ผ๋ค. ๊ทธ ์ฌ์ฌ์ด ์์ผ๋ฉด ใ์ด ๊ณต์ ์ ์ํ๋ฅ ใ์ ์ ๋์\n * ๋จ์ง ์๋๋ค(์ค๋น ๋์ ์นด์ดํฐ๋ ์ข
๋ฅ๋ฅผ ๋ชจ๋ฅธ๋ค).\n */\nfunction qualityOf(rows: CompletionRecord[]): { quality?: { good: number; scrap: number } } {\n let good = 0\n let scrap = 0\n for (const r of rows) {\n const o = r.facets.outcome\n if (o === 'good') good++\n else if (o === 'scrap') scrap++\n }\n return good + scrap > 0 ? { quality: { good, scrap } } : {}\n}\n\n/**\n * ๊ธฐ๋ก์ ์ถ์ผ๋ก ๋ฌถ์ด ์ถ๋ณ ํต๊ณ๋ฅผ ๋ธ๋ค โ **์ ์ฒด์ ๊ฐ์ ๊ท์น**์ผ๋ก(๊ฐ์ stats ํจ์, ๊ฐ์ ์ฐฝ).\n *\n * ์ถ์ ๊ฐ์ด ์์ฃผ ๋ง์ ์ ์๋ค(์ค๋ ์ถ์ ์์ฒ ๊ฐ). ๊ทธ๋์ ๊ฑด์ ํฐ ๊ฒ๋ถํฐ ์ํ๊น์ง๋ง ๋๋ ค์ฃผ๊ณ \n * **์๋ผ๋ธ ์๋ฅผ ํจ๊ป ์๋ฆฐ๋ค** โ ๋ค์ด์จ ๊ฒ์ด ์๋ ์ ๋จ์ \"์ด๊ฒ ์ ๋ถ\" ๋ผ๋ ๊ฑฐ์ง์ ๋ง๋ ๋ค.\n */\nfunction groupRecords(\n records: CompletionRecord[],\n options: KpiFoldOptions\n): { by: KpiGroupBy; items: KpiGroup[]; truncated?: number; truncatedTasks?: number } {\n const by = options.groupBy as KpiGroupBy\n const bins = new Map<string, CompletionRecord[]>()\n for (const rec of records) {\n const key = facetKey(rec, options)\n const bin = bins.get(key)\n if (bin) bin.push(rec)\n else bins.set(key, [rec])\n }\n\n const all = [...bins.entries()]\n .map(([key, rows]) => ({\n key,\n tasks: rows.length,\n leadTime: stats(rows.map(r => r.leadMs).filter((v): v is number => v !== undefined)),\n workTime: stats(rows.map(r => r.workMs).filter((v): v is number => v !== undefined)),\n waitTime: stats(rows.map(r => r.waitMs).filter((v): v is number => v !== undefined)),\n busyMs: rows.reduce((a, r) => a + (r.workMs ?? 0), 0),\n ...qualityOf(rows)\n }))\n .sort((a, b) => b.tasks - a.tasks || (a.key < b.key ? -1 : 1))\n\n const limit = Math.max(1, Math.min(100, options.groupLimit ?? 20))\n const items = all.slice(0, limit)\n const dropped = all.slice(limit)\n /* ์ถ๋ณ๋ก \"์ฐฝ ๋๋น ๋น์จ\" ์ ๋ด์ง ์๋๋ค โ ์์ ์๋ ์ถ(์ค๋ยท์์
์ข
๋ฅ)์์ ๊ทธ ๋น์จ์ ์๋ฏธ๊ฐ ์๊ณ ,\n * ์๋ฏธ ์๋ ์ซ์๋ฅผ ๋ด๋ฉด ์ฌ์ฉ์๊ฐ ๊ทธ๊ฒ์ผ๋ก ํ๋จํ๋ค. ์์ ์ ์ ๋ `utilization` ์ด ์ด๋ฏธ ๋ธ๋ค. */\n return {\n by,\n items,\n ...(dropped.length\n ? { truncated: dropped.length, truncatedTasks: dropped.reduce((a, g) => a + g.tasks, 0) }\n : {})\n }\n}\n\nfunction ms(value: string | undefined): number | null {\n if (!value) return null\n const t = Date.parse(value)\n return Number.isFinite(t) ? t : null\n}\n\n/** ๋ถ์์ โ ์ ๋ ฌ๋ ๊ฐ์์ ์ ํ ๋ณด๊ฐ ์์ด ๊ฐ์ฅ ๊ฐ๊น์ด ์๋ ๊ฐ(์์ ํ๋ณธ์์ ๊ณผ์ฅํ์ง ์๋๋ค). */\nfunction quantile(sorted: number[], q: number): number {\n if (sorted.length === 0) return 0\n const idx = Math.min(sorted.length - 1, Math.max(0, Math.floor(q * sorted.length)))\n return sorted[idx]\n}\n\nfunction stats(values: number[]): DurationStats {\n if (values.length === 0) return { count: 0, p10Ms: 0, p50Ms: 0, p90Ms: 0, avgMs: 0 }\n const sorted = [...values].sort((a, b) => a - b)\n const sum = sorted.reduce((a, b) => a + b, 0)\n return {\n count: sorted.length,\n p10Ms: quantile(sorted, 0.1),\n p50Ms: quantile(sorted, 0.5),\n p90Ms: quantile(sorted, 0.9),\n avgMs: Math.round(sum / sorted.length)\n }\n}\n\n/**\n * ์ด๋ฒคํธ๋ฅผ ๊ณ์ฐํด ์๊ฐ์ฐฝ KPI ๋ฅผ ๋ง๋ ๋ค.\n *\n * **ํธ์ถ๋ถ ๊ท์ฝ**: `events` ๋ ์ฐฝ๋ณด๋ค **๋๋ํ ์๊น์ง** ๋ด์ ๋๊ธด๋ค(์: ์ฐฝ ์์ โ ๋ฆฌ๋ํ์ ์ํ).\n * ์๋ฃ๋ ์์
์ ์์ ์ด๋ฒคํธ๊ฐ ์ฐฝ ๋ฐ์ ์์ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๋ชป ์ฐพ์ ๊ฒ์ `unpaired` ๋ก ์๋ฆฐ๋ค โ\n * ํ๊ท ์์ ์ค๋ฅ ์์ด ๋น ์ง๋ฉด ์งํ๊ฐ ๊ฑฐ์ง์ด ๋๋ค.\n *\n * ์๊ฐ์ถ์ `eventTime`(ISO) ์ฐจ๋ถ์ด๋ค. sim ํด๋ก์ด ์ค์ ์๊ฐ๊ณผ ์คํ์
์ด ์์ด๋ **์ฐจ๋ถ์ ์ ํ**ํ๋ค\n * (๊ณ ์ ์คํ์
์ ์์๋๋ค). ํ์ฑ ๋ถ๊ฐํ ์ค์ ๋ฒ๋ฆฐ๋ค.\n */\nexport function foldKpi(events: KpiEvent[], window: KpiWindow, options: KpiFoldOptions = {}): KpiResult {\n /* ์์
์ง๋ง์ถค์ **์ปค๋ ๊ท์น**์ผ๋ก(์ค๋ณต ๊ตฌํ ๊ธ์ง โ ๋ ๊ณณ์ ์ ์ผ๋ฉด ๊ฐ์ ์ ๋๋ก ๋ค๋ฅธ ๋ต์ด ๋์จ๋ค). */\n const { records: tasks } = foldTaskRecords(events.filter(e => e.eventType === 'task.status'))\n let completedOrders = 0\n /* ์๋ฃ๋ก ์ฝ์ง ๋ชปํ ์ค๋ ์ํ ๋ฑ๋ง โ ๊ฑด์(ยง`orderStatusNotCounted`). */\n const orderStatusNotCounted = new Map<string, number>()\n /* ์ด๋ฏธ ์๋ฃ๋ก ์ผ ์ค๋ โ ํด๋ง ์๋ณธ์ด ๊ฐ์ ์ข
๊ฒฐ์ ๋ค์ ๋ณด๋ด๋ ํ ๋ฒ๋ง ์ผ๋ค. */\n const completedOrderIds = new Set<string>()\n let seen = 0\n let inWindow = 0\n\n for (const e of events) {\n const at = ms(e.eventTime)\n if (at === null) continue\n seen++\n if (at >= window.fromMs && at <= window.toMs) inWindow++\n const d = e.payload?.data ?? e.payload ?? {}\n\n if (e.eventType === 'order.status') {\n /*\n * **๋๋ฌ๋๋ ์ปค๋์ด ๋ตํ๋ค** (2026-08-23) โ `isOrderTerminal`.\n *\n * ์์ ์๋ ์ฌ๊ธฐ์ **๋์์ด ๋ชฉ๋ก**์ผ๋ก ์ถ๋ก ํ๋ค(`completed`ยท`fulfilled`ยท`done`ยท`finished`).\n * ๊ทธ ๋ฐฉ์์ด ๋ธ ๋๊ฐ๊ฐ ๋์ด์๊ณ ๋ ๋ค ๋ค์ด์จ ๊ฒ์ด ์์๋ค.\n *\n * โ ์๋ณธ์ ๋ฑ๋ง์ด ๋ชฉ๋ก์ ์์ผ๋ฉด ์๋ฃ๊ฐ 0 ์ด ๋๋ค. ์ค์ ๋ก ๊ทธ๋ฌ๋ค โ ์ฒซ ์ค ์์คํ
์ `FINISHED`\n * ๊ฐ ๋น ์ ธ ์์๊ณ , ๊ทธ๋ ๋ชฉ๋ก์ ๋ฑ๋ง์ ๋ํ ๊ฒ์ ์ง์ง ๋น ์๋ฆฌ(๊ทธ ์ปค๋ฅํฐ๊ฐ ์๊ธฐ ์ํ ํ๋ฅผ\n * ์ ์ฐ๊ณ ์์๋ค)๋ฅผ ๊ฐ๋ฆฐ ๋๋นต์ด์๋ค.\n * โก **์๋ฎฌ ํธ์์์๋ ์ธ์ ๋ 0 ์ด์๋ค.** ์๋ฎฌ์ ์ค๋๋ฅผ ์ดํํ๋ฉฐ `fulfilled` ๋ง ์ฌ๋ฆฌ๊ณ \n * `status` ๋ ๋ฐ๊พธ์ง ์๋๋ค โ ๋ฑ๋ง๋ก ๋ฌป๋ ํ์ ์ ์๋ฎฌ์ ์๋ฃ๋ฅผ ํ ๊ฑด๋ ์ธ์ง ๋ชปํ๋ค.\n *\n * ํ์ค์ด ๊ทธ ์ถ์ ๊ฐ๋ผ ๋์๋ค: `orders.status` โ `RequestState`(ํ์ค๋ ์ด๊ฑฐํ์ง ์๋๋ค)์ด๊ณ ,\n * ใ๋๋ใ๋ **์ค์ **์์ ์ฝ๋๋ค(`JobResponse`, ์๊ตฌ๋ `SegmentRequirement.Quantity`). ๊ทธ๋์\n * ํ์ ์ 1์ฐจ ๊ทผ๊ฑฐ๋ **์**์ด๊ณ ๋ฑ๋ง์ ์์ผ๋ก ๋งํ ์ ์๋ ์ข
๊ฒฐ(์ทจ์ยท์ค๋ ์ข
๋ฃ)์๋ง ์ด๋ค.\n */\n const status = String(d.status ?? '').toLowerCase()\n const done = isOrderTerminal({ status: d.status, requested: d.requested, fulfilled: d.fulfilled })\n if (at >= window.fromMs && at <= window.toMs) {\n /*\n * **์ค๋๋น ํ ๋ฒ๋ง ์ผ๋ค.** ํด๋งํ๋ ์๋ณธ์ ๊ฐ์ ์ค๋์ ์ข
๊ฒฐ์ ์ฌ๋ฌ ์ฃผ๊ธฐ์ ๊ฑธ์ณ ๋ค์ ๋ณด๋ผ ์\n * ์๊ณ (๊ทธ๊ฒ์ ๊ฒฐํจ์ด ์๋๋ผ ํด๋ง์ ์ฑ์ง์ด๋ค), ์ฌ๊ฑด๋ง๋ค ์ธ๋ฉด ์ฒ๋ฆฌ๋์ด ์๋ฆฌ์ง ์๊ณ ๋ถํ๋ ค์ง๋ค.\n * ์์
์ชฝ์ ์ปค๋์ ์ง๋ง์ถค์ด ์ด๋ฏธ ๊ทธ ๊ท์จ์ ๊ฐ๊ณ ์๋ค(ใ์๋ฃ๋ ์์
๋น ํ๋ใ) โ ์ค๋๋ง ์์๋ค.\n */\n if (done) {\n const id = String(d.orderId ?? '')\n if (id && !completedOrderIds.has(id)) {\n completedOrderIds.add(id)\n completedOrders++\n } else if (!id) completedOrders++ // ์ ์ฒด๋ฅผ ๋ชจ๋ฅด๋ฉด ์
์์ ๋นผ์ง ์๋๋ค(์๋ฆฌ์ง ์๊ณ ์ค์ด์ง ์๋๋ค)\n }\n /*\n * **์๋ฃ๋ก ์ธ์ง ์์ ๋ฑ๋ง์ ์ธ๊ตฌ์กฐ์ฌ.** ใ๋ชป ์ฝ์๋คใ๊ฐ ์๋๋ค โ `picking` ์ฒ๋ผ ์๋ฃ๊ฐ ์๋\n * ๋ฑ๋ง์ด ์ฌ๊ธฐ ์ค๋ ๊ฒ์ ์ ์์ด๋ค. ์๋ฃ๊ฐ 0 ์ธ๋ฐ ์ฌ๊ธฐ ๋ฑ๋ง์ด ์์ฌ ์์ผ๋ฉด ์์ธ์ด ๊ณง ๋ณด์ธ๋ค.\n *\n * ๋น ๋ฑ๋ง์ ์ธ์ง ์๋๋ค: ์ํ๋ฅผ ๋งํ์ง ์์ ์ฌ๊ฑด์ ๋ค๋ฅธ ๊ฒฐํจ์ด๊ณ (์ ์
๋ฌธ์ด ์ํ๋ฅผ ํ์๋ก\n * ๋ฐ๋๋ค) ์ฌ๊ธฐ์ ์์ผ๋ฉด ์ด ๊ฐ์ ๋ป์ด ํ๋ ค์ง๋ค.\n */\n else if (status) orderStatusNotCounted.set(status, (orderStatusNotCounted.get(status) ?? 0) + 1)\n }\n }\n }\n\n /*\n * ์๋์ง โ ์ฐฝ์ **์จ์ ํ ๋ ** ๊ตฌ๊ฐ ๋ง๊ฐ ์ฌ๊ฑด๋ง ์ผ๋ค(๊ฑธ์น ๊ตฌ๊ฐ์ ์ปค๋ ๊ท์น์ด ๋บ๋ค).\n * ์ฌ๊ฑด์ด ํ๋๋ ์์ผ๋ฉด ์ด ํธ์์๋ ์๋์ง๊ฐ ์๋ ๊ฒ์ด๋ฏ๋ก ๋ธ๋ก ์์ฒด๋ฅผ ๋ด์ง ์๋๋ค.\n */\n const demandWindows = events\n .filter(e => e.eventType === ENERGY_EVENT.demandWindow)\n .map(e => {\n const d = e.payload?.data ?? e.payload ?? {}\n /* ์ต๋(`maxKW`)๋ ํจ๊ป ๋๊ธด๋ค โ ์๊ธ์ด ๊ฑธ๋ฆฌ๋ ์๋ ํ๊ท ์ด ์๋๋ผ ์ต๋๋ค.\n ์ด๋ถํ(`grossMaxKW`)๋ ใ๋ฌด์์ด ๊น์๋ใ๋ฅผ ๋์ง๋ ์ถ์ด๋ค(๋ฐ์ ยท๋ฐฉ์ ์ฐจ๊ฐ ์ ). */\n return {\n startMs: Number(d.startMs),\n endMs: Number(d.endMs),\n meanKW: Number(d.meanKW),\n maxKW: Number(d.maxKW),\n grossMaxKW: Number(d.grossMaxKW),\n /* ์ง์ ๋ณ ๋ชซ โ ๊ณ๋์ด ๋ถ๊ธฐ์ ์์ผ๋ฉด ๊ทธ ๊ฐ์ **์ธก์ **์ด๋ค(๋ฐฐ๋ถ์ด ์๋๋ค). ์ปค๋์ด ๊ณ์ธต ํ์ \n (`root`)๊น์ง ์ค์ด ์ฃผ๋ฏ๋ก ์ฌ๊ธฐ์ ๊ฐ์ ๊ท์น์ ๋ค์ ์ฐ์ง ์๋๋ค. */\n points: (Array.isArray(d.points) ? d.points : [])\n .map((p: any) => ({ id: String(p?.id ?? ''), kWh: Number(p?.kWh), root: p?.root === true }))\n .filter((p: any) => p.id && Number.isFinite(p.kWh)),\n /* ํผํฌ๊ฐ ์ฐํ ์๊ฐ์ ์ง์ ๋ณ kW โ ์๊ธ์ด ๊ฑธ๋ฆฐ ์๋ kW ๋ค(์ ๋ ฅ๋์ด ํฐ ๋ถ๊ธฐ์ ํผํฌ๋ฅผ ๋ง๋ ๋ถ๊ธฐ๋ ๋ค๋ฅด๋ค). */\n pointsAtPeak: (Array.isArray(d.pointsAtPeak) ? d.pointsAtPeak : [])\n .map((p: any) => ({ id: String(p?.id ?? ''), kW: Number(p?.kW) }))\n .filter((p: any) => p.id && Number.isFinite(p.kW))\n }\n })\n .filter(w => Number.isFinite(w.startMs) && Number.isFinite(w.endMs))\n\n /*\n * ๋ฐ์ ๊ธฐ๊ฐ ์ฌ์ค โ ์ปค๋์ด ๊ธฐ๊ฐ์ ๋ง๊ฐํ ๋ ๋ธ ๊ฒ์ด๋ค. ๊ตฌ๊ฐ ๋ง๊ฐ๊ณผ ๊ฐ์ ๊ท์น์ผ๋ก **์ฐฝ์ ์จ์ ํ ๋ \n * ๊ฒ๋ง** ์ผ๋ค(๊ฑธ์น ๊ธฐ๊ฐ์ ๋ฐ๋ง ์ธ๋ฉด ํฉ์ด ์ฐฝ์ ๋๋๋ค).\n *\n * ๊ด์ธก ๊ตฌ๊ฐ(`observedFrom`ยท`observedTo`)์ ํจ๊ป ์ฝ๋๋ค โ ๊ฐ์ ๊ทผ๊ฑฐ๊ฐ ์ผ๋ง๋ ๋ฎ์๋์ง๊ฐ ๊ทธ ๋์ ์๋ค.\n */\n const generationPeriods = onceById(events.filter(e => e.eventType === ENERGY_EVENT.generationPeriod))\n .map(e => {\n const d = e.payload?.data ?? e.payload ?? {}\n return {\n equipmentId: String(d.equipmentId ?? ''),\n kWh: Number(d.kWh),\n startMs: Date.parse(String(d.periodStart ?? '')),\n endMs: Date.parse(String(d.periodEnd ?? '')),\n observedFromMs: Date.parse(String(d.observedFrom ?? '')),\n observedToMs: Date.parse(String(d.observedTo ?? ''))\n }\n })\n .filter(g => g.equipmentId && Number.isFinite(g.kWh) && Number.isFinite(g.startMs) && Number.isFinite(g.endMs))\n\n /*\n * ๋ฐ์์ ๋ง๊ฐ๋์ด ์จ ์ฌ์ฉ ๊ตฌ๊ฐ โ ๊ตฌ๊ฐ ๋ง๊ฐ๊ณผ ๊ฐ์ ๊ท์น์ผ๋ก **์ฐฝ์ ์จ์ ํ ๋ ๊ฒ๋ง** ์ผ๋ค.\n */\n const usagePeriods = onceById(events.filter(e => e.eventType === ENERGY_EVENT.usagePeriod))\n .map(e => {\n const d = e.payload?.data ?? e.payload ?? {}\n return {\n meterId: String(d.meterId ?? ''),\n kWh: Number(d.kWh),\n startMs: Date.parse(String(d.from ?? '')),\n endMs: Date.parse(String(d.to ?? '')),\n unitPrice: Number(d.unitPrice),\n maxKW: Number(d.maxKW),\n currency: d.currency ? String(d.currency) : undefined,\n basis: d.basis ? String(d.basis) : 'unstated'\n }\n })\n .filter(u => u.meterId && Number.isFinite(u.kWh) && Number.isFinite(u.startMs) && Number.isFinite(u.endMs))\n\n /* ์ฒญ๊ตฌ์ โ ์ฐฝ์ ์จ์ ํ ๋ ๊ฒ ์ค ๊ฐ์ฅ ๋ฆ๊ฒ ๋๋ ๊ฒ ํ๋. */\n const bills = onceById(events.filter(e => e.eventType === ENERGY_EVENT.bill))\n .map(e => {\n const d = e.payload?.data ?? e.payload ?? {}\n return {\n from: String(d.from ?? ''),\n to: String(d.to ?? ''),\n startMs: Date.parse(String(d.from ?? '')),\n endMs: Date.parse(String(d.to ?? '')),\n total: Number(d.total),\n energyCharge: Number(d.energyCharge),\n demandCharge: Number(d.demandCharge),\n currency: d.currency ? String(d.currency) : undefined,\n billingDemandKW: Number(d.billingDemandKW)\n }\n })\n .filter(b => Number.isFinite(b.startMs) && Number.isFinite(b.endMs))\n\n /* ๋ฐ์ ๋จ๊ฐ โ ๊ธฐ๊ฐ๋ง๋ค ๊ทธ๋์ ๊ฐ์ด๋ค(๋ ๋ง๋ค ๋ฐ๋๋ค). */\n const generationPrices = onceById(events.filter(e => e.eventType === ENERGY_EVENT.generationPrice))\n .map(e => {\n const d = e.payload?.data ?? e.payload ?? {}\n return {\n startMs: Date.parse(String(d.from ?? '')),\n endMs: Date.parse(String(d.to ?? '')),\n unitPrice: Number(d.unitPrice),\n currency: String(d.currency ?? '')\n }\n })\n .filter(p => Number.isFinite(p.startMs) && Number.isFinite(p.endMs) && Number.isFinite(p.unitPrice) && p.currency)\n\n const leads: number[] = []\n const works: number[] = []\n const waits: number[] = []\n const busyByResource = new Map<string, number>()\n /* ์ฐฝ ์์ ์๋ฃ๋ ๊ฑด๋ค์ **๊ธฐ๋ก** โ ํต๊ณ๋ฅผ ๋ธ ๋ค์๋ ๋ฒ๋ฆฌ์ง ์๋๋ค. ๊ด์ ์ถ์ ๊ฐ์ ๊ธฐ๋ก์ ๋ค์\n * ๋ฌถ๋ ๊ฒ์ผ ๋ฟ์ด๋ฏ๋ก, ๊ธฐ๋ก์ ๋จ๊ธฐ๋ฉด ์ถ์ ํ๋ ๋ ๋ถ์ด๋ ๊ฐ์ด ๊ฑฐ์ 0 ์ด ๋๋ค. */\n const records: CompletionRecord[] = []\n let tasksInWindow = 0\n let unpairedLead = 0\n let unpairedWork = 0\n\n for (const t of tasks) {\n const completed = t.completedMs\n if (completed === undefined) continue // ์์ง ์๋ฃ๋์ง ์์ ์์
โ ์ฑ๊ณผ๋ก ์ธ์ง ์๋๋ค\n if (completed < window.fromMs || completed > window.toMs) continue // ์ฑ๊ณผ๋ ์๋ฃ ์์ ์ผ๋ก ์ผ๋ค\n tasksInWindow++\n const c = t.createdMs\n const s = t.startedMs\n const rec: CompletionRecord = { taskId: t.taskId, at: completed, facets: t.facets }\n const resource = rec.facets.resource\n if (c !== undefined && completed >= c) leads.push((rec.leadMs = completed - c))\n else unpairedLead++\n if (s !== undefined && completed >= s) {\n const busy = completed - s\n works.push((rec.workMs = busy))\n if (resource) busyByResource.set(resource, (busyByResource.get(resource) ?? 0) + busy)\n } else {\n unpairedWork++\n }\n if (c !== undefined && s !== undefined && s >= c) waits.push((rec.waitMs = s - c))\n records.push(rec)\n }\n\n const span = Math.max(1, window.toMs - window.fromMs)\n const utilization = [...busyByResource.entries()]\n .map(([resourceId, busyMs]) => ({ resourceId, busyMs, ratio: Math.min(1, busyMs / span) }))\n .sort((a, b) => b.busyMs - a.busyMs)\n\n return {\n window: { fromMs: window.fromMs, toMs: window.toMs },\n throughput: { tasks: tasksInWindow, orders: completedOrders },\n /* ๋ฐ์ ๋ง ์๋ ํ์ฅ(๊ณ๋ ์๋ ๋ฐ์ ์)๋ ๋ต์ด ๋์์ผ ํ๋ค โ ๋ ์ค ํ๋๋ง ์์ด๋ ๋ธ๋ก์ ๋ธ๋ค. */\n ...(demandWindows.length || generationPeriods.length || usagePeriods.length || bills.length\n ? (() => {\n const e = energyOfWindows(demandWindows, { startMs: window.fromMs, endMs: window.toMs })\n const usage = usageOfPeriods(usagePeriods, { startMs: window.fromMs, endMs: window.toMs })\n /*\n * ์ด๋ ํ๊ณ๋ฅผ ์ธ์ง ์ ํ๋ค โ **๋ํ์ง ์๋๋ค.** ๊ณ๋ ํ๋ณธ์์ ์ฐ๋ฆฌ๊ฐ ๋ง๊ฐํ ๊ฐ์ด ์์ผ๋ฉด ๊ทธ๊ฒ์\n * ์ฐ๊ณ (๊ฐํ ๊ทผ๊ฑฐ), ์์ผ๋ฉด ๋ฐ์์ ๋ง๊ฐ๋์ด ์จ ๊ฐ์ ์ด๋ค. ๋ฌด์์ ์ผ๋์ง ํจ๊ป ๋ธ๋ค.\n */\n const usedKWh = e.kWh !== undefined ? e.kWh : usage?.kWh\n const kWhBasis = e.kWh !== undefined ? 'demand-window' : usage ? 'usage-period' : undefined\n /* ๋ถ๋ชจ๋ **์๋ฃ ์ค๋**๋ค(๋๋น ์ ๋ ฅ). ์ฐฝ์ ์๋ฃ๊ฐ ์์ผ๋ฉด ์ปค๋ ๊ท์น์ด ใ์ ์๋์ง ์์ใ์ผ๋ก ๋ตํ๋ค. */\n const i = energyIntensity({\n kWh: usedKWh,\n energyWindow: e.window,\n denominator: { kind: 'output', value: completedOrders, window: e.window }\n })\n /*\n * ์๊ธ์ **๊ตฌ๊ฐ๋ง๋ค ์ ๋จ๊ฐ๋ก** ๋งค๊ธด ๊ฐ์ด ์์ผ๋ฉด ๊ทธ๊ฒ์ ์ด๋ค. ๋จ์ผ ๋จ๊ฐ๋ก ์ ์ผ๋ฉด ์๊ฐ๋๋ง๋ค\n * ๋ค๋ฅธ ๋จ๊ฐ๊ฐ ์ฌ๋ผ์ง๊ณ , ใํผํฌ๋ฅผ ๊น์ ์ผ๋ง๋ฅผ ์๋ผ๋ใ๊ฐ ๊ทธ ์ฐจ์ด ์์ ์ ๋ค.\n */\n /* ์๊ธ์ ์ฉ์ ๋ ฅ์ ์ฒญ๊ตฌ์๊ฐ ๋จผ์ ๋ค โ ์ ์ธ์ ์ฒญ๊ตฌ๊ฐ ์ค์ง ์๋ ํ์ฅ์ ๋ชซ์ด๋ค. */\n /* ์ด ์ฐฝ์ ์ต๊ณ ์์ โ ์ฌ์ฉ ๊ตฌ๊ฐ์ด ์ค์ด ์จ ๊ฐ ์ค ๊ฐ์ฅ ํฐ ๊ฒ(์๋ณธ ๊ณ๋๊ธฐ๊ฐ ์ฐ ๊ฐ์ด๋ค). */\n const peaks = usagePeriods\n .filter(u => u.startMs >= window.fromMs && u.endMs <= window.toMs && Number.isFinite(u.maxKW))\n .map(u => ({ kW: u.maxKW as number, toMs: u.endMs }))\n const observedPeak = peaks.length ? peaks.reduce((a, x) => (x.kW > a.kW ? x : a)) : undefined\n const billingDemand = billingDemandOf(\n bills.filter(b => Number.isFinite(b.billingDemandKW)).map(b => ({ endMs: b.endMs, billingDemandKW: b.billingDemandKW })),\n options.tariffBasis,\n options.lastBill,\n options.tariff?.billingDemandKW,\n observedPeak\n )\n const cost = options.tariff\n ? electricityCost({\n kWh: usedKWh,\n peakKW: e.peakKW,\n tariff: { ...options.tariff, ...(billingDemand ? { billingDemandKW: billingDemand.kW } : {}) },\n ...(usage?.charge !== undefined ? { energyChargeFromPeriods: usage.charge } : {})\n })\n : undefined\n return {\n energy: {\n ...(usedKWh !== undefined ? { kWh: usedKWh } : {}),\n ...(kWhBasis ? { kWhBasis } : {}),\n ...(billingDemand ? { billingDemand } : {}),\n ...(usage ? { usage } : {}),\n /* ์ด ์ฐฝ์ ์ต๋์์ โ ๊ณ์ฝ ๋๋น ํ์ ์ด ๋ณด๋ ์๋ค(์ ๋ ฅ๋๊ณผ ๊ฐ์ ๊ตฌ๊ฐ ์งํฉ์์ ์๋ค). */\n ...(e.peakKW !== undefined ? { peakKW: e.peakKW, peakStartMs: e.peakStartMs } : {}),\n /* ๊น์ธ ์์ **๊ฐ์ ๊ตฌ๊ฐ์ ๋ ์**์ ์ฐจ์ด๋ค โ ์ฌ๊ธฐ์ ํ ๋ฒ๋ง ๊ณ์ฐํด ๋ ๊ณณ์ด ๊ฐ๋ผ์ง์ง ์๊ฒ. */\n ...(e.peakGrossKW !== undefined && e.peakKW !== undefined\n ? { peakGrossKW: e.peakGrossKW, ...(e.peakGrossKW > e.peakKW ? { shavedKW: e.peakGrossKW - e.peakKW } : {}) }\n : {}),\n basis: e.basis,\n counted: e.counted,\n skipped: e.skipped,\n intensity:\n i.value === null\n ? { value: null, reason: (i as any).reason }\n : { value: i.value, unit: (i as any).unit },\n ...(measuredFeeders(demandWindows, { startMs: window.fromMs, endMs: window.toMs }, e.kWh, options.meterFeeder) ??\n feederShares(e.kWh, utilization, options.resourceFeeder)),\n /* ๊ธ์ก์ ๊ฐ์ ์ฐฝ์ ์ ๋ ฅ๋ยท์ต๋์์์์ ๋์จ๋ค โ ์ฐฝ์ด ํ๋๋ฟ์ด๋ผ ์ด๊ธ๋ ์ ์๋ค. */\n ...(cost ? { cost } : {}),\n ...generatedOfPeriods(\n generationPeriods,\n { startMs: window.fromMs, endMs: window.toMs },\n options.generationRated,\n /* ์ฐฝ ์์ ๋จ๊ฐ ์ฌ์ค์ด ๋จผ์ ์ด๊ณ , ์์ผ๋ฉด ์ด์ด๋ฐ์ ๋ง์ง๋ง ๋จ๊ฐ๋ฅผ ์ด๋ค. */\n generationPrices.length\n ? generationPrices\n : options.generationPrice\n ? [\n {\n startMs: Date.parse(options.generationPrice.from),\n endMs: Date.parse(options.generationPrice.to),\n unitPrice: options.generationPrice.unitPrice,\n currency: options.generationPrice.currency\n }\n ]\n : []\n ),\n /* ์ฒญ๊ตฌ์๋ ์ฌ์ค์ด๋ค โ ์ฐ๋ฆฌ ๊ณ์ฐ์ ๋ฎ์ง ์๊ณ ๋๋ํ ๋๋ค(ยง`billOfWindow`). */\n ...(() => {\n const b = billOfWindow(bills, { startMs: window.fromMs, endMs: window.toMs }, cost as any)\n return b ? { bill: b } : {}\n })()\n }\n }\n })()\n : {}),\n leadTime: stats(leads),\n workTime: stats(works),\n waitTime: stats(waits),\n utilization,\n unpaired: { leadTime: unpairedLead, workTime: unpairedWork },\n /* ๋ชป ์ฝ์ ์ค๋ ์ํ ๋ฑ๋ง โ ๋น๋ฉด ๋น ๊ฐ์ฒด๋ค(ยง`orderStatusNotCounted`). */\n orderStatusNotCounted: Object.fromEntries(orderStatusNotCounted),\n eventsSeen: seen,\n eventsInWindow: inWindow,\n ...(options.groupBy ? { groups: groupRecords(records, options) } : {})\n }\n}\n\n/**\n * ๊ด์ ร ๋น๊ต ๊ต์ฐจ โ **\"๊ตฌ์ญ๋ณ๋ก ์ด์ ๋๋น ์ด๋ค๊ฐ\"**.\n *\n * ์ถ(๋ฌด์์)๊ณผ ๋น๊ต(์ธ์ ๋๋น)๋ฅผ ๋ฐ๋ก ๋ณด๋ฉด ์ฌ์ฉ์๊ฐ ๋จธ๋ฆฟ์์์ ๋ ํ๋ฅผ ๋์กฐํด์ผ ํ๋ค. ์ด์์์ ๊ฐ์ฅ\n * ๊ฐ ์๋ ์ง๋ฌธ์ ๊ทธ ๊ต์ฐจ๋ค: ์ ์ฒด๋ ๋น์ทํ๋ฐ **ํ ๊ตฌ์ญ๋ง ๋๋น ์ง** ๊ฒฝ์ฐ๋ฅผ ์ ์ฒด ์ซ์๋ก๋ ์ ๋ ๋ชป ๋ณธ๋ค.\n *\n * ์ ์ง์ฑ ๊ท์จ:\n * ยท ๋ ๊ตฌ๊ฐ์ **๋ชจ๋ ์๋** ์ถ๋ง delta ๋ฅผ ๋ธ๋ค.\n * ยท ์ง๊ธ๋ง ์๋ ์ถ์ `isNew`(์ด์ ์ ์๋ ์ผ) โ delta ๋ฅผ ๊ฑด์์ ๊ฐ๊ฒ ์ ์ผ๋ฉด \"๋์๋ค\" ๋ก ์ค๋
๋๋ค.\n * ยท **์ฌ๋ผ์ง ์ถ**(์ ์ ์์๊ณ ์ง๊ธ ์๋ ๊ฒ)์ ๋ฐ๋ก ๋๋ ค์ค๋ค. ํ์์ ๊ทธ๋ฅ ๋น ์ง๋ฉด **๋ฉ์ถ ๊ตฌ์ญ์ด\n * ๋์ ๋ณด์ด์ง ์๋๋ค** โ ์ด์์์๋ ์ด๊ฒ์ด ๊ฐ์ฅ ์ค์ํ ์ ํธ์ผ ์ ์๋ค.\n */\nexport interface CrossedGroup extends KpiGroup {\n /** ๋น๊ต ๊ตฌ๊ฐ์ ๊ฑด์(๋ ๊ตฌ๊ฐ์ ๋ชจ๋ ์์ ๋๋ง). */\n prevTasks?: number\n /** ํ์ฌ โ ๋น๊ต๊ตฌ๊ฐ ๊ฑด์(๋ ๊ตฌ๊ฐ์ ๋ชจ๋ ์์ ๋๋ง). */\n deltaTasks?: number\n /** ๋น๊ต ๊ตฌ๊ฐ ๋๋น ์์
์๊ฐ ์ค์๊ฐ ์ฐจ์ด(๋ ๋ค ์ธก์ ๋ ๋๋ง). */\n deltaWorkP50Ms?: number\n /** ๋น๊ต ๊ตฌ๊ฐ์๋ ์๋ ์ถ โ delta ๋์ ์ด ํ์์ ์ค๋ค. */\n isNew?: boolean\n}\n\nexport function crossGroups(\n now: KpiGroup[],\n prev: KpiGroup[]\n): { items: CrossedGroup[]; disappeared: { key: string; tasks: number }[] } {\n const before = new Map(prev.map(g => [g.key, g]))\n const items: CrossedGroup[] = now.map(g => {\n const p = before.get(g.key)\n if (!p) return { ...g, isNew: true }\n return {\n ...g,\n prevTasks: p.tasks,\n deltaTasks: g.tasks - p.tasks,\n ...(deltaP50(g.workTime, p.workTime) !== undefined ? { deltaWorkP50Ms: deltaP50(g.workTime, p.workTime) } : {})\n }\n })\n const present = new Set(now.map(g => g.key))\n const disappeared = prev.filter(g => !present.has(g.key)).map(g => ({ key: g.key, tasks: g.tasks }))\n return { items, disappeared }\n}\n\n/* โโ ์๊ฐ ๋น๊ต โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ซ์ ํ๋๋ก๋ ์ข์์ก๋์ง ๋๋น ์ก๋์ง ์ ์ ์๋ค(\"29์ด\" ๊ฐ ๊ฐ์ ์ธ์ง ์
ํ์ธ์ง). ๊ฐ์ ๊ธธ์ด์ ์ฐฝ์ ์ฎ๊ฒจ\n * ํ ๋ฒ ๋ ๊ณ์ฐํ๋ฉด ๋๋ฏ๋ก(ํด๋๋ ์์) ๊ฐ์ธ๋ค. ์ฐฝ ์ฎ๊ธฐ๊ธฐ์ ์ฐจ์ด ๊ณ์ฐ์ ๊ณ์ฐ ๊ท์น์ด๋ผ ์ฌ๊ธฐ ์๋ค โ\n * ์กฐํ ์ธต์ ๋๋ฉด ํ
์คํธ๊ฐ DB ๋ฅผ ๋๊ณ ์์ผ ํ๋ค.\n */\n\n/**\n * ๋น๊ต ๊ตฌ๊ฐ์ ์ฐฝ โ ๊ฐ์ **๊ธธ์ด**๋ก ์ฎ๊ธด๋ค.\n *\n * previous: ๋ฐ๋ก ์ ๊ตฌ๊ฐ(๊ฒฝ๊ณ๊ฐ ๋ง๋ฌผ๋ฆฌ๊ฒ โ ๊ฒน์น๊ฑฐ๋ ๋ฒ์ด์ง๋ฉด ๊ตฌ๊ฐ์ ํฉ์ด ์ด๊ธ๋๋ค).\n * yesterday: ์ ํํ 24์๊ฐ ์ ๊ฐ์ ์๋ฆฌ. ์๋ฎฌ ํธ์์ ํด๋ก์ด ์ค์ ์๊ฐ๊ณผ ๋ฌ๋ผ๋ **์ฐจ๋ถ์ ์ ํ**ํ๋ค.\n */\nexport function shiftWindow(fromMs: number, toMs: number, basis: 'previous' | 'yesterday'): KpiWindow {\n const span = toMs - fromMs\n const back = basis === 'yesterday' ? 24 * 60 * 60_000 : span\n return { fromMs: fromMs - back, toMs: toMs - back }\n}\n\n/**\n * ์ค์๊ฐ ์ฐจ์ด(ํ์ฌ โ ๋น๊ต๊ตฌ๊ฐ) โ **๋ ๋ค ์ธก์ ๋ ๊ฒ๋ง** ๋ธ๋ค.\n *\n * ํ์ชฝ์ด ๊ฒฐ์ธก์ด๋ฉด ์ฐจ์ด๋ **์๋ ๊ฒ**์ด๋ค(0 ์ด ์๋๋ค). 0 ์ผ๋ก ๋ด๋ฉด \"๋ณํ ์์\" ์ด๋ผ๋ ๊ฑฐ์ง์ด ๋๋ค.\n * ์ข๊ณ ๋์จ์ ํ๋จํ์ง ์๋๋ค โ ์ฒ๋ฆฌ๋์ ํด์๋ก, ์์๋ ์์์๋ก ์ข๋ค๋ ํด์์ ์๋น์ฒ์ ๋ชซ์ด๋ค.\n */\nexport function deltaP50(now: DurationStats, prev: DurationStats): number | undefined {\n return now.count > 0 && prev.count > 0 ? now.p50Ms - prev.p50Ms : undefined\n}\n\n/** ๊ตฌ๊ฐ ํ๋์ ์ต์ ์์ฝ โ ์ถ์ธ๋ฅผ ๊ทธ๋ฆด ์ ๋ณด๋ง(์ ์ฒด KPI ๋ฅผ ๊ตฌ๊ฐ๋ง๋ค ์ค์ด ๋ณด๋ด์ง ์๋๋ค). */\nexport interface KpiBucket {\n fromMs: number\n toMs: number\n tasks: number\n orders: number\n /** ๊ทธ ๊ตฌ๊ฐ์ ์์
์๊ฐ ์ค์๊ฐ โ ์ถ์ธ์์ \"๋๋ ค์ง๊ณ ์๋๊ฐ\" ๋ฅผ ๋ณด๋ ๊ฐ. */\n workP50Ms: number\n}\n\n/**\n * ์ฐฝ์ N ๋ฑ๋ถํด ๊ตฌ๊ฐ๋ณ๋ก ์ฒ๋ฆฌํ๋ค โ **๊ฐ์ ์ด๋ฒคํธ๋ฅผ ์ฐฝ๋ง ๋ฐ๊ฟ** ๋ค์ ๊ณ์ฐํ๋ค(์กฐํ ์ถ๊ฐ ์์).\n *\n * ๋ง์ง๋ง ๊ตฌ๊ฐ์ ๋๋จธ์ง๋ฅผ ํก์ํ๋ค(๋ถ๋์์ ๋๋์
์ผ๋ก ๋์ด ๋ฐ๋ฆฌ๋ฉด ๋ง์ง๋ง ์๋ฃ๊ฐ ๋น ์ง๋ค).\n * `count <= 1` ์ด๋ฉด ์ชผ๊ฐค ๊ฒ์ด ์์ผ๋ฏ๋ก ๋น ๋ฐฐ์ด โ ํธ์ถ๋ถ๊ฐ \"์ถ์ธ ์์\" ์ผ๋ก ๋ค๋ฃฌ๋ค.\n */\nexport function foldKpiBuckets(events: KpiEvent[], window: KpiWindow, count: number): KpiBucket[] {\n const n = Math.max(0, Math.min(48, Math.floor(count)))\n if (n <= 1) return []\n const step = (window.toMs - window.fromMs) / n\n const out: KpiBucket[] = []\n for (let i = 0; i < n; i++) {\n const fromMs = window.fromMs + step * i\n const toMs = i === n - 1 ? window.toMs : window.fromMs + step * (i + 1)\n const b = foldKpi(events, { fromMs, toMs })\n out.push({ fromMs, toMs, tasks: b.throughput.tasks, orders: b.throughput.orders, workP50Ms: b.workTime.p50Ms })\n }\n return out\n}\n"]}
|
|
1
|
+
{"version":3,"file":"kpi-fold.js","sourceRoot":"","sources":["../../server/engine/kpi-fold.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * ์
๋ฌด KPI ํด๋ โ **์ด๋ฒคํธ ์ ๋์ ๊ณ์ฐํด** ์๊ฐ์ฐฝ ์งํ๋ฅผ ๋ง๋ ๋ค(์์).\n *\n * โโ ์ ํ์ํ๊ฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ง๊ธ ํธ์์ด ๋ตํ ์ ์๋ ๊ฒ์ \"์ด ์๊ฐ์ ๊ฐ\"(์ ์ 92%)๊ณผ \"์ธํ๋ผ ๋ถํ\"(์ด๋น ์ด๋ฒคํธ ์)๋ฟ์ด๋ค.\n * ์ด์์ด ๋ฌป๋ ๊ฒ์ ๋ค๋ฅด๋ค โ **์ง๋ ํ ์๊ฐ์ ๋ช ๊ฑด ์ฒ๋ฆฌํ๋, ํ ๊ฑด์ ์ผ๋ง๋ ๊ฑธ๋ฆฌ๋, ์์์ ์ผ๋ง๋\n * ์ผํ๋.** ๊ทธ ๊ฐ์ด ์์ผ๋ฉด AI ๋ \"์ ์ 92%\" ๋ ๋งํด๋ \"๋ชฉํ๋ณด๋ค ๋์๊ฐ\" ๋ ๋ตํ ์ ์๋ค.\n *\n * โโ ์๋ฃ๋ ์ด๋ฏธ ์๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ๋(`TwinEvent`)์ `task.status`ยท`order.status`ยท`equipment.status` ์ ์ด๊ฐ `eventTime`(ISO)๊ณผ ํจ๊ป\n * append-only ๋ก ์์ธ๋ค. ๊ทธ๋์ ์ ๊ณ์ธก์ ์ฌ์ ํ์๊ฐ ์๋ค โ **๊ณ์ฐ๋ง ํ๋ฉด ๋๋ค.**\n * ๊ฐ์ ๋ชจ์์ ์ ๋ก๊ฐ ์ด ํด๋์ ์๋ค(`oee-accumulator.ts` โ equipment ์ ์ด๋ฅผ ๊ณ์ฐํด OEE ์นด์ดํฐ ์์ฐ).\n *\n * โโ ์ด ํ์ผ์ด ํ์ง ์๋ ๊ฒ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ยท ๋ชฉํ์ ๋น๊ตํ์ง ์๋๋ค. \"95% ๋ชฉํ ๋๋น\" ๋ ๋ชฉํ๋ฅผ ์ ์ฅํ๋ ๋ณ๊ฐ ์ธต(๊ฒฝ์ KPI)์ ๋ชซ์ด๊ณ ,\n * ์ด ์ธต์ **์ฌ์ค๋ง** ์์ฐํ๋ค. ๋ ์ธต์ ์์ผ๋ฉด ๋ชฉํ๋ฅผ ์ ์ํ์ง ์์ ํ์ฅ์ ์ฌ์ค์กฐ์ฐจ ๋ชป ๋ณธ๋ค.\n * ยท ์ฒด๋ฅ์๊ฐ(dwell)์ ์์ง ๋ด์ง ์๋๋ค. ๋ฌผ๊ฑด์ด ๋
ธ๋์ ๋จธ๋ฌธ ์๊ฐ์ item ๋จ์ ์ด๋ฒคํธ(epcis.*)๋ฅผ\n * ์ง์ง์ด์ผ ํ๊ณ , ๊ทธ ์ง๋ง์ถค ๊ท์น์ด ๋๋ฉ์ธ๋ง๋ค ๋ค๋ฅด๋ค. **์๋ ๊ฒ์ 0 ์ผ๋ก ๊พธ๋ฏธ์ง ์๋๋ค.**\n * ยท DBยท์ปค๋์ ๋ชจ๋ฅธ๋ค. ์
๋ ฅ์ ํ๋ฒํ ๋ฐฐ์ด์ด๊ณ ์ถ๋ ฅ์ ํ๋ฒํ ๊ฐ์ฒด๋ค(ํ
์คํธ๊ฐ ๊ฐ์ธ๋ค).\n */\n\n/*\n * ์ง๋ง์ถค์ **์ปค๋์ด ์์ ํ๋ค**(`foldTaskRecords`). ์๋ฃ๋ ์์
๋น ํ๋ยท๋์ค ๊ฒ์ด ์ฌ์ค, ์ฐฉ์๋ ์ฒ์ ๊ฒ,\n * ์ข
๋ฅยท์ค๋๋ ์ด๋ ์ ์ด์์๋ โ ๊ทธ ๊ท์น์ ์ปค๋ ์ํ ๊ธฐ๊ณ์์ ๋์ค๋ ์ง์์ด๋ค. ์ฌ๊ธฐ์ ๋ค์ ์ ์๋๋\n * ๊ณต์ ํ์๋ผ์ธ๊ณผ **๋ค๋ฅธ ๋ต**์ ๋๋ค(์ฌ์ ์ก๋ ์๋ฃ๋ฅผ ๋ ๊ฑด์ผ๋ก ์ธ์ด ์ฒ๋ฆฌ๋ยท์ ์ ๊ฐ ๋ถํ๋ ค์ก๋ค).\n * ์ด ํ์ผ์ ์ด์ \"๊ณ์ฐํ ๊ธฐ๋ก โ ์ฐฝ ์งํ\" ๋ง ํ๋ค.\n */\nimport { attributeEnergy, electricityCost, energyIntensity, energyOfWindows, foldTaskRecords, type ElectricityCost, type TariffDeclaration, type TaskFacets } from '@operato/twin-kernel'\nimport { type WorkCalendarEntry } from '@operato/ops-contract'\nimport { ENERGY_EVENT, isOrderTerminal, activeShiftAt } from '@operato/ops-contract'\n\n/** ์ ๋ ํ ์ค โ ํ์ํ ๊ฒ๋ง(์ํฐํฐยทtypeorm ๋น์์กด). */\nexport interface KpiEvent {\n eventType?: string\n /** ISO ์๊ฐ. ํ์ฑ ๋ถ๊ฐํ๋ฉด ๊ทธ ์ค์ ๋ฒ๋ฆฐ๋ค(์๋ฆฌ์ง ์๊ณ 0 ์ผ๋ก ์ธ์ง ์๋๋ค). */\n eventTime?: string\n payload?: any\n}\n\nexport interface KpiWindow {\n /** ์ฐฝ์ ์์ยท๋(epoch ms). ์๋ฃ ์๊ฐ์ด ์ด ์์ ๋ ๊ฒ๋ง ์ฑ๊ณผ๋ก ์ผ๋ค. */\n fromMs: number\n toMs: number\n}\n\nexport interface DurationStats {\n /** ์ง์ด ๋ง์ ๊ณ์ฐ๋ ๊ฑด์. */\n count: number\n /**\n * ํ์ ๊ผฌ๋ฆฌ โ **๋ถํฌ๋ฅผ ์์ชฝ์์ ๊ณ์ฐํ์งํ๊ธฐ ์ํด** ๋ธ๋ค.\n * p50ยทp90 ๋ง ์์ผ๋ฉด ์๋์ชฝ ํผ์ง์ ์์ชฝ์์ ๊ฑฐ์ธ์ฒ๋ผ ๋ฒ ๊ปด ์ธ ์๋ฐ์ ์๋ค(๋ฐ๋ช
). ๊ด์ธก์ด ๋งํ๊ฒ ํ๋ค.\n */\n p10Ms: number\n p50Ms: number\n p90Ms: number\n avgMs: number\n}\n\n/**\n * ๊ด์ ์ถ โ **๊ฐ์ ์ฌ์ค์ ๋ค๋ฅธ ๊ฐ์ผ๋ก** ๋ณธ๋ค.\n *\n * ๊ณ ์ ๋ ํ ๋ ์ฆ(์์๋ณ)๋ง ๋ผ ์ ์์ผ๋ฉด ์ฌ์ฉ์๊ฐ \"๊ตฌ์ญ๋ณ๋ก๋?\" ์ด๋ผ๊ณ ๋ฌผ์ด๋ ๋ต์ด ์๋ค. ์ฌ์ค ๊ณ์ฐ์ด\n * ์ถ์ ๋ชป ๋ด๋ฉด AI ๋ ๋ชป ๋ธ๋ค โ ๊ทธ๋์ ์ถ์ ๊ณ์ฐ ์ธต์ ๋ฅ๋ ฅ์ด์ด์ผ ํ๋ค.\n *\n * resource ์์๋ณ(๋๊ฐ ํ๋) taskKind ์์
์ข
๋ฅ๋ณ(๋ฌด์์ ํ๋)\n * location ๋์ฐฉ ์ง์ ๋ณ(์ด๋์) order ์ค๋๋ณ(๋ฌด์์ ์ํด)\n * area ๊ตฌ์ญ๋ณ โ ๋
ธ๋โ๊ตฌ์ญ ์ง๋๊ฐ ํ์ํ๋ค(์ด๋ฒคํธ์ ์๋ค. ํธ์ถ๋ถ๊ฐ ์ค๋ค)\n * shift ๊ต๋๋ณ(์ธ์ ) โ ์๋ฃ ์๊ฐ + ํ์ฅ์ ์๊ฐ ๊ธฐ์ค์์ **๊ณ์ฐํ๋ค**(์ด๋ฒคํธ์ ์๋ค)\n */\nexport type KpiGroupBy = 'resource' | 'taskKind' | 'location' | 'order' | 'area' | 'shift'\n\nexport interface KpiGroup {\n /** ์ถ์ ๊ฐ(์์ idยท์์
์ข
๋ฅยท๋
ธ๋ idยท์ค๋ idยท๊ตฌ์ญ id). ๊ฐ์ด ์๋ ๊ธฐ๋ก์ 'unknown'. */\n key: string\n /** ์ด ์ถ์์ ์๋ฃ๋ ๊ฑด์. */\n tasks: number\n leadTime: DurationStats\n workTime: DurationStats\n waitTime: DurationStats\n /** ์ด ์ถ์ ๋ถ์ด ์๋ ์๊ฐ์ ํฉ(์์ ์ถ์์ ํนํ ์๋ฏธ ์๋ค). */\n busyMs: number\n /**\n * **ํ์ง ํ์ ์ด ์์๋ ๊ฑด์๋ง** ์ผ๋ค (2026-08-19).\n *\n * ํ์ ์ด ์๋ ์์
(์ด๋ยท์ฒด๋ฅยท์ค๊ฐ ์คํ
์ด์
)์ ์ด๋ ์ชฝ์๋ ์ธ์ง ์๋๋ค โ ๋ชจ๋ฆ์ ์ํ์ผ๋ก ์ธ๋ฉด ์ํ๋ฅ ์ด\n * ์๋ฆฌ์ง ์๊ณ 100% ๋ก ์ฌ๋ผ๊ฐ๋ค. ๊ทธ๋์ `good + scrap` ์ `tasks` ๋ณด๋ค ์์ ์ ์๊ณ , ๊ทธ๊ฒ์ด ์ ์์ด๋ค.\n *\n * ํ์ ์ด ํ๋๋ ์์ผ๋ฉด **ํ๋๋ฅผ ๋ง๋ค์ง ์๋๋ค**(0/0 ์ ใ์ํ๋ฅ 0%ใ๋ก ์ฝํ๊ฒ ๋์ง ์๋๋ค).\n */\n quality?: { good: number; scrap: number }\n}\n\nexport interface KpiResult {\n window: { fromMs: number; toMs: number }\n /** ์ฐฝ ์์ **์๋ฃ๋** ๊ฑด์ โ ์ฑ๊ณผ๋ ์๋ฃ ์์ ์ผ๋ก ์ผ๋ค(์์ ์์ ์ผ๋ก ์ธ๋ฉด ์งํ ์ค์ธ ๊ฒ์ด ์์ธ๋ค). */\n throughput: { tasks: number; orders: number }\n /**\n * ์๋์ง โ **์ด ์ฐฝ์ ์ ๋ ฅ๋๊ณผ ์๋จ์.** ์๋์ง ํธ์์ด ์์ผ๋ฉด `undefined`(0 ์ด ์๋๋ค).\n *\n * โโ ์ KPI ํด๋ ์์ ์๋ (2026-08-14, ยง10 7๋จ๊ณ) โโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์๋จ์๋ ๋ถ์(์ ๋ ฅ๋)์ ๋ถ๋ชจ(์ฐ์ถ)๋ฅผ **๊ฐ์ ์ฐฝ**์์ ๋๋ ๊ฐ์ด๋ค. ์ง์๋ฅผ ๋ฐ๋ก ๋๋ฉด ๋ ์ฐฝ์ ๋ง์ถ๋\n * ์ผ์ด ์๋น์ฒ์ ๋ชซ์ด ๋๊ณ , ์ด๊ธ๋ ๋ ์ฌ์ค์ ๋๋ ์ซ์๋ ์๋ฌด๊ฒ๋ ๋ปํ์ง ์๋๋ค(์ปค๋์ ๊ท์น์ด ๊ทธ๊ฒ์\n * ๊ฑฐ์ ํ๋ค). ๊ฐ์ ํด๋ ์์ ๋๋ฉด ์ฐฝ์ด ํ๋๋ฟ์ด๋ผ ์ด๊ธ๋ ์ ์๋ค.\n *\n * ๋ถ์๋ **์ ๋์ ๊ตฌ๊ฐ ๋ง๊ฐ ์ฌ๊ฑด**์์ ์จ๋ค(`energy.demand.window`) โ ์ปค๋ ์ํ๊ฐ ์๋๋ผ ์ ๋์ด๋ฏ๋ก\n * ๋ฉ์ถ ํธ์ยท๊ณผ๊ฑฐ ๊ตฌ๊ฐ์๋ ๋ตํ ์ ์๋ค.\n */\n energy?: {\n /** ์ด ์ฐฝ์ ์ ๋ ฅ๋. ์
์ ์๋ ๊ตฌ๊ฐ์ด ์์ผ๋ฉด `undefined`. */\n kWh?: number\n /**\n * ์ด ์ฐฝ์ **์ต๋์์**(kW)์ ๊ทธ๊ฒ์ด ๋ ๊ตฌ๊ฐ์ ์์.\n *\n * ์ ๋ ฅ๋๊ณผ ๋ค๋ฅธ ์ง๋ฌธ์ด๋ค: ์ ๋ ฅ๋์ ์๊ธ์ ์ฌ์ฉ๋ ๋ถ๋ถ์ด๊ณ , ์ต๋์์๋ **๊ธฐ๋ณธ์๊ธ**๊ณผ ๊ณ์ฝ ์๋ฐ์\n * ์ ํ๋ค. ํ๊ท ์ผ๋ก ๊ฐ์ํ ์ ์์ด์ ์ปค๋์ด ๊ตฌ๊ฐ์ ์ต๋๋ค ์ค ๊ฐ์ฅ ํฐ ๊ฐ์ ๋ฐ๋ก ๋ธ๋ค.\n */\n peakKW?: number\n peakStartMs?: number\n /**\n * ๊ทธ ํผํฌ ๊ตฌ๊ฐ์์ **์ค๋น๊ฐ ๋์ด๋น๊ธด** ์ต๋(๋ฐ์ ยท๋ฐฉ์ ์ฐจ๊ฐ ์ )์ ๊ทธ ์ฐจ์ด(๊น์ธ ์).\n *\n * ์๊ธ์ ๊ณํต ์์(`peakKW`)๋ก ๋งค๊ฒจ์ง์ง๋ง, ใ๋ฌด์์ด ๊ทธ ์์๋ฅผ ๋ง๋ค์๋ใ์ ใ๋ฌด์์ด ๋์ด๋๋ใ๋\n * ์ด ๋ ์์ ๊ฐ๊ฒฉ์ด ๋ตํ๋ค. ๋ฐ์ ยท์ถ์ ์ ์ ์ธํ์ง ์์ ํ์ฅ์์๋ ์๋ค(์ฐจ๊ฐํ ๊ฒ์ด ์๋ค).\n */\n peakGrossKW?: number\n shavedKW?: number\n /**\n * ์ด ์ฐฝ์ **๋ฐ์ ๋** โ ์ปค๋์ด ๋ง๊ฐํ ๊ธฐ๊ฐ ์ฌ์ค(`energy.generation.period`)์์ ์จ๋ค.\n *\n * ๋ถํ(`kWh`)์ ๋ํ์ง ์๋๋ค: ๋ฐ์ ์ ์ค๋น๊ฐ ๋ง๋ ์์ด๊ณ ๋ถํ๋ ๊ณ๋ ์ง์ ์ ์ง๋ ์์ด๋ค. ๋ ์๋ฅผ\n * ๋ํ๋ฉด ์ด๋ ์ชฝ๋ ์๋ ์ซ์๊ฐ ๋๋ค.\n *\n * ์ฑ๊ณผ์งํ(ISO 50001 EnPI)์ ํ์๊ด ์ฑ๋ฅ๋น๊ฐ ์ด ๊ฐ์ ๋ถ์๋ก ์ด๋ค. ๋ฐ์ ์ฌ์ค์ด ์์ผ๋ฉด `undefined`\n * ๋ค(0 ์ด ์๋๋ค โ ใ๋ฐ์ ์ด ์๋คใ์ ใ๋ฐ์ ์ค๋น๊ฐ ์๋คใ๋ ๋ค๋ฅด๋ค).\n */\n generated?: {\n /** ์ฐฝ์ ์จ์ ํ ๋ ๊ธฐ๊ฐ๋ค์ ํฉ(kWh). */\n kWh: number\n /** ์ผ ๊ธฐ๊ฐ ์. */\n counted: number\n /**\n * ๊ทธ์ค **๊ด์ธก์ด ๊ธฐ๊ฐ์ ๋ค ๋ฎ์ง ๋ชปํ** ๊ธฐ๊ฐ ์.\n *\n * ์ปค๋์ด ๊ธฐ๊ฐ๋ง๋ค ๊ด์ธก ๊ตฌ๊ฐ์ ํจ๊ป ๋ธ๋ค. ๋ง์ง๋ง ํ๋ณธ์ด ๊ธฐ๊ฐ ๋๋ณด๋ค ์ด๋ฅด๋ฉด ๊ทธ๋งํผ ์ฌ์ง ์์\n * ๊ฒ์ด๊ณ , ๊ทธ ์๋ฅผ ๊ฐ์ถ๋ฉด ํ๋ฉด์ด ๋ ์ฐ ํฉ์ ์จ์ ํ ํฉ์ผ๋ก ๋งํ๋ค.\n */\n partial: number\n /** ์ค๋น๋ณ ๋ชซ โ ์ด๊ฒ์ **์ธก์ **์ด๋ค(๋ฐฐ๋ถ์ด ์๋๋ค). ๊ฐ ์ค๋น์ ์ ์ฐ์์ ์๋ค. */\n byEquipment: { id: string; kWh: number }[]\n /**\n * **์ด ์ฐฝ์ ๋ค ๋ค์ด์ค์ง ์์ ๋ํ์ง ๋ชปํ ๊ธฐ๊ฐ** โ ์กฐ์ฉํ ๋ฒ๋ฆฌ์ง ์๋๋ค.\n *\n * ๋ํ๋ ๊ฒ์ ์ฐฝ์ ์จ์ ํ ๋ ๊ธฐ๊ฐ๋ฟ์ด๋ค(๊ฑธ์น ๊ธฐ๊ฐ์ ๋ํ๋ฉด ๋ค๋ฅธ ๋ ๊ฐ์ด ์ด ์ฐฝ์ ๊ฐ์ธ ์ฒํ๋ค).\n * ๊ทธ๋ฐ๋ฐ ํ๋ฃจ ๋จ์ ๊ธฐ๊ฐ์ ใ์ง๊ธ๋ถํฐ 24์๊ฐ ์ ใ ์ฐฝ์ ์จ์ ํ ๋๋ ์ผ์ด ๊ฑฐ์ ์๋ค โ ์ฐฝ์ด ํ๋ฎ์์\n * ์์ํ๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋์ ์ด์ ๋ฐ์ ๋์ด ์ ๋์ ๋ฉ์ฉกํ ์๋๋ฐ ํ๋ฉด์ด ๋น์๊ณ , ์ฌ์ฉ์๋ ๊ทธ๊ฒ์\n * ใ๋ฐ์ ๋์ด ์๋คใ๋ก ์ฝ์๋ค(2026-08-30 ์ค์ธก).\n *\n * ์ด ๊ฐ์ด ์์ผ๋ฉด ํ๋ฉด์ **ใ์ด ๊ตฌ๊ฐ์ ๋ค ๋ค์ด์ค์ง ์์ ๊ธฐ๊ฐ์ด ์๋คใ**๋ฅผ ๋งํด์ผ ํ๋ค.\n */\n notCounted?: { periods: number; kWh: number; earliestStart: string; latestEnd: string }\n /**\n * ์ด์ฉ๋ฅ โ ๋ง๋ ์ รท (์ ๊ฒฉ ร ๊ทธ ๊ธฐ๊ฐ์ ์๊ฐ).\n *\n * **์ด๋ ์ ๊ฒฉ์ผ๋ก ๋๋ด๋์ง๋ฅผ ํจ๊ป ๋ธ๋ค.** ๋ณํ๊ธฐ๋ฅผ ๋ ๋ฐ์ ์ ์ง๋ฅ ์ ๊ฒฉ์ด ๊ต๋ฅ๋ณด๋ค ํฌ๊ณ ,\n * ์ง๋ฅ๋ก ๋๋ ๋ณด์ฌ ์ฃผ๋ ์์คํ
์ด ์ค์ ๋ก ์๋ค. ๋ฐํ์ง ์์ผ๋ฉด ๋ ํ๋ฉด์ ์๊ฐ ๋ ๋ฐฐ ๋ฌ๋ผ๋\n * ์ ๋ค๋ฅธ์ง ๋งํ ์ ์๋ค.\n *\n * ์ฐฝ ์ ์ฒด๊ฐ ์๋๋ผ **์ผ ๊ธฐ๊ฐ๋ค์ ๊ธธ์ด**๋ก ๋๋๋ค โ ํ๋ฃจ์น ํ๋๋ง ์ผ 24์๊ฐ ์ฐฝ์์ ์ฐฝ ๊ธธ์ด๋ก\n * ๋๋๋ฉด ๊ทธ ํ๋ฃจ๊ฐ ์ฐฝ ์ ์ฒด์ ๊ฑธ์ณ ์์๋ ๊ฒ์ฒ๋ผ ์์์ง๋ค.\n */\n capacityFactor?: { value: number; ratedKW: number; basis: 'ac' | 'dc'; from: 'equipment' | 'location'; hours: number }\n /**\n * ๋ธ ๊ฒ์ ๊ฐ โ ๊ธฐ๊ฐ๋ง๋ค ๊ทธ๋์ ๋จ๊ฐ๋ก ๋งค๊ธด๋ค.\n *\n * **๋ชจ๋ ๊ธฐ๊ฐ์ ๋จ๊ฐ๊ฐ ์์ ๋๋ง** ๊ธ์ก์ ๋ง๋ ๋ค. ์ผ๋ถ๋ง ๋งค๊ธฐ๊ณ ๋ํ๋ฉด ๊ทธ ํฉ์ด ์ฐฝ ์ ์ฒด์ ๊ฐ์ธ\n * ์ฒํ๋ค โ ๋ชป ๋งค๊ธด ๊ธฐ๊ฐ ์๋ฅผ ํจ๊ป ๋ธ๋ค.\n */\n revenue?: { amount: number; currency: string; priced: number; unpriced: number }\n }\n /**\n * `kWh` ๊ฐ ์ด๋ ํ๊ณ์์ ์๋.\n *\n * 'demand-window' ์ฐ๋ฆฌ๊ฐ ํ๋ณธ์์ ๋ง๊ฐํ ๊ตฌ๊ฐ (๊ณ๋์ด ์ค๋ ํ์ฅ)\n * 'usage-period' ๋ฐ์์ ๋ง๊ฐ๋์ด ์จ ๊ตฌ๊ฐ (๊ณ๋ ํ๋ณธ์ด ์๋ ํ์ฅ)\n *\n * ๋์ ๋ํ์ง ์๋๋ค โ ๊ฐ์ ์ ๊ธฐ๋ฅผ ๋ ๋ฒ ์ผ๋ค. ๋ ๋ค ์์ผ๋ฉด ๊ณ๋ ์ชฝ์ ์ฐ๊ณ ๊ทธ ์ฌ์ค์ ๋ธ๋ค.\n */\n kWhBasis?: 'demand-window' | 'usage-period'\n /**\n * ๊ธฐ๋ณธ์๊ธ์ ๋งค๊ธด **์๊ธ์ ์ฉ์ ๋ ฅ๊ณผ ๊ทธ ๊ทผ๊ฑฐ**.\n *\n * ์ด ๊ฐ์ ๋งค๋ฌ ๋ค์ ์ ํด์ง๋ค. ์ ์ธ์ ๋ฐ์ ๋๋ฉด ์ฌ๋์ด ๊ฐฑ์ ํด์ผ ํ๊ณ , ์ ํ๋ฉด ๋ก์ ๊ฐ์ผ๋ก\n * ๊ธฐ๋ณธ์๊ธ์ด ์กฐ์ฉํ ํ๋ฆฐ๋ค. ๊ทธ๋์ **์ฒญ๊ตฌ์๊ฐ ๋จผ์ ๋ค** โ ์๋ณธ์ด ๋งค์ผ ์ค์ด ๋ณด๋ธ๋ค.\n *\n * 'bill' ์ด ์ฐฝ์ ๋ฎ๋ ์ฒญ๊ตฌ์๊ฐ ๋งํ ๊ฐ\n * 'carried-forward' ๊ฐ์ฅ ์ต๊ทผ ์ฒญ๊ตฌ์์ ๊ฐ์ ์ด์ด ์ด๋ค(์๊ธ ์ ๋๊ฐ ์ค์ ๋ก ๊ทธ๋ ๊ฒ ๊ตฐ๋ค)\n * 'declaration' ์ฒญ๊ตฌ๊ฐ ์ค์ง ์๋ ํ์ฅ โ ๋ชจ๋ธ์ ์ ์ธ\n *\n * `declaredKW` ์ ๋ค๋ฅด๋ฉด **์ ์ธ์ด ๋ก์๋ค**(`stale`). ๊ทธ ์ฌ์ค์ ๊ฐ์ถ๋ฉด ์๋ฌด๋ ๋ค์ ์ฝ์ง ์๋๋ค.\n */\n billingDemand?: {\n kW: number\n from: 'tariff-basis' | 'bill' | 'carried-forward' | 'declaration'\n declaredKW?: number\n stale?: boolean\n /**\n * ์ด ์ฐฝ์์ ๊ด์ธกํ ์ต๊ณ ์์๊ฐ ๊ทธ ๊ธฐ์ค์ ๋์๋ค โ **๋ค์ ์ฃผ๊ธฐ์ ๊ธฐ๋ณธ์๊ธ์ด ์ค๋ฅธ๋ค.**\n *\n * ๊ณ์ฝ ์ด๊ณผ์ ๋ค๋ฅธ ๊ฐ์ด๋ค. ๊ณ์ฝ ์ด๊ณผ๋ ์ง๊ธ ์ค์ด๋ฉด ๋๊ณ , ์ด๊ฒ์ ์ด๋ฏธ ์ ํด์ง ๊ฒฐ๊ณผ๋ค.\n *\n * `observedTo` ๋ ์ด ์ต๊ณ ๊ฐ์ด ์ธ์ ๊น์ง์ ๊ฒ์ธ์ง๋ค. ์ต๊ณ ์์๋ ๊ตฌ๊ฐ์ด ๋ง๊ฐ๋์ด์ผ ์ค๋ฏ๋ก\n * ๋์ ๊ฒ์ ๋ค๋ฆ๊ฒ ์๋ค โ ๊ทธ ํ๊ณ๋ฅผ ํ๋ฉด์ด ๋งํ ์ ์์ด์ผ ํ๋ค.\n */\n exceeded?: { peakKW: number; overKW: number; observedTo: string }\n }\n /**\n * ๋ฐ์์ ๋ง๊ฐ๋์ด ์จ ์ฌ์ฉ ๊ตฌ๊ฐ โ ๊ณ๋ ํ๋ณธ์ด ์๋ ํ์ฅ์ ์ ์ผํ ๊ทผ๊ฑฐ๋ค.\n *\n * `basis` ๋ณ ๊ฑด์๋ฅผ ํจ๊ป ๋ธ๋ค: ๊ฐ์ kWh ๋ผ๋ ๊ณ๋๊ธฐ๊ฐ ์ฐ ๊ฒ๊ณผ ๊ณต๊ธ์ ํ๋ฉด์์ ๊ธ์ด์จ ๊ฒ์ ๋ฌด๊ฒ๊ฐ\n * ๋ค๋ฅด๊ณ , ์ค์ ๋ก ๊ธ์ด์จ ๊ฐ์ด ๋ง๊ฐ์ ธ ์๋ ๊ฒ์ ๋ณธ ์ ์ด ์๋ค.\n */\n usage?: {\n kWh: number\n counted: number\n /** ๊ตฌ๊ฐ๋ง๋ค ์ ๋จ๊ฐ๋ก ๋งค๊ธด ์ฌ์ฉ๋ ์๊ธ โ ๋ชจ๋ ๊ตฌ๊ฐ์ด ๋จ๊ฐ๋ฅผ ์ค์์ ๋๋ง. */\n charge?: number\n currency?: string\n /** ๋จ๊ฐ๊ฐ ์์ด ์๊ธ์ ๋งค๊ธฐ์ง ๋ชปํ ๊ตฌ๊ฐ ์ โ ์กฐ์ฉํ ๋นผ์ง ์๋๋ค. */\n unpriced: number\n byBasis: { basis: string; counted: number }[]\n }\n /**\n * ์ด ์ฐฝ์ ์จ์ ํ ๋ **์ฒญ๊ตฌ์** โ ๊ณต๊ธ์๊ฐ ํ์ ํ ๊ธ์ก.\n *\n * ์ฐ๋ฆฌ ๊ณ์ฐ์ ๋ฎ์ง ์๋๋ค. ์ฐฝ์ด ์ฒญ๊ตฌ ์ฃผ๊ธฐ์ ์ ํํ ๊ฐ์ ๋๋ง ๊ฒฌ์ค ์ ์์ผ๋ฏ๋ก ๊ทธ ์ฌ์ค์\n * `matchesWindow` ๋ก ํจ๊ป ๋ธ๋ค โ ๋ค๋ฅธ ์ฐฝ์ ๋ ์๋ฅผ ๋นผ๋ฉด ๊ทธ ์ฐจ์ด๋ ์๋ฌด๊ฒ๋ ๋ปํ์ง ์๋๋ค.\n */\n bill?: {\n from: string\n to: string\n total?: number\n energyCharge?: number\n demandCharge?: number\n currency?: string\n billingDemandKW?: number\n matchesWindow: boolean\n /**\n * ์ฐฝ์ด ๊ฐ์ ๋, **์ฐ๋ฆฌ ๊ณ์ฐ์์ ์ฒญ๊ตฌ์ก์ ๋บ ๊ฐ** โ 0 ์ด ์๋๋ฉด ์ฐ๋ฆฌ ๊ณ์ฐ์ด ํ๋ ธ๋ค๋ ๋ป์ด๋ค.\n *\n * ํญ๋ชฉ๋ณ๋ก๋ ๋ธ๋ค(2026-08-29). ์ด์ก๋ง ๊ฒฌ์ฃผ๋ฉด ์๋ณธ์ด ์ด์ก์ ์ฃผ์ง ์๋ ์ฒญ๊ตฌ์์์๋ ๋น๊ต๊ฐ\n * ์์ ๋์ค์ง ์๋๋ค โ ์ค์ ๋ก ์ฒซ ์ฒญ๊ตฌ์์ ๊ธฐ๋ณธ์๊ธ๋ง ์์๋ค. ์์ชฝ์ ์๋ ํญ๋ชฉ๋ง ๊ฒฌ์ค๋ค.\n */\n diff?: { total?: number; demandCharge?: number; energyCharge?: number }\n }\n /** ํ์์ ๊ทผ๊ฑฐ โ ๊ตฌ๊ฐ ํ๊ท ๋ถํ ร ๊ธธ์ด(`mean-kw`). */\n basis: string\n /** ์ผ ๊ตฌ๊ฐ ์ ยท ๋ชป ์ผ ๊ตฌ๊ฐ ์(๊ณ์ธก์ด ๋๊ธด ๊ตฌ๊ฐ) โ ์๋ฆฌ์ง ์๊ณ ์๋ฅด์ง ์๋๋ค. */\n counted: number\n skipped: number\n /** ์๋ฃ ์ค๋๋น ์ ๋ ฅ๋ โ ๋ตํ ์ ์์ผ๋ฉด `null` ๊ณผ ์ด์ . */\n intensity: { value: number | null; unit?: string; reason?: string }\n /**\n * ๋ฐฐ์ ๊ณํต์ **์๋ฆฌ๋ณ ๋ชซ** โ ใ์ด ๋ถ๊ธฐ๊ฐ ์ผ๋ง ์ผ๋ใ.\n *\n * โโ ์ด๊ฒ์ ์ธก์ ์ด ์๋๋ผ ๋ฐฐ๋ถ์ด๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ๋์ ์๋ ์๋์ง ์ฌ์ค์ **ํ์ฅ ์ด๋ ํ ์ค**์ด๋ค(๋ฟ๋ฆฌ ๊ณ๋๊ธฐ ํฉ). ๊ณ๋๊ธฐ๋ณ ๊ตฌ๊ฐ ์ฌ์ค์ด ์์ผ๋ฏ๋ก\n * ์๋ฆฌ๋ณ ๋ชซ์ **๋๋ ๊ฒ**์ด๊ณ , ๋ฌด์์ผ๋ก ๋๋ด๋์ง(`weightKind`)๋ฅผ ๊ฐ๊ณผ ํจ๊ป ๋ธ๋ค. ๊ทผ๊ฑฐ๋ฅผ ๊ฐ์ถ๋ฉด\n * ๋๋ ์ซ์๊ฐ ์ฐ ์ซ์์ ๊ฐ์ ๋ฌด๊ฒ๋ก ์ฝํ๋ค โ CBAMยทESG ๋ณด๊ณ ์์ ์ฒซ ์ง๋ฌธ์ ๊นจ์ง๋ ์ง์ ์ด๋ค.\n *\n * ๊ฐ์ค์น๋ **์์
๊ฐ๋์๊ฐ**์ด๋ค. ์ ๊ฒฉ(kW)์ผ๋ก ๋๋์ง ์๋๋ค: ์๋ฎฌ ํธ์์ ์ด๋ถํ๊ฐ ์ ๊ฒฉ์ ํฉ์ผ๋ก\n * ํ์๋๋ฏ๋ก, ๊ทธ ์ด๋์ ๋ค์ ์ ๊ฒฉ์ผ๋ก ๋๋๋ฉด ๋ฃ์ ๊ฐ์ด ๊ทธ๋๋ก ๋์ค๋ ๋์ด๋ฐ๋ณต์ด ๋๋ค.\n *\n * ๊ทธ๋์ ์ด ๊ฐ์๋ **๊ฐ์ ์ด ํ๋ ์ค๋ ค ์๋ค**: ์ ๊ธฐ๊ฐ ๊ฐ๋์๊ฐ์ ๋น๋กํ๋ค. ๊ณต์กฐยท์กฐ๋ช
์ฒ๋ผ ๊ณต์ ์\n * ๋ถ์ง ์๋ ๋ถํ๋ ๊ทธ ๋น์จ์ ์์ธ๋ค โ ํ๋ฉด์ด ๊ทธ ๋ฌธ์ฅ์ ํจ๊ป ๋งํด์ผ ํ๋ค.\n */\n byFeeder?: {\n /** ์๋ฆฌ(๋ถ๊ธฐยท์์ ) id. ์๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋ ์์์ `unknown` ์ผ๋ก ๋ชจ์ธ๋ค(์๋ฆฌ์ง ์๊ณ ๋ฒ๋ฆฌ์ง ์๋๋ค). */\n key: string\n kWh: number\n /**\n * ์ด ๋ชซ์ ๊ทผ๊ฑฐ โ **์ปค๋์ด ์ ํ๋ค.**\n *\n * ์ ์ธ๋ ๋ถํ๊ฐ ์ฌ๋ฟ์ด๋ฉด ๋ฐฐ๋ถ(`apportioned`)์ด๋ค. ์ ์ธ๋ ๋ถํ๊ฐ **ํ๋๋ฟ์ธ** ํ์ฅ์์๋ ์ปค๋์ด\n * ใ๊ทธ ๊ณ๋๊ธฐ๋ ๊ทธ๊ฒ๋ง ์ฐ๋คใ๊ณ ์ฝ์ด `measured` ๋ฅผ ๋ธ๋ค โ ๋ชจ๋ธ์ด ๊ทธ๋ ๊ฒ ๋งํ์ผ๋ฏ๋ก ๊ทธ๊ฒ๋ ์ฌ์ค์ด๋ค.\n * ์ฐ๋ฆฌ๊ฐ ์ด๋ ์ชฝ์ผ๋ก๋ ๋์ธ์ฐ์ง ์๋๋ค.\n */\n basis: 'apportioned' | 'measured'\n /**\n * ๋ฌด์์ผ๋ก ๋๋ด๋ โ **๋ฐฐ๋ถ์ผ ๋๋ง** ์๋ค.\n *\n * ๋ถ๊ธฐ๋ง๋ค ๊ณ๋๊ธฐ๊ฐ ์๋ ํ์ฅ์์๋ ๋๋์ง ์๋๋ค(๊ทธ ๊ฐ์ด ๊ณง ๊ณ๋์ด๋ค). ๊ทธ๋ ์ด ์นธ์\n * `runtimeMs` ๋ก ์ฑ์ฐ๋ฉด ใ๊ฐ๋์๊ฐ์ผ๋ก ๋๋ด๋คใ๋ ์๋ ์ฌ์ค์ ๋งํ๊ฒ ๋๋ค.\n */\n weightKind?: 'runtimeMs'\n /** ์ด ์๋ฆฌ์ ๋ชซ์ด ์ ์ฒด์ ์ผ๋ง์๋ โ ๋ฐฐ๋ถ์ผ ๋๋ง. */\n weightShare?: number\n /**\n * **ํผํฌ๊ฐ ์ฐํ ์๊ฐ** ์ด ๋ถ๊ธฐ๊ฐ ์ผ๋ง์๋(kW) โ ์๊ธ์ด ๊ฑธ๋ฆฐ ์๋ค.\n *\n * ์ฐฝ์ ํ๊ท ์ด๋ ํฉ์ด ์๋๋ค: ์ต๋์์๋ฅผ ๋ธ ๊ตฌ๊ฐ์ ๊ทธ ์๊ฐ ๊ฐ์ด๋ค(๋ค๋ฅธ ์๊ฐ์ ์์ผ๋ฉด ใ์ด๋ ๋ถ๊ธฐ๋ฅผ\n * ๊น์์ผ ํผํฌ๊ฐ ๋ด๋ ค๊ฐ๋ใ์ ๋ต์ด ํ๋ ค์ง๋ค). ๊ทธ ๊ตฌ๊ฐ์ ์ด ๋ถ๊ธฐ์ ํ๋ณธ์ด ์์์ผ๋ฉด **์๋ค**.\n */\n peakKW?: number\n }[]\n /**\n * ๋๋์ง ๋ชปํ ์๊ณผ ๊ทธ ์ด์ โ **์๋ฆฌ์ง ์๊ณ 0 ์ผ๋ก ๋ง๋ค์ง ์๋๋ค.**\n * `no-weights` = ๊ทธ ์ฐฝ์ ๋์๊ฐ ์์์ด ์๋ค(๊ฐ๋์๊ฐ์ด ์ ๋ถ 0). ๊ทธ๋ฌ๋ฉด ์ด๋์ ๊ทธ๋๋ก ๋จ๋๋ค.\n */\n unattributedKWh?: number\n /**\n * ์ ๋๋์ง ๋ชปํ๋(์ปค๋ ์ฝ๋) โ `no-weights`(๊ฐ๋์๊ฐ์ด ์ ๋ถ 0) ยท `no-consumers`(๋ฎ๋ ๋์ ๋ฏธ์ ์ธ) ยท\n * `not-submetered`(๋ฟ๋ฆฌ์์ ์ฌ์์ผ๋ ํ์ ๊ณ๋์ด ๋ฎ์ง ์๋ ๋ถ๋ถ โ ๊ฒฐ์์ด ์๋๋ผ ๊ณ๋ ๋ฒ์์ ์ฌ์ค).\n */\n unattributedReason?: string\n /**\n * ๋ถ๊ธฐ ๊ณ๋์ ํฉ์ด ๋ฟ๋ฆฌ ๊ณ๋๋ณด๋ค **ํฐ** ์ โ ๋ ๊ณ๋๊ธฐ์ ํ๊ณ๊ฐ ๋ค๋ฅด๋ค๋ ์ฌ์ค์ด๋ค.\n *\n * ๊ฐ์ ๊น์ ๋ง์ถ์ง ์๋๋ค: ๊ทธ๊ฒ์ ๊ณ๋์ ์ฐ๋ฆฌ๊ฐ ๊ณ ์ณ ์ฐ๋ ์ผ์ด๊ณ , ์ด๋ ์ชฝ์ด ๋ง๋์ง๋ ํ์ฅ์ด ์๋ค.\n */\n submeterExcessKWh?: number\n /**\n * ๋ฐฐ๋ถ์์ **๋น ์ง ์์ ์** โ ๊ทธ ์ฐฝ์ ๊ฐ๋ ๊ธฐ๋ก์ด ์๋ ์ค๋น๋ค. 0kWh ๋ฅผ ์ฃผ์ง ์๋ ๋์ ๋ช ๋๊ฐ\n * ๋น ์ก๋์ง ์ผ๋ค(๋๊ธฐ์ ๋ ฅ์ด ์๋ ์ค๋น์์ 0 ์ ๊ณง ๊ฑฐ์ง์ด๋ค).\n */\n excludedResources?: number\n /**\n * ์ด ์ฐฝ์ ์ ๊ธฐ์๊ธ โ **์ฒญ๊ตฌ์๊ฐ ์๋๋ค.** ๊ณ์ฐ๊ณผ ๊ทธ ํ๊ณ(TOUยท๋์นซยท์ต์์ฒญ๊ตฌ์ก ๋ฏธ๋ชจ๋ธ)๋ ์ปค๋\n * (`electricityCost`)์ด ๊ฐ๊ณ ์ฌ๊ธฐ์๋ ๋๋ฅธ๋ค. ๋จ๊ฐ๊ฐ ์์ผ๋ฉด `reason: 'no-tariff'` ๋ก ์จ๋ค.\n */\n cost?: ElectricityCost\n }\n /** ๋ฆฌ๋ํ์ โ ์์ฑ(created)์์ ์๋ฃ๊น์ง. ์ฌ์ฉ์๊ฐ ์ฒด๊ฐํ๋ ์์ ์๊ฐ. */\n leadTime: DurationStats\n /** ์์
์๊ฐ โ ์ฐฉ์(in-progress)์์ ์๋ฃ๊น์ง. ๋๊ธฐ๋ฅผ ๋บ ์ค์์
. */\n workTime: DurationStats\n /** ๋๊ธฐ์๊ฐ โ ์์ฑ์์ ์ฐฉ์๊น์ง. ์์์ด ๋ถ์กฑํ๋ฉด ์ฌ๊ธฐ๊ฐ ๋์ด๋๋ค. */\n waitTime: DurationStats\n /** ์์๋ณ ์ ์ โ ์์
์ ๋ถ์ด ์๋ ์๊ฐ์ ํฉ๊ณผ ์ฐฝ ๋๋น ๋น์จ(์์
์ผ๋ก ์ค๋ช
๋๋ ๋ถ๋ถ๋ง). */\n utilization: { resourceId: string; busyMs: number; ratio: number }[]\n /**\n * **์
์์ ๋น ์ง ๊ฒ** โ ์๋ฃ๋ ์ฐฝ ์์ด์ง๋ง ์์ ์ด๋ฒคํธ๋ฅผ ๋ชป ์ฐพ์ ๊ฑด์.\n * ์กฐํ ๊ตฌ๊ฐ์ด ์งง์ ์์์ด ์๋ ธ๊ฑฐ๋ ์ ๋์ด ์ ์ค๋ ๊ฒฝ์ฐ๋ค. ์ด ๊ฐ์ ์จ๊ธฐ๋ฉด ํ๊ท ์ด ์๋ฆฌ์ง ์๊ณ ๊ฑฐ์ง์ด ๋๋ค.\n */\n unpaired: { leadTime: number; workTime: number }\n /**\n * **์๋ฃ๋ก ์ธ์ง ์์ ์ค๋ ์ํ ๋ฑ๋ง์ ์ธ๊ตฌ์กฐ์ฌ** โ ๋ฑ๋ง โ ์ฐฝ ์์์ ๊ทธ ๋ฑ๋ง๋ก ๋ณธ ๊ฑด์.\n *\n * ใ๋ชป ์ฝ์๋คใ๊ฐ **์๋๋ค.** `picking` ์ฒ๋ผ ์๋ฃ๊ฐ ์๋ ๋ฑ๋ง์ด ์ฌ๊ธฐ ์ค๋ ๊ฒ์ ์ ์์ด๋ค. ์ด ๊ฐ์\n * ํ์ ์ด ์๋๋ผ **์ฌ๋ฃ**๋ค: ์๋ฃ๊ฐ 0 ์ธ๋ฐ ์ฌ๊ธฐ `{ finished: 2780 }` ์ด ์์ผ๋ฉด ์์ธ์ด ๊ณง ๋ณด์ธ๋ค.\n *\n * โโ ์ ํ์ํ๊ฐ, ๊ทธ๋ฆฌ๊ณ ๋ฌด์์ ๋์ฒด๊ฐ ์๋๊ฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ด ํด๋๋ ์๋ฃ๋ฅผ **๋์์ด ๋ชฉ๋ก**์ผ๋ก ํ์ ํ๋ค(`completed`ยท`fulfilled`ยท`done`ยท`finished`). ๊ทธ ๋ฐฉ์์\n * ์๋ณธ์ ๋ฑ๋ง์์ ๋ป์ **์ถ๋ก **ํ๋ ๊ฒ์ด๊ณ , ์ด ์ ์ฅ์๊ฐ ๋ค๋ฅธ ์๋ฆฌ์์ ๊ฑฐ์ ํ๋ ๊ทธ๊ฒ์ด๋ค\n * (ใ์ ์ธ์ด ์์ผ๋ฉด ๋ณํ์ด์ง๋ง ์์ผ๋ฉด ๋ฐ๋ช
์ด๋คใ).\n *\n * ์ค์ ๋ก ๊ทธ ๋๊ฐ๋ฅผ ์น๋ ๋ค: `finished` ๊ฐ ๋ชฉ๋ก์ ์์ด ์ฒซ ์ค ์์คํ
์ ์๋ฃ ์ค๋๊ฐ ์ ๋ถ 0 ์ด์๋ค.\n * ๊ทธ๋ฐ๋ฐ **๋น ์๋ฆฌ๋ ์ด ๋ชฉ๋ก์ด ์๋๋ผ ์ปค๋ฅํฐ์๋ค** โ ๊ทธ ์ปค๋ฅํฐ์ ์ํ ํ(`WORK_ORDER_STATE`)๊ฐ\n * ์ ์๋ผ ์์ผ๋ฉด์ ์ค๋ ๊ฒฝ๋ก์์ ์ฐ์ด์ง ์์๊ณ (๋กํธ ๊ฒฝ๋ก๋ ์ผ๋ค), ์๋ณธ ๋ฑ๋ง์ด ๊ทธ๋๋ก ํ๋ ๋ค.\n * ๋ชฉ๋ก์ `finished` ๋ฅผ ๋ํ ๊ฒ์ ๊ทธ ์ฌ์ค์ ๊ฐ๋ฆฐ ๋๋นต์ด์๋ค.\n *\n * **์ ์์ ์ปค๋ฅํฐ๊ฐ ์๊ธฐ ํ๋ก ์ฎ๊ธฐ๊ณ , ์ฎ๊ธธ ์ ์๋ ๋ฑ๋ง์ ์ธ๊ณ ๋ฃ์ง ์๋ ๊ฒ์ด๋ค**(์ฌ๊ณ ์ฒ๋ถ์ด ์ด๋ฏธ\n * ๊ทธ ๊ท์จ๋ก ์ ๋ค: ใํํํ ๊ธธ์ด ์๋ ๊ฒ์ ๋ฃ์ง ์๋๋คใ). ๊ทธ๋ฌ๋ฉด ์ด ํด๋๋ ์ถ๋ก ํ์ง ์์๋ ๋๋ค.\n *\n * ๊ทธ๋ฌ๋ฏ๋ก ์ด ๊ฐ์ **๋์์ด ๋ชฉ๋ก์ ๋๋ฆฌ๋ ๊ทผ๊ฑฐ๊ฐ ์๋๋ค.** ๋ชฉ๋ก์ ์ปค๋ฅํฐ๋ค์ด ์ฎ๊ธฐ๊ธฐ ์์ํ๋ฉด\n * ๋ซํ ์ดํ๋ก ์ขํ์ผ ํ๊ณ , ๊ทธ๋๊น์ง ์ด ๊ฐ์ด ์ด๊ธ๋จ์ ๋งํด ์ค๋ค. ์์๊ฐ ์ค์ํ๋ค โ ๋ชฉ๋ก์ ๋จผ์ \n * ์ขํ๋ฉด ์์ง ์ฎ๊ธฐ์ง ์๋ ์๋ณธ์ ์๋ฃ๊ฐ ๊ทธ ์๊ฐ 0 ์ด ๋๋ค.\n *\n * ์ํ๋ฅผ ๋งํ์ง ์์ ์ฌ๊ฑด์ ์ฌ๊ธฐ ์ค์ง ์๋๋ค. ๊ทธ๊ฒ์ ใ๋ชจ๋ฅด๋ ๋ฑ๋งใ์ด ์๋๋ผ ๋ค๋ฅธ ๊ฒฐํจ์ด๊ณ \n * (์ ์
๋ฌธ์ด ์ํ๋ฅผ ํ์๋ก ๋ฐ๋๋ค) ๊ทธ ์ง๋จ์ ๊ทธ ๋ฌธ์ ๋ชซ์ด๋ค.\n */\n orderStatusNotCounted: Record<string, number>\n /**\n * ์๋นํ ์ด๋ฒคํธ ์ โ **๋๊ฒจ๋ฐ์ ๋ฐฐ์ด ์ ์ฒด**(์ฐฝ ์ lookback ํฌํจ). ์ง๋จ์ฉ์ด๋ค.\n *\n * \"์ธก์ ๋ ๊ธฐ๋ก์ด ์๋๊ฐ\" ์ ํ๋จ์๋ ์ฐ์ง ๋ง ๊ฒ โ ํธ์ถ๋ถ๋ ์ฐฝ๋ณด๋ค ์๊น์ง ์ฝ์ด ๋๊ธฐ๋ฏ๋ก(์๋ฃ๋ ์์
์\n * ์์์ด ์ฐฝ ๋ฐ์ผ ์ ์๋ค) ์ฐฝ ์์ด ๋น์ด ์์ด๋ ์ด ๊ฐ์ 0 ์ด ์๋๋ค. ๊ทธ ํ๋จ์ `eventsInWindow` ๋ก ํ๋ค.\n */\n eventsSeen: number\n /**\n * **์ฐฝ ์์** ๋ค์ด์จ ์ด๋ฒคํธ ์ โ \"์ด ๊ตฌ๊ฐ์ ์ธก์ ํ ๊ธฐ๋ก์ด ์์๋๊ฐ\" ์ ์ ๋ต.\n *\n * ์ด๊ฒ์ด 0 ์ด๋ฉด \"์ฒ๋ฆฌ๋ 0\" ์ด ์๋๋ผ **\"๊ธฐ๋ก์ด ์๋ค\"** ๋ค. ๋ ์ํฉ์ ์์ผ๋ฉด ์ฌ์ฉ์๊ฐ ์๋ชป๋ ๊ฒฐ๋ก ์\n * ๋ธ๋ค(์ ๊ตฌ๊ฐ์ ๊ธฐ๋ก๋ง ์ฝ์ด ๋๊ณ \"0๊ฑด ์ฒ๋ฆฌ\" ๋ผ๊ณ ๋งํ๋ ์ผ์ด ์ค์ ๋ก ๊ฐ๋ฅํ๋ค).\n */\n eventsInWindow: number\n /** ์์ฒญํ ๊ด์ ์ผ๋ก ์ชผ๊ฐ ๊ฐ(์์ฒญํ์ ๋๋ง). */\n groups?: { by: KpiGroupBy; items: KpiGroup[]; truncated?: number; truncatedTasks?: number }\n}\n\n/**\n * ์ฐฝ์ ์ ๋ ฅ๋์ **๋ฐฐ์ ๊ณํต์ ์๋ฆฌ๋ณ๋ก ๋๋๋ค** โ ๊ทผ๊ฑฐ๋ฅผ ํจ๊ป.\n *\n * โโ ์ ์ปค๋ ํจ์๋ฅผ ์ฐ๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ใ๋๋ ๊ทผ๊ฑฐ๊ฐ ์์ผ๋ฉด ๋๋์ง ์๋๋คใยทใํฉ์ ๋ณด์กด๋๋คใยทใ๋ชซ์ด 0 ์ด๋ฉด 0kWh ๋ฅผ ์ฃผ์ง ์๋๋คใ๋ ๊ท์น์ด\n * ์ปค๋์ `attributeEnergy` ์ ์ด๋ฏธ ์๋ค. ์ฌ๊ธฐ์ ๋ค์ ์ฐ๋ฉด ๋ ๋ฒ์ด ๋๊ณ , ๊ทธ๋๋ถํฐ ๋ ํ๋ฉด์ด ๋ค๋ฅธ ํฉ์\n * ๋งํ๋ค. ์ด ํจ์๊ฐ ํ๋ ์ผ์ **์ฌ๋ฃ๋ฅผ ๋ชจ์ ๋๊ธฐ๊ณ ๋ต์ ์๋ฆฌ๋ณ๋ก ๋ฌถ๋ ๊ฒ**๋ฟ์ด๋ค.\n *\n * โโ ๊ฐ์ค์น๋ ๊ฐ๋์๊ฐ์ด๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ๊ฒฉ(kW)์ผ๋ก ๋๋์ง ์๋๋ค: ์๋ฎฌ ํธ์์ ์ด๋ถํ๊ฐ ์ ๊ฒฉ์ ํฉ์์ ํ์๋๋ฏ๋ก ๊ทธ ์ด๋์ ๋ค์ ์ ๊ฒฉ์ผ๋ก\n * ๋๋๋ฉด ๋ฃ์ ๊ฐ์ด ๊ทธ๋๋ก ๋์จ๋ค(์ ์ ๋ณด 0์ ๋์ด๋ฐ๋ณต). ๊ฐ๋์๊ฐ์ **์ ๋์ด ๊ด์ธกํ ์ฌ์ค**์ด๋ค.\n *\n * ์๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋ ์์์ `unknown` ์ผ๋ก ๋ชจ์ธ๋ค โ ๋นผ๋ฉด ํฉ์ด ์ค๊ณ , ์๋ฌด ์๋ฆฌ์ ๋ฃ์ผ๋ฉด ๊ฑฐ์ง์ด ๋๋ค.\n */\nfunction feederShares(\n kWh: number | undefined,\n utilization: { resourceId: string; busyMs: number }[],\n resourceFeeder?: Record<string, string>\n): Partial<NonNullable<KpiResult['energy']>> {\n /* ์ ์ธ์ด ์์ผ๋ฉด ๋ถํดํ์ง ์๋๋ค โ ์๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋ ์ฑ ๋๋ ์ซ์๋ ์๋ฌด ๊ฒ์ ๋ชซ๋ ์๋๋ค. */\n if (!resourceFeeder || !Object.keys(resourceFeeder).length) return {}\n if (kWh === undefined || !(kWh > 0)) return {}\n\n /*\n * โโ ํ์ด **๋ฌด์์ ๋ฎ๋์ง ์ฌ์ค๋๋ก** ๋งํ๋ค (2026-08-17) โโโโโโโโโโโโโโโโโโโโ\n *\n * ์ฒ์์๋ ใ๊ทธ ์ฐฝ์ ๋์๊ฐ ์์ใ๋ง ๋ฎ๋๋ค๊ณ ๋๊ฒผ๋ค. ๊ทธ๋ฌ์ ๋์๊ฐ ์์์ด ํ๋์ธ ์ฐฝ์์ ์ปค๋์ด\n * ๊ทธ๊ฒ์ **`measured`(์ ์ฉ ๊ณ๋)** ๋ก ํ์ ํ๋ค โ ์ปค๋์ ๊ท์น์ ์ณ๋ค(ใ๋ฎ๋ ์๋น์ฒ๊ฐ ํ๋๋ฉด ๊ทธ\n * ๊ณ๋๊ธฐ๋ ๊ทธ๊ฒ๋ง ์ฐ๋ค๋ ์ ์ธ์ด๋คใ). ํ๋ฆฐ ๊ฒ์ ๋ด ์ ์ธ์ด์๋ค: ํ์ฅ ๊ณ๋๊ธฐ๋ ๋์๊ฐ ๊ฒ๋ง ์ฌ์ง ์๋๋ค.\n *\n * ๊ทธ๋์ **์ ์ธ๋ ๋ถํ ์ ๋ถ**๋ฅผ ๋ฎ๋๋ค๊ณ ๋งํ๋ค(`resourceFeeder` ์ ํค๊ฐ ๊ณง ๊ทธ ์ ์ธ์ด๋ค).\n * ๊ทธ๋ฌ๋ฉด ๊ทธ ์ฐฝ์ ๋์ง ์์ ์ค๋น๋ ๋ชซ 0 ์ผ๋ก **๋ฐฐ๋ถ์์ ๋น ์ง๊ณ ๊ทธ ์๊ฐ ๋ณด๊ณ ๋๋ค** โ 0kWh ๋ฅผ ์ฃผ๋\n * ๋์ ใ์ด ์ค๋น๋ ์ด ์ฐฝ์ ๊ฐ๋ ๊ธฐ๋ก์ด ์๋คใ๋ฅผ ๋งํ๋ ์ชฝ์ด๋ค.\n */\n /*\n * ๋ฎ๋ ๋์์ **์ ์ธ๋ ๋ถํ โช ๊ทธ ์ฐฝ์ ๋์๊ฐ ์์**์ด๋ค.\n *\n * ์ ์ธ๋ง ์ฐ๋ฉด, ๋์๋๋ฐ ์ ๊ธฐ ๊ณํต์ ์ ์ธ๋์ง ์์ ์ค๋น์ ๋ชซ์ด ๋๋จธ์ง ์ค๋น์ ์นํ๋ค โ ๊ทธ ์ค๋น๊ฐ\n * ์ ์ด ์ ๊ธฐ๋ฅผ ์ด ๊ฒ์ผ๋ก ๋ง๋ ๋ค. ๋์๊ฐ ๊ฒ๋ง ์ฐ๋ฉด, ์ ์ธ๋์ง๋ง ์ฐ ์ค๋น๊ฐ ์ฌ๋ผ์ ธ ใ์ด ์ฐฝ์ ์ ๋์๋คใ๋ฅผ\n * ๋งํ ์ ์๋ค. ๋์ ํฉํด์ผ ๋ ์ฌ์ค์ด ๋ค ๋จ๋๋ค(์๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋ ๋ชซ์ `unknown` ์ผ๋ก ๋ชจ์ธ๋ค).\n */\n const busyOf = new Map(utilization.map(u => [u.resourceId, u.busyMs]))\n const ids = new Set<string>([...Object.keys(resourceFeeder), ...busyOf.keys()])\n const consumers = [...ids].map(id => ({ id, weight: busyOf.get(id) ?? 0 }))\n if (!consumers.length) return {}\n\n const r = attributeEnergy({\n pools: [{ meterId: 'site', kWh, consumerIds: consumers.map(c => c.id) }],\n consumers,\n weightKind: 'runtimeMs'\n })\n\n const byKey = new Map<string, { kWh: number; weightShare: number; apportioned: boolean }>()\n for (const sh of r.shares) {\n /* ์๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋ฉด `unknown` โ ๊ทธ ๋ชซ์ด ์๋ค๋ ์ฌ์ค์ ๋จ๊ธฐ๊ณ , ์ด๋์ ๊ฒ์ธ์ง๋ ์ง์ด๋ด์ง ์๋๋ค. */\n const key = resourceFeeder[sh.consumerId] ?? 'unknown'\n const cur = byKey.get(key) ?? { kWh: 0, weightShare: 0, apportioned: false }\n cur.kWh += sh.kWh\n cur.weightShare += sh.weightShare ?? 0\n /* **๊ทผ๊ฑฐ๋ ์ปค๋์ด ์ ํ๋ค.** ์ฌ๊ธฐ์ ๋์ธ์ฐ์ผ๋ฉด ์ปค๋์ด ใ์๋คใ๊ณ ํ ๊ฒ์ ใ๋๋ด๋คใ๊ณ ๋ฐ๊ฟ ๋งํ๊ฑฐ๋\n ๊ทธ ๋ฐ๋๊ฐ ๋๋ค. ์์ด๋ฉด ์ฝํ ์ชฝ(๋ฐฐ๋ถ)์ผ๋ก ์ ๋๋ค โ ๊ฐํ ์ฃผ์ฅ์ ์ฌ๋ ค ์ก์ง ์๋๋ค. */\n if (sh.basis === 'apportioned') cur.apportioned = true\n byKey.set(key, cur)\n }\n\n const byFeeder = [...byKey.entries()]\n .map(([key, v]) => ({\n key,\n kWh: v.kWh,\n basis: (v.apportioned ? 'apportioned' : 'measured') as 'apportioned' | 'measured',\n weightKind: 'runtimeMs' as const,\n weightShare: v.weightShare\n }))\n .sort((a, b) => b.kWh - a.kWh)\n\n const un = r.unattributed.reduce((sum, u) => sum + u.kWh, 0)\n return {\n ...(byFeeder.length ? { byFeeder } : {}),\n ...(un > 0 ? { unattributedKWh: un, unattributedReason: r.unattributed[0]?.reason } : {}),\n ...(r.excluded.length ? { excludedResources: r.excluded.length } : {})\n }\n}\n\n/**\n * ๋ถ๊ธฐ๋ณ ์ ๋ ฅ๋์ **๊ณ๋์ผ๋ก** ์ฝ๋๋ค โ ๊ณ๋์ด ์์ผ๋ฉด ๋ฐฐ๋ถํ์ง ์๋๋ค.\n *\n * โโ ์ ํ์ํ๋ (2026-08-18) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ค ๊ฒ์ดํธ์จ์ด๋ ๋ถ๊ธฐ๋ง๋ค ๊ณ๋๊ธฐ๋ฅผ ๋ณด๋ธ๋ค. ๊ทธ๋ฐ๋ฐ ํ๋ฉด์ ใ๋๋์ง ๋ชปํจใ์ผ๋ก ๋ตํ๊ณ ์์๋ค โ ์ฌ๊ธฐ์\n * ๊ฐ๋์๊ฐ ๋ฐฐ๋ถ ๊ฒฝ๋ก๋ง ์์๊ธฐ ๋๋ฌธ์ด๋ค. ๊ณ๋์ด ์๋๋ฐ ๋ฐฐ๋ถ์ผ๋ก ๋งํ๋ฉด **๊ทผ๊ฑฐ๋ฅผ ์ค์ ๋ณด๋ค ์ฝํ๊ฒ** ๋ณด๊ณ ํ๋\n * ๊ฒ์ด๊ณ , ๊ทธ ์์ ์ธ์ด SEU ํ๋จ์ด ๋ฌด๊ฑฐ์ด ๊ฐ์ ๋์น๋ค. ๋ฏธ๋ฌ ํธ์์๋ ์ค๋น ๊ฐ๋ ๊ธฐ๋ก์กฐ์ฐจ ์์ด์\n * (์์ฒ์ด ๊ณ๋๋ง ์ค๋ค) ๊ทธ ๊ฒฝ๋ก๋ก๋ ๋ถ๊ธฐ๋ณ ๊ฐ์ด ์์ํ ๋์ค์ง ์์๋ค.\n *\n * ๊ฐ์ ์ถ์ฒ๋ ์ปค๋์ด ๊ตฌ๊ฐ ๋ง๊ฐ ์ฌ์ค์ ์ค์ด ์ฃผ๋ **์ง์ ๋ณ ๋ชซ**์ด๋ค(์ ์ฐ์ ๋บ์
). ํ๋ณธ์ ์ง์ ์ฝ์ง ์๋\n * ์ด์ ๋ ์กฐํ ์ํ์ด๋ค โ ๊ณ์ธก์ ์ด๋น ์ฌ๋ฌ ๊ฑด์ด๋ผ ํ๋ณธ์ผ๋ก๋ ์ฐฝ์ ์ฑ์ฐ๊ธฐ ์ ์ ์ํ์ ๊ฑธ๋ฆฐ๋ค.\n *\n * ๋๋จธ์ง(๋ฟ๋ฆฌ โ ๋ถ๊ธฐ ํฉ)๋ **๋ฒ๋ฆฌ์ง๋ ์น์ง๋ ์๋๋ค**: ์์ ์ง๊ฒฐ ๋ถํยท์์คยท๊ณ๋๋์ง ์์ ํ๋ก๊ฐ ๊ทธ\n * ์ฐจ์ด์ด๋ฏ๋ก, ์ด๋ ๋ถ๊ธฐ์ ์น์ผ๋ฉด ๊ทธ ๋ถ๊ธฐ๊ฐ ์ฐ์ง ์์ ์ ๊ธฐ๋ฅผ ์ด ๊ฒ์ผ๋ก ๋ง๋ ๋ค. ์ปค๋์ `remainder` ํ๋ก\n * ๋๊ฒจ ใํ์ ๊ณ๋์ด ๋ฎ์ง ์๋๋คใ๋ก ๋จ๊ธด๋ค.\n *\n * ๋ถ๊ธฐ ๊ณ๋ ํฉ์ด ๋ฟ๋ฆฌ๋ณด๋ค ํฌ๋ฉด(ํ๊ณ๊ฐ ๋ค๋ฅธ ๋ ๊ณ๋๊ธฐ) **๊ทธ ์ฌ์ค์ ๋ธ๋ค** โ ๊ฐ์ ๊น์ ๋ง์ถ๋ฉด ๊ณ๋์\n * ์ฐ๋ฆฌ๊ฐ ๊ณ ์ณ ์ฐ๋ ๊ฒ์ด๋ค.\n */\n/**\n * ์ฐฝ์ **๋ฐ์ ๋** โ ์ปค๋์ด ๋ง๊ฐํ ๊ธฐ๊ฐ ์ฌ์ค์ ํฉํ๋ค.\n *\n * โโ ์ ํฉ์ด ์ ๋ถ์ธ๊ฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๊ธฐ๊ฐ ๋ฐ์ ๋์ ์ปค๋์ด ์ด๋ฏธ ํ์ ํ ์ฌ์ค์ด๋ค(์ ์ฐ์ ์ข
๋ฅ๋ง๋ค ๋ค๋ฅธ ๊ท์น์ผ๋ก ์ป๋๋ค). ์ฌ๊ธฐ์ ๋ค์\n * ๊ณ์ฐํ๋ฉด ๊ท์น์ด ๋ ๋ฒ์ด ๋๊ณ , ๊ทธ๋๋ถํฐ ๋ ํ๋ฉด์ด ๋ค๋ฅธ ๋ฐ์ ๋์ ๋งํ๋ค. ์ด ํจ์๊ฐ ํ๋ ์ผ์\n * **์ฐฝ์ ๋ ๊ฒ์ ๊ณ ๋ฅด๊ณ , ์ค๋น๋ณ๋ก ๋ฌถ๊ณ , ๊ทผ๊ฑฐ๊ฐ ์ผ๋ง๋ ๋ฎ์๋์ง ์ธ๋ ๊ฒ**์ด๋ค.\n *\n * โโ ๊ฑธ์น ๊ธฐ๊ฐ์ ์ธ์ง ์๋๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๊ตฌ๊ฐ ๋ง๊ฐ๊ณผ ๊ฐ์ ๊ท์น์ด๋ค. ํ๋ฃจ์ ์ ๋ฐ์ด ์ฐฝ์ ๋ค์๋ค๊ณ ์ ๋ฐ์ ์ธ๋ฉด ๊ทธ๊ฒ์ ๊ด์ธก์ด ์๋๋ผ ์ฐ๋ฆฌ๊ฐ ๋๋\n * ๊ฐ์ด๊ณ , ํฉ์ด ์ฐฝ์ ๋๋๋ค.\n *\n * โโ ๋ ๋ฎ์ธ ๊ธฐ๊ฐ์ ์ผ๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๊ธฐ๊ฐ์ ๋์ด ์์ ์ธ๋ฐ ๋ง์ง๋ง ํ๋ณธ์ด ์ ๋
์ด์์ผ๋ฉด ๊ทธ ์ฌ์ด๋ ์ฌ์ง ์์ ๊ฒ์ด๋ค. ๊ทธ ์๋ฅผ ํจ๊ป ๋ด์ผ ํ๋ฉด์ด\n * ใ์ด ํฉ์ ์ด๋งํผ ๋ ์ฐ ๊ฒใ์ด๋ผ๊ณ ๋งํ ์ ์๋ค. ์ผ๋ง๋ ์ด๊ธ๋๋ฉด ๋ฌธ์ ์ธ์ง๋ ํ์ฅ์ด ์ ํ๋ค.\n */\nfunction generatedOfPeriods(\n periods: readonly {\n equipmentId: string\n kWh: number\n startMs: number\n endMs: number\n observedFromMs: number\n observedToMs: number\n }[],\n range: { startMs: number; endMs: number },\n /** ์ด์ฉ๋ฅ ์ ๋ถ๋ชจ โ ์์ผ๋ฉด ์ด์ฉ๋ฅ ์ ๋ด์ง ์๋๋ค(0 ์ด๋ ์ง์์ ๋ง๋ค์ง ์๋๋ค). */\n rated?: { kW: number; basis: 'ac' | 'dc'; from: 'equipment' | 'location' },\n /** ๊ธฐ๊ฐ๋ง๋ค ์ ์ฉํ ๋จ๊ฐ โ ๊ธฐ๊ฐ์ ๋ฎ๋ ๊ฒ์ ์ด๋ค. ์์ผ๋ฉด ๊ธ์ก์ ๋ง๋ค์ง ์๋๋ค. */\n prices?: readonly { startMs: number; endMs: number; unitPrice: number; currency: string }[]\n): Partial<NonNullable<KpiResult['energy']>> {\n const inside = periods.filter(g => g.startMs >= range.startMs && g.endMs <= range.endMs)\n\n /*\n * โโ **๊ฑธ์น ๊ธฐ๊ฐ์ ์กฐ์ฉํ ๋ฒ๋ฆฌ์ง ์๋๋ค** (2026-08-30) โโโโโโโโโโโโโโโโโโโโโโ\n *\n * ๋ํ๋ ๊ฒ์ ์ฐฝ์ **์จ์ ํ ๋ค์ด์จ ๊ธฐ๊ฐ**๋ฟ์ด๋ค. ๊ทธ๊ฒ์ด ๋ง๋ ์
์ด๋ค โ ๊ฑธ์น ๊ธฐ๊ฐ์ ๋ํ๋ฉด ๋ค๋ฅธ ๋ ์\n * ๊ฐ์ด ์ด ์ฐฝ์ ๊ฐ์ธ ์ฒํ๋ค.\n *\n * ๊ทธ๋ฐ๋ฐ ๋ฒ๋ฆฐ ๊ฒ์ ๋งํ์ง ์์๋ค. ํ๋ฃจ ๋จ์ ๊ธฐ๊ฐ์ ใ์ง๊ธ๋ถํฐ 24์๊ฐ ์ ใ ์ฐฝ์ ์จ์ ํ ๋ค์ด์ค๋ ์ผ์ด\n * ๊ฑฐ์ ์๋ค(์ฐฝ์ด ํ๋ฎ์์ ์์ํ๋ฏ๋ก). ๊ทธ๋์ ์ด์ ๋ฐ์ ๋์ด ์ ๋์ ๋ฉ์ฉกํ ์๋๋ฐ ํ๋ฉด์ด ๋น์๊ณ ,\n * ์ฌ์ฉ์๋ ๊ทธ๊ฒ์ **ใ๋ฐ์ ๋์ด ์๋คใ**๋ก ์ฝ์๋ค. ์ค์ธก์ผ๋ก ๊ทธ ์ผ์ด ๋ฌ๋ค.\n *\n * ์ด์ ๊ฑธ์น ๊ฒ์ ์ธ์ด ํจ๊ป ๋ธ๋ค. ํ๋ฉด์ด ใ์ด ์ฐฝ์ ๋ค ๋ค์ด์ค์ง ์์ ๊ธฐ๊ฐ์ด ์๋คใ๋ฅผ ๋งํ ์ ์๋ค.\n */\n const straddling = periods.filter(\n g => !(g.startMs >= range.startMs && g.endMs <= range.endMs) && g.endMs > range.startMs && g.startMs < range.endMs\n )\n const notCounted = straddling.length\n ? {\n periods: straddling.length,\n kWh: straddling.reduce((a, g) => a + g.kWh, 0),\n earliestStart: new Date(Math.min(...straddling.map(g => g.startMs))).toISOString(),\n latestEnd: new Date(Math.max(...straddling.map(g => g.endMs))).toISOString()\n }\n : undefined\n\n if (!inside.length) {\n /* ์จ์ ํ ๋ค์ด์จ ๊ฒ์ด ์๋ค โ ๊ทธ๋๋ ๊ฑธ์น ๊ฒ์ด ์์ผ๋ฉด ๊ทธ ์ฌ์ค์ ๋ธ๋ค(๋น ๊ฐ๊ณผ ใ์์ใ์ ๋ค๋ฅด๋ค). */\n return notCounted ? { generated: { kWh: 0, counted: 0, partial: 0, byEquipment: [], notCounted } } : {}\n }\n\n const byEquipment = new Map<string, number>()\n let partial = 0\n for (const g of inside) {\n byEquipment.set(g.equipmentId, (byEquipment.get(g.equipmentId) ?? 0) + g.kWh)\n const coveredFrom = Number.isFinite(g.observedFromMs) ? g.observedFromMs <= g.startMs : false\n const coveredTo = Number.isFinite(g.observedToMs) ? g.observedToMs >= g.endMs : false\n if (!coveredFrom || !coveredTo) partial++\n }\n\n const kWh = inside.reduce((a, g) => a + g.kWh, 0)\n /*\n * ์ด์ฉ๋ฅ ์ ๋ถ๋ชจ๋ **์ผ ๊ธฐ๊ฐ๋ค์ ๊ธธ์ด**๋ค. ์ฐฝ ๊ธธ์ด๋ก ๋๋๋ฉด, ํ๋ฃจ์น ํ๋๋ง ์ผ 24์๊ฐ ์ฐฝ์์ ๊ทธ ํ๋ฃจ๊ฐ\n * ์ฐฝ ์ ์ฒด์ ๊ฑธ์ณ ์์๋ ๊ฒ์ฒ๋ผ ์์์ง๋ค.\n */\n const hours = inside.reduce((a, g) => a + (g.endMs - g.startMs) / 3_600_000, 0)\n const capacityFactor =\n rated && rated.kW > 0 && hours > 0\n ? { value: kWh / (rated.kW * hours), ratedKW: rated.kW, basis: rated.basis, from: rated.from, hours }\n : undefined\n\n /*\n * ๋ธ ๊ฒ์ ๊ฐ โ ๊ธฐ๊ฐ๋ง๋ค **๊ทธ ๊ธฐ๊ฐ์ ๋ฎ๋ ๋จ๊ฐ**๋ก ๋งค๊ธด๋ค. ๊ฑธ์น ๋จ๊ฐ๋ ์ฐ์ง ์๋๋ค: ํ๋ฃจ ๋จ๊ฐ๋ก\n * ์ดํ์น๋ฅผ ๋งค๊ธฐ๋ฉด ๊ทธ ์ ๋ฐ์ ๋ค๋ฅธ ๋ ์ ๊ฐ์ด ๋๋ค.\n *\n * ๋ชจ๋ ๊ธฐ๊ฐ์ ๋จ๊ฐ๊ฐ ์์ ๋๋ง ๊ธ์ก์ ๋ง๋ ๋ค. ์ผ๋ถ๋ง ๋งค๊ธฐ๊ณ ๋ํ๋ฉด ๊ทธ ํฉ์ด ์ฐฝ ์ ์ฒด์ ๊ฐ์ธ ์ฒํ๋ค.\n */\n let amount = 0\n let priced = 0\n let currency: string | undefined\n for (const g of inside) {\n const p = (prices ?? []).find(x => x.startMs <= g.startMs && x.endMs >= g.endMs)\n if (!p) continue\n amount += g.kWh * p.unitPrice\n priced++\n currency = currency ?? p.currency\n }\n const unpriced = inside.length - priced\n const revenue = priced > 0 && unpriced === 0 && currency ? { amount, currency, priced, unpriced } : undefined\n\n return {\n generated: {\n kWh,\n counted: inside.length,\n partial,\n byEquipment: [...byEquipment.entries()]\n .map(([id, kWh]) => ({ id, kWh }))\n .sort((a, b) => b.kWh - a.kWh),\n ...(capacityFactor ? { capacityFactor } : {}),\n ...(revenue ? { revenue } : {}),\n /* ์ด ์ฐฝ์ ๋ค ๋ค์ด์ค์ง ์์ ๋ํ์ง ๋ชปํ ๊ธฐ๊ฐ โ ์์ผ๋ฉด ํ๋ฉด์ด ๊ทธ๊ฒ์ ๋งํ๋ค. */\n ...(notCounted ? { notCounted } : {})\n }\n }\n}\n\n/**\n * ๋ฐ์์ ๋ง๊ฐ๋์ด ์จ ์ฌ์ฉ ๊ตฌ๊ฐ์ ํฉํ๋ค โ **๊ตฌ๊ฐ ๋ง๊ฐ๊ณผ ๋ํ์ง ์๋๋ค.**\n *\n * ๋ ํ๊ณ๊ฐ ๊ฐ์ ์ ๊ธฐ๋ฅผ ๋งํ๋ค. ๋ํ๋ฉด ๋ ๋ฒ ์ธ๊ณ , ๋ ๋ค ์๋ ํ์ฅ์์๋ ๊ณ๋ ์ชฝ์ด ๊ฐํ ๊ทผ๊ฑฐ์ด๋ฏ๋ก\n * ๊ทธ์ชฝ์ ์ด๋ค. ์ฌ๊ธฐ์๋ ์ด์ชฝ ๋ชซ๋ง ๊ณ์ฐํ๊ณ , ๋ฌด์์ ์ธ์ง๋ ๋ถ๋ฅด๋ ์ชฝ์ด ์ ํ๋ค.\n *\n * ๋จ๊ฐ๋ **๋ชจ๋ ๊ตฌ๊ฐ์ด ์ค์์ ๋๋ง** ์๊ธ์ ๋ง๋ ๋ค. ์ผ๋ถ๋ง ์ค์๋๋ฐ ์๋ ๊ฒ๋ง ๋ํ๋ฉด ๊ทธ ํฉ์ด ์ฐฝ์\n * ์๊ธ์ธ ์ฒํ๋ค โ ๋ชป ๋งค๊ธด ๊ตฌ๊ฐ ์๋ฅผ ํจ๊ป ๋ธ๋ค.\n */\nfunction usageOfPeriods(\n periods: readonly { meterId: string; kWh: number; startMs: number; endMs: number; unitPrice: number; currency?: string; basis: string }[],\n range: { startMs: number; endMs: number }\n): NonNullable<KpiResult['energy']>['usage'] | undefined {\n const inside = periods.filter(u => u.startMs >= range.startMs && u.endMs <= range.endMs)\n if (!inside.length) return undefined\n\n const byBasis = new Map<string, number>()\n let kWh = 0\n let charge = 0\n let unpriced = 0\n let currency: string | undefined\n for (const u of inside) {\n kWh += u.kWh\n byBasis.set(u.basis, (byBasis.get(u.basis) ?? 0) + 1)\n if (Number.isFinite(u.unitPrice)) {\n charge += u.kWh * u.unitPrice\n if (!currency) currency = u.currency\n } else unpriced++\n }\n\n return {\n kWh,\n counted: inside.length,\n ...(unpriced === 0 && currency ? { charge, currency } : {}),\n unpriced,\n byBasis: [...byBasis.entries()].map(([basis, counted]) => ({ basis, counted })).sort((a, b) => b.counted - a.counted)\n }\n}\n\n/**\n * **์๊ธ์ ์ฉ์ ๋ ฅ์ ๊ณ ๋ฅธ๋ค โ ์ฒญ๊ตฌ์๊ฐ ๋จผ์ ๋ค.**\n *\n * ์์์ ๋ป์ด ์๋ค. ์ฒญ๊ตฌ์๋ ๊ทธ ๊ธฐ๊ฐ์ ์ค์ ๋ก ๋งค๊ฒจ์ง ๊ฐ์ด๊ณ , ์ ์ธ์ ์ฌ๋์ด ์ฎ๊ฒจ ์ ์ ๊ฐ์ด๋ค.\n * ๊ทธ ๊ฐ์ด ๋งค๋ฌ ๋ฐ๋๋ฏ๋ก ์ฎ๊ฒจ ์ ์ ๊ฒ์ ๊ณง ๋ก๋๋ค.\n */\nfunction billingDemandOf(\n billsInWindow: readonly { endMs: number; billingDemandKW: number }[],\n tariffBasis: { billingDemandKW?: number } | undefined,\n lastBill: { billingDemandKW?: number } | undefined,\n declaredKW: number | undefined,\n /** ์ด ์ฐฝ์์ ๊ด์ธกํ ์ต๊ณ ์์์ ๊ทธ ๊ฐ์ด ์ธ์ ๊น์ง์ ๊ฒ์ธ์ง โ ์ฌ์ฉ ๊ตฌ๊ฐ์ `maxKW` ์์ ์จ๋ค. */\n observedPeak?: { kW: number; toMs: number }\n): NonNullable<KpiResult['energy']>['billingDemand'] | undefined {\n const declared = Number.isFinite(Number(declaredKW)) ? Number(declaredKW) : undefined\n const withValue = billsInWindow.filter(b => Number.isFinite(b.billingDemandKW))\n const fromBill = withValue.length ? withValue.reduce((a, x) => (x.endMs > a.endMs ? x : a)).billingDemandKW : undefined\n const carried = Number.isFinite(Number(lastBill?.billingDemandKW)) ? Number(lastBill?.billingDemandKW) : undefined\n /* ์ด ์ฃผ๊ธฐ์ ์ ์ฉ๋๋ ๊ธฐ์ค์ด ๊ฐ์ฅ ๋จผ์ ๋ค โ ์ฒญ๊ตฌ์๋ ๋๋ ๊ธฐ๊ฐ์ ๊ฒ์ด๋ค. */\n const fromBasis = Number.isFinite(Number(tariffBasis?.billingDemandKW)) ? Number(tariffBasis?.billingDemandKW) : undefined\n\n const picked =\n fromBasis !== undefined\n ? { kW: fromBasis, from: 'tariff-basis' as const }\n : fromBill !== undefined\n ? { kW: fromBill, from: 'bill' as const }\n : carried !== undefined\n ? { kW: carried, from: 'carried-forward' as const }\n : declared !== undefined\n ? { kW: declared, from: 'declaration' as const }\n : undefined\n if (!picked) return undefined\n\n /* ์ ์ธ์ด ์๋๋ฐ ์ฒญ๊ตฌ์์ ๋ค๋ฅด๋ฉด ๊ทธ ์ฌ์ค์ ๋ธ๋ค โ ๋ก์ ์ ์ธ์ ์ค์ค๋ก ๋งํด์ผ ํ๋ค. */\n const stale = picked.from !== 'declaration' && declared !== undefined && declared !== picked.kW\n const exceeded =\n observedPeak && observedPeak.kW > picked.kW\n ? {\n peakKW: observedPeak.kW,\n overKW: observedPeak.kW - picked.kW,\n observedTo: new Date(observedPeak.toMs).toISOString()\n }\n : undefined\n\n return {\n ...picked,\n ...(declared !== undefined ? { declaredKW: declared } : {}),\n ...(stale ? { stale: true } : {}),\n ...(exceeded ? { exceeded } : {})\n }\n}\n\n/**\n * ์ฐฝ์ ์จ์ ํ ๋ ์ฒญ๊ตฌ์ ํ๋ โ ๊ฐ์ฅ ๋ฆ๊ฒ ๋๋ ๊ฒ.\n *\n * **์ฐฝ์ด ์ฒญ๊ตฌ ์ฃผ๊ธฐ์ ๊ฐ์ ๋๋ง ๊ฒฌ์ค๋ค.** ํ ๋ฌ ์ฒญ๊ตฌ์๋ฅผ ํ๋ฃจ ์ฐฝ์ ๊ฐ๊ณผ ๋นผ๋ฉด ๊ทธ ์ฐจ์ด๋ ์๋ฌด๊ฒ๋ ๋ปํ์ง\n * ์๋๋ค. ๊ทธ๋์ ๊ฐ์์ง๋ฅผ ๊ฐ๊ณผ ํจ๊ป ๋ธ๋ค.\n */\nfunction billOfWindow(\n bills: readonly {\n from: string\n to: string\n startMs: number\n endMs: number\n total: number\n energyCharge: number\n demandCharge: number\n currency?: string\n billingDemandKW: number\n }[],\n range: { startMs: number; endMs: number },\n ours?: { total?: number; demandCharge?: number; energyCharge?: number }\n): NonNullable<KpiResult['energy']>['bill'] | undefined {\n const inside = bills.filter(b => b.startMs >= range.startMs && b.endMs <= range.endMs)\n if (!inside.length) return undefined\n const b = inside.reduce((a, x) => (x.endMs > a.endMs ? x : a))\n const matchesWindow = b.startMs === range.startMs && b.endMs === range.endMs\n /* ์์ชฝ์ ์๋ ํญ๋ชฉ๋ง ๊ฒฌ์ค๋ค โ ํ์ชฝ์ด ์๋ ๊ฒ์ 0 ์ผ๋ก ๋๋ฉด ๊ทธ ์ฐจ์ด๊ฐ ํต์งธ๋ก ์ด๊ธ๋จ์ฒ๋ผ ๋ณด์ธ๋ค. */\n const gap = (mine: unknown, billed: number): number | undefined =>\n Number.isFinite(Number(mine)) && Number.isFinite(billed) ? Number(mine) - billed : undefined\n const diff = matchesWindow\n ? {\n ...(gap(ours?.total, b.total) !== undefined ? { total: gap(ours?.total, b.total) as number } : {}),\n ...(gap(ours?.demandCharge, b.demandCharge) !== undefined\n ? { demandCharge: gap(ours?.demandCharge, b.demandCharge) as number }\n : {}),\n ...(gap(ours?.energyCharge, b.energyCharge) !== undefined\n ? { energyCharge: gap(ours?.energyCharge, b.energyCharge) as number }\n : {})\n }\n : {}\n return {\n from: b.from,\n to: b.to,\n ...(Number.isFinite(b.total) ? { total: b.total } : {}),\n ...(Number.isFinite(b.energyCharge) ? { energyCharge: b.energyCharge } : {}),\n ...(Number.isFinite(b.demandCharge) ? { demandCharge: b.demandCharge } : {}),\n ...(b.currency ? { currency: b.currency } : {}),\n ...(Number.isFinite(b.billingDemandKW) ? { billingDemandKW: b.billingDemandKW } : {}),\n matchesWindow,\n ...(Object.keys(diff).length ? { diff } : {})\n }\n}\n\nfunction measuredFeeders(\n windows: readonly {\n startMs: number\n endMs: number\n maxKW?: number\n points: { id: string; kWh: number; root: boolean }[]\n pointsAtPeak?: { id: string; kW: number }[]\n }[],\n range: { startMs: number; endMs: number },\n totalKWh: number | undefined,\n meterFeeder?: Record<string, string>\n): Partial<NonNullable<KpiResult['energy']>> | undefined {\n if (!meterFeeder || !Object.keys(meterFeeder).length) return undefined\n if (totalKWh === undefined || !(totalKWh > 0)) return undefined\n\n /* ์ฐฝ์ ์จ์ ํ ๋ ๊ตฌ๊ฐ๋ง โ ์ ์ฒด ์ ๋ ฅ๋๊ณผ ๊ฐ์ ๊ท์น์ด์ด์ผ ๋ชซ๊ณผ ํฉ์ด ๊ฐ์ ์ฐฝ์ ๋งํ๋ค. */\n const byFeederKWh = new Map<string, number>()\n let sawPoints = false\n for (const w of windows) {\n if (!(w.startMs >= range.startMs && w.endMs <= range.endMs)) continue\n for (const p of w.points ?? []) {\n const feeder = meterFeeder[p.id]\n if (!feeder) continue // ๋ฟ๋ฆฌ ๊ณ๋๊ธฐยท๋ชจ๋ฅด๋ ์ง์ โ ๋ถ๊ธฐ์ ๋ชซ์ด ์๋๋ค\n sawPoints = true\n byFeederKWh.set(feeder, (byFeederKWh.get(feeder) ?? 0) + p.kWh)\n }\n }\n if (!sawPoints) return undefined // ๊ณ๋์ด ์์ผ๋ฉด ์ด ๊ฒฝ๋ก๋ฅผ ์ฐ์ง ์๋๋ค(๋ฐฐ๋ถ์ผ๋ก ๋์๊ฐ๋ค)\n\n const feeders = [...byFeederKWh.entries()].filter(([, kWh]) => kWh > 0)\n if (!feeders.length) return undefined\n const submetered = feeders.reduce((sum, [, kWh]) => sum + kWh, 0)\n const remainder = totalKWh - submetered\n\n const r = attributeEnergy({\n pools: [\n ...feeders.map(([feeder, kWh]) => ({ meterId: `${feeder}:meter`, kWh, consumerIds: [feeder] })),\n ...(remainder > 0 ? [{ meterId: 'root:remainder', kWh: remainder, consumerIds: [], remainder: true }] : [])\n ],\n consumers: feeders.map(([feeder]) => ({ id: feeder }))\n })\n\n /*\n * โโ ํผํฌ๋ฅผ ๋ง๋ ๋ถ๊ธฐ (2026-08-18) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n *\n * ์๊ธ์ kW ๋ก ๋งค๊ฒจ์ง๋ฏ๋ก ใ์ด๋ ๋ถ๊ธฐ๋ฅผ ๊น์์ผ ํผํฌ๊ฐ ๋ด๋ ค๊ฐ๋ใ๊ฐ ์ค๋ฌด์ ์ง๋ฌธ์ด๋ค. ๊ทธ ๋ต์ **ํผํฌ๊ฐ\n * ์ฐํ ๊ตฌ๊ฐ์ ๊ทธ ์๊ฐ** ๊ฐ์ด๊ณ , ์ฐฝ ์์ ์ฌ๋ฌ ๊ตฌ๊ฐ์ ๋ํ๊ฑฐ๋ ํ๊ท ํ๋ฉด ๋ป์ด ์ฌ๋ผ์ง๋ค(๋ค๋ฅธ ์๊ฐ์ ๊ฐ์\n * ์๋ ๊ฒ์ด๋ค). ๊ทธ๋์ **์ต๋์์๋ฅผ ๋ธ ๊ตฌ๊ฐ ํ๋**๋ง ๊ณจ๋ผ ๊ทธ ์๊ฐ์ ์ง์ ๊ฐ์ ์ด๋ค.\n */\n const peakWindow = windows\n .filter(w => w.startMs >= range.startMs && w.endMs <= range.endMs && Number.isFinite(Number(w.maxKW)))\n .reduce<(typeof windows)[number] | undefined>((best, w) => (!best || Number(w.maxKW) > Number(best.maxKW) ? w : best), undefined)\n const peakOf = new Map<string, number>()\n for (const p of peakWindow?.pointsAtPeak ?? []) {\n const feeder = meterFeeder[p.id]\n if (!feeder) continue // ๋ฟ๋ฆฌ ๊ณ๋๊ธฐยท๋ชจ๋ฅด๋ ์ง์ โ ๋ถ๊ธฐ์ ๋ชซ์ด ์๋๋ค\n peakOf.set(feeder, (peakOf.get(feeder) ?? 0) + p.kW)\n }\n\n const byFeeder = r.shares\n .map(sh => ({\n key: sh.consumerId,\n kWh: sh.kWh,\n basis: sh.basis,\n weightKind: undefined,\n weightShare: undefined,\n /* ํผํฌ ์๊ฐ์ ๊ฐ์ด ์์ผ๋ฉด ๋ง๋ค์ง ์๋๋ค โ ๊ทธ ๊ตฌ๊ฐ์ ์ด ๋ถ๊ธฐ์ ํ๋ณธ์ด ์์๋ค๋ ๋ป์ด๋ค. */\n ...(peakOf.has(sh.consumerId) ? { peakKW: peakOf.get(sh.consumerId) } : {})\n }))\n .sort((a, b) => b.kWh - a.kWh) as NonNullable<KpiResult['energy']>['byFeeder']\n\n const un = r.unattributed.reduce((sum, u) => sum + u.kWh, 0)\n return {\n ...(byFeeder?.length ? { byFeeder } : {}),\n ...(un > 0 ? { unattributedKWh: un, unattributedReason: r.unattributed[0]?.reason } : {}),\n /* ๋ถ๊ธฐ ํฉ์ด ๋ฟ๋ฆฌ๋ฅผ ๋์๋ค โ ๋ ๊ณ๋๊ธฐ์ ํ๊ณ๊ฐ ๋ค๋ฅด๋ค๋ ์ฌ์ค์ด๋ค(๊น์ ๋ง์ถ์ง ์๋๋ค). */\n ...(remainder < 0 ? { submeterExcessKWh: -remainder } : {})\n }\n}\n\n/** ํด๋ ์ต์
โ ๊ด์ ์ถ๊ณผ, ๊ทธ ์ถ์ ๋ง๋ค๊ธฐ ์ํด ์ด๋ฒคํธ ๋ฐ์์ ์์ผ ํ๋ ์ง๋. */\n/*\n * โโ ๊ฐ์ ์ฌ์ค์ด ๋ ๋ฒ ์์ด๋ ํ ๋ฒ๋ง ์ผ๋ค (2026-08-30) โโโโโโโโโโโโโโโโโโโโโโ\n *\n * ๋ง๊ฐ๋ ๊ตฌ๊ฐ ์ฌ์ค์ ์ ์ฒด์ฑ์ด ๋ด์ฉ์ ์๋ค(์ปค๋ 0.7.81). ๊ทธ๋ฐ๋ฐ ์ ๋์ ์ด๋ฏธ ์ฌ๋ฌ ๋ฒ ์ ํ ๊ฒ์ด ์๋ค โ\n * ์ฐ๋ ์๋ฆฌ์์ ๋ง๊ธฐ ์ ์ ๋ค์ด๊ฐ ๊ฒ๋ค์ด๋ค(์ค์ธก: ์ด๋ ๋ ์ ๋ฐ์ ๋จ๊ฐ๊ฐ ์ธ ๋ฒ).\n *\n * ์ง๋ ๊ธฐ๋ก์ ์ง์ฐ์ง ์๋๋ค โ ์ ๋์ ์ผ์ด๋ ์ผ์ ๊ธฐ๋ก์ด๋ค. ๋์ **์ฝ์ ๋ ํ ๋ฒ๋ง ์ผ๋ค.**\n * ๊ทธ๋ฌ์ง ์์ผ๋ฉด ๊ทธ ๊ตฌ๊ฐ์ ์์ตยท์ฌ์ฉ๋์ด ๊ทธ ํ์๋งํผ ์ธ์ด์ง๋ค.\n */\nfunction onceById<T extends { payload?: any }>(rows: readonly T[]): T[] {\n const seen = new Set<string>()\n return rows.filter(r => {\n const id = (r as any)?.payload?.eventId\n if (typeof id !== 'string' || !id) return true\n if (seen.has(id)) return false\n seen.add(id)\n return true\n })\n}\n\nexport interface KpiFoldOptions {\n groupBy?: KpiGroupBy\n /**\n * ์ด ํธ์์ด ์ด์ด๋ฐ๊ณ ์๋ **๋ง์ง๋ง ์ฒญ๊ตฌ์** โ ์๊ธ์ ์ฉ์ ๋ ฅ์ ์ฐ์ ๊ทผ๊ฑฐ(ยง`billingDemandOf`).\n *\n * ์ฐฝ ๋ฐ์ ์ฒญ๊ตฌ์๋ ์ ๋ ์กฐํ์ ๊ฑธ๋ฆฌ์ง ์๋๋ค. ๊ทธ๋ฐ๋ฐ ๊ทธ ๊ฐ์ ์ด ์ฐฝ์๋ ์ ์ฉ๋๋ฏ๋ก ํธ์ถ๋ถ๊ฐ\n * ์ปค๋ ์ํ์์ ์ฝ์ด ๋๊ธด๋ค.\n */\n lastBill?: { to: string; billingDemandKW?: number }\n /**\n * ์ด ํธ์์ด ์ด์ด๋ฐ๊ณ ์๋ **์๊ธ ๊ธฐ์ค** โ ์ด ์ฃผ๊ธฐ์ ์ ์ฉ๋๋ ๊ฐ(ยง`ENERGY_EVENT.tariffBasis`).\n *\n * ์ฒญ๊ตฌ์๋ณด๋ค ๋จผ์ ๋ค. ์ฒญ๊ตฌ์๋ ๋๋ ๊ธฐ๊ฐ์ ์ ์ฐ์ด๋ผ ์ด๋ฒ ์ฃผ๊ธฐ์ ๊ธฐ์ค์ ๋งํ์ง ์๋๋ค.\n */\n tariffBasis?: { from: string; billingDemandKW?: number }\n /**\n * ์ด ํธ์์ **๋ฐ์ ์ ๊ฒฉ**๊ณผ ๊ทธ ๊ทผ๊ฑฐ โ ์ด์ฉ๋ฅ ์ ๋ถ๋ชจ(ยง ์ปค๋ `generationRated`).\n *\n * ๋ชจ๋ธ์ ์ ์ธ์์ ์ค๋ฏ๋ก ํธ์ถ๋ถ๊ฐ ์ฝ์ด ๋๊ธด๋ค. ํด๋๋ ์ ๋๋ง ๋ณธ๋ค.\n */\n generationRated?: { kW: number; basis: 'ac' | 'dc'; from: 'equipment' | 'location' }\n /**\n * ์ด ํธ์์ด ์ด์ด๋ฐ๊ณ ์๋ **๋ฐ์ ๋จ๊ฐ** โ ์ฐฝ ๋ฐ์ ๋จ๊ฐ๋ ์ด ์ฐฝ์ ์ ์ฉ๋ ์ ์๋ค.\n *\n * ์ฐฝ ์์ ๋จ๊ฐ ์ฌ์ค์ด ๋จผ์ ๋ค. ์ด๊ฒ์ ๊ทธ ์ฐฝ์ ๋จ๊ฐ๊ฐ ์์ ๋ ์ด๋ค.\n */\n generationPrice?: { from: string; to: string; unitPrice: number; currency: string }\n /**\n * ๋
ธ๋ โ ๊ตฌ์ญ ์ง๋. **์ด๋ฒคํธ์๋ ๊ตฌ์ญ์ด ์๋ค**(๋
ธ๋๊น์ง๋ง ์๋ค) โ ์ค๋
์ทยท๋ง์คํฐ๊ฐ ์๋ ๊ฐ์ด๋ผ\n * ํธ์ถ๋ถ๊ฐ ๋๊ธด๋ค. ์์ผ๋ฉด ๊ตฌ์ญ ์ถ์ 'unknown' ์ผ๋ก ๋ชจ์ธ๋ค(์๋ฆฌ์ง ์๊ณ ๋ค๋ฅธ ์ถ์ผ๋ก ๋ฐ๊พธ์ง ์๋๋ค).\n */\n locationArea?: Record<string, string>\n /**\n * ์์ โ **๋ฐฐ์ ๊ณํต์ ์๋ฆฌ**(๋ถ๊ธฐยท์์ ) ์ง๋.\n *\n * โโ ์ ๋ฐ์์ ์ค๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ด๋ฒคํธ์๋ ์ ๊ธฐ ๊ณํต์ด ์๋ค. ใ์ด ์ค๋น๊ฐ ์ด๋ ๋ถ๊ธฐ์์ ๋จน๋๊ฐใ๋ ์๋์ง ํธ์์ ๋ชจ๋ธ์ด ์๋\n * ์ ์ธ์ด๊ณ (์ค๋น ํ๋์ ์ฌ์ค ๋ โ ๊ณต์ฅ์์๋ ์์, ์ ๊ธฐ์์๋ ๋ถํ), ๊ทธ ์ ์ธ์ ์ฝ๋ ๊ฒ์ ํธ์ถ๋ถ์ ์ผ์ด๋ค.\n *\n * ์์ผ๋ฉด ๋ถ๊ธฐ ๋ถํด๋ฅผ **ํ์ง ์๋๋ค** โ ์๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋ ์ฑ ๋๋๋ฉด ๊ทธ ์ซ์๋ ์๋ฌด ๊ฒ์ ๋ชซ๋ ์๋๋ค.\n */\n resourceFeeder?: Record<string, string>\n /**\n * **๊ณ๋ ์ง์ โ ๊ทธ๊ฒ์ด ์ฌ๋ ๋ถ๊ธฐ** ์ง๋.\n *\n * ์์ผ๋ฉด ๋ถ๊ธฐ๋ณ ์ ๋ ฅ๋์ ๊ณ๋์ผ๋ก ์ฝ๋๋ค(๋ฐฐ๋ถ๋ณด๋ค ๊ฐํ ๊ทผ๊ฑฐ). ์ด ์ง๋๋ ๋ชจ๋ธ์ ์ ์ธ์์ ์ค๊ณ \n * (๊ณ๋๊ธฐ์ ์๋ฆฌ), ๊ทธ๊ฒ์ ์ฝ๋ ๊ฒ์ ํธ์ถ๋ถ์ ์ผ์ด๋ค โ ํด๋๋ ์ ๋๋ง ๋ณธ๋ค.\n */\n meterFeeder?: Record<string, string>\n /**\n * ์ ์ธ๋ **์ ๊ธฐ์๊ธ ๋จ๊ฐ** โ ์๋ฅผ ๊ธ์ก์ผ๋ก ๋ฐ๊พธ๋ ์ ์ผํ ์
๋ ฅ.\n *\n * ์ด๋ฒคํธ์๋ ์๊ธ์ด ์๋ค. ๋จ๊ฐ๋ ํ์ฅ์ ๊ณ์ฝ์ด๊ณ (์๋์ง ํธ์ ๋ชจ๋ธ์ ์์ ์๋ฆฌ์ ์ ์ธํ๋ค), ๊ทธ๊ฒ์\n * ์ฝ๋ ๊ฒ์ ํธ์ถ๋ถ์ ์ผ์ด๋ค. ์์ผ๋ฉด ๊ธ์ก์ ๋ง๋ค์ง ์๋๋ค โ ์ง์ํ ๋จ๊ฐ๋ก ๋ธ ๊ธ์ก์ ์ซ์๊ฐ ์๋ค๋\n * ๊ฒ๋ง์ผ๋ก ์ฌ๋์ ๊ฒฐ์ ์ผ๋ก ๋ฐ์ด๋ถ์ธ๋ค.\n */\n tariff?: TariffDeclaration\n /**\n * ๊ต๋ ์ ์ธ โ **์ด๋ฒคํธ์๋ ๊ต๋๊ฐ ์๋ค**(์๊ฐ๋ง ์๋ค). ํ์ฅ ๋ง์คํฐ๊ฐ ์๋ ๊ฐ์ด๋ผ ํธ์ถ๋ถ๊ฐ ๋๊ธด๋ค.\n * ์์ผ๋ฉด ๊ต๋ ์ถ์ 'unknown' ์ผ๋ก ๋ชจ์ธ๋ค(๋ค๋ฅธ ์ถ์ผ๋ก ์๋ฆฌ์ง ์๊ณ ๋ฐ๊พธ์ง ์๋๋ค).\n */\n shifts?: WorkCalendarEntry[]\n /**\n * ํ์ฅ์ ์๊ฐ ๊ธฐ์ค(๋ถ) โ ๊ต๋ ์ถ์ด `HH:MM` ์ ์ด๋ ๊ธฐ์ค์ผ๋ก ์ฝ์์ง. **๊ณต๊ฐ์ด ๊ฐ๋ ๊ฐ**์ด๋ค\n * (ํ
๋ํธ๊ฐ ์๋๋ค: ํ ํ
๋ํธ๊ฐ ๋ค๋ฅธ ์๊ฐ๋์ ๊ณต์ฅ์ ํจ๊ป ๊ฐ์ง ์ ์๋ค). ์์ผ๋ฉด UTC.\n *\n * โ ํ ์๋ค. ์ ๊ธฐ๋ ์ง๋ ๊ตฌ๊ฐ์ ํ์ผ๋ฏ๋ก **์ผ๊ด์ ์ฝ์๊ฐ ์ ํ์ ๋์ ์ ์๋ค** โ ๊ทธ๋๋\n * `offsetAt` ์ ๋๊ธด๋ค.\n */\n utcOffsetMinutes?: number\n /**\n * ๊ทธ ์๊ฐ์ ์๊ฐ ๊ธฐ์ค์ ํธ๋ ํจ์ โ **`utcOffsetMinutes` ๋ณด๋ค ๋จผ์ ๋ณธ๋ค**.\n *\n * โโ ์ ์๊ฐ ์๋๋ผ ํจ์์ธ๊ฐ (2026-09-07) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ๊ธฐ๋ ์ง๋ ๊ตฌ๊ฐ์ ํ๋๋ค. 1๋
์น๋ฅผ ๊ต๋๋ณ๋ก ์ ์ผ๋ฉด ๊ทธ 1๋
์์ ์ผ๊ด์ ์ฝ์๊ฐ ์ ํ์ด ๋ ๋ฒ ๋ค์ด\n * ์๋๋ฐ, ๊ณ ์ ์คํ์
ํ๋๋ก ์ฝ์ผ๋ฉด ์ ํ ๋ค์ ์ฌ์ค์ด **ํ ์๊ฐ ๋ฐ๋ ค ๋ค๋ฅธ ๊ต๋๋ก ์ธ์ด์ง๋ค.**\n * ์ค๋ฅ๊ฐ ๋์ง ์์ผ๋ฏ๋ก ๊ต๋๋ณ ์ฑ๊ณผ๊ฐ ์กฐ์ฉํ ๊ฑฐ์ง์ด ๋๋ค. `America/Tijuana`(PST โ480 / PDT โ420)๊ฐ\n * ์ด๋ฏธ ์๋ฃ์ ์๋ค.\n *\n * ์ด ํ์ผ์ ์๊ฐ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค์ง ์๋๋ค(์ปค๋๊ณผ ๊ฐ์ ์์ธ๋ค) โ ๋ถ๋ฅด๋ ์ชฝ์ด ํธ๋ ๋ฒ์ ์ค๋ค. ๊ทธ๋์\n * ์ด ์ธ์๊ฐ ํจ์์ด๊ณ , ์ํ์ ์ฌ์ ํ ํ๋ฒํ ๊ฐ์ผ๋ก ๋๋ค.\n *\n * `undefined` ๋ฅผ ๋๋ ค์ฃผ๋ฉด ๊ทธ ์๊ฐ์ ๊ธฐ์ค์ ๋ชจ๋ฅด๋ ๊ฒ์ด๋ค โ 0(UTC)์ผ๋ก ์ฑ์ฐ์ง ์๊ณ \n * `utcOffsetMinutes` ๋ก ๋จ์ด์ง๋ค.\n */\n offsetAt?: (atMs: number) => number | undefined\n /**\n * ์ถ์ ์ํ(๊ธฐ๋ณธ 20). ๋์น๋ฉด ์๋ผ๋ด๊ณ **์๋ฆฐ ์ถ์ ์์ ๊ทธ ์์ ๊ฑด์๋ฅผ ํจ๊ป ์๋ฆฐ๋ค**.\n *\n * ์ถ์ ์๋ง ์๋ฆฌ๋ฉด ๋ถ์กฑํ๋ค โ \"๊ทธ ์ธ 89๊ฐ\" ๋ก๋ ๊ทธ๊ฒ์ด 3๊ฑด์ธ์ง 300๊ฑด์ธ์ง ๋ชจ๋ฅธ๋ค. ๋ณด์ฌ์ค ์ถ์ด ์ ๋ถ์ธ\n * ๊ฒ์ฒ๋ผ ์ฝํ๋ฉด ์ฌ์ฉ์๊ฐ ๊ผฌ๋ฆฌ๋ฅผ ๋์น๋ค.\n */\n groupLimit?: number\n}\n\n/* โโ ๊ด์ ์ถ์ ์ฌ๋ฃ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ถ์ ๊ฐ์ ์ด๋ฒคํธ payload ์ ์ด๋ฏธ ๋ค์ด ์๋ค(`TaskStatusDelta`: kindยทorderIdยทfromNodeยทtoNodeยท\n * resourceRef). ์ ๊ณ์ธก์ ์ฌ์ ํ์๊ฐ ์๋ค โ **์ด๋ฏธ ์์ธ ์ ๋์ ๋ค๋ฅด๊ฒ ๋ฌถ๊ธฐ๋ง** ํ๋ค.\n */\n/** ์ฐฝ ์์ ์๋ฃ๋ ํ ๊ฑด์ ๊ธฐ๋ก โ ํต๊ณ์ ์๋ฃ์ด์ ๊ด์ ์ถ์ ์๋ฃ. */\ninterface CompletionRecord {\n taskId: string\n at: number\n facets: TaskFacets\n leadMs?: number\n workMs?: number\n waitMs?: number\n}\n\n/** ์ด ๊ธฐ๋ก์ด ์์ฒญํ ์ถ์์ ์ด๋ ๊ฐ์ ์ํ๋๊ฐ. ๊ฐ์ด ์์ผ๋ฉด 'unknown'(์๋ฆฌ์ง ์๊ณ ๋ฒ๋ฆฌ์ง ์๋๋ค). */\nfunction facetKey(rec: CompletionRecord, options: KpiFoldOptions): string {\n const f = rec.facets\n switch (options.groupBy) {\n case 'resource':\n return f.resource ?? 'unknown'\n case 'taskKind':\n return f.kind ?? 'unknown'\n case 'location':\n return f.location ?? 'unknown'\n case 'order':\n return f.order ?? 'unknown'\n case 'area':\n /* ๊ตฌ์ญ์ ์ด๋ฒคํธ ๋ฐ์ ์ง์์ด๋ค โ ์ง๋๊ฐ ์์ผ๋ฉด ์๋ค๊ณ ๋งํ๋ค(๋
ธ๋ id ๋ก ๋์ฒดํ๋ฉด ์ฌ์ฉ์๊ฐ\n * ๊ทธ๊ฒ์ ๊ตฌ์ญ์ผ๋ก ์คํดํ๋ค). */\n return (f.location && options.locationArea?.[f.location]) ?? 'unknown'\n case 'shift':\n /*\n * ๊ต๋๋ **์ ๋์ ์ฐํ ์์ง ์๋ค โ ๊ณ์ฐํ๋ค.**\n *\n * ์ด๋ฒคํธ์ ๊ต๋ ์ด๋ฆ์ ์คํฌํํ๋ฉด ๋ ๊ฐ์ง๊ฐ ๋ฌด๋์ง๋ค: โ ๊ฐ์ ์ฌ์ค์ด ๋ ๊ณณ์ ์๊ธฐ๊ณ ,\n * โก ๋์ค์ ๊ต๋ ์๊ฐ์ ๊ณ ์น๋ฉด **๊ณผ๊ฑฐ๊ฐ ์ ๊ตฌ๋ถ์ผ๋ก ๊ตณ์ด** ๋ค์ ์
์ ์๋ค. ๊ต๋๋\n * `์๋ฃ ์๊ฐ + ํ์ฅ์ ์๊ฐ ๊ธฐ์ค + ๊ต๋ ์ ์ธ`์์ ๋์ค๋ ์์ ํ์์ด๋ฏ๋ก ์ฌ๊ธฐ์ ๋ธ๋ค โ\n * ๋ผ์ด๋ธยทํ์คํ ๋ฆฌยท์์ธก์ด **์ปค๋๊ณผ ๊ฐ์ ํจ์**(`activeShiftOf`)๋ฅผ ์ด๋ค.\n *\n * ์ ์ธ์ด ์์ผ๋ฉด 'unknown' ์ด๋ค. ๊ต๋๋ฅผ ๋๋ ๋์ง ์์ ํ์ฅ์ ์ด๋ฆ์ ์ง์ด๋ด์ง ์๋๋ค.\n */\n if (!options.shifts?.length) return 'unknown'\n /* ์๊ฐ๊น์ง ๋๊ธด๋ค โ **ํด์ผ์ ์ผ์ด๋ ์ผ์ ์ด๋ ๊ต๋์๋ ์ํ์ง ์๋๋ค.** ๋ํ์ด๋ง ๋ณด๋ฉด ๊ทธ๋ ์์ง๋\n ์์ ๊ต๋์ ์ง๊ณ๋ผ, ๊ต๋๋ณ ์ฑ๊ณผ๊ฐ ์๋ฆฌ์ง ์๊ณ ๊ฑฐ์ง์ด ๋๋ค. */\n /* ๊ทธ ์๊ฐ์ ๊ธฐ์ค์ ๋จผ์ ๋ฌป๋๋ค โ ์์ผ๋ฉด ํ ์๋ก ๋จ์ด์ง๋ค(ยง`offsetAt`). */\n const atMs = typeof rec.at === 'number' ? rec.at : Date.parse(String(rec.at))\n const offset =\n (Number.isFinite(atMs) ? options.offsetAt?.(atMs) : undefined) ?? options.utcOffsetMinutes\n return activeShiftAt(options.shifts, rec.at, offset) ?? 'unknown'\n default:\n return 'unknown'\n }\n}\n\n/**\n * ์ด ์ถ์ ํ์ง โ **ํ์ ์ด ์์๋ ๊ฒ๋ง** ์ผ๋ค(์์ผ๋ฉด ํ๋๋ฅผ ๋ง๋ค์ง ์๋๋ค).\n *\n * ์ํ๋ฅ ์ ์ด๋ ฅ์ด ์ฌ๊ธฐ์ ๋์จ๋ค: ์ปค๋์ด ์์
์๋ฃ์ ๊ฒฐ๊ณผ๋ฅผ ์ ๊ณ (`TaskStatusDelta.outcome`), ํด๋๊ฐ ์ถ์ผ๋ก\n * ๋ค๊ณ (`TaskFacets.outcome`), ์ฌ๊ธฐ์ ์ข
๋ฅ๋ณ๋ก ์ผ๋ค. ๊ทธ ์ฌ์ฌ์ด ์์ผ๋ฉด ใ์ด ๊ณต์ ์ ์ํ๋ฅ ใ์ ์ ๋์\n * ๋จ์ง ์๋๋ค(์ค๋น ๋์ ์นด์ดํฐ๋ ์ข
๋ฅ๋ฅผ ๋ชจ๋ฅธ๋ค).\n */\nfunction qualityOf(rows: CompletionRecord[]): { quality?: { good: number; scrap: number } } {\n let good = 0\n let scrap = 0\n for (const r of rows) {\n const o = r.facets.outcome\n if (o === 'good') good++\n else if (o === 'scrap') scrap++\n }\n return good + scrap > 0 ? { quality: { good, scrap } } : {}\n}\n\n/**\n * ๊ธฐ๋ก์ ์ถ์ผ๋ก ๋ฌถ์ด ์ถ๋ณ ํต๊ณ๋ฅผ ๋ธ๋ค โ **์ ์ฒด์ ๊ฐ์ ๊ท์น**์ผ๋ก(๊ฐ์ stats ํจ์, ๊ฐ์ ์ฐฝ).\n *\n * ์ถ์ ๊ฐ์ด ์์ฃผ ๋ง์ ์ ์๋ค(์ค๋ ์ถ์ ์์ฒ ๊ฐ). ๊ทธ๋์ ๊ฑด์ ํฐ ๊ฒ๋ถํฐ ์ํ๊น์ง๋ง ๋๋ ค์ฃผ๊ณ \n * **์๋ผ๋ธ ์๋ฅผ ํจ๊ป ์๋ฆฐ๋ค** โ ๋ค์ด์จ ๊ฒ์ด ์๋ ์ ๋จ์ \"์ด๊ฒ ์ ๋ถ\" ๋ผ๋ ๊ฑฐ์ง์ ๋ง๋ ๋ค.\n */\nfunction groupRecords(\n records: CompletionRecord[],\n options: KpiFoldOptions\n): { by: KpiGroupBy; items: KpiGroup[]; truncated?: number; truncatedTasks?: number } {\n const by = options.groupBy as KpiGroupBy\n const bins = new Map<string, CompletionRecord[]>()\n for (const rec of records) {\n const key = facetKey(rec, options)\n const bin = bins.get(key)\n if (bin) bin.push(rec)\n else bins.set(key, [rec])\n }\n\n const all = [...bins.entries()]\n .map(([key, rows]) => ({\n key,\n tasks: rows.length,\n leadTime: stats(rows.map(r => r.leadMs).filter((v): v is number => v !== undefined)),\n workTime: stats(rows.map(r => r.workMs).filter((v): v is number => v !== undefined)),\n waitTime: stats(rows.map(r => r.waitMs).filter((v): v is number => v !== undefined)),\n busyMs: rows.reduce((a, r) => a + (r.workMs ?? 0), 0),\n ...qualityOf(rows)\n }))\n .sort((a, b) => b.tasks - a.tasks || (a.key < b.key ? -1 : 1))\n\n const limit = Math.max(1, Math.min(100, options.groupLimit ?? 20))\n const items = all.slice(0, limit)\n const dropped = all.slice(limit)\n /* ์ถ๋ณ๋ก \"์ฐฝ ๋๋น ๋น์จ\" ์ ๋ด์ง ์๋๋ค โ ์์ ์๋ ์ถ(์ค๋ยท์์
์ข
๋ฅ)์์ ๊ทธ ๋น์จ์ ์๋ฏธ๊ฐ ์๊ณ ,\n * ์๋ฏธ ์๋ ์ซ์๋ฅผ ๋ด๋ฉด ์ฌ์ฉ์๊ฐ ๊ทธ๊ฒ์ผ๋ก ํ๋จํ๋ค. ์์ ์ ์ ๋ `utilization` ์ด ์ด๋ฏธ ๋ธ๋ค. */\n return {\n by,\n items,\n ...(dropped.length\n ? { truncated: dropped.length, truncatedTasks: dropped.reduce((a, g) => a + g.tasks, 0) }\n : {})\n }\n}\n\nfunction ms(value: string | undefined): number | null {\n if (!value) return null\n const t = Date.parse(value)\n return Number.isFinite(t) ? t : null\n}\n\n/** ๋ถ์์ โ ์ ๋ ฌ๋ ๊ฐ์์ ์ ํ ๋ณด๊ฐ ์์ด ๊ฐ์ฅ ๊ฐ๊น์ด ์๋ ๊ฐ(์์ ํ๋ณธ์์ ๊ณผ์ฅํ์ง ์๋๋ค). */\nfunction quantile(sorted: number[], q: number): number {\n if (sorted.length === 0) return 0\n const idx = Math.min(sorted.length - 1, Math.max(0, Math.floor(q * sorted.length)))\n return sorted[idx]\n}\n\nfunction stats(values: number[]): DurationStats {\n if (values.length === 0) return { count: 0, p10Ms: 0, p50Ms: 0, p90Ms: 0, avgMs: 0 }\n const sorted = [...values].sort((a, b) => a - b)\n const sum = sorted.reduce((a, b) => a + b, 0)\n return {\n count: sorted.length,\n p10Ms: quantile(sorted, 0.1),\n p50Ms: quantile(sorted, 0.5),\n p90Ms: quantile(sorted, 0.9),\n avgMs: Math.round(sum / sorted.length)\n }\n}\n\n/**\n * ์ด๋ฒคํธ๋ฅผ ๊ณ์ฐํด ์๊ฐ์ฐฝ KPI ๋ฅผ ๋ง๋ ๋ค.\n *\n * **ํธ์ถ๋ถ ๊ท์ฝ**: `events` ๋ ์ฐฝ๋ณด๋ค **๋๋ํ ์๊น์ง** ๋ด์ ๋๊ธด๋ค(์: ์ฐฝ ์์ โ ๋ฆฌ๋ํ์ ์ํ).\n * ์๋ฃ๋ ์์
์ ์์ ์ด๋ฒคํธ๊ฐ ์ฐฝ ๋ฐ์ ์์ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๋ชป ์ฐพ์ ๊ฒ์ `unpaired` ๋ก ์๋ฆฐ๋ค โ\n * ํ๊ท ์์ ์ค๋ฅ ์์ด ๋น ์ง๋ฉด ์งํ๊ฐ ๊ฑฐ์ง์ด ๋๋ค.\n *\n * ์๊ฐ์ถ์ `eventTime`(ISO) ์ฐจ๋ถ์ด๋ค. sim ํด๋ก์ด ์ค์ ์๊ฐ๊ณผ ์คํ์
์ด ์์ด๋ **์ฐจ๋ถ์ ์ ํ**ํ๋ค\n * (๊ณ ์ ์คํ์
์ ์์๋๋ค). ํ์ฑ ๋ถ๊ฐํ ์ค์ ๋ฒ๋ฆฐ๋ค.\n */\nexport function foldKpi(events: KpiEvent[], window: KpiWindow, options: KpiFoldOptions = {}): KpiResult {\n /* ์์
์ง๋ง์ถค์ **์ปค๋ ๊ท์น**์ผ๋ก(์ค๋ณต ๊ตฌํ ๊ธ์ง โ ๋ ๊ณณ์ ์ ์ผ๋ฉด ๊ฐ์ ์ ๋๋ก ๋ค๋ฅธ ๋ต์ด ๋์จ๋ค). */\n const { records: tasks } = foldTaskRecords(events.filter(e => e.eventType === 'task.status'))\n let completedOrders = 0\n /* ์๋ฃ๋ก ์ฝ์ง ๋ชปํ ์ค๋ ์ํ ๋ฑ๋ง โ ๊ฑด์(ยง`orderStatusNotCounted`). */\n const orderStatusNotCounted = new Map<string, number>()\n /* ์ด๋ฏธ ์๋ฃ๋ก ์ผ ์ค๋ โ ํด๋ง ์๋ณธ์ด ๊ฐ์ ์ข
๊ฒฐ์ ๋ค์ ๋ณด๋ด๋ ํ ๋ฒ๋ง ์ผ๋ค. */\n const completedOrderIds = new Set<string>()\n let seen = 0\n let inWindow = 0\n\n for (const e of events) {\n const at = ms(e.eventTime)\n if (at === null) continue\n seen++\n if (at >= window.fromMs && at <= window.toMs) inWindow++\n const d = e.payload?.data ?? e.payload ?? {}\n\n if (e.eventType === 'order.status') {\n /*\n * **๋๋ฌ๋๋ ์ปค๋์ด ๋ตํ๋ค** (2026-08-23) โ `isOrderTerminal`.\n *\n * ์์ ์๋ ์ฌ๊ธฐ์ **๋์์ด ๋ชฉ๋ก**์ผ๋ก ์ถ๋ก ํ๋ค(`completed`ยท`fulfilled`ยท`done`ยท`finished`).\n * ๊ทธ ๋ฐฉ์์ด ๋ธ ๋๊ฐ๊ฐ ๋์ด์๊ณ ๋ ๋ค ๋ค์ด์จ ๊ฒ์ด ์์๋ค.\n *\n * โ ์๋ณธ์ ๋ฑ๋ง์ด ๋ชฉ๋ก์ ์์ผ๋ฉด ์๋ฃ๊ฐ 0 ์ด ๋๋ค. ์ค์ ๋ก ๊ทธ๋ฌ๋ค โ ์ฒซ ์ค ์์คํ
์ `FINISHED`\n * ๊ฐ ๋น ์ ธ ์์๊ณ , ๊ทธ๋ ๋ชฉ๋ก์ ๋ฑ๋ง์ ๋ํ ๊ฒ์ ์ง์ง ๋น ์๋ฆฌ(๊ทธ ์ปค๋ฅํฐ๊ฐ ์๊ธฐ ์ํ ํ๋ฅผ\n * ์ ์ฐ๊ณ ์์๋ค)๋ฅผ ๊ฐ๋ฆฐ ๋๋นต์ด์๋ค.\n * โก **์๋ฎฌ ํธ์์์๋ ์ธ์ ๋ 0 ์ด์๋ค.** ์๋ฎฌ์ ์ค๋๋ฅผ ์ดํํ๋ฉฐ `fulfilled` ๋ง ์ฌ๋ฆฌ๊ณ \n * `status` ๋ ๋ฐ๊พธ์ง ์๋๋ค โ ๋ฑ๋ง๋ก ๋ฌป๋ ํ์ ์ ์๋ฎฌ์ ์๋ฃ๋ฅผ ํ ๊ฑด๋ ์ธ์ง ๋ชปํ๋ค.\n *\n * ํ์ค์ด ๊ทธ ์ถ์ ๊ฐ๋ผ ๋์๋ค: `orders.status` โ `RequestState`(ํ์ค๋ ์ด๊ฑฐํ์ง ์๋๋ค)์ด๊ณ ,\n * ใ๋๋ใ๋ **์ค์ **์์ ์ฝ๋๋ค(`JobResponse`, ์๊ตฌ๋ `SegmentRequirement.Quantity`). ๊ทธ๋์\n * ํ์ ์ 1์ฐจ ๊ทผ๊ฑฐ๋ **์**์ด๊ณ ๋ฑ๋ง์ ์์ผ๋ก ๋งํ ์ ์๋ ์ข
๊ฒฐ(์ทจ์ยท์ค๋ ์ข
๋ฃ)์๋ง ์ด๋ค.\n */\n const status = String(d.status ?? '').toLowerCase()\n const done = isOrderTerminal({ status: d.status, requested: d.requested, fulfilled: d.fulfilled })\n if (at >= window.fromMs && at <= window.toMs) {\n /*\n * **์ค๋๋น ํ ๋ฒ๋ง ์ผ๋ค.** ํด๋งํ๋ ์๋ณธ์ ๊ฐ์ ์ค๋์ ์ข
๊ฒฐ์ ์ฌ๋ฌ ์ฃผ๊ธฐ์ ๊ฑธ์ณ ๋ค์ ๋ณด๋ผ ์\n * ์๊ณ (๊ทธ๊ฒ์ ๊ฒฐํจ์ด ์๋๋ผ ํด๋ง์ ์ฑ์ง์ด๋ค), ์ฌ๊ฑด๋ง๋ค ์ธ๋ฉด ์ฒ๋ฆฌ๋์ด ์๋ฆฌ์ง ์๊ณ ๋ถํ๋ ค์ง๋ค.\n * ์์
์ชฝ์ ์ปค๋์ ์ง๋ง์ถค์ด ์ด๋ฏธ ๊ทธ ๊ท์จ์ ๊ฐ๊ณ ์๋ค(ใ์๋ฃ๋ ์์
๋น ํ๋ใ) โ ์ค๋๋ง ์์๋ค.\n */\n if (done) {\n const id = String(d.orderId ?? '')\n if (id && !completedOrderIds.has(id)) {\n completedOrderIds.add(id)\n completedOrders++\n } else if (!id) completedOrders++ // ์ ์ฒด๋ฅผ ๋ชจ๋ฅด๋ฉด ์
์์ ๋นผ์ง ์๋๋ค(์๋ฆฌ์ง ์๊ณ ์ค์ด์ง ์๋๋ค)\n }\n /*\n * **์๋ฃ๋ก ์ธ์ง ์์ ๋ฑ๋ง์ ์ธ๊ตฌ์กฐ์ฌ.** ใ๋ชป ์ฝ์๋คใ๊ฐ ์๋๋ค โ `picking` ์ฒ๋ผ ์๋ฃ๊ฐ ์๋\n * ๋ฑ๋ง์ด ์ฌ๊ธฐ ์ค๋ ๊ฒ์ ์ ์์ด๋ค. ์๋ฃ๊ฐ 0 ์ธ๋ฐ ์ฌ๊ธฐ ๋ฑ๋ง์ด ์์ฌ ์์ผ๋ฉด ์์ธ์ด ๊ณง ๋ณด์ธ๋ค.\n *\n * ๋น ๋ฑ๋ง์ ์ธ์ง ์๋๋ค: ์ํ๋ฅผ ๋งํ์ง ์์ ์ฌ๊ฑด์ ๋ค๋ฅธ ๊ฒฐํจ์ด๊ณ (์ ์
๋ฌธ์ด ์ํ๋ฅผ ํ์๋ก\n * ๋ฐ๋๋ค) ์ฌ๊ธฐ์ ์์ผ๋ฉด ์ด ๊ฐ์ ๋ป์ด ํ๋ ค์ง๋ค.\n */\n else if (status) orderStatusNotCounted.set(status, (orderStatusNotCounted.get(status) ?? 0) + 1)\n }\n }\n }\n\n /*\n * ์๋์ง โ ์ฐฝ์ **์จ์ ํ ๋ ** ๊ตฌ๊ฐ ๋ง๊ฐ ์ฌ๊ฑด๋ง ์ผ๋ค(๊ฑธ์น ๊ตฌ๊ฐ์ ์ปค๋ ๊ท์น์ด ๋บ๋ค).\n * ์ฌ๊ฑด์ด ํ๋๋ ์์ผ๋ฉด ์ด ํธ์์๋ ์๋์ง๊ฐ ์๋ ๊ฒ์ด๋ฏ๋ก ๋ธ๋ก ์์ฒด๋ฅผ ๋ด์ง ์๋๋ค.\n */\n const demandWindows = events\n .filter(e => e.eventType === ENERGY_EVENT.demandWindow)\n .map(e => {\n const d = e.payload?.data ?? e.payload ?? {}\n /* ์ต๋(`maxKW`)๋ ํจ๊ป ๋๊ธด๋ค โ ์๊ธ์ด ๊ฑธ๋ฆฌ๋ ์๋ ํ๊ท ์ด ์๋๋ผ ์ต๋๋ค.\n ์ด๋ถํ(`grossMaxKW`)๋ ใ๋ฌด์์ด ๊น์๋ใ๋ฅผ ๋์ง๋ ์ถ์ด๋ค(๋ฐ์ ยท๋ฐฉ์ ์ฐจ๊ฐ ์ ). */\n return {\n startMs: Number(d.startMs),\n endMs: Number(d.endMs),\n meanKW: Number(d.meanKW),\n maxKW: Number(d.maxKW),\n grossMaxKW: Number(d.grossMaxKW),\n /* ์ง์ ๋ณ ๋ชซ โ ๊ณ๋์ด ๋ถ๊ธฐ์ ์์ผ๋ฉด ๊ทธ ๊ฐ์ **์ธก์ **์ด๋ค(๋ฐฐ๋ถ์ด ์๋๋ค). ์ปค๋์ด ๊ณ์ธต ํ์ \n (`root`)๊น์ง ์ค์ด ์ฃผ๋ฏ๋ก ์ฌ๊ธฐ์ ๊ฐ์ ๊ท์น์ ๋ค์ ์ฐ์ง ์๋๋ค. */\n points: (Array.isArray(d.points) ? d.points : [])\n .map((p: any) => ({ id: String(p?.id ?? ''), kWh: Number(p?.kWh), root: p?.root === true }))\n .filter((p: any) => p.id && Number.isFinite(p.kWh)),\n /* ํผํฌ๊ฐ ์ฐํ ์๊ฐ์ ์ง์ ๋ณ kW โ ์๊ธ์ด ๊ฑธ๋ฆฐ ์๋ kW ๋ค(์ ๋ ฅ๋์ด ํฐ ๋ถ๊ธฐ์ ํผํฌ๋ฅผ ๋ง๋ ๋ถ๊ธฐ๋ ๋ค๋ฅด๋ค). */\n pointsAtPeak: (Array.isArray(d.pointsAtPeak) ? d.pointsAtPeak : [])\n .map((p: any) => ({ id: String(p?.id ?? ''), kW: Number(p?.kW) }))\n .filter((p: any) => p.id && Number.isFinite(p.kW))\n }\n })\n .filter(w => Number.isFinite(w.startMs) && Number.isFinite(w.endMs))\n\n /*\n * ๋ฐ์ ๊ธฐ๊ฐ ์ฌ์ค โ ์ปค๋์ด ๊ธฐ๊ฐ์ ๋ง๊ฐํ ๋ ๋ธ ๊ฒ์ด๋ค. ๊ตฌ๊ฐ ๋ง๊ฐ๊ณผ ๊ฐ์ ๊ท์น์ผ๋ก **์ฐฝ์ ์จ์ ํ ๋ \n * ๊ฒ๋ง** ์ผ๋ค(๊ฑธ์น ๊ธฐ๊ฐ์ ๋ฐ๋ง ์ธ๋ฉด ํฉ์ด ์ฐฝ์ ๋๋๋ค).\n *\n * ๊ด์ธก ๊ตฌ๊ฐ(`observedFrom`ยท`observedTo`)์ ํจ๊ป ์ฝ๋๋ค โ ๊ฐ์ ๊ทผ๊ฑฐ๊ฐ ์ผ๋ง๋ ๋ฎ์๋์ง๊ฐ ๊ทธ ๋์ ์๋ค.\n */\n const generationPeriods = onceById(events.filter(e => e.eventType === ENERGY_EVENT.generationPeriod))\n .map(e => {\n const d = e.payload?.data ?? e.payload ?? {}\n return {\n equipmentId: String(d.equipmentId ?? ''),\n kWh: Number(d.kWh),\n startMs: Date.parse(String(d.periodStart ?? '')),\n endMs: Date.parse(String(d.periodEnd ?? '')),\n observedFromMs: Date.parse(String(d.observedFrom ?? '')),\n observedToMs: Date.parse(String(d.observedTo ?? ''))\n }\n })\n .filter(g => g.equipmentId && Number.isFinite(g.kWh) && Number.isFinite(g.startMs) && Number.isFinite(g.endMs))\n\n /*\n * ๋ฐ์์ ๋ง๊ฐ๋์ด ์จ ์ฌ์ฉ ๊ตฌ๊ฐ โ ๊ตฌ๊ฐ ๋ง๊ฐ๊ณผ ๊ฐ์ ๊ท์น์ผ๋ก **์ฐฝ์ ์จ์ ํ ๋ ๊ฒ๋ง** ์ผ๋ค.\n */\n const usagePeriods = onceById(events.filter(e => e.eventType === ENERGY_EVENT.usagePeriod))\n .map(e => {\n const d = e.payload?.data ?? e.payload ?? {}\n return {\n meterId: String(d.meterId ?? ''),\n kWh: Number(d.kWh),\n startMs: Date.parse(String(d.from ?? '')),\n endMs: Date.parse(String(d.to ?? '')),\n unitPrice: Number(d.unitPrice),\n maxKW: Number(d.maxKW),\n currency: d.currency ? String(d.currency) : undefined,\n basis: d.basis ? String(d.basis) : 'unstated'\n }\n })\n .filter(u => u.meterId && Number.isFinite(u.kWh) && Number.isFinite(u.startMs) && Number.isFinite(u.endMs))\n\n /* ์ฒญ๊ตฌ์ โ ์ฐฝ์ ์จ์ ํ ๋ ๊ฒ ์ค ๊ฐ์ฅ ๋ฆ๊ฒ ๋๋ ๊ฒ ํ๋. */\n const bills = onceById(events.filter(e => e.eventType === ENERGY_EVENT.bill))\n .map(e => {\n const d = e.payload?.data ?? e.payload ?? {}\n return {\n from: String(d.from ?? ''),\n to: String(d.to ?? ''),\n startMs: Date.parse(String(d.from ?? '')),\n endMs: Date.parse(String(d.to ?? '')),\n total: Number(d.total),\n energyCharge: Number(d.energyCharge),\n demandCharge: Number(d.demandCharge),\n currency: d.currency ? String(d.currency) : undefined,\n billingDemandKW: Number(d.billingDemandKW)\n }\n })\n .filter(b => Number.isFinite(b.startMs) && Number.isFinite(b.endMs))\n\n /* ๋ฐ์ ๋จ๊ฐ โ ๊ธฐ๊ฐ๋ง๋ค ๊ทธ๋์ ๊ฐ์ด๋ค(๋ ๋ง๋ค ๋ฐ๋๋ค). */\n const generationPrices = onceById(events.filter(e => e.eventType === ENERGY_EVENT.generationPrice))\n .map(e => {\n const d = e.payload?.data ?? e.payload ?? {}\n return {\n startMs: Date.parse(String(d.from ?? '')),\n endMs: Date.parse(String(d.to ?? '')),\n unitPrice: Number(d.unitPrice),\n currency: String(d.currency ?? '')\n }\n })\n .filter(p => Number.isFinite(p.startMs) && Number.isFinite(p.endMs) && Number.isFinite(p.unitPrice) && p.currency)\n\n const leads: number[] = []\n const works: number[] = []\n const waits: number[] = []\n const busyByResource = new Map<string, number>()\n /* ์ฐฝ ์์ ์๋ฃ๋ ๊ฑด๋ค์ **๊ธฐ๋ก** โ ํต๊ณ๋ฅผ ๋ธ ๋ค์๋ ๋ฒ๋ฆฌ์ง ์๋๋ค. ๊ด์ ์ถ์ ๊ฐ์ ๊ธฐ๋ก์ ๋ค์\n * ๋ฌถ๋ ๊ฒ์ผ ๋ฟ์ด๋ฏ๋ก, ๊ธฐ๋ก์ ๋จ๊ธฐ๋ฉด ์ถ์ ํ๋ ๋ ๋ถ์ด๋ ๊ฐ์ด ๊ฑฐ์ 0 ์ด ๋๋ค. */\n const records: CompletionRecord[] = []\n let tasksInWindow = 0\n let unpairedLead = 0\n let unpairedWork = 0\n\n for (const t of tasks) {\n const completed = t.completedMs\n if (completed === undefined) continue // ์์ง ์๋ฃ๋์ง ์์ ์์
โ ์ฑ๊ณผ๋ก ์ธ์ง ์๋๋ค\n if (completed < window.fromMs || completed > window.toMs) continue // ์ฑ๊ณผ๋ ์๋ฃ ์์ ์ผ๋ก ์ผ๋ค\n tasksInWindow++\n const c = t.createdMs\n const s = t.startedMs\n const rec: CompletionRecord = { taskId: t.taskId, at: completed, facets: t.facets }\n const resource = rec.facets.resource\n if (c !== undefined && completed >= c) leads.push((rec.leadMs = completed - c))\n else unpairedLead++\n if (s !== undefined && completed >= s) {\n const busy = completed - s\n works.push((rec.workMs = busy))\n if (resource) busyByResource.set(resource, (busyByResource.get(resource) ?? 0) + busy)\n } else {\n unpairedWork++\n }\n if (c !== undefined && s !== undefined && s >= c) waits.push((rec.waitMs = s - c))\n records.push(rec)\n }\n\n const span = Math.max(1, window.toMs - window.fromMs)\n const utilization = [...busyByResource.entries()]\n .map(([resourceId, busyMs]) => ({ resourceId, busyMs, ratio: Math.min(1, busyMs / span) }))\n .sort((a, b) => b.busyMs - a.busyMs)\n\n return {\n window: { fromMs: window.fromMs, toMs: window.toMs },\n throughput: { tasks: tasksInWindow, orders: completedOrders },\n /* ๋ฐ์ ๋ง ์๋ ํ์ฅ(๊ณ๋ ์๋ ๋ฐ์ ์)๋ ๋ต์ด ๋์์ผ ํ๋ค โ ๋ ์ค ํ๋๋ง ์์ด๋ ๋ธ๋ก์ ๋ธ๋ค. */\n ...(demandWindows.length || generationPeriods.length || usagePeriods.length || bills.length\n ? (() => {\n const e = energyOfWindows(demandWindows, { startMs: window.fromMs, endMs: window.toMs })\n const usage = usageOfPeriods(usagePeriods, { startMs: window.fromMs, endMs: window.toMs })\n /*\n * ์ด๋ ํ๊ณ๋ฅผ ์ธ์ง ์ ํ๋ค โ **๋ํ์ง ์๋๋ค.** ๊ณ๋ ํ๋ณธ์์ ์ฐ๋ฆฌ๊ฐ ๋ง๊ฐํ ๊ฐ์ด ์์ผ๋ฉด ๊ทธ๊ฒ์\n * ์ฐ๊ณ (๊ฐํ ๊ทผ๊ฑฐ), ์์ผ๋ฉด ๋ฐ์์ ๋ง๊ฐ๋์ด ์จ ๊ฐ์ ์ด๋ค. ๋ฌด์์ ์ผ๋์ง ํจ๊ป ๋ธ๋ค.\n */\n const usedKWh = e.kWh !== undefined ? e.kWh : usage?.kWh\n const kWhBasis = e.kWh !== undefined ? 'demand-window' : usage ? 'usage-period' : undefined\n /* ๋ถ๋ชจ๋ **์๋ฃ ์ค๋**๋ค(๋๋น ์ ๋ ฅ). ์ฐฝ์ ์๋ฃ๊ฐ ์์ผ๋ฉด ์ปค๋ ๊ท์น์ด ใ์ ์๋์ง ์์ใ์ผ๋ก ๋ตํ๋ค. */\n const i = energyIntensity({\n kWh: usedKWh,\n energyWindow: e.window,\n denominator: { kind: 'output', value: completedOrders, window: e.window }\n })\n /*\n * ์๊ธ์ **๊ตฌ๊ฐ๋ง๋ค ์ ๋จ๊ฐ๋ก** ๋งค๊ธด ๊ฐ์ด ์์ผ๋ฉด ๊ทธ๊ฒ์ ์ด๋ค. ๋จ์ผ ๋จ๊ฐ๋ก ์ ์ผ๋ฉด ์๊ฐ๋๋ง๋ค\n * ๋ค๋ฅธ ๋จ๊ฐ๊ฐ ์ฌ๋ผ์ง๊ณ , ใํผํฌ๋ฅผ ๊น์ ์ผ๋ง๋ฅผ ์๋ผ๋ใ๊ฐ ๊ทธ ์ฐจ์ด ์์ ์ ๋ค.\n */\n /* ์๊ธ์ ์ฉ์ ๋ ฅ์ ์ฒญ๊ตฌ์๊ฐ ๋จผ์ ๋ค โ ์ ์ธ์ ์ฒญ๊ตฌ๊ฐ ์ค์ง ์๋ ํ์ฅ์ ๋ชซ์ด๋ค. */\n /* ์ด ์ฐฝ์ ์ต๊ณ ์์ โ ์ฌ์ฉ ๊ตฌ๊ฐ์ด ์ค์ด ์จ ๊ฐ ์ค ๊ฐ์ฅ ํฐ ๊ฒ(์๋ณธ ๊ณ๋๊ธฐ๊ฐ ์ฐ ๊ฐ์ด๋ค). */\n const peaks = usagePeriods\n .filter(u => u.startMs >= window.fromMs && u.endMs <= window.toMs && Number.isFinite(u.maxKW))\n .map(u => ({ kW: u.maxKW as number, toMs: u.endMs }))\n const observedPeak = peaks.length ? peaks.reduce((a, x) => (x.kW > a.kW ? x : a)) : undefined\n const billingDemand = billingDemandOf(\n bills.filter(b => Number.isFinite(b.billingDemandKW)).map(b => ({ endMs: b.endMs, billingDemandKW: b.billingDemandKW })),\n options.tariffBasis,\n options.lastBill,\n options.tariff?.billingDemandKW,\n observedPeak\n )\n const cost = options.tariff\n ? electricityCost({\n kWh: usedKWh,\n peakKW: e.peakKW,\n tariff: { ...options.tariff, ...(billingDemand ? { billingDemandKW: billingDemand.kW } : {}) },\n ...(usage?.charge !== undefined ? { energyChargeFromPeriods: usage.charge } : {})\n })\n : undefined\n return {\n energy: {\n ...(usedKWh !== undefined ? { kWh: usedKWh } : {}),\n ...(kWhBasis ? { kWhBasis } : {}),\n ...(billingDemand ? { billingDemand } : {}),\n ...(usage ? { usage } : {}),\n /* ์ด ์ฐฝ์ ์ต๋์์ โ ๊ณ์ฝ ๋๋น ํ์ ์ด ๋ณด๋ ์๋ค(์ ๋ ฅ๋๊ณผ ๊ฐ์ ๊ตฌ๊ฐ ์งํฉ์์ ์๋ค). */\n ...(e.peakKW !== undefined ? { peakKW: e.peakKW, peakStartMs: e.peakStartMs } : {}),\n /* ๊น์ธ ์์ **๊ฐ์ ๊ตฌ๊ฐ์ ๋ ์**์ ์ฐจ์ด๋ค โ ์ฌ๊ธฐ์ ํ ๋ฒ๋ง ๊ณ์ฐํด ๋ ๊ณณ์ด ๊ฐ๋ผ์ง์ง ์๊ฒ. */\n ...(e.peakGrossKW !== undefined && e.peakKW !== undefined\n ? { peakGrossKW: e.peakGrossKW, ...(e.peakGrossKW > e.peakKW ? { shavedKW: e.peakGrossKW - e.peakKW } : {}) }\n : {}),\n basis: e.basis,\n counted: e.counted,\n skipped: e.skipped,\n intensity:\n i.value === null\n ? { value: null, reason: (i as any).reason }\n : { value: i.value, unit: (i as any).unit },\n ...(measuredFeeders(demandWindows, { startMs: window.fromMs, endMs: window.toMs }, e.kWh, options.meterFeeder) ??\n feederShares(e.kWh, utilization, options.resourceFeeder)),\n /* ๊ธ์ก์ ๊ฐ์ ์ฐฝ์ ์ ๋ ฅ๋ยท์ต๋์์์์ ๋์จ๋ค โ ์ฐฝ์ด ํ๋๋ฟ์ด๋ผ ์ด๊ธ๋ ์ ์๋ค. */\n ...(cost ? { cost } : {}),\n ...generatedOfPeriods(\n generationPeriods,\n { startMs: window.fromMs, endMs: window.toMs },\n options.generationRated,\n /* ์ฐฝ ์์ ๋จ๊ฐ ์ฌ์ค์ด ๋จผ์ ์ด๊ณ , ์์ผ๋ฉด ์ด์ด๋ฐ์ ๋ง์ง๋ง ๋จ๊ฐ๋ฅผ ์ด๋ค. */\n generationPrices.length\n ? generationPrices\n : options.generationPrice\n ? [\n {\n startMs: Date.parse(options.generationPrice.from),\n endMs: Date.parse(options.generationPrice.to),\n unitPrice: options.generationPrice.unitPrice,\n currency: options.generationPrice.currency\n }\n ]\n : []\n ),\n /* ์ฒญ๊ตฌ์๋ ์ฌ์ค์ด๋ค โ ์ฐ๋ฆฌ ๊ณ์ฐ์ ๋ฎ์ง ์๊ณ ๋๋ํ ๋๋ค(ยง`billOfWindow`). */\n ...(() => {\n const b = billOfWindow(bills, { startMs: window.fromMs, endMs: window.toMs }, cost as any)\n return b ? { bill: b } : {}\n })()\n }\n }\n })()\n : {}),\n leadTime: stats(leads),\n workTime: stats(works),\n waitTime: stats(waits),\n utilization,\n unpaired: { leadTime: unpairedLead, workTime: unpairedWork },\n /* ๋ชป ์ฝ์ ์ค๋ ์ํ ๋ฑ๋ง โ ๋น๋ฉด ๋น ๊ฐ์ฒด๋ค(ยง`orderStatusNotCounted`). */\n orderStatusNotCounted: Object.fromEntries(orderStatusNotCounted),\n eventsSeen: seen,\n eventsInWindow: inWindow,\n ...(options.groupBy ? { groups: groupRecords(records, options) } : {})\n }\n}\n\n/**\n * ๊ด์ ร ๋น๊ต ๊ต์ฐจ โ **\"๊ตฌ์ญ๋ณ๋ก ์ด์ ๋๋น ์ด๋ค๊ฐ\"**.\n *\n * ์ถ(๋ฌด์์)๊ณผ ๋น๊ต(์ธ์ ๋๋น)๋ฅผ ๋ฐ๋ก ๋ณด๋ฉด ์ฌ์ฉ์๊ฐ ๋จธ๋ฆฟ์์์ ๋ ํ๋ฅผ ๋์กฐํด์ผ ํ๋ค. ์ด์์์ ๊ฐ์ฅ\n * ๊ฐ ์๋ ์ง๋ฌธ์ ๊ทธ ๊ต์ฐจ๋ค: ์ ์ฒด๋ ๋น์ทํ๋ฐ **ํ ๊ตฌ์ญ๋ง ๋๋น ์ง** ๊ฒฝ์ฐ๋ฅผ ์ ์ฒด ์ซ์๋ก๋ ์ ๋ ๋ชป ๋ณธ๋ค.\n *\n * ์ ์ง์ฑ ๊ท์จ:\n * ยท ๋ ๊ตฌ๊ฐ์ **๋ชจ๋ ์๋** ์ถ๋ง delta ๋ฅผ ๋ธ๋ค.\n * ยท ์ง๊ธ๋ง ์๋ ์ถ์ `isNew`(์ด์ ์ ์๋ ์ผ) โ delta ๋ฅผ ๊ฑด์์ ๊ฐ๊ฒ ์ ์ผ๋ฉด \"๋์๋ค\" ๋ก ์ค๋
๋๋ค.\n * ยท **์ฌ๋ผ์ง ์ถ**(์ ์ ์์๊ณ ์ง๊ธ ์๋ ๊ฒ)์ ๋ฐ๋ก ๋๋ ค์ค๋ค. ํ์์ ๊ทธ๋ฅ ๋น ์ง๋ฉด **๋ฉ์ถ ๊ตฌ์ญ์ด\n * ๋์ ๋ณด์ด์ง ์๋๋ค** โ ์ด์์์๋ ์ด๊ฒ์ด ๊ฐ์ฅ ์ค์ํ ์ ํธ์ผ ์ ์๋ค.\n */\nexport interface CrossedGroup extends KpiGroup {\n /** ๋น๊ต ๊ตฌ๊ฐ์ ๊ฑด์(๋ ๊ตฌ๊ฐ์ ๋ชจ๋ ์์ ๋๋ง). */\n prevTasks?: number\n /** ํ์ฌ โ ๋น๊ต๊ตฌ๊ฐ ๊ฑด์(๋ ๊ตฌ๊ฐ์ ๋ชจ๋ ์์ ๋๋ง). */\n deltaTasks?: number\n /** ๋น๊ต ๊ตฌ๊ฐ ๋๋น ์์
์๊ฐ ์ค์๊ฐ ์ฐจ์ด(๋ ๋ค ์ธก์ ๋ ๋๋ง). */\n deltaWorkP50Ms?: number\n /** ๋น๊ต ๊ตฌ๊ฐ์๋ ์๋ ์ถ โ delta ๋์ ์ด ํ์์ ์ค๋ค. */\n isNew?: boolean\n}\n\nexport function crossGroups(\n now: KpiGroup[],\n prev: KpiGroup[]\n): { items: CrossedGroup[]; disappeared: { key: string; tasks: number }[] } {\n const before = new Map(prev.map(g => [g.key, g]))\n const items: CrossedGroup[] = now.map(g => {\n const p = before.get(g.key)\n if (!p) return { ...g, isNew: true }\n return {\n ...g,\n prevTasks: p.tasks,\n deltaTasks: g.tasks - p.tasks,\n ...(deltaP50(g.workTime, p.workTime) !== undefined ? { deltaWorkP50Ms: deltaP50(g.workTime, p.workTime) } : {})\n }\n })\n const present = new Set(now.map(g => g.key))\n const disappeared = prev.filter(g => !present.has(g.key)).map(g => ({ key: g.key, tasks: g.tasks }))\n return { items, disappeared }\n}\n\n/* โโ ์๊ฐ ๋น๊ต โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ซ์ ํ๋๋ก๋ ์ข์์ก๋์ง ๋๋น ์ก๋์ง ์ ์ ์๋ค(\"29์ด\" ๊ฐ ๊ฐ์ ์ธ์ง ์
ํ์ธ์ง). ๊ฐ์ ๊ธธ์ด์ ์ฐฝ์ ์ฎ๊ฒจ\n * ํ ๋ฒ ๋ ๊ณ์ฐํ๋ฉด ๋๋ฏ๋ก(ํด๋๋ ์์) ๊ฐ์ธ๋ค. ์ฐฝ ์ฎ๊ธฐ๊ธฐ์ ์ฐจ์ด ๊ณ์ฐ์ ๊ณ์ฐ ๊ท์น์ด๋ผ ์ฌ๊ธฐ ์๋ค โ\n * ์กฐํ ์ธต์ ๋๋ฉด ํ
์คํธ๊ฐ DB ๋ฅผ ๋๊ณ ์์ผ ํ๋ค.\n */\n\n/**\n * ๋น๊ต ๊ตฌ๊ฐ์ ์ฐฝ โ ๊ฐ์ **๊ธธ์ด**๋ก ์ฎ๊ธด๋ค.\n *\n * previous: ๋ฐ๋ก ์ ๊ตฌ๊ฐ(๊ฒฝ๊ณ๊ฐ ๋ง๋ฌผ๋ฆฌ๊ฒ โ ๊ฒน์น๊ฑฐ๋ ๋ฒ์ด์ง๋ฉด ๊ตฌ๊ฐ์ ํฉ์ด ์ด๊ธ๋๋ค).\n * yesterday: ์ ํํ 24์๊ฐ ์ ๊ฐ์ ์๋ฆฌ. ์๋ฎฌ ํธ์์ ํด๋ก์ด ์ค์ ์๊ฐ๊ณผ ๋ฌ๋ผ๋ **์ฐจ๋ถ์ ์ ํ**ํ๋ค.\n */\nexport function shiftWindow(fromMs: number, toMs: number, basis: 'previous' | 'yesterday'): KpiWindow {\n const span = toMs - fromMs\n const back = basis === 'yesterday' ? 24 * 60 * 60_000 : span\n return { fromMs: fromMs - back, toMs: toMs - back }\n}\n\n/**\n * ์ค์๊ฐ ์ฐจ์ด(ํ์ฌ โ ๋น๊ต๊ตฌ๊ฐ) โ **๋ ๋ค ์ธก์ ๋ ๊ฒ๋ง** ๋ธ๋ค.\n *\n * ํ์ชฝ์ด ๊ฒฐ์ธก์ด๋ฉด ์ฐจ์ด๋ **์๋ ๊ฒ**์ด๋ค(0 ์ด ์๋๋ค). 0 ์ผ๋ก ๋ด๋ฉด \"๋ณํ ์์\" ์ด๋ผ๋ ๊ฑฐ์ง์ด ๋๋ค.\n * ์ข๊ณ ๋์จ์ ํ๋จํ์ง ์๋๋ค โ ์ฒ๋ฆฌ๋์ ํด์๋ก, ์์๋ ์์์๋ก ์ข๋ค๋ ํด์์ ์๋น์ฒ์ ๋ชซ์ด๋ค.\n */\nexport function deltaP50(now: DurationStats, prev: DurationStats): number | undefined {\n return now.count > 0 && prev.count > 0 ? now.p50Ms - prev.p50Ms : undefined\n}\n\n/** ๊ตฌ๊ฐ ํ๋์ ์ต์ ์์ฝ โ ์ถ์ธ๋ฅผ ๊ทธ๋ฆด ์ ๋ณด๋ง(์ ์ฒด KPI ๋ฅผ ๊ตฌ๊ฐ๋ง๋ค ์ค์ด ๋ณด๋ด์ง ์๋๋ค). */\nexport interface KpiBucket {\n fromMs: number\n toMs: number\n tasks: number\n orders: number\n /** ๊ทธ ๊ตฌ๊ฐ์ ์์
์๊ฐ ์ค์๊ฐ โ ์ถ์ธ์์ \"๋๋ ค์ง๊ณ ์๋๊ฐ\" ๋ฅผ ๋ณด๋ ๊ฐ. */\n workP50Ms: number\n}\n\n/**\n * ์ฐฝ์ N ๋ฑ๋ถํด ๊ตฌ๊ฐ๋ณ๋ก ์ฒ๋ฆฌํ๋ค โ **๊ฐ์ ์ด๋ฒคํธ๋ฅผ ์ฐฝ๋ง ๋ฐ๊ฟ** ๋ค์ ๊ณ์ฐํ๋ค(์กฐํ ์ถ๊ฐ ์์).\n *\n * ๋ง์ง๋ง ๊ตฌ๊ฐ์ ๋๋จธ์ง๋ฅผ ํก์ํ๋ค(๋ถ๋์์ ๋๋์
์ผ๋ก ๋์ด ๋ฐ๋ฆฌ๋ฉด ๋ง์ง๋ง ์๋ฃ๊ฐ ๋น ์ง๋ค).\n * `count <= 1` ์ด๋ฉด ์ชผ๊ฐค ๊ฒ์ด ์์ผ๋ฏ๋ก ๋น ๋ฐฐ์ด โ ํธ์ถ๋ถ๊ฐ \"์ถ์ธ ์์\" ์ผ๋ก ๋ค๋ฃฌ๋ค.\n */\nexport function foldKpiBuckets(events: KpiEvent[], window: KpiWindow, count: number): KpiBucket[] {\n const n = Math.max(0, Math.min(48, Math.floor(count)))\n if (n <= 1) return []\n const step = (window.toMs - window.fromMs) / n\n const out: KpiBucket[] = []\n for (let i = 0; i < n; i++) {\n const fromMs = window.fromMs + step * i\n const toMs = i === n - 1 ? window.toMs : window.fromMs + step * (i + 1)\n const b = foldKpi(events, { fromMs, toMs })\n out.push({ fromMs, toMs, tasks: b.throughput.tasks, orders: b.throughput.orders, workP50Ms: b.workTime.p50Ms })\n }\n return out\n}\n"]}
|