-
Risultati Stimati
-
-
-
--
-
Consumo Dispositivo
-
-
-
-
--
-
Energia da Batteria
-
-
-
--
-
Energia a Batteria
-
-
-
--
-
Prelievo da Rete
-
-
-
--
-
Costo Totale Rete
+
+
+
+
+ Risultati Stimati
+
+
+
+
+ --
+
+
+ Consumo Dispositivo
+
+
+
+
--
+
+ Energia da FV
+
+
+
+
+ --
+
+
+ Energia da Batteria
+
+
+
+
+ --
+
+
+ Energia a Batteria
+
+
+
+
+ --
+
+
+ Prelievo da Rete
+
+
+
+
--
+
+ Costo Totale Rete
+
+
+
+ Nota: il consumo del dispositivo avviene solo nelle
+ ore specificate e presenta fluttuazioni (5%). La
+ produzione FV è stimata (con fluttuazioni dinamiche
+ basate su zona/stagione/tipo giornata) considerando
+ un ciclo giorno/notte.
+
-
- Nota: il consumo del dispositivo avviene solo nelle ore specificate e presenta fluttuazioni (5%). La produzione FV è stimata (con fluttuazioni dinamiche basate su zona/stagione/tipo giornata) considerando un ciclo giorno/notte.
-
-
-
-
Andamento Energetico Simulato
-
-
+
+
+ Andamento Energetico Simulato
+
+
+
+
+
+ Premi "Calcola" per generare il grafico.
+
-
Premi "Calcola" per generare il grafico.
+
+
-
-
+
-
+ includeBatteryCheckbox.addEventListener("change", () =>
+ batteryInputsDiv.classList.toggle(
+ "hidden",
+ !includeBatteryCheckbox.checked,
+ ),
+ );
+
+ function displayError(messageKey, lang = currentLang) {
+ errorMessageDiv.textContent =
+ translations[lang][messageKey] || messageKey;
+ errorMessageDiv.classList.remove("hidden");
+ }
+ function clearError() {
+ errorMessageDiv.classList.add("hidden");
+ errorMessageDiv.textContent = "";
+ }
+ function formatEnergy(wh) {
+ if (wh === null || isNaN(wh)) return "--";
+ if (Math.abs(wh) < 1000) return wh.toFixed(1) + " Wh";
+ if (Math.abs(wh) < 1000000)
+ return (wh / 1000).toFixed(2) + " kWh";
+ return (wh / 1000000).toFixed(3) + " MWh";
+ }
+
+ calculateBtn.addEventListener("click", () => {
+ clearError();
+ chartMessageP.classList.add("hidden");
+ const t = translations[currentLang];
+
+ const powerDeviceAvgW = parseFloat(powerInput.value);
+ const deviceStartHour = parseInt(
+ deviceStartHourInput.value,
+ 10,
+ );
+ const deviceOpHours = parseFloat(
+ deviceOperatingHoursInput.value,
+ );
+ const costPerKwh = parseFloat(
+ costInput.value.replace(",", "."),
+ );
+ const totalHours = parseFloat(timeInput.value);
+
+ let errors = [];
+ if (isNaN(powerDeviceAvgW) || powerDeviceAvgW <= 0)
+ errors.push("errorDevicePower");
+ if (
+ isNaN(deviceStartHour) ||
+ deviceStartHour < 0 ||
+ deviceStartHour > 23
+ )
+ errors.push("errorDeviceStartHour");
+ if (isNaN(deviceOpHours) || deviceOpHours <= 0)
+ errors.push("errorDeviceOpHours");
+ if (isNaN(costPerKwh) || costPerKwh < 0)
+ errors.push("errorGridCost");
+ if (isNaN(totalHours) || totalHours <= 0)
+ errors.push("errorSimDuration");
+
+ const usePv = includePvCheckbox.checked;
+ let pvPeakPowerkWp = 0,
+ season = seasonSelect.value,
+ zone = geographicZoneSelect.value,
+ dayType = dayTypeSelect.value;
+ let useSimWeather = useSimulatedWeatherCheckbox.checked;
+
+ let avgDailyPvEnergyWh_target_base = 0;
+ let pvDaylightConfig =
+ seasonalDaylightAndPowerRefHours[season] ||
+ seasonalDaylightAndPowerRefHours.mezzaStagione;
+ let currentDayTypeModifier =
+ dayTypeModifiers[dayType] || dayTypeModifiers.sunny;
+
+ // Validate pvDaylightConfig exists and has required properties
+ if (
+ !pvDaylightConfig ||
+ typeof pvDaylightConfig.refHoursForPowerCalc !== "number" ||
+ pvDaylightConfig.refHoursForPowerCalc <= 0
+ ) {
+ pvDaylightConfig =
+ seasonalDaylightAndPowerRefHours.mezzaStagione;
+ }
+
+ if (usePv) {
+ pvPeakPowerkWp = parseFloat(pvPeakPowerInput.value);
+ if (isNaN(pvPeakPowerkWp) || pvPeakPowerkWp <= 0)
+ errors.push("errorPvPeakPower");
+
+ const currentYieldFactors = yieldFactors[zone];
+ if (
+ currentYieldFactors &&
+ currentYieldFactors[season] !== undefined
+ ) {
+ const selectedYieldFactor = currentYieldFactors[season];
+ avgDailyPvEnergyWh_target_base =
+ pvPeakPowerkWp * 1000 * selectedYieldFactor; // Energy for a sunny day
+ } else {
+ errors.push("errorPvCombination");
+ }
+ }
+
+ const useBattery = includeBatteryCheckbox.checked;
+ let batteryCapacityKWh = 0,
+ currentBatteryChargePercentage = 0;
+ let batteryMaxEnergyWh = 0,
+ currentBatteryEnergyWh = 0;
+ if (useBattery) {
+ batteryCapacityKWh = parseFloat(batteryCapacityInput.value);
+ currentBatteryChargePercentage = parseFloat(
+ initialBatteryChargeInput.value,
+ );
+ if (isNaN(batteryCapacityKWh) || batteryCapacityKWh <= 0)
+ errors.push("errorBatteryCapacity");
+ if (
+ isNaN(currentBatteryChargePercentage) ||
+ currentBatteryChargePercentage < 0 ||
+ currentBatteryChargePercentage > 100
+ )
+ errors.push("errorInitialBattery");
+ batteryMaxEnergyWh = batteryCapacityKWh * 1000;
+ currentBatteryEnergyWh =
+ batteryMaxEnergyWh *
+ (currentBatteryChargePercentage / 100);
+ }
+
+ if (errors.length > 0) {
+ displayError(errors[0]);
+ return;
+ }
+
+ const numberOfIntervals = Math.max(
+ Math.ceil(totalHours * 4),
+ 96,
+ ); // Higher resolution for PV curve
+ const timePerIntervalHours = totalHours / numberOfIntervals;
+ const deviceFluctuationPercentage = 0.05;
+
+ // Apply day type modifier to the target daily energy
+ let avgDailyPvEnergyWh_target_adjusted =
+ avgDailyPvEnergyWh_target_base *
+ currentDayTypeModifier.yieldFactor;
+
+ // Apply simulated weather modifier
+ if (usePv && useSimWeather) {
+ const weatherModifier = 0.8 + Math.random() * 0.4; // Random factor between 0.8 (-20%) and 1.2 (+20%)
+ avgDailyPvEnergyWh_target_adjusted *= weatherModifier;
+ }
+
+ let pvPowerBaseForCurveShape = 0;
+ if (
+ usePv &&
+ pvDaylightConfig &&
+ pvDaylightConfig.refHoursForPowerCalc > 0 &&
+ avgDailyPvEnergyWh_target_adjusted > 0
+ ) {
+ pvPowerBaseForCurveShape =
+ avgDailyPvEnergyWh_target_adjusted /
+ pvDaylightConfig.refHoursForPowerCalc;
+ }
+
+ let totalDeviceEnergyWh = 0,
+ simulatedTotalPvEnergyWh_beforeScaling = 0,
+ totalEnergyDrawnFromBatteryWh = 0;
+ let totalEnergyChargedToBatteryWh = 0,
+ totalGridEnergyWh = 0;
+
+ const timeLabels = [],
+ deviceConsumptionData = [],
+ pvProductionData_raw = [],
+ batteryChargeData = [],
+ gridConsumptionData = [];
+
+ // --- Simulation Loop (Phase 1: Calculate Raw PV Production based on curve shape) ---
+ for (let i = 0; i < numberOfIntervals; i++) {
+ const currentIntervalStartSimTime =
+ i * timePerIntervalHours;
+ const currentHourOfDay = currentIntervalStartSimTime % 24;
+
+ let intervalPvPowerW_shaped = 0;
+ if (usePv) {
+ if (
+ currentHourOfDay >= pvDaylightConfig.start &&
+ currentHourOfDay < pvDaylightConfig.end
+ ) {
+ // Bell-curve shaping (simplified sinusoidal)
+ const hoursIntoDaylight =
+ currentHourOfDay - pvDaylightConfig.start;
+ const daylightDuration =
+ pvDaylightConfig.end - pvDaylightConfig.start;
+ const peakHour =
+ pvDaylightConfig.start + daylightDuration / 2;
+
+ // More pronounced peak for sunny days, flatter for cloudy
+ let shapeFactor = Math.sin(
+ (Math.PI * hoursIntoDaylight) /
+ daylightDuration,
+ );
+ shapeFactor = Math.pow(
+ shapeFactor,
+ currentDayTypeModifier.shapeIntensity,
+ ); // Sharpen/flatten peak
+
+ intervalPvPowerW_shaped =
+ pvPowerBaseForCurveShape * shapeFactor;
+
+ // Add random fluctuation based on day type variability
+ const randomFluctuation =
+ (Math.random() * 2 - 1) *
+ currentDayTypeModifier.variabilityFactor;
+ intervalPvPowerW_shaped *= 1 + randomFluctuation;
+
+ intervalPvPowerW_shaped = Math.max(
+ 0,
+ Math.min(
+ intervalPvPowerW_shaped,
+ pvPeakPowerkWp * 1000,
+ ),
+ );
+ } else {
+ intervalPvPowerW_shaped = 0; // Night time
+ }
+ const intervalPvEnergyWh =
+ intervalPvPowerW_shaped * timePerIntervalHours;
+ simulatedTotalPvEnergyWh_beforeScaling +=
+ intervalPvEnergyWh;
+ pvProductionData_raw.push(intervalPvPowerW_shaped);
+ } else {
+ pvProductionData_raw.push(0);
+ }
+ }
+
+ // --- PV Energy Reconciliation (Phase 2) ---
+ let pvScalingFactor = 1;
+ if (usePv && simulatedTotalPvEnergyWh_beforeScaling > 0.001) {
+ // Avoid division by zero or tiny numbers
+ const numberOfSimulatedDays = totalHours / 24;
+ const targetTotalPvEnergyWh_forSimDuration =
+ avgDailyPvEnergyWh_target_adjusted *
+ numberOfSimulatedDays;
+ pvScalingFactor =
+ targetTotalPvEnergyWh_forSimDuration /
+ simulatedTotalPvEnergyWh_beforeScaling;
+ } else if (usePv && avgDailyPvEnergyWh_target_adjusted > 0) {
+ // If target > 0 but simulated is very small/zero, use a high scaling factor instead of 0
+ const numberOfSimulatedDays = totalHours / 24;
+ const targetTotalPvEnergyWh_forSimDuration =
+ avgDailyPvEnergyWh_target_adjusted *
+ numberOfSimulatedDays;
+ pvScalingFactor = Math.min(
+ targetTotalPvEnergyWh_forSimDuration / 0.001,
+ 1000,
+ ); // Cap at 1000x scaling
+ }
+
+ const pvProductionData_scaled = pvProductionData_raw.map((p) =>
+ Math.max(0, p * pvScalingFactor),
+ ); // Ensure no negative after scaling
+ let finalTotalPvEnergyWh = 0;
+ if (usePv) {
+ pvProductionData_scaled.forEach((power) => {
+ finalTotalPvEnergyWh += power * timePerIntervalHours;
+ });
+ }
+
+ // --- Simulation Loop (Phase 3: Device, Battery, Grid with Scaled PV) ---
+ // Reset totals for the main simulation pass
+ totalDeviceEnergyWh = 0;
+ totalGridEnergyWh = 0;
+ // totalEnergyDrawnFromBatteryWh and totalEnergyChargedToBatteryWh are reset implicitly by not accumulating from prev runs
+ // currentBatteryEnergyWh is reset to initial for each calculation run
+
+ if (useBattery) {
+ // Reset battery for this simulation run
+ currentBatteryEnergyWh =
+ batteryMaxEnergyWh *
+ (currentBatteryChargePercentage / 100);
+ totalEnergyDrawnFromBatteryWh = 0; // Explicitly reset these for clarity
+ totalEnergyChargedToBatteryWh = 0;
+ }
+
+ for (let i = 0; i < numberOfIntervals; i++) {
+ const currentIntervalStartSimTime =
+ i * timePerIntervalHours;
+ let intervalDevicePowerW = 0;
+ const intervalMidPoint =
+ currentIntervalStartSimTime + timePerIntervalHours / 2;
+ let deviceIsActiveInThisInterval = false;
+
+ if (currentIntervalStartSimTime < totalHours) {
+ for (let dayOffset = 0; ; dayOffset++) {
+ // Loop through potential days
+ const dayStartTimeOffset = dayOffset * 24;
+ const currentDayDeviceStart =
+ dayStartTimeOffset + deviceStartHour;
+ const currentDayDeviceEnd =
+ dayStartTimeOffset +
+ deviceStartHour +
+ deviceOpHours;
+
+ if (currentDayDeviceStart >= totalHours) break; // This device cycle starts after simulation ends
+
+ if (
+ intervalMidPoint >= currentDayDeviceStart &&
+ intervalMidPoint < currentDayDeviceEnd
+ ) {
+ deviceIsActiveInThisInterval = true;
+ break;
+ }
+ if (
+ currentDayDeviceEnd >
+ currentIntervalStartSimTime + totalHours + 24
+ )
+ break; // Optimization
+ }
+ }
+
+ if (deviceIsActiveInThisInterval) {
+ const deviceRandomFluctuation =
+ (Math.random() * 2 - 1) *
+ deviceFluctuationPercentage;
+ intervalDevicePowerW =
+ powerDeviceAvgW * (1 + deviceRandomFluctuation);
+ intervalDevicePowerW = Math.max(
+ 0,
+ intervalDevicePowerW,
+ );
+ }
+ const actualIntervalDeviceEnergyWh =
+ intervalDevicePowerW * timePerIntervalHours;
+ totalDeviceEnergyWh += actualIntervalDeviceEnergyWh;
+
+ const intervalPvPowerW_final = usePv
+ ? pvProductionData_scaled[i]
+ : 0;
+ const intervalPvEnergyWh_final =
+ intervalPvPowerW_final * timePerIntervalHours;
+
+ let energyFromGridThisInterval = 0,
+ energyFromBatteryThisInterval = 0,
+ energyToBatteryThisInterval = 0;
+ let energyToGridThisInterval = 0; // Track energy fed back to grid
+ let netAfterPv =
+ actualIntervalDeviceEnergyWh - intervalPvEnergyWh_final;
+
+ if (useBattery) {
+ if (netAfterPv > 0) {
+ // Need more energy than PV provides
+ const canDrawFromBattery = Math.min(
+ netAfterPv,
+ currentBatteryEnergyWh,
+ );
+ energyFromBatteryThisInterval = canDrawFromBattery;
+ currentBatteryEnergyWh -= canDrawFromBattery;
+ totalEnergyDrawnFromBatteryWh += canDrawFromBattery;
+ energyFromGridThisInterval =
+ netAfterPv - canDrawFromBattery;
+ } else {
+ // Have surplus PV energy
+ const surplusPv = Math.abs(netAfterPv);
+ const canChargeToBattery = Math.min(
+ surplusPv,
+ batteryMaxEnergyWh - currentBatteryEnergyWh,
+ );
+ energyToBatteryThisInterval = canChargeToBattery;
+ currentBatteryEnergyWh += canChargeToBattery;
+ totalEnergyChargedToBatteryWh += canChargeToBattery;
+ // Remaining surplus goes to grid
+ energyToGridThisInterval =
+ surplusPv - canChargeToBattery;
+ }
+ } else {
+ if (netAfterPv > 0) {
+ energyFromGridThisInterval = netAfterPv;
+ } else {
+ // All surplus goes to grid when no battery
+ energyToGridThisInterval = Math.abs(netAfterPv);
+ }
+ }
+
+ energyFromGridThisInterval = Math.max(
+ 0,
+ energyFromGridThisInterval,
+ );
+ energyToGridThisInterval = Math.max(
+ 0,
+ energyToGridThisInterval,
+ );
+ totalGridEnergyWh += energyFromGridThisInterval;
+
+ timeLabels.push(
+ currentIntervalStartSimTime.toFixed(1) + "h",
+ );
+ deviceConsumptionData.push(intervalDevicePowerW.toFixed(1));
+ if (useBattery)
+ batteryChargeData.push(
+ (
+ (currentBatteryEnergyWh / batteryMaxEnergyWh) *
+ 100
+ ).toFixed(1),
+ );
+ gridConsumptionData.push(
+ (
+ energyFromGridThisInterval / timePerIntervalHours
+ ).toFixed(1),
+ );
+ }
+
+ const finalTotalCost = (totalGridEnergyWh / 1000) * costPerKwh;
+
+ energyConsumedDeviceOutput.textContent =
+ formatEnergy(totalDeviceEnergyWh);
+ energyFromPvOutput.textContent = usePv
+ ? formatEnergy(finalTotalPvEnergyWh)
+ : "--";
+ energyFromBatteryOutput.textContent = useBattery
+ ? formatEnergy(totalEnergyDrawnFromBatteryWh)
+ : "--";
+ energyToBatteryOutput.textContent = useBattery
+ ? formatEnergy(totalEnergyChargedToBatteryWh)
+ : "--";
+ energyFromGridOutput.textContent =
+ formatEnergy(totalGridEnergyWh);
+ totalCostOutput.textContent = finalTotalCost.toLocaleString(
+ currentLang === "it" ? "it-IT" : "en-US",
+ { style: "currency", currency: "EUR" },
+ );
+
+ if (consumptionChart) consumptionChart.destroy();
+ const datasets = [
+ {
+ label: t.chartLabelDeviceConsumption,
+ data: deviceConsumptionData,
+ borderColor: "rgba(255, 99, 132, 1)",
+ backgroundColor: "rgba(255, 99, 132, 0.1)",
+ tension: 0.3,
+ fill: true,
+ yAxisID: "yPower",
+ },
+ {
+ label: t.chartLabelGridDraw,
+ data: gridConsumptionData,
+ borderColor: "rgba(255, 159, 64, 1)",
+ backgroundColor: "rgba(255, 159, 64, 0.1)",
+ tension: 0.3,
+ fill: true,
+ yAxisID: "yPower",
+ },
+ ];
+ if (usePv) {
+ datasets.push({
+ label: t.chartLabelPvProduction,
+ data: pvProductionData_scaled.map((p) => p.toFixed(1)),
+ borderColor: "rgba(75, 192, 192, 1)",
+ backgroundColor: "rgba(75, 192, 192, 0.1)",
+ tension: 0.3,
+ fill: true,
+ yAxisID: "yPower",
+ });
+ datasets.push({
+ label: t.chartLabelAvgPvProduction,
+ data: Array(numberOfIntervals).fill(
+ (avgDailyPvEnergyWh_target_adjusted / 24).toFixed(
+ 1,
+ ),
+ ),
+ borderColor: "rgba(75, 192, 192, 0.5)",
+ borderDash: [3, 3],
+ tension: 0.1,
+ fill: false,
+ pointRadius: 0,
+ yAxisID: "yPower",
+ });
+ }
+ if (useBattery) {
+ datasets.push({
+ label: t.chartLabelBatteryCharge,
+ data: batteryChargeData,
+ borderColor: "rgba(54, 162, 235, 1)",
+ backgroundColor: "rgba(54, 162, 235, 0.1)",
+ tension: 0.3,
+ fill: false,
+ yAxisID: "yBattery",
+ });
+ }
+
+ consumptionChart = new Chart(consumptionChartCanvas, {
+ type: "line",
+ data: { labels: timeLabels, datasets: datasets },
+ options: {
+ responsive: true,
+ maintainAspectRatio: false,
+ interaction: { mode: "index", intersect: false },
+ stacked: false,
+ scales: {
+ yPower: {
+ type: "linear",
+ display: true,
+ position: "left",
+ title: {
+ display: true,
+ text: t.chartAxisPower,
+ font: { size: 12 },
+ color: "#4a5568",
+ },
+ grid: { color: "#e2e8f0" },
+ ticks: { color: "#718096" },
+ },
+ yBattery: {
+ type: "linear",
+ display: useBattery,
+ position: "right",
+ min: 0,
+ max: 100,
+ title: {
+ display: true,
+ text: t.chartAxisBattery,
+ font: { size: 12 },
+ color: "#4a5568",
+ },
+ grid: { drawOnChartArea: false },
+ ticks: { color: "#718096" },
+ },
+ x: {
+ title: {
+ display: true,
+ text: t.chartAxisDuration,
+ font: { size: 14, weight: "500" },
+ color: "#4a5568",
+ },
+ grid: { display: false },
+ ticks: {
+ color: "#718096",
+ maxRotation: 45,
+ autoSkip: true,
+ maxTicksLimit: 24,
+ },
+ },
+ },
+ plugins: {
+ legend: {
+ position: "top",
+ labels: {
+ font: { size: 10 },
+ color: "#4a5568",
+ },
+ },
+ tooltip: {
+ callbacks: {
+ label: function (context) {
+ let label = context.dataset.label || "";
+ if (label) label += ": ";
+ if (context.parsed.y !== null) {
+ const unit =
+ context.dataset.yAxisID ===
+ "yBattery"
+ ? " %"
+ : " W";
+ label +=
+ parseFloat(
+ context.parsed.y,
+ ).toLocaleString(
+ currentLang === "it"
+ ? "it-IT"
+ : "en-US",
+ {
+ minimumFractionDigits: 1,
+ maximumFractionDigits: 1,
+ },
+ ) + unit;
+ }
+ return label;
+ },
+ },
+ },
+ },
+ animation: { duration: 500, easing: "easeInOutQuart" },
+ },
+ });
+ });
+
+ updateUI(currentLang);
+ chartMessageP.classList.remove("hidden");
+
+
diff --git a/pages/savings-calculator.html b/pages/savings-calculator.html
index 26d826b..43b70c1 100644
--- a/pages/savings-calculator.html
+++ b/pages/savings-calculator.html
@@ -1,377 +1,806 @@
-
+
-
-
-
-
Calcolatore di Risparmio Fotovoltaico (Completo)
-
-
-
-
-
-
-
+
+
+
+
Calcolatore di Risparmio Fotovoltaico (Completo)
+
+
+
+
+
+
+
+
+
+
+ IT
+ EN
+
-
-
-
- IT
- EN
-
+
+ Calcolatore Economico Fotovoltaico
+
+
+ Analizza costi, risparmi e guadagni del tuo impianto solare.
+
-
Calcolatore Economico Fotovoltaico
-
Analizza costi, risparmi e guadagni del tuo impianto solare.
-
-
-
-
-
-
-
Gestione Gruppi di Utenze
-
-
-
- Nome Nuovo Gruppo
-
-
-
Salva Lista Corrente come Gruppo
+
+
+
+ Consumo Totale Casa (kWh)
+
-
-
-
+
+
+
+
+ Gestione Gruppi di Utenze
+
+
+
+
+ Nome Nuovo Gruppo
+
+
+
+ Salva Lista Corrente come Gruppo
+
-
-
Carica
-
Elimina
+
+
+
+ Gruppi Salvati
+
+
+
+
+ Carica
+
+
+ Elimina
+
+
-
+
+
+
+
+
+ Aggiungi Utenze Specifiche (Opzionale)
+
+
+
+ Nome Utenza
+
+
+
+ Consumo (kWh)
+
+
+
+ Aggiungi
+
+
+
+
+
+
+
+
+
+
+ Calcola Bilancio
+
+
+
+
-
-
-
Aggiungi Utenze Specifiche (Opzionale)
-
-
- Nome Utenza
-
-
-
- Consumo (kWh)
-
-
-
Aggiungi
-
-
-
-
-
+
+
+
+
+
+ Riepilogo Economico
+
+
+
+
+ Costo dalla Rete
+
+
+ -
+
+
+
+
+ Risparmio Autoconsumo
+
+
+ -
+
+
+
+
+ Guadagno Immissione
+
+
+ -
+
+
+
+
+ Bilancio Finale
+
+
+ -
+
+
+
+
-
-
-
- Calcola Bilancio
-
+
+
+
+ Riepilogo Energetico (kWh)
+
+
+
+
+ Energia Autoconsumata
+
+
+ -
+
+
+
+
+ Energia da Rete
+
+
+ -
+
+
+
+
+ Energia Immessa
+
+
+ -
+
+
+
+
+ Totale Prodotto da FV
+
+
+ -
+
+
+
+
+
+
+
+
+ Analisi Costi Utenze Specifiche
+
+
+
+
+
+
+
+
+
+ Ripartizione Fonti Energetiche (Consumo Casa)
+
+
+
+
+
+ Dalla Rete: -%
+
+
+
+ Da Fotovoltaico: -%
+
+
+
+
+
+
+
+ Incidenza Utenze sui Consumi Totali
+
+
+
+
+
+ Totale Utenze Specifiche: -%
+
+
+
+ Altri Consumi: -%
+
+
+
-
-
-
-
-
-
-
-
Riepilogo Economico
-
-
-
-
Risparmio Autoconsumo
-
-
-
-
-
Guadagno Immissione
-
-
-
-
-
-
+
-
+
+