do flow pridana ekonomika
This commit is contained in:
@@ -41,6 +41,11 @@ function kwh(v: number | null | undefined, d = 2): string {
|
||||
return v.toFixed(d)
|
||||
}
|
||||
|
||||
function czk(v: number | null | undefined): string {
|
||||
if (v == null) return '–'
|
||||
return v.toLocaleString('cs-CZ', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
||||
}
|
||||
|
||||
function aggregateFlows(days: DailyEnergyFlows[]): FlowTotals & {
|
||||
pv_production_kwh: number
|
||||
grid_import_kwh: number
|
||||
@@ -48,6 +53,10 @@ function aggregateFlows(days: DailyEnergyFlows[]): FlowTotals & {
|
||||
batt_charge_kwh: number
|
||||
batt_discharge_kwh: number
|
||||
load_kwh: number
|
||||
grid_import_cashflow_czk: number
|
||||
grid_export_revenue_czk: number
|
||||
grid_to_load_cost_czk: number
|
||||
grid_to_batt_cost_czk: number
|
||||
} {
|
||||
const z = {
|
||||
pv_production_kwh: 0,
|
||||
@@ -63,6 +72,10 @@ function aggregateFlows(days: DailyEnergyFlows[]): FlowTotals & {
|
||||
batt_to_grid_kwh: 0,
|
||||
grid_to_load_kwh: 0,
|
||||
grid_to_batt_kwh: 0,
|
||||
grid_import_cashflow_czk: 0,
|
||||
grid_export_revenue_czk: 0,
|
||||
grid_to_load_cost_czk: 0,
|
||||
grid_to_batt_cost_czk: 0,
|
||||
}
|
||||
for (const d of days) {
|
||||
z.pv_production_kwh += d.pv_production_kwh
|
||||
@@ -78,6 +91,10 @@ function aggregateFlows(days: DailyEnergyFlows[]): FlowTotals & {
|
||||
z.batt_to_grid_kwh += d.batt_to_grid_kwh
|
||||
z.grid_to_load_kwh += d.grid_to_load_kwh
|
||||
z.grid_to_batt_kwh += d.grid_to_batt_kwh
|
||||
z.grid_import_cashflow_czk += d.grid_import_cashflow_czk ?? 0
|
||||
z.grid_export_revenue_czk += d.grid_export_revenue_czk ?? 0
|
||||
z.grid_to_load_cost_czk += d.grid_to_load_cost_czk ?? 0
|
||||
z.grid_to_batt_cost_czk += d.grid_to_batt_cost_czk ?? 0
|
||||
}
|
||||
return z
|
||||
}
|
||||
@@ -167,6 +184,17 @@ export default function EnergyFlows() {
|
||||
? Math.min(100, (totals.batt_discharge_kwh / totals.batt_charge_kwh) * 100)
|
||||
: null
|
||||
|
||||
const avgImportKcPerKwh =
|
||||
totals && totals.grid_import_kwh > 0.001
|
||||
? totals.grid_import_cashflow_czk / totals.grid_import_kwh
|
||||
: null
|
||||
const avgExportKcPerKwh =
|
||||
totals && totals.grid_export_kwh > 0.001
|
||||
? totals.grid_export_revenue_czk / totals.grid_export_kwh
|
||||
: null
|
||||
const gridNetCzk =
|
||||
totals != null ? totals.grid_import_cashflow_czk - totals.grid_export_revenue_czk : null
|
||||
|
||||
return (
|
||||
<main className="mx-auto max-w-7xl space-y-6 px-4 py-6 md:px-8">
|
||||
{siteReady && siteRow && (
|
||||
@@ -239,7 +267,7 @@ export default function EnergyFlows() {
|
||||
)}
|
||||
|
||||
{totals && (
|
||||
<div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-4">
|
||||
<div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-5">
|
||||
<div className="rounded-xl border border-slate-800 bg-slate-900 p-4">
|
||||
<p className="text-xs font-medium uppercase tracking-wide text-amber-400">Perspektiva FVE</p>
|
||||
<p className="mt-2 text-2xl font-semibold text-white">{totals.pv_production_kwh.toFixed(1)} kWh</p>
|
||||
@@ -296,6 +324,50 @@ export default function EnergyFlows() {
|
||||
zaokrouhlení po 15min intervalech.
|
||||
</p>
|
||||
</div>
|
||||
<div className="rounded-xl border border-slate-800 bg-slate-900 p-4">
|
||||
<p className="text-xs font-medium uppercase tracking-wide text-rose-400">Perspektiva financí</p>
|
||||
<p className="mt-2 text-sm text-slate-400">
|
||||
Nákup ze sítě:{' '}
|
||||
<span className="font-semibold text-red-200">{czk(totals.grid_import_cashflow_czk)}</span> Kč
|
||||
</p>
|
||||
<p className="mt-1 text-sm text-slate-400">
|
||||
Prodej do sítě:{' '}
|
||||
<span className="font-semibold text-green-200">{czk(totals.grid_export_revenue_czk)}</span> Kč
|
||||
</p>
|
||||
<p className="mt-1 text-sm text-slate-300">
|
||||
Bilance sítě (nákup − prodej):{' '}
|
||||
<span className="font-semibold text-white">{czk(gridNetCzk)}</span> Kč
|
||||
</p>
|
||||
<ul className="mt-2 space-y-1 border-t border-slate-800 pt-2 text-xs text-slate-400">
|
||||
<li>
|
||||
Prům. cena nákupu:{' '}
|
||||
{avgImportKcPerKwh != null ? (
|
||||
<span className="text-rose-200/90">{avgImportKcPerKwh.toFixed(3)} Kč/kWh</span>
|
||||
) : (
|
||||
<span>–</span>
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
Prům. cena prodeje:{' '}
|
||||
{avgExportKcPerKwh != null ? (
|
||||
<span className="text-emerald-200/90">{avgExportKcPerKwh.toFixed(3)} Kč/kWh</span>
|
||||
) : (
|
||||
<span>–</span>
|
||||
)}
|
||||
</li>
|
||||
</ul>
|
||||
<p className="mt-2 text-[11px] font-medium uppercase tracking-wide text-slate-500">
|
||||
Rozpad nákladů importu (efektivní cena × modelovaný tok)
|
||||
</p>
|
||||
<ul className="mt-1 space-y-1 text-xs text-slate-400">
|
||||
<li>Do spotřeby: {czk(totals.grid_to_load_cost_czk)} Kč</li>
|
||||
<li>Do baterie: {czk(totals.grid_to_batt_cost_czk)} Kč</li>
|
||||
</ul>
|
||||
<p className="mt-2 border-t border-slate-800 pt-2 text-[11px] leading-snug text-slate-500">
|
||||
Stejná jednotková cena v každém 15min slotu; součet rozpadu se může mírně lišit od celkového nákupu kvůli
|
||||
zaokrouhlení a odchylce modelu toků od měřeného importu.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -14,6 +14,10 @@ export type DailyEnergyFlows = {
|
||||
batt_to_grid_kwh: number
|
||||
grid_to_load_kwh: number
|
||||
grid_to_batt_kwh: number
|
||||
grid_import_cashflow_czk: number
|
||||
grid_export_revenue_czk: number
|
||||
grid_to_load_cost_czk: number
|
||||
grid_to_batt_cost_czk: number
|
||||
}
|
||||
|
||||
export type DailyEnergyFlowsResponse = {
|
||||
|
||||
Reference in New Issue
Block a user