<script lang="ts">
import * as H from '../../../../helpers'
import type { Sample } from '../../../../plot'
import { Derived, updatePv } from './calcul'
import type { PVGIS } from './calcul'
import { getContext } from 'svelte'
import { derived, type Readable, type Writable } from 'svelte/store'
import { onMount } from 'svelte'
import type { Communaute } from '../../../../grain-types'
const _simulation: Derived = getContext('simulation')
let communaute: Writable<Communaute | null> = getContext('communaute')
const soleil: Writable<Sample> = getContext('soleil')
const pvgis: Writable<{ pvgis: PVGIS | null; loading: boolean }> =
getContext('pvgis')
let maxProd = $state(0)
soleil.subscribe((value: Sample) => {
console.log('Soleil', value)
for (let v of value.weekly.y) {
maxProd = Math.max(maxProd, v)
}
})
_simulation.p.puissance.subscribe((value: number) => {
console.log('Puissance change')
updatePv(value, $communaute, pvgis, soleil)
})
const fmt2 = Intl.NumberFormat('fr-FR', { maximumFractionDigits: 2 })
const fmt0 = Intl.NumberFormat('fr-FR', { maximumFractionDigits: 0 })
const tarifLocal = _simulation.tarifLocal
const chiffreAffaires = _simulation.chiffreAffaires
const N = _simulation.N
const investissement = _simulation.investissement
const charges = _simulation.charges
const interetsDetteSenior = _simulation.interetsDetteSenior
const banque = _simulation.banque.resultat
const resultatNet = _simulation.resultatNet
const _coutElec = _simulation.p.cout_elec
const inflationElec = _simulation.p.inflation_elec
const autoprod = _simulation.p.autoprod
const productible = _simulation.p.productible
const puissance = _simulation.p.puissance
const degradation = _simulation.p.degradation
const _consoMoyenneFoyer = _simulation.p.conso_moyenne_foyer
onMount(() => {
updatePv(_simulation.s.puissance, $communaute, pvgis, soleil)
})
// let an = new Date().getFullYear()
const arr = 0
// let resultatNetData: { id: string; data: { x: number; y: number }[] }[] =
// $derived(() => {
// return [
// {
// id: '',
// data: new Array($N).fill(0).map((_, i) => {
// return { x: an + i, y: $resultatNet[i] }
// }),
// },
// ]
// })
// data: new Array($N).fill(0).map((_, i) => {
// return { x: an + i, y: $resultatNet[i] }
// }),
// Synthèse
const consoMoyenneFoyer = $derived((i: number) =>
Math.min(
$_consoMoyenneFoyer,
H.productionAnnuelle($productible, $puissance, $degradation, i) /
$autoprod
)
)
const coutElec = $derived.by(() => {
let cout = 0
for (let i = 0; i < $N; i++) {
cout +=
$_coutElec *
Math.pow(1 + $inflationElec / 100, i) *
consoMoyenneFoyer(i)
}
return cout
})
const coutElecAuto = $derived.by(() => {
let cout = 0
for (let i = 0; i < $N; i++) {
cout +=
($tarifLocal[i] * consoMoyenneFoyer(i) * $autoprod) / 100 +
($_coutElec *
Math.pow(1 + $inflationElec / 100, i) *
consoMoyenneFoyer(i) *
(100 - $autoprod)) /
100
}
return cout
})
function sum_(x: number[], n: number) {
let sum = 0
for (let i = 0; i < n; i++) {
sum += x[i]
}
return sum
}
function format(x: number) {
let f = 0
let s = ''
if (Math.abs(x) <= 1000) {
s = ' €'
f = x
} else if (Math.abs(x) < 1000000) {
s = ' k€'
f = x / 1000
} else if (Math.abs(x) < 1000000000) {
s = ' M€'
f = x / 1000000
} else {
s = ' mds€'
f = x / 1000000000
}
return fmt2.format(f) + s
}
function rentabiliteTaux(resultat: number): string {
return (
fmt0.format(
$investissement ? (resultat * 100) / $investissement - 100 : 0
) + '%'
)
}
// let maxa = $state(0)
// let mina = $state(0)
// let margin = $state(1)
function traceArray(
f: Array<number>,
n: number
): { maxa: number; mina: number; margin: number; c: string } {
let maxa = 0
let mina = 0
let margin = 1
let c = ''
let ai = 0
maxa = -1 / 0
mina = 1 / 0
for (let i = 0; i < n; i++) {
ai += f[i]
maxa = Math.max(maxa, ai)
mina = Math.min(mina, ai)
c += ` ${c ? 'L' : 'M'} ${i.toFixed(arr)}, ${-ai.toFixed(arr)}`
}
if (maxa == -1 / 0) {
maxa = 0
mina = 0
}
margin = Math.max(1, (maxa - mina) / 20)
return { maxa, mina, margin, c }
}
let tr: Readable<{
mina: number
maxa: number
c: string
margin: number
}> = derived([resultatNet, N], ([$resultatNet, $N]) => {
console.log('TRACE')
// return { maxa: 0, mina: 0, margin: 1, c: '' }
return traceArray($resultatNet, $N)
})
const roiDate = $derived.by(() => {
let sum = 0
let lastNeg = 0
for (let i = 0; i < $N; i += 1) {
sum += $resultatNet[i]
if (sum < 0) lastNeg = i
}
lastNeg += 1
if (lastNeg < $N) {
if (lastNeg <= 1 && sum >= 0) {
return `Tout de suite`
} else if (lastNeg == 1) {
return `1 an`
} else {
return `${lastNeg} ans`
}
} else {
return 'À la saint Glinglin'
}
})
const rembPret = $derived((n: number) => {
let totalRembAnnuel_n = $banque.remboursementAnnuel
.slice(0, n)
.reduce((a, b) => a + b, 0)
let totalInteret_n = sum_($interetsDetteSenior, n)
let totalRembAnnuel = $banque.remboursementAnnuel.reduce(
(a, b) => a + b,
0
)
let totalInteret = sum_($interetsDetteSenior, n)
return fmt0.format(
totalRembAnnuel + totalInteret
? ((totalRembAnnuel_n + totalInteret_n) * 100) /
(totalRembAnnuel + totalInteret)
: 0
)
})
const economieFoyerMois = $derived(
fmt2.format(
coutElec ? (coutElec - coutElecAuto) / (coutElec / ($N * 12)) : 0
)
)
</script>
<div class="p-10">
<h1 class="my-8 text-4xl font-bold">
En un regard, <span class="text-primary">tout</span> votre projet.
</h1>
<div class="my-5 py-2 total flex flex-col gap-20">
<h2 class="text-2xl my-4">Synthèse durée totale {$N} ans</h2>
<div class="flex justify-around gap-10 px-10">
<div class="flex flex-col text-center gap-2">
<div class="donnee">
{format(sum_($chiffreAffaires, $N))}
</div>
<div>Chiffre d'affaire</div>
</div>
<div class="flex flex-col text-center gap-2">
<div class="donnee">
{format(sum_($charges, $N))}
</div>
<div>Charges d'exploitation</div>
</div>
<div class="flex flex-col text-center gap-2">
<div class="donnee">
{format(sum_($resultatNet, $N))}
</div>
<div>Résultat net</div>
</div>
</div>
<div class="flex justify-around gap-10 px-10">
<div class="flex-col text-center gap-2">
<div class="donnee">
{format($investissement)}
</div>
<div>Montant de l'investissement</div>
</div>
<div class="flex-col text-center gap-2">
<div class="donnee">
{rentabiliteTaux(sum_($resultatNet, $N))}
</div>
<div>Retour sur investissement</div>
</div>
<div class="flex-col text-center gap-2">
<div class="donnee">{roiDate}</div>
<div>Point de rentabilité</div>
</div>
</div>
<div class="flex justify-around gap-10 px-10">
<div class="flex flex-col justify-around text-center gap-2">
<div class="py-3 my-auto">
<svg
viewBox="{Math.floor(-$N * 0.05)} {Math.floor(
-$tr.maxa - $tr.margin
)} {Math.ceil($N * 1.1)} {Math.ceil(
$tr.maxa - $tr.mina + 2 * $tr.margin
)}"
xmlns="http://www.w3.org/2000/svg"
width="250px"
height="100px"
preserveAspectRatio="none">
<path
d={$tr.c}
fill="transparent"
stroke-width="2"
vector-effect="non-scaling-stroke"
stroke="#b71515" />
</svg>
</div>
<div>Résultat net</div>
</div>
<div class="flex flex-col justify-between text-center gap-2">
<div
style="width:250px"
class="py-3 flex justify-center my-auto">
<div class="ms-3 loading" class:hidden={!$pvgis.loading}>
</div>
<svg
class:hidden={$pvgis.loading || !maxProd}
viewBox="-10 0 270 {maxProd}"
preserveAspectRatio="none"
xmlns="http://www.w3.org/2000/svg"
width="250px"
height="100px">
{#each $soleil.weekly.y as p, i (i)}
<path
d="M {i * 5}, {maxProd} L {i * 5}, {maxProd -
p}"
fill="transparent"
stroke-width="2"
stroke="#ffbf00" />
{/each}
</svg>
<svg
class="donnee"
class:hidden={$pvgis.loading || maxProd}
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
fill="currentColor"
viewBox="0 0 16 16">
<path
d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278" />
</svg>
</div>
<div>Production annuelle</div>
</div>
</div>
<div class="flex justify-around p-5">
<div class="me-3 flex flex-col text-center gap-2">
<div class="donnee">
{$N ? format(sum_($resultatNet, $N) / $N) : '0€'}
</div>
<div>Bénéfice annuel moyen</div>
</div>
<div class="ms-3 flex flex-col text-center gap-2">
<div class="donnee">
{#if coutElec - coutElecAuto > 0}
{format(coutElec - coutElecAuto)}
({economieFoyerMois} mois)
{:else}
Aucune 😢
{/if}
</div>
<div>Economies consommateur</div>
</div>
</div>
</div>
<div class="my-10 py-2 dix">
<h2 class="text-2xl my-4">Synthèse 10 ans</h2>
<div class="flex justify-around p-10">
<div class="flex flex-col text-center gap-2">
<div class="donnee">
{format(sum_($chiffreAffaires, 10))}
</div>
<div>Chiffre d'affaire</div>
</div>
<div class="flex flex-col text-center gap-2">
<div class="donnee">
{format(sum_($charges, 10))}
</div>
<div>Coût total</div>
</div>
<div class="flex flex-col text-center gap-2">
<div class="donnee">
{format(sum_($resultatNet, 10))}
</div>
<div>Résultat net</div>
</div>
</div>
<div class="flex justify-around p-5">
<div class="flex flex-col text-center gap-2">
<div class="donnee">{rembPret(10)}%</div>
<div>Prêt remboursé</div>
</div>
<div class="flex flex-col text-center gap-2">
<div class="donnee">
{rentabiliteTaux(sum_($resultatNet, 10))}
</div>
<div>Rentabilité</div>
</div>
</div>
</div>
<div class="my-5 py-10 cinq">
<h2 class="text-2xl my-4">Synthèse 5 ans</h2>
<div class="flex justify-around p-5 gap-3">
<div class="flex flex-col text-center">
<div class="donnee">
{format(sum_($chiffreAffaires, 5))}
</div>
<div>Chiffre d'affaire</div>
</div>
<div class="flex flex-col text-center">
<div class="donnee">
{format(sum_($charges, 5))}
</div>
<div>Coût total</div>
</div>
<div class="flex flex-col text-center">
<div class="donnee">
{format(sum_($resultatNet, 5))}
</div>
<div>Résultat net</div>
</div>
</div>
<div class="flex justify-around p-5">
<div class="flex flex-col text-center">
<div class="donnee">{rembPret(5)}%</div>
<div>Prêt remboursé</div>
</div>
<div class="flex-col text-center gap-2">
<div class="donnee">
{rentabiliteTaux(sum_($resultatNet, 5))}
</div>
<div>Rentabilité</div>
</div>
</div>
</div>
<div class="my-5 py-10 moyenne">
<h2 class="text-2xl my-4">Synthèse année moyenne</h2>
<div class="flex justify-between flex-wrap py-5">
<div class="flex flex-col text-center mx-3">
<div class="donnee">
{format(sum_($resultatNet, $N) / $N)}
</div>
<div>Bénéfices moyen</div>
</div>
<div class="flex flex-col text-center mx-3">
<div class="donnee">
{format(sum_($chiffreAffaires, $N) / $N)}
</div>
<div>Chiffre d'affaire</div>
</div>
<div class="flex flex-col text-center mx-3">
<div class="donnee">
{fmt2.format(
($investissement
? (sum_($resultatNet, $N) * 100) / $investissement -
100
: 0) / $N
)}%
</div>
<div>Rentabilité annuelle</div>
</div>
<div class="flex flex-col text-center mx-3">
<div class="donnee">
{#if coutElec - coutElecAuto > 0}
{fmt0.format(
((coutElec - coutElecAuto) * 100) / coutElec
)}%
{:else}
Aucune 😢
{/if}
</div>
<div>Économies consommateur</div>
</div>
</div>
</div>
</div>
<style lang="scss">
$gp-1: #b71515;
$gp-2: #d71c19;
$gp-3: #de601e;
$gs-1: #cf3e39;
.loading {
color: #ffbf00;
}
h5 {
font-size: 1.5rem;
font-weight: bold;
}
#syntheseTabContent h5 {
border-bottom: 3px solid;
font-size: 1.75rem;
padding-bottom: 5px;
}
.donnee {
font-size: 2rem;
font-weight: bold;
}
.total .donnee {
color: $gp-1;
}
.total h5 {
color: $gp-1;
border-color: $gp-1;
}
.dix .donnee {
color: $gp-2;
}
.dix h5 {
color: $gp-2;
border-color: $gp-2;
}
.cinq .donnee {
color: $gp-3;
}
.cinq h5 {
color: $gp-3;
border-color: $gp-3;
}
.moyenne .donnee {
color: $gs-1;
}
.moyenne h5 {
color: $gs-1;
border-color: $gs-1;
}
</style>