E6LXIE7VBUGCR762DFTHYZISEWYFV5E3NM3MGLT5Z7YFQQ5GTYRQC
5R7SS5AWSCPT4WWCS5WUBRFULLXATBZW4FFPBT6S5EYJVEWKL5NQC
LX2ZVNAYX2FRCEIJ6XBCBILB3O7YT52AP56QDWCCGLATFCEB7KHQC
7MCTB5G2W6IB7JQXGO2HCMRHBUYIOKXI4MBODKLAJIK66EMLC5ZQC
P7KZ25R4CNS4PZITRWPBVXRFSLY5TKCOFO6U3SDKX45ITNVU773QC
C56DYYC72SFNR6BSKCOVDY2QW6XNP66EUGGKCBROTCFJVQDB4FUAC
DB6B3MEDBTEEIS6KOSJH7L5JFXKDMATJARZ6AR7TF2HCCKTFRZJQC
PI6D6Y5EHSXHSILBYHKRKXWXZ6H6JOR5ZTP44CXBW4LUUIREY7OQC
XTPX4PYLPGJAEK52LYOYHLVRCL7N5FFAEY4E3OL23LOWLYPLCILQC
V3QTRVNR5EVDZ2O2WRK7ZCVKSGGYBSNILH44OWXKOJK2ME5JC7UQC
QHVOZBISIQ3E3P5F6GGKWVDSXC4OA23HCIH2OMXEVGXKSF5W4APAC
KNH5OGCTL3YCOQQPA32M76SGWHGHAPQRIZ7S2CBC5DGIEV32SOYQC
FERLNXU2QISSKOUBSPABB2ERHOWHQRI2GVKDJ352Y4B2FUXBRGRQC
RLLNOBJM5LB446HWBUNDLNMG35PTUFRBRRVNHMFTX7CMQC4JSXUQC
Y62XTAEHAC5MNJELNKACRLEVBUU2MKYKFPHB5M2S5X46B4EI2JJQC
import Banque from '../../Banque.svelte'
import Simulation from './Simulation.svelte'
import { page } from '$app/stores';
import { enhance, applyAction } from '$app/forms';
import { onMount } from 'svelte';
import type { SubmitFunction } from '@sveltejs/kit';
import Banque from '../../Banque.svelte'
import Simulation from './Simulation.svelte'
import { page } from '$app/stores';
import { base as b, assets as a } from '$app/paths';
import { enhance, applyAction } from '$app/forms';
import { onMount } from 'svelte';
import type { SubmitFunction } from '@sveltejs/kit';
let fmt = (n: number) => Intl.NumberFormat('fr-FR', { maximumFractionDigits: n });
$: p = data.simulation
let fmt = (n: number) => Intl.NumberFormat('fr-FR', { maximumFractionDigits: n });
$: p = data.simulation
onMount(async () => {
email.set(data.email || null)
email.subscribe((value) => { if(value) data.email = value })
let modal = document.getElementById('grainSaveModal')
console.log("mount modal", modal)
if(modal) {
document.body.appendChild(modal);
}
if(!window.bootstrap) {
console.log("no window bootstrap, load");
window.bootstrap = await import('bootstrap')
}
menuElt = document.getElementById('menuoff')
if(!menuElt) {
return
}
menu = new window.bootstrap.Offcanvas(menuElt)
const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]')
for(let t of popoverTriggerList) {
new window.bootstrap.Popover(t)
}
})
onMount(async () => {
email.set(data.email || null)
email.subscribe((value) => { if(value) data.email = value })
let modal = document.getElementById('grainSaveModal')
console.log("mount modal", modal)
if(modal) {
document.body.appendChild(modal);
}
if(!window.bootstrap) {
console.log("no window bootstrap, load");
window.bootstrap = await import('bootstrap')
}
menuElt = document.getElementById('menuoff')
if(!menuElt) {
return
}
menu = new window.bootstrap.Offcanvas(menuElt)
const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]')
for(let t of popoverTriggerList) {
new window.bootstrap.Popover(t)
}
})
async function saveModal(_e: Event) {
console.log("saveModal", _e)
if(!saveModal_) {
console.log("no saveModal")
saveModal_ = new window.bootstrap.Modal('#grainSaveModal', {
focus: false,
keyboard: true,
})
}
async function saveModal(_e: Event) {
console.log("saveModal", _e)
if(!saveModal_) {
console.log("no saveModal")
saveModal_ = new window.bootstrap.Modal('#grainSaveModal', {
focus: false,
keyboard: true,
})
}
function showSaveModalAfterMenuHide() {
// menuElt?.removeEventListener('hidden.bs.offcanvas', showSaveModalAfterMenuHide)
let c = document.getElementsByClassName("offcanvas-backdrop")
for(const elt of c) {
elt.parentElement?.removeChild(elt)
}
saveModal_?.show()
}
function showSaveModalAfterMenuHide() {
// menuElt?.removeEventListener('hidden.bs.offcanvas', showSaveModalAfterMenuHide)
let c = document.getElementsByClassName("offcanvas-backdrop")
for(const elt of c) {
elt.parentElement?.removeChild(elt)
}
saveModal_?.show()
}
let save: SubmitFunction = async ({ formData }) => {
console.log("save called")
formData.set('data', JSON.stringify(p))
formData.set('prms', JSON.stringify(data.prms))
saveModal_?.hide()
return async ({ result }) => {
console.log(JSON.stringify(result))
await applyAction(result);
};
}
let save: SubmitFunction = async ({ formData }) => {
console.log("save called")
formData.set('data', JSON.stringify(p))
formData.set('prms', JSON.stringify(data.prms))
saveModal_?.hide()
return async ({ result }) => {
console.log(JSON.stringify(result))
await applyAction(result);
};
}
$: compteActive = ($page.url.hash == "#compte") ? "active": ""
$: banqueActive = ($page.url.hash == "#banque") ? "active": ""
$: expertActive = (expert && $page.url.hash == "#expert") ? "active": ""
$: simuActive = ((true || !data.guest) && $page.url.hash == "#simu") ? "active": ""
$: syntheseActive = (!compteActive && !banqueActive && !simuActive && !expertActive) ? "active": ""
$: compteActive = ($page.url.hash == "#compte") ? "active": ""
$: banqueActive = ($page.url.hash == "#banque") ? "active": ""
$: expertActive = (expert && $page.url.hash == "#expert") ? "active": ""
$: simuActive = ((true || !data.guest) && $page.url.hash == "#simu") ? "active": ""
$: syntheseActive = (!compteActive && !banqueActive && !simuActive && !expertActive) ? "active": ""
$: compteShow = compteActive ? "show": ""
$: banqueShow = banqueActive ? "show": ""
$: simuShow = simuActive ? "show": ""
$: syntheseShow = syntheseActive ? "show": ""
$: expertShow = expertActive ? "show": ""
$: compteShow = compteActive ? "show": ""
$: banqueShow = banqueActive ? "show": ""
$: simuShow = simuActive ? "show": ""
$: syntheseShow = syntheseActive ? "show": ""
$: expertShow = expertActive ? "show": ""
function tarifSurplus_(puissance: number): number {
let resultat = p.tarifCRE.prix[0];
for(let i = 0; i < p.tarifCRE.limites.length; i++) {
if(puissance < p.tarifCRE.limites[i]) {
return resultat
} else {
resultat = p.tarifCRE.prix[i]
}
}
return resultat
}
function tarifSurplus_(puissance: number): number {
let resultat = p.tarifCRE.prix[0];
for(let i = 0; i < p.tarifCRE.limites.length; i++) {
if(puissance < p.tarifCRE.limites[i]) {
return resultat
} else {
resultat = p.tarifCRE.prix[i]
}
}
return resultat
}
const surface_kwc = 5
let surface = surface_kwc * (p?.puissance || 0)
function onSurfaceChange(ev: ChangeEvent) {
surface = ev.target.value
p.puissance = surface / surface_kwc
}
function onPuissanceChange(ev: ChangeEvent) {
p.puissance = ev.target.value
surface = p.puissance * surface_kwc
}
$: chiffreAffaires = (i: number) =>((i == 0) ? primeInvestissement : 0) + productionAnnuelle(i) * (autoconso * tarifLocal(i) + (1 - autoconso) * tarifSurplus(i) + p.autoprod * tarifAllo(i)/100)
$: chiffreAffaires = (i: number) =>((i == 0) ? primeInvestissement : 0) + productionAnnuelle(i) * (autoconso * tarifLocal(i) + (1 - autoconso) * tarifSurplus(i) + p.autoprod * tarifAllo(i)/100)
$: turpe = (i: number) => (p.puissance * p.turpe + (1-autoconso) * productionAnnuelle(i) * p.turpeInjection) * Math.pow(1+p.inflation/100, i)
$: turpe = (i: number) => (p.puissance * p.turpe + (1-autoconso) * productionAnnuelle(i) * p.turpeInjection) * Math.pow(1+p.inflation/100, i)
$: charges = (i: number) => (investissement && i == 0 ? p.fraisDivers : 0) + exploitation(i) + turpe(i) + assurance(i) + divers(i)
$: charges = (i: number) => (investissement && i == 0 ? p.fraisDivers : 0) + exploitation(i) + turpe(i) + assurance(i) + divers(i)
// Exonération de taxe foncière: https://www.legifrance.gouv.fr/codes/article_lc/LEGIARTI000044996150
$: taxeFonciere = (_: number) => 0
// Exonération de taxe foncière: https://www.legifrance.gouv.fr/codes/article_lc/LEGIARTI000044996150
$: taxeFonciere = (_: number) => 0
// Déductions fiscales
$: amortissement = (i: number) => (i < p.dureeAmortissement) ? investissement / p.dureeAmortissement: 0
// Déductions fiscales
$: amortissement = (i: number) => (i < p.dureeAmortissement) ? investissement / p.dureeAmortissement: 0
$: resultatFiscal = (i: number) => ebe(i) - amortissement(i) - provisionOnduleurs(i) - interetsDetteSenior(i) - interetsDSRA(i)
$: resultatFiscal = (i: number) => ebe(i) - amortissement(i) - provisionOnduleurs(i) - interetsDetteSenior(i) - interetsDSRA(i)
$: coutElec = () => {
let cout = 0
for(let i = 0; i < N; i++) {
cout += p.coutElec * Math.pow(1 + p.inflationElec / 100, i) * consoMoyenneFoyer(i)
$: coutElec = () => {
let cout = 0
for(let i = 0; i < N; i++) {
cout += p.coutElec * Math.pow(1 + p.inflationElec / 100, i) * consoMoyenneFoyer(i)
$: coutElecAuto = () => {
let cout = 0
for(let i = 0; i < N; i++) {
cout += tarifLocal(i) * consoMoyenneFoyer(i) * p.autoprod / 100
+ p.coutElec * Math.pow(1 + p.inflationElec / 100, i) * consoMoyenneFoyer(i) * (100 - p.autoprod) / 100
}
return cout
}
$: coutElecAuto = () => {
let cout = 0
for(let i = 0; i < N; i++) {
cout += tarifLocal(i) * consoMoyenneFoyer(i) * p.autoprod / 100
+ p.coutElec * Math.pow(1 + p.inflationElec / 100, i) * consoMoyenneFoyer(i) * (100 - p.autoprod) / 100
}
return cout
}
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 fmt(2).format(f) + s
}
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 fmt(2).format(f) + s
}
function rentabiliteTaux(x:number,y:number){
return fmt(2).format(
y ?
((x*100/y)-100)
: 0
) + "%"
}
function rentabiliteTaux(resultat: number): string {
return fmt(2).format(
investissement ?
((resultat*100/investissement)-100)
: 0
) + "%"
}
let maxa = -1/0
let mina = 1/0
let margin = 1
function traceArray(f: (_: number) => number, n:number){
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))}`
}
margin = Math.max(1, (maxa - mina) / 20)
return c
}
let maxa = -1/0
let mina = 1/0
let margin = 1
function traceArray(f: (_: number) => number, n:number){
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))}`
}
margin = Math.max(1, (maxa - mina) / 20)
return c
}
$: roiDate = () => {
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"
}
}
$: roiDate = () => {
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"
}
}
$: rembPret = (n:number) => {
let totalRembAnnuel_n = remboursementAnnuel.slice(0, n).reduce((a, b) => a + b, 0)
let totalInteret_n = sum(interetsDetteSenior, n)
let totalRembAnnuel =remboursementAnnuel.reduce((a, b) => a + b, 0)
let totalInteret = sum(interetsDetteSenior, n)
return fmt(2).format(
(totalRembAnnuel + totalInteret) ?
((totalRembAnnuel_n + totalInteret_n) * 100 / (totalRembAnnuel + totalInteret))
: 0
)
}
$: rembPret = (n:number) => {
let totalRembAnnuel_n = remboursementAnnuel.slice(0, n).reduce((a, b) => a + b, 0)
let totalInteret_n = sum(interetsDetteSenior, n)
let totalRembAnnuel =remboursementAnnuel.reduce((a, b) => a + b, 0)
let totalInteret = sum(interetsDetteSenior, n)
return fmt(2).format(
(totalRembAnnuel + totalInteret) ?
((totalRembAnnuel_n + totalInteret_n) * 100 / (totalRembAnnuel + totalInteret))
: 0
)
}
<input class="form-control form-control-sm" type="number" id="puissance" min="1" bind:value={p.puissance}/>
<input class="form-control form-control-sm" type="number" id="puissance" min="1" value={p.puissance} on:change={onPuissanceChange} />
</div>
<div class="my-3">
<label class="form-label" for="puissance">Surface totale (m²)</label>
<input class="form-control form-control-sm" type="number" id="surface" min="1" value={surface} on:change={onSurfaceChange} />
<div class="flex-column text-center">
<div class="flex-column text-center mx-3">
<div class="donnee">{fmt(2).format((investissement ? ((sum(resultatNet, N)*100/investissement)-100): 0) / N)}%
</div>
<div>Rentabilité annuelle</div>
</div>
<div class="flex-column text-center mx-3">
<Simulation prmsFeature={prmsFeature} bind:prms={data.prms} puissance={p.puissance} bind:prodWeekly={prodWeekly} bind:maxProd={maxProd} bind:pvgis_loading={pvgis_loading} />
<Simulation base={base} assets={assets} prmsFeature={prmsFeature} bind:prms={data.prms} puissance={p.puissance} bind:prodWeekly={prodWeekly} bind:maxProd={maxProd} bind:pvgis_loading={pvgis_loading} />
let fmt = (n: number) => Intl.NumberFormat('fr-FR', { maximumFractionDigits: n });
function format(x : number){
let f = 0
let s = ''
if (Math.abs(x) <= 1000){
s = ' kWc'
f = x
} else if(Math.abs(x) <= 1000000) {
s = ' MWc€'
f = x/1000
} else {
s = ' GWc'
f = x/1000000
}
return fmt(2).format(f) + s
}