@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.
Files changed (327) hide show
  1. package/dist-server/engine/canonical-ingest.d.ts +10 -1
  2. package/dist-server/engine/canonical-ingest.js +110 -33
  3. package/dist-server/engine/canonical-ingest.js.map +1 -1
  4. package/dist-server/engine/event-time.d.ts +25 -0
  5. package/dist-server/engine/event-time.js +98 -0
  6. package/dist-server/engine/event-time.js.map +1 -0
  7. package/dist-server/engine/index.d.ts +2 -0
  8. package/dist-server/engine/index.js +23 -0
  9. package/dist-server/engine/index.js.map +1 -1
  10. package/dist-server/engine/ingest-dedupe.d.ts +18 -6
  11. package/dist-server/engine/ingest-dedupe.js +201 -15
  12. package/dist-server/engine/ingest-dedupe.js.map +1 -1
  13. package/dist-server/engine/ingest-health.d.ts +60 -1
  14. package/dist-server/engine/ingest-health.js +43 -8
  15. package/dist-server/engine/ingest-health.js.map +1 -1
  16. package/dist-server/engine/kpi-fold.d.ts +19 -0
  17. package/dist-server/engine/kpi-fold.js +4 -1
  18. package/dist-server/engine/kpi-fold.js.map +1 -1
  19. package/dist-server/engine/kpi-query.js +23 -3
  20. package/dist-server/engine/kpi-query.js.map +1 -1
  21. package/dist-server/engine/oee-accumulator.d.ts +35 -2
  22. package/dist-server/engine/oee-accumulator.js +56 -4
  23. package/dist-server/engine/oee-accumulator.js.map +1 -1
  24. package/dist-server/engine/twin-engine.d.ts +72 -3
  25. package/dist-server/engine/twin-engine.js +118 -5
  26. package/dist-server/engine/twin-engine.js.map +1 -1
  27. package/dist-server/index.js +21 -0
  28. package/dist-server/index.js.map +1 -1
  29. package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.d.ts +5 -0
  30. package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.js +66 -0
  31. package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.js.map +1 -0
  32. package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.d.ts +5 -0
  33. package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.js +79 -0
  34. package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.js.map +1 -0
  35. package/dist-server/migrations/index.js +5 -1
  36. package/dist-server/migrations/index.js.map +1 -1
  37. package/dist-server/routes.js +12 -20
  38. package/dist-server/routes.js.map +1 -1
  39. package/dist-server/service/actuation/actuation-advisor.d.ts +60 -0
  40. package/dist-server/service/actuation/actuation-advisor.js +53 -0
  41. package/dist-server/service/actuation/actuation-advisor.js.map +1 -0
  42. package/dist-server/service/actuation/actuation-outcome.d.ts +52 -0
  43. package/dist-server/service/actuation/actuation-outcome.js +34 -0
  44. package/dist-server/service/actuation/actuation-outcome.js.map +1 -0
  45. package/dist-server/service/actuation/actuation-rule-resolver.d.ts +19 -0
  46. package/dist-server/service/actuation/actuation-rule-resolver.js +161 -0
  47. package/dist-server/service/actuation/actuation-rule-resolver.js.map +1 -0
  48. package/dist-server/service/actuation/actuation-rule.d.ts +55 -0
  49. package/dist-server/service/actuation/actuation-rule.js +130 -0
  50. package/dist-server/service/actuation/actuation-rule.js.map +1 -0
  51. package/dist-server/service/actuation/approval-gateway.d.ts +20 -0
  52. package/dist-server/service/actuation/approval-gateway.js +14 -0
  53. package/dist-server/service/actuation/approval-gateway.js.map +1 -0
  54. package/dist-server/service/actuation/catch-up-effects.d.ts +16 -0
  55. package/dist-server/service/actuation/catch-up-effects.js +120 -0
  56. package/dist-server/service/actuation/catch-up-effects.js.map +1 -0
  57. package/dist-server/service/actuation/command-dispatcher.d.ts +206 -8
  58. package/dist-server/service/actuation/command-dispatcher.js +191 -14
  59. package/dist-server/service/actuation/command-dispatcher.js.map +1 -1
  60. package/dist-server/service/actuation/command-store.d.ts +10 -2
  61. package/dist-server/service/actuation/command-store.js +168 -5
  62. package/dist-server/service/actuation/command-store.js.map +1 -1
  63. package/dist-server/service/actuation/dispatch-after-approval.d.ts +11 -0
  64. package/dist-server/service/actuation/dispatch-after-approval.js +73 -0
  65. package/dist-server/service/actuation/dispatch-after-approval.js.map +1 -0
  66. package/dist-server/service/actuation/effect-match.d.ts +53 -0
  67. package/dist-server/service/actuation/effect-match.js +65 -0
  68. package/dist-server/service/actuation/effect-match.js.map +1 -0
  69. package/dist-server/service/actuation/index.d.ts +21 -2
  70. package/dist-server/service/actuation/index.js +21 -2
  71. package/dist-server/service/actuation/index.js.map +1 -1
  72. package/dist-server/service/actuation/retry-plan.d.ts +63 -0
  73. package/dist-server/service/actuation/retry-plan.js +99 -0
  74. package/dist-server/service/actuation/retry-plan.js.map +1 -0
  75. package/dist-server/service/actuation/rule-evaluate.d.ts +127 -0
  76. package/dist-server/service/actuation/rule-evaluate.js +205 -0
  77. package/dist-server/service/actuation/rule-evaluate.js.map +1 -0
  78. package/dist-server/service/actuation/rule-loop.d.ts +5 -0
  79. package/dist-server/service/actuation/rule-loop.js +156 -0
  80. package/dist-server/service/actuation/rule-loop.js.map +1 -0
  81. package/dist-server/service/actuation/rule-runner.d.ts +52 -0
  82. package/dist-server/service/actuation/rule-runner.js +135 -0
  83. package/dist-server/service/actuation/rule-runner.js.map +1 -0
  84. package/dist-server/service/actuation/rule-wiring.d.ts +24 -0
  85. package/dist-server/service/actuation/rule-wiring.js +80 -0
  86. package/dist-server/service/actuation/rule-wiring.js.map +1 -0
  87. package/dist-server/service/actuation/settle-effects.d.ts +21 -0
  88. package/dist-server/service/actuation/settle-effects.js +101 -0
  89. package/dist-server/service/actuation/settle-effects.js.map +1 -0
  90. package/dist-server/service/actuation/sweep-dispatch.d.ts +37 -0
  91. package/dist-server/service/actuation/sweep-dispatch.js +125 -0
  92. package/dist-server/service/actuation/sweep-dispatch.js.map +1 -0
  93. package/dist-server/service/actuation/twin-command-resolver.d.ts +120 -0
  94. package/dist-server/service/actuation/twin-command-resolver.js +406 -0
  95. package/dist-server/service/actuation/twin-command-resolver.js.map +1 -0
  96. package/dist-server/service/actuation/twin-command.d.ts +81 -0
  97. package/dist-server/service/actuation/twin-command.js +60 -0
  98. package/dist-server/service/actuation/twin-command.js.map +1 -1
  99. package/dist-server/service/actuation/twin-now.d.ts +41 -0
  100. package/dist-server/service/actuation/twin-now.js +65 -0
  101. package/dist-server/service/actuation/twin-now.js.map +1 -0
  102. package/dist-server/service/index.d.ts +5 -2
  103. package/dist-server/service/index.js +8 -0
  104. package/dist-server/service/index.js.map +1 -1
  105. package/dist-server/service/reference/actuation-routing.d.ts +60 -0
  106. package/dist-server/service/reference/actuation-routing.js +126 -0
  107. package/dist-server/service/reference/actuation-routing.js.map +1 -0
  108. package/dist-server/service/reference/actuation-target.d.ts +65 -0
  109. package/dist-server/service/reference/actuation-target.js +94 -0
  110. package/dist-server/service/reference/actuation-target.js.map +1 -0
  111. package/dist-server/service/reference/connection-portability-resolver.d.ts +29 -0
  112. package/dist-server/service/reference/connection-portability-resolver.js +181 -0
  113. package/dist-server/service/reference/connection-portability-resolver.js.map +1 -0
  114. package/dist-server/service/reference/connection-portability.d.ts +138 -0
  115. package/dist-server/service/reference/connection-portability.js +230 -0
  116. package/dist-server/service/reference/connection-portability.js.map +1 -0
  117. package/dist-server/service/reference/fill-cadence.d.ts +17 -0
  118. package/dist-server/service/reference/fill-cadence.js +31 -0
  119. package/dist-server/service/reference/fill-cadence.js.map +1 -0
  120. package/dist-server/service/reference/fill-dedupe.d.ts +16 -0
  121. package/dist-server/service/reference/fill-dedupe.js +63 -0
  122. package/dist-server/service/reference/fill-dedupe.js.map +1 -0
  123. package/dist-server/service/reference/fill-loop.d.ts +35 -0
  124. package/dist-server/service/reference/fill-loop.js +187 -0
  125. package/dist-server/service/reference/fill-loop.js.map +1 -0
  126. package/dist-server/service/reference/fill-span.d.ts +10 -0
  127. package/dist-server/service/reference/fill-span.js +37 -0
  128. package/dist-server/service/reference/fill-span.js.map +1 -0
  129. package/dist-server/service/reference/hook-contract.d.ts +88 -4
  130. package/dist-server/service/reference/hook-contract.js +105 -4
  131. package/dist-server/service/reference/hook-contract.js.map +1 -1
  132. package/dist-server/service/reference/hook-rejected.d.ts +25 -0
  133. package/dist-server/service/reference/hook-rejected.js +48 -0
  134. package/dist-server/service/reference/hook-rejected.js.map +1 -0
  135. package/dist-server/service/reference/index.d.ts +4 -1
  136. package/dist-server/service/reference/index.js +5 -1
  137. package/dist-server/service/reference/index.js.map +1 -1
  138. package/dist-server/service/reference/live-cadence.d.ts +68 -0
  139. package/dist-server/service/reference/live-cadence.js +44 -0
  140. package/dist-server/service/reference/live-cadence.js.map +1 -0
  141. package/dist-server/service/reference/live-feed-lease.d.ts +15 -0
  142. package/dist-server/service/reference/live-feed-lease.js +56 -0
  143. package/dist-server/service/reference/live-feed-lease.js.map +1 -0
  144. package/dist-server/service/reference/live-ingest.d.ts +21 -0
  145. package/dist-server/service/reference/live-ingest.js +66 -0
  146. package/dist-server/service/reference/live-ingest.js.map +1 -0
  147. package/dist-server/service/reference/reference-adapter.d.ts +291 -2
  148. package/dist-server/service/reference/reference-adapter.js +19 -1
  149. package/dist-server/service/reference/reference-adapter.js.map +1 -1
  150. package/dist-server/service/reference/reference-fill-run.d.ts +50 -0
  151. package/dist-server/service/reference/reference-fill-run.js +142 -0
  152. package/dist-server/service/reference/reference-fill-run.js.map +1 -0
  153. package/dist-server/service/reference/reference-fill.d.ts +90 -0
  154. package/dist-server/service/reference/reference-fill.js +141 -0
  155. package/dist-server/service/reference/reference-fill.js.map +1 -0
  156. package/dist-server/service/reference/reference-hook.d.ts +22 -0
  157. package/dist-server/service/reference/reference-hook.js +135 -55
  158. package/dist-server/service/reference/reference-hook.js.map +1 -1
  159. package/dist-server/service/reference/reference-link-groups.d.ts +10 -0
  160. package/dist-server/service/reference/reference-link-groups.js +15 -0
  161. package/dist-server/service/reference/reference-link-groups.js.map +1 -0
  162. package/dist-server/service/reference/reference-links.d.ts +14 -0
  163. package/dist-server/service/reference/reference-links.js +73 -0
  164. package/dist-server/service/reference/reference-links.js.map +1 -0
  165. package/dist-server/service/reference/reference-live.d.ts +1 -0
  166. package/dist-server/service/reference/reference-live.js +32 -6
  167. package/dist-server/service/reference/reference-live.js.map +1 -1
  168. package/dist-server/service/reference/reference-master.d.ts +56 -2
  169. package/dist-server/service/reference/reference-master.js +33 -3
  170. package/dist-server/service/reference/reference-master.js.map +1 -1
  171. package/dist-server/service/reference/reference-resolver.d.ts +27 -0
  172. package/dist-server/service/reference/reference-resolver.js +79 -1
  173. package/dist-server/service/reference/reference-resolver.js.map +1 -1
  174. package/dist-server/service/twin-event/twin-event-keys.d.ts +31 -3
  175. package/dist-server/service/twin-event/twin-event-keys.js +36 -4
  176. package/dist-server/service/twin-event/twin-event-keys.js.map +1 -1
  177. package/dist-server/service/twin-event/twin-event.d.ts +1 -0
  178. package/dist-server/service/twin-event/twin-event.js +11 -2
  179. package/dist-server/service/twin-event/twin-event.js.map +1 -1
  180. package/dist-server/service/twin-model/choose-recipe.d.ts +15 -0
  181. package/dist-server/service/twin-model/choose-recipe.js +33 -0
  182. package/dist-server/service/twin-model/choose-recipe.js.map +1 -0
  183. package/dist-server/service/twin-model/external-resolver.d.ts +76 -0
  184. package/dist-server/service/twin-model/external-resolver.js +109 -0
  185. package/dist-server/service/twin-model/external-resolver.js.map +1 -0
  186. package/dist-server/service/twin-model/project-structure.js +16 -3
  187. package/dist-server/service/twin-model/project-structure.js.map +1 -1
  188. package/dist-server/service/twin-model/twin-equipment.d.ts +17 -0
  189. package/dist-server/service/twin-model/twin-equipment.js +10 -0
  190. package/dist-server/service/twin-model/twin-equipment.js.map +1 -1
  191. package/dist-server/service/twin-model/twin-lineage-query.js +75 -1
  192. package/dist-server/service/twin-model/twin-lineage-query.js.map +1 -1
  193. package/dist-server/service/twin-model/twin-model-item-query.js +94 -5
  194. package/dist-server/service/twin-model/twin-model-item-query.js.map +1 -1
  195. package/dist-server/service/twin-model/twin-model-tree-query.js.map +1 -1
  196. package/dist-server/service/twin-space/twin-space.d.ts +29 -0
  197. package/dist-server/service/twin-space/twin-space.js +13 -0
  198. package/dist-server/service/twin-space/twin-space.js.map +1 -1
  199. package/dist-server/service/twin-subject/event-subjects.d.ts +3 -1
  200. package/dist-server/service/twin-subject/event-subjects.js +8 -1
  201. package/dist-server/service/twin-subject/event-subjects.js.map +1 -1
  202. package/dist-shared/entity-delta.js +1 -1
  203. package/dist-shared/entity-delta.js.map +1 -1
  204. package/package.json +7 -7
  205. package/server/engine/canonical-ingest.ts +119 -33
  206. package/server/engine/event-time.ts +96 -0
  207. package/server/engine/index.ts +20 -0
  208. package/server/engine/ingest-dedupe.ts +203 -27
  209. package/server/engine/ingest-health.ts +91 -6
  210. package/server/engine/kpi-fold.ts +24 -1
  211. package/server/engine/kpi-query.ts +23 -4
  212. package/server/engine/oee-accumulator.ts +80 -8
  213. package/server/engine/twin-engine.ts +119 -5
  214. package/server/index.ts +23 -0
  215. package/server/migrations/1786600000000-RenameOperatoMesAdapterType.ts +66 -0
  216. package/server/migrations/1786700000000-AddDispatchRetryColumns.ts +82 -0
  217. package/server/migrations/index.ts +5 -1
  218. package/server/routes.ts +12 -24
  219. package/server/service/actuation/actuation-advisor.ts +124 -0
  220. package/server/service/actuation/actuation-outcome.ts +97 -0
  221. package/server/service/actuation/actuation-rule-resolver.ts +147 -0
  222. package/server/service/actuation/actuation-rule.ts +139 -0
  223. package/server/service/actuation/approval-gateway.ts +44 -0
  224. package/server/service/actuation/catch-up-effects.ts +152 -0
  225. package/server/service/actuation/command-dispatcher.ts +401 -20
  226. package/server/service/actuation/command-store.ts +182 -8
  227. package/server/service/actuation/dispatch-after-approval.ts +71 -0
  228. package/server/service/actuation/effect-match.ts +124 -0
  229. package/server/service/actuation/index.ts +21 -2
  230. package/server/service/actuation/retry-plan.ts +145 -0
  231. package/server/service/actuation/rule-evaluate.ts +352 -0
  232. package/server/service/actuation/rule-loop.ts +160 -0
  233. package/server/service/actuation/rule-runner.ts +216 -0
  234. package/server/service/actuation/rule-wiring.ts +84 -0
  235. package/server/service/actuation/settle-effects.ts +115 -0
  236. package/server/service/actuation/sweep-dispatch.ts +179 -0
  237. package/server/service/actuation/twin-command-resolver.ts +387 -0
  238. package/server/service/actuation/twin-command.ts +128 -1
  239. package/server/service/actuation/twin-now.ts +97 -0
  240. package/server/service/index.ts +9 -1
  241. package/server/service/reference/actuation-routing.ts +165 -0
  242. package/server/service/reference/actuation-target.ts +163 -0
  243. package/server/service/reference/connection-portability-resolver.ts +171 -0
  244. package/server/service/reference/connection-portability.ts +285 -0
  245. package/server/service/reference/fill-cadence.ts +29 -0
  246. package/server/service/reference/fill-dedupe.ts +66 -0
  247. package/server/service/reference/fill-loop.ts +153 -0
  248. package/server/service/reference/fill-span.ts +31 -0
  249. package/server/service/reference/hook-contract.ts +185 -5
  250. package/server/service/reference/hook-rejected.ts +53 -0
  251. package/server/service/reference/index.ts +5 -1
  252. package/server/service/reference/live-cadence.ts +129 -0
  253. package/server/service/reference/live-feed-lease.ts +56 -0
  254. package/server/service/reference/live-ingest.ts +94 -0
  255. package/server/service/reference/reference-adapter.ts +327 -5
  256. package/server/service/reference/reference-fill-run.ts +165 -0
  257. package/server/service/reference/reference-fill.ts +223 -0
  258. package/server/service/reference/reference-hook.ts +162 -56
  259. package/server/service/reference/reference-link-groups.ts +21 -0
  260. package/server/service/reference/reference-links.ts +77 -0
  261. package/server/service/reference/reference-live.ts +30 -5
  262. package/server/service/reference/reference-master.ts +90 -5
  263. package/server/service/reference/reference-resolver.ts +77 -2
  264. package/server/service/twin-event/twin-event-keys.ts +37 -4
  265. package/server/service/twin-event/twin-event.ts +18 -1
  266. package/server/service/twin-model/choose-recipe.ts +31 -0
  267. package/server/service/twin-model/external-resolver.ts +161 -0
  268. package/server/service/twin-model/project-structure.ts +16 -3
  269. package/server/service/twin-model/twin-equipment.ts +22 -0
  270. package/server/service/twin-model/twin-lineage-query.ts +82 -1
  271. package/server/service/twin-model/twin-model-item-query.ts +95 -4
  272. package/server/service/twin-model/twin-model-tree-query.ts +1 -1
  273. package/server/service/twin-space/twin-space.ts +39 -0
  274. package/server/service/twin-subject/event-subjects.ts +8 -1
  275. package/shared/entity-delta.ts +1 -1
  276. package/test/ack-shape-alignment.test.ts +97 -0
  277. package/test/actuation-approval-door.test.ts +421 -0
  278. package/test/actuation-dispatch.test.ts +16 -3
  279. package/test/actuation-effect.test.ts +162 -0
  280. package/test/actuation-outcome.test.ts +152 -0
  281. package/test/actuation-rule-runner.test.ts +281 -0
  282. package/test/actuation-rule.test.ts +266 -0
  283. package/test/actuation-seam.test.ts +249 -0
  284. package/test/actuation-settle.test.ts +164 -0
  285. package/test/actuation-target.test.ts +145 -0
  286. package/test/canonical-ingest-vocabularies.test.ts +49 -2
  287. package/test/capability-mapping.test.ts +1 -1
  288. package/test/choose-recipe.test.ts +117 -0
  289. package/test/command-store-writes-columns.test.ts +126 -0
  290. package/test/connection-portability-doors.test.ts +87 -0
  291. package/test/connector-capability-declaration.test.ts +54 -4
  292. package/test/declaration-reaches-model.test.ts +43 -0
  293. package/test/dedupe-transformation.test.ts +112 -0
  294. package/test/entity-delta.test.ts +1 -1
  295. package/test/event-subjects.test.ts +2 -1
  296. package/test/external-resolver.test.ts +171 -0
  297. package/test/fill-dedupe.test.ts +59 -0
  298. package/test/fill-loop.test.ts +35 -0
  299. package/test/first-envelope.test.ts +153 -0
  300. package/test/fold-shift-dst.test.ts +110 -0
  301. package/test/home-in-area.test.ts +90 -0
  302. package/test/hook-rejected-shape.test.ts +86 -0
  303. package/test/hook-response-sum.test.ts +193 -0
  304. package/test/hook-sequence.test.ts +1 -1
  305. package/test/ingest-dedupe.test.ts +56 -0
  306. package/test/ingest-expected-quiet.test.ts +111 -0
  307. package/test/ingest-idempotent.test.ts +79 -0
  308. package/test/ingest-reconcile-four-ways.test.ts +97 -0
  309. package/test/ingest-rules-header.test.ts +100 -0
  310. package/test/ingest-window-rolls-unobserved.test.ts +72 -0
  311. package/test/intake-mapping-parity.test.ts +175 -0
  312. package/test/live-cadence.test.ts +170 -0
  313. package/test/live-feed-lease.test.ts +63 -0
  314. package/test/live-mirror-parity.test.ts +1 -1
  315. package/test/oee-accumulator.test.ts +3 -3
  316. package/test/oee-site-calendar.test.ts +146 -0
  317. package/test/order-and-transaction-split.test.ts +107 -0
  318. package/test/reference-fill.test.ts +235 -0
  319. package/test/reference-hook.test.ts +1 -1
  320. package/test/reference-links.test.ts +56 -0
  321. package/test/retry-plan.test.ts +139 -0
  322. package/test/sweep-dispatch.test.ts +191 -0
  323. package/test/twin-event-keys.test.ts +20 -6
  324. package/test/twin-model-item-db.test.ts +6 -6
  325. package/test/twin-model-tree-db.test.ts +6 -6
  326. package/tsconfig.shared.tsbuildinfo +1 -1
  327. 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"]}