6NB2PU2F64XDSURKYMBECKEN7ZQ63RMDN2GL5CP74YA6HE4K3TTAC
3LZ4UD3N3VL3ZVTS25P3QKICCM4VXODR2OHTE5GPS2WGG3WRILYQC
J47EV2H73JKATJDKBZZNSIGAPC7G5X5DCWZ7YDN55XUNPYPS54TQC
FWV2VPFI3VIQXMY4LZ266AHP7PKBSKVMSJ6ERABTUFXCTFVEMFZQC
5LXKHEZNPK7RBJ33RTHN4Q3V5OUTM4WXZ477UOHTA34RNBPUN5DAC
UPEYNW7CF54F2XHS3SZ7NDZTFAUGJL4OJ6FHLKC7M6XLXL3M2L4QC
7MCTB5G2W6IB7JQXGO2HCMRHBUYIOKXI4MBODKLAJIK66EMLC5ZQC
PIULOOUAM6OIXXSEIAETIVEEEIQ45DEQXB6QHTDSNVQDH57TGTUAC
P7KZ25R4CNS4PZITRWPBVXRFSLY5TKCOFO6U3SDKX45ITNVU773QC
YLOKW6ERT2XEQG4T6GBPSBCQWVIHWAKBESCXJBKMQBSDXV3C2ACQC
FERLNXU2QISSKOUBSPABB2ERHOWHQRI2GVKDJ352Y4B2FUXBRGRQC
PI6D6Y5EHSXHSILBYHKRKXWXZ6H6JOR5ZTP44CXBW4LUUIREY7OQC
E6LXIE7VBUGCR762DFTHYZISEWYFV5E3NM3MGLT5Z7YFQQ5GTYRQC
QHVOZBISIQ3E3P5F6GGKWVDSXC4OA23HCIH2OMXEVGXKSF5W4APAC
5FNNIOUNDS5SG75A4ZR6VY7DS6WU2GNNCOSSHX34RFTRB7LJ3D2QC
LX2ZVNAYX2FRCEIJ6XBCBILB3O7YT52AP56QDWCCGLATFCEB7KHQC
C56DYYC72SFNR6BSKCOVDY2QW6XNP66EUGGKCBROTCFJVQDB4FUAC
DB6B3MEDBTEEIS6KOSJH7L5JFXKDMATJARZ6AR7TF2HCCKTFRZJQC
XTPX4PYLPGJAEK52LYOYHLVRCL7N5FFAEY4E3OL23LOWLYPLCILQC
V3QTRVNR5EVDZ2O2WRK7ZCVKSGGYBSNILH44OWXKOJK2ME5JC7UQC
KNH5OGCTL3YCOQQPA32M76SGWHGHAPQRIZ7S2CBC5DGIEV32SOYQC
3DZWNZUZGMHJH3JL3H7KN746C6XVNBRBFHBSVSB5AH7YYUFVYVDAC
5R7SS5AWSCPT4WWCS5WUBRFULLXATBZW4FFPBT6S5EYJVEWKL5NQC
PI4VBCLQL4EGBUJ7B2FA3GH25B22CUIOMOZZ7GNPYCS5OSLIRKPAC
LU257USNNJW57H5M5E46IB2E3IBFNYBXB6EPEM63BYC23NNVHCFQC
RLLNOBJM5LB446HWBUNDLNMG35PTUFRBRRVNHMFTX7CMQC4JSXUQC
UR5RFMWCD455OQZMTDQ2MSVJUPBNEUQHOBJ2UJBDWVHRJ4SOA5NAC
TLRGOVFX6KIWQSWRPXS73WW4EHJQ5L5W5NYMO6UM2EF2H3EPAHHQC
Y62XTAEHAC5MNJELNKACRLEVBUU2MKYKFPHB5M2S5X46B4EI2JJQC
GBEGPEQZPTMSSEHTK5MKHFYCA5ZFGYCYURMQGWC4SJSWIPHNSPHAC
F2MO5GK2AE5RLTNGFTPRGRGTJBNN5OTRXYNGDIY7QIPF5LXAAXCQC
632SZPUQC6KX3CDZLYWV22OSFIOG66CJ7PONRNTXYTFLQX3JFFXQC
"exclude": ["node_modules", "dist", "test"],
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
"exclude": ["node_modules", "dist", "test"],
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Projects */
"incremental": true, /* Enable incremental compilation */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Projects */
"incremental": true /* Enable incremental compilation */,
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2020" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"lib": [
"es2020"
] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
"jsx": "react" /* Specify what JSX code is generated. */,
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
/* Language and Environment */
"target": "es2020" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"lib": [
"es2020"
] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
"jsx": "react" /* Specify what JSX code is generated. */,
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
/* Modules */
"module": "es2020" /* Specify what module code is generated. */,
// "rootDir": "./", /* Specify the root folder within your source files. */
"moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
"types": [
"@cloudflare/workers-types",
"@types/jest",
] /* Specify type package names to be included without being referenced in a source file. */,
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
"resolveJsonModule": true /* Enable importing .json files */,
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* Modules */
"module": "es2020" /* Specify what module code is generated. */,
// "rootDir": "./", /* Specify the root folder within your source files. */
"moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
"types": [
"@cloudflare/workers-types",
"@types/jest"
] /* Specify type package names to be included without being referenced in a source file. */,
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
"resolveJsonModule": true /* Enable importing .json files */,
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
"allowJs": true /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */,
"checkJs": false /* Enable error reporting in type-checked JavaScript files. */,
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
/* JavaScript Support */
"allowJs": true /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */,
"checkJs": false /* Enable error reporting in type-checked JavaScript files. */,
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
"noEmit": true /* Disable emitting files from a compilation. */,
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
"noEmit": true /* Disable emitting files from a compilation. */,
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Interop Constraints */
"isolatedModules": true /* Ensure that each file can be safely transpiled without relying on other imports. */,
"allowSyntheticDefaultImports": true /* Allow 'import x from y' when a module doesn't have a default export. */,
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
/* Interop Constraints */
"isolatedModules": true /* Ensure that each file can be safely transpiled without relying on other imports. */,
"allowSyntheticDefaultImports": true /* Allow 'import x from y' when a module doesn't have a default export. */,
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
this.state.storage.put(
`pi.${id}`,
{
name: json.CreateProjet.name,
porteur: json.CreateProjet.porteur,
tel: json.CreateProjet.tel,
adresse: json.CreateProjet.adresse,
simulation: json.CreateProjet.simulation,
t: Date.now(),
}
)
console.log("saved", id)
this.state.storage.put(`pi.${id}`, {
name: json.CreateProjet.name,
porteur: json.CreateProjet.porteur,
tel: json.CreateProjet.tel,
adresse: json.CreateProjet.adresse,
simulation: json.CreateProjet.simulation,
t: Date.now(),
})
console.log('saved', id)
if ("SaveProjet" in json) {
let x: undefined | Grain.GetProjetResp = await this.state.storage.get(`pi.${json.SaveProjet.id}`)
if ('SaveProjet' in json) {
let x: undefined | Grain.GetProjetResp =
await this.state.storage.get(`pi.${json.SaveProjet.id}`)
if ("GetProjet" in json) {
let resp = <Grain.GetProjetResp> await this.state.storage.get(
`pi.${json.GetProjet}`
if ('GetProjet' in json) {
let resp = <Grain.GetProjetResp>(
await this.state.storage.get(`pi.${json.GetProjet}`)
if ("DelProjet" in json) {
let t: undefined | { t: string } = await this.state.storage.get(`pi.${json.DelProjet.id}`)
if(t) {
await this.state.storage.delete(
`pi.${json.DelProjet.id}`
)
if ('DelProjet' in json) {
let t: undefined | { t: string } = await this.state.storage.get(
`pi.${json.DelProjet.id}`
)
if (t) {
await this.state.storage.delete(`pi.${json.DelProjet.id}`)
let keys: Map<string, { id: string, name: string, simulation: Grain.SimulationCommunaute, t: number }> = await this.state.storage.list(opts)
let keys: Map<
string,
{
id: string
name: string
simulation: Grain.SimulationCommunaute
t: number
}
> = await this.state.storage.list(opts)
"exclude": ["node_modules", "dist", "test"],
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
"exclude": ["node_modules", "dist", "test"],
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Projects */
"incremental": true, /* Enable incremental compilation */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Projects */
"incremental": true /* Enable incremental compilation */,
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2020" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"lib": [
"es2020"
] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
"jsx": "react" /* Specify what JSX code is generated. */,
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
/* Language and Environment */
"target": "es2020" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"lib": [
"es2020"
] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
"jsx": "react" /* Specify what JSX code is generated. */,
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
/* Modules */
"module": "es2020" /* Specify what module code is generated. */,
// "rootDir": "./", /* Specify the root folder within your source files. */
"moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
"types": [
"@cloudflare/workers-types",
"@types/jest",
] /* Specify type package names to be included without being referenced in a source file. */,
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
"resolveJsonModule": true /* Enable importing .json files */,
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* Modules */
"module": "es2020" /* Specify what module code is generated. */,
// "rootDir": "./", /* Specify the root folder within your source files. */
"moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
"types": [
"@cloudflare/workers-types",
"@types/jest"
] /* Specify type package names to be included without being referenced in a source file. */,
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
"resolveJsonModule": true /* Enable importing .json files */,
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
"allowJs": true /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */,
"checkJs": false /* Enable error reporting in type-checked JavaScript files. */,
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
/* JavaScript Support */
"allowJs": true /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */,
"checkJs": false /* Enable error reporting in type-checked JavaScript files. */,
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
"noEmit": true /* Disable emitting files from a compilation. */,
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
"noEmit": true /* Disable emitting files from a compilation. */,
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Interop Constraints */
"isolatedModules": true /* Ensure that each file can be safely transpiled without relying on other imports. */,
"allowSyntheticDefaultImports": true /* Allow 'import x from y' when a module doesn't have a default export. */,
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
/* Interop Constraints */
"isolatedModules": true /* Ensure that each file can be safely transpiled without relying on other imports. */,
"allowSyntheticDefaultImports": true /* Allow 'import x from y' when a module doesn't have a default export. */,
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
console.log(coords);
let u = `https://re.jrc.ec.europa.eu/api/seriescalc?lat=${coords.lat}&lon=${coords.lng}&startyear=2016&pvcalculation=1&peakpower=1&loss=${coords.loss || 14}&outputformat=json`
console.log(coords)
let u = `https://re.jrc.ec.europa.eu/api/seriescalc?lat=${
coords.lat
}&lon=${coords.lng}&startyear=2016&pvcalculation=1&peakpower=1&loss=${
coords.loss || 14
}&outputformat=json`
import type { PlaywrightTestConfig } from '@playwright/test';
const config: PlaywrightTestConfig = {
webServer: {
command: 'npm run build && npm run preview',
port: 4173
},
testDir: 'tests'
};
export default config;
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
import adapter from '@sveltejs/adapter-cloudflare-workers';
import preprocess from 'svelte-preprocess';
import { vitePreprocess } from '@sveltejs/kit/vite';
import adapter from '@sveltejs/adapter-cloudflare-workers'
import preprocess from 'svelte-preprocess'
import { vitePreprocess } from '@sveltejs/kit/vite'
import { browser } from '$app/environment';
import { onMount, tick } from 'svelte';
import { assets as a } from '$app/paths'
import type { Grain } from '../../../grain-types'
export let lat: number = 45
export let lng: number = 7
export let puissance: number
export let prmsFeature: boolean = false
export let id: string = ""
export let prms: Grain.Prm [] = []
export let prodWeekly: number[] = []
export let maxProd: number = 0
export let assets = a as string
export let server = "https://coturnix.fr"
let consentement = false
import { browser } from '$app/environment'
import { onMount, tick } from 'svelte'
import { assets as a } from '$app/paths'
import type { Grain } from '../../../grain-types'
export let lat: number = 45
export let lng: number = 7
export let puissance: number
export let prmsFeature: boolean = false
export let id: string = ''
export let prms: Grain.Prm[] = []
export let prodWeekly: number[] = []
export let maxProd: number = 0
export let assets = a as string
export let server = 'https://coturnix.fr'
let consentement = false
let pvgis: null | {
inputs: {location:{lat:number,lng:number}},
outputs: { hourly: {time: string, "G(i)": number, P: number, T2m: number, H_sun: number, Int: number}[]}
} = null
let pvgis: null | {
inputs: { location: { lat: number; lng: number } }
outputs: {
hourly: {
time: string
'G(i)': number
P: number
T2m: number
H_sun: number
Int: number
}[]
}
} = null
$: {
initialised && updatePlot(puissance)
}
$: {
initialised && updatePlot(puissance)
}
onMount(async () => {
//@ts-ignore
Plotly = await import('plotly.js-dist')
await updatePlot(puissance)
initialised = true
})
onMount(async () => {
//@ts-ignore
Plotly = await import('plotly.js-dist')
await updatePlot(puissance)
initialised = true
})
let darkMode = false;
if(browser) {
darkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
darkMode = !!event.matches
redraw()
});
}
let darkMode = false
if (browser) {
darkMode =
window.matchMedia &&
window.matchMedia('(prefers-color-scheme: dark)').matches
window
.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', (event) => {
darkMode = !!event.matches
redraw()
})
}
let profils: Record<string, { profils: string[]}> = {
"Résidentiel ≤6kVA":{
"profils":[ "RES1-P1" ]
},
let profils: Record<string, { profils: string[] }> = {
'Résidentiel ≤6kVA': {
profils: ['RES1-P1'],
},
async function delProfil(i: number) {
pr.splice(i, 1)
pr = pr
await updatePlot(puissance)
}
async function delProfil(i: number) {
pr.splice(i, 1)
pr = pr
await updatePlot(puissance)
}
async function profile(name: string): Promise<{ coefs: number[], total: number }> {
prm_loading = true
await tick()
let profiles = await Promise.all(profils[name].profils.map(async (x) => {
let resp = await fetch(
`${assets}/profiles/${x}.csv`,
)
return await resp.text()
}))
prm_loading = false
await tick()
async function profile(
name: string
): Promise<{ coefs: number[]; total: number }> {
prm_loading = true
await tick()
let profiles = await Promise.all(
profils[name].profils.map(async (x) => {
let resp = await fetch(`${assets}/profiles/${x}.csv`)
return await resp.text()
})
)
prm_loading = false
await tick()
let annee = []
let total = 0
let file = 0;
for(let p of profiles) {
let l = 0;
for(let line of p.split('\n')) {
if(!line) {
continue
}
const col = line.split(',')
// const week = parseInt(col[0])
// const dow = parseInt(col[1])
const cs = parseFloat(col[2])
const cj = parseFloat(col[3])
for(let i = 0; i < 48; i++) {
let ch = parseFloat(col[5+i])
const c = cs * cj * ch
if(file == 0) {
annee.push(c)
} else {
annee[l] += c
}
total += c
}
l += 1
}
file += 1
}
return { coefs: annee, total }
}
let annee = []
let total = 0
let file = 0
for (let p of profiles) {
let l = 0
for (let line of p.split('\n')) {
if (!line) {
continue
}
const col = line.split(',')
// const week = parseInt(col[0])
// const dow = parseInt(col[1])
const cs = parseFloat(col[2])
const cj = parseFloat(col[3])
for (let i = 0; i < 48; i++) {
let ch = parseFloat(col[5 + i])
const c = cs * cj * ch
if (file == 0) {
annee.push(c)
} else {
annee[l] += c
}
total += c
}
l += 1
}
file += 1
}
return { coefs: annee, total }
}
async function refresh(event: SubmitEvent) {
event.preventDefault()
if(prms) {
prm_loading = true
await tick()
const resp = await fetch(
`${server}/api/grain/projet/${id || "nouveau"}/prms`, {
method: "POST",
body: JSON.stringify(prms)
}
)
if(resp.ok) {
annee = await resp.json()
}
prm_loading = false
await tick()
} else {
erreur = "La liste des PRMs est vide"
}
await updatePlot(puissance)
}
async function refresh(event: SubmitEvent) {
event.preventDefault()
if (prms) {
prm_loading = true
await tick()
const resp = await fetch(
`${server}/api/grain/projet/${id || 'nouveau'}/prms`,
{
method: 'POST',
body: JSON.stringify(prms),
}
)
if (resp.ok) {
annee = await resp.json()
}
prm_loading = false
await tick()
} else {
erreur = 'La liste des PRMs est vide'
}
await updatePlot(puissance)
}
let auto = 0
let totalProd = 0
let totalConso = 0
let soleil = {
hourly: {
x: <string[]>[],
y: <number[]>[],
},
daily: {
x: <string[]>[],
y: <number[]>[],
},
weekly: {
x: <string[]>[],
y: <number[]>[],
},
x: <string[]>[],
y: <number[]>[],
type: 'bar',
line: {
color: "#ffbf00",
width: 1,
},
marker: {
color: "#ffbf00",
width: 1,
},
name: "Production solaire",
bucket: 1,
}
let somme = {
hourly: {
x: <string[]>[],
y: <number[]>[],
},
daily: {
x: <string[]>[],
y: <number[]>[],
},
weekly: {
x: <string[]>[],
y: <number[]>[],
},
x: <string[]>[],
y: <number[]>[],
type: 'bar',
line: {
color: "#b81111",
width: 1,
},
marker: {
color: "#b81111",
width: 1,
},
name: "Consommation totale",
bucket: 1,
}
let auto = 0
let totalProd = 0
let totalConso = 0
let soleil = {
hourly: {
x: <string[]>[],
y: <number[]>[],
},
daily: {
x: <string[]>[],
y: <number[]>[],
},
weekly: {
x: <string[]>[],
y: <number[]>[],
},
x: <string[]>[],
y: <number[]>[],
type: 'bar',
line: {
color: '#ffbf00',
width: 1,
},
marker: {
color: '#ffbf00',
width: 1,
},
name: 'Production solaire',
bucket: 1,
}
let somme = {
hourly: {
x: <string[]>[],
y: <number[]>[],
},
daily: {
x: <string[]>[],
y: <number[]>[],
},
weekly: {
x: <string[]>[],
y: <number[]>[],
},
x: <string[]>[],
y: <number[]>[],
type: 'bar',
line: {
color: '#b81111',
width: 1,
},
marker: {
color: '#b81111',
width: 1,
},
name: 'Consommation totale',
bucket: 1,
}
async function updatePv(puissance: number) {
let d = new Date()
let min_t = (new Date(d.getFullYear(), 0, 1)).getTime() / 1000
let max_t = min_t + 364 * 24 * 3600
if(!pvgis || pvgis.inputs.location.latitude != lat || pvgis.inputs.location.longitude != lng) {
pvgis_loading = true
await tick()
let annuelle = await fetch(
`${server}/pvgis`, {
method: "POST",
body: JSON.stringify({
lat,
lng,
})
})
pvgis = await annuelle.json()
pvgis_loading = false
await tick()
}
soleil.hourly = {x: [], y: []};
soleil.daily = {x: [], y: []};
soleil.weekly = {x: [], y: []};
maxProd = 0
const start = new Date(min_t * 1000)
const janvier = new Date(start.getFullYear(), 0, 1)
for(let t = min_t; t < max_t; t += 3600) {
let tt = new Date(t*1000);
let tts = tt.toLocaleString()
let tds = tt.toLocaleDateString()
let pp = 0
if(pvgis) {
let len = pvgis.outputs.hourly.length
let n = ((t * 1000 - janvier.getTime()) / 3600000) % len
const pvvar = 'P'
pp = pvgis.outputs.hourly[Math.floor(n)][pvvar] * puissance / 1000
soleil.hourly.x.push(tts)
soleil.hourly.y.push(pp)
if((t - min_t) % (24 * 3600) == 0) {
if((t - min_t) % (24 * 7 * 3600) == 0) {
if(soleil.weekly.y.length) {
maxProd = Math.max(maxProd, soleil.weekly.y[soleil.weekly.y.length-1])
}
soleil.weekly.x.push(tds)
soleil.weekly.y.push(pp)
} else {
soleil.weekly.y[soleil.weekly.y.length-1] += pp
}
soleil.daily.x.push(tds)
soleil.daily.y.push(pp)
} else {
soleil.daily.y[soleil.daily.y.length-1] += pp
soleil.weekly.y[soleil.weekly.y.length-1] += pp
}
}
}
prodWeekly = soleil.weekly.y
}
async function updatePv(puissance: number) {
let d = new Date()
let min_t = new Date(d.getFullYear(), 0, 1).getTime() / 1000
let max_t = min_t + 364 * 24 * 3600
if (
!pvgis ||
pvgis.inputs.location.latitude != lat ||
pvgis.inputs.location.longitude != lng
) {
pvgis_loading = true
await tick()
let annuelle = await fetch(`${server}/pvgis`, {
method: 'POST',
body: JSON.stringify({
lat,
lng,
}),
})
pvgis = await annuelle.json()
pvgis_loading = false
await tick()
}
soleil.hourly = { x: [], y: [] }
soleil.daily = { x: [], y: [] }
soleil.weekly = { x: [], y: [] }
maxProd = 0
const start = new Date(min_t * 1000)
const janvier = new Date(start.getFullYear(), 0, 1)
for (let t = min_t; t < max_t; t += 3600) {
let tt = new Date(t * 1000)
let tts = tt.toLocaleString()
let tds = tt.toLocaleDateString()
let pp = 0
if (pvgis) {
let len = pvgis.outputs.hourly.length
let n = ((t * 1000 - janvier.getTime()) / 3600000) % len
const pvvar = 'P'
pp =
(pvgis.outputs.hourly[Math.floor(n)][pvvar] * puissance) /
1000
soleil.hourly.x.push(tts)
soleil.hourly.y.push(pp)
if ((t - min_t) % (24 * 3600) == 0) {
if ((t - min_t) % (24 * 7 * 3600) == 0) {
if (soleil.weekly.y.length) {
maxProd = Math.max(
maxProd,
soleil.weekly.y[soleil.weekly.y.length - 1]
)
}
soleil.weekly.x.push(tds)
soleil.weekly.y.push(pp)
} else {
soleil.weekly.y[soleil.weekly.y.length - 1] += pp
}
soleil.daily.x.push(tds)
soleil.daily.y.push(pp)
} else {
soleil.daily.y[soleil.daily.y.length - 1] += pp
soleil.weekly.y[soleil.weekly.y.length - 1] += pp
}
}
}
prodWeekly = soleil.weekly.y
}
let d = new Date()
const min_t = (new Date(d.getFullYear(), 0, 1)).getTime() / 1000
const max_t = min_t + 364 * 24 * 3600
for(let [prm, r] of Object.entries(annee)) {
let d: { t: number[], y: number[], i: number } = {
t: [],
y: [],
i: 0,
}
let i = 0;
for(let t = min_t; t < max_t; t += 1800) {
d.t.push(t);
d.y.push(r[i] / 1000);
i += 1
}
annee_[prm] = d
}
let d = new Date()
const min_t = new Date(d.getFullYear(), 0, 1).getTime() / 1000
const max_t = min_t + 364 * 24 * 3600
for (let [prm, r] of Object.entries(annee)) {
let d: { t: number[]; y: number[]; i: number } = {
t: [],
y: [],
i: 0,
}
let i = 0
for (let t = min_t; t < max_t; t += 1800) {
d.t.push(t)
d.y.push(r[i] / 1000)
i += 1
}
annee_[prm] = d
}
if (pr.length > 0) {
for (let p of pr) {
let d: { t: number[]; y: number[]; i: number } = {
t: [],
y: [],
i: 0,
}
let i = 0
for (let t = min_t; t <= max_t; t += 1800) {
d.t.push(t)
let pp = profs.get(p.type)
if (!pp) {
profs.set(p.type, await profile(p.type))
}
if (pp) {
d.y.push((pp.coefs[i] * p.conso) / pp.total)
}
i += 1
}
annee_[p.type] = d
}
}
if(pr.length > 0) {
for (let p of pr) {
let d: { t: number[], y: number[], i: number } = {
t: [],
y: [],
i: 0,
}
let i = 0
for(let t = min_t; t <= max_t; t += 1800) {
d.t.push(t);
let pp = profs.get(p.type)
if(!pp) {
profs.set(p.type, await profile(p.type))
}
if(pp) {
d.y.push(pp.coefs[i] * p.conso / pp.total)
}
i += 1
}
annee_[p.type] = d
}
}
auto = 0
totalProd = 0
totalConso = 0
somme.hourly = {x: [], y: []};
somme.daily = {x: [], y: []};
somme.weekly = {x: [], y: []};
const start = new Date(min_t * 1000)
const janvier = new Date(start.getFullYear(), 0, 1)
let i = 0
for (let [_, r] of Object.entries(annee_)) {
r.i = 0
}
for (let t = min_t; t < max_t; t += 3600) {
let tt = new Date(t * 1000)
let tds = tt.toLocaleDateString()
let tts = tt.toLocaleString()
let y = 0
for (let [_, r] of Object.entries(annee_)) {
// Les profils Enedis sont échantillonnés à la
// demi-heure, il faut ajouter deux points consécutifs
while (r.i < r.t.length && r.t[r.i] < t + 3600) {
if (!isNaN(r.y[r.i])) y += r.y[r.i]
r.i += 1
}
}
somme.hourly.x.push(tts)
somme.hourly.y.push(y)
if ((t - min_t) % (24 * 3600) == 0) {
if ((t - min_t) % (24 * 7 * 3600) == 0) {
somme.weekly.x.push(tds)
somme.weekly.y.push(y)
} else {
somme.weekly.y[somme.weekly.y.length - 1] += y
}
somme.daily.x.push(tds)
somme.daily.y.push(y)
} else {
somme.daily.y[somme.daily.y.length - 1] += y
somme.weekly.y[somme.weekly.y.length - 1] += y
}
totalConso += y
totalProd += soleil.hourly.y[i] * puissance
auto += Math.min(y, soleil.hourly.y[i] * puissance)
i += 1
}
if (!Plotly)
//@ts-ignore
Plotly = await import('plotly.js-dist')
const start = new Date(min_t * 1000)
const janvier = new Date(start.getFullYear(), 0, 1)
let i = 0
for(let [_, r] of Object.entries(annee_)) {
r.i = 0
}
for(let t = min_t; t < max_t; t += 3600) {
let tt = new Date(t*1000);
let tds = tt.toLocaleDateString()
let tts = tt.toLocaleString()
let y = 0
for(let [_, r] of Object.entries(annee_)) {
// Les profils Enedis sont échantillonnés à la
// demi-heure, il faut ajouter deux points consécutifs
while(r.i < r.t.length && r.t[r.i] < t + 3600) {
if(!isNaN(r.y[r.i]))
y += r.y[r.i]
r.i += 1
}
}
somme.hourly.x.push(tts)
somme.hourly.y.push(y)
if((t - min_t) % (24 * 3600) == 0) {
if((t - min_t) % (24 * 7 * 3600) == 0) {
somme.weekly.x.push(tds)
somme.weekly.y.push(y)
} else {
somme.weekly.y[somme.weekly.y.length-1] += y
}
somme.daily.x.push(tds)
somme.daily.y.push(y)
} else {
somme.daily.y[somme.daily.y.length-1] += y
somme.weekly.y[somme.weekly.y.length-1] += y
}
totalConso += y
totalProd += soleil.hourly.y[i]
auto += Math.min(y, soleil.hourly.y[i] * puissance)
i+= 1
}
if(!Plotly)
//@ts-ignore
Plotly = await import('plotly.js-dist')
await tick()
redraw()
}
await tick()
redraw()
}
function sample(
s: {
weekly: { x: (number | string)[]; y: number[] }
daily: { x: (number | string)[]; y: number[] }
hourly: { x: (number | string)[]; y: number[] }
x: (number | string)[]
y: number[]
bucket: number
},
w?: number
) {
// ww: nombre d'échantillons bruts à afficher
let ww = w || s.hourly.x.length
let bbox = (<SVGGraphicsElement | undefined>(
document.getElementsByClassName('bglayer')[0]
))?.getBBox()
let width = (bbox?.width || 10) / 3
if (ww <= width) {
s.x = s.hourly.x
s.y = s.hourly.y
s.bucket = 1
} else if (ww / 24 <= width) {
s.x = s.daily.x
s.y = s.daily.y
s.bucket = 24
} else {
s.x = s.weekly.x
s.y = s.weekly.y
s.bucket = 24 * 7
}
}
function sample(
s: { weekly: { x: (number|string)[], y: number[] },
daily: { x: (number|string)[], y: number[] },
hourly: { x: (number|string)[], y: number[] },
x: (number|string)[],
y: number[], bucket: number },
w?: number,
) {
// ww: nombre d'échantillons bruts à afficher
let ww = w || s.hourly.x.length
let bbox = (<SVGGraphicsElement | undefined>(document.getElementsByClassName("bglayer")[0]))?.getBBox()
let width = (bbox?.width || 10)/3
if(ww <= width) {
s.x = s.hourly.x
s.y = s.hourly.y
s.bucket = 1
} else if (ww / 24 <= width) {
s.x = s.daily.x
s.y = s.daily.y
s.bucket = 24
} else {
s.x = s.weekly.x
s.y = s.weekly.y
s.bucket = 24 * 7
}
}
let has_plot = false
let layout = {}
function relayout(event: any) {
if (event.bucket) {
return
}
let w = event['xaxis.range[1]'] - Math.max(0, event['xaxis.range[0]'])
let layout_ = JSON.parse(JSON.stringify(layout))
if (isNaN(w)) {
sample(soleil)
sample(somme)
layout_.xaxis.autorange = true
layout_.yaxis.autorange = true
event.bucket = soleil.bucket
plotStyle = 'min-height:450px'
if (has_plot) {
Plotly!.update('plot', [soleil, somme], layout_)
} else {
Plotly!.newPlot('plot', [soleil, somme], layout_, {
responsive: true,
})
//@ts-ignore
document.getElementById('plot')?.on('plotly_relayout', relayout)
has_plot = true
}
} else {
let sb = soleil.bucket
if (event.bucket) {
w *= event.bucket
} else {
w *= soleil.bucket
}
sample(soleil, w)
sample(somme, w)
let sb_ = soleil.bucket
event['xaxis.range[0]'] *= sb / sb_
event['xaxis.range[1]'] *= sb / sb_
event.bucket = soleil.bucket
layout_.xaxis.range = [
event['xaxis.range[0]'],
event['xaxis.range[1]'],
]
let unite: string
if (soleil.bucket == 24) {
unite = 'kWh/jour'
} else if (soleil.bucket == 24 * 7) {
unite = 'kWh/semaine'
} else {
unite = 'kWh'
}
layout_.yaxis.title.text = unite
layout_.yaxis.autorange = true
layout_.yaxis.fixedrange = false
plotStyle = 'min-height:450px'
if (has_plot) {
Plotly!.update('plot', [soleil, somme], layout_)
} else {
Plotly!.newPlot('plot', [soleil, somme], layout_, {
responsive: true,
})
//@ts-ignore
document.getElementById('plot')?.on('plotly_relayout', relayout)
has_plot = true
}
}
}
let has_plot = false
let layout = {}
function relayout(event: any) {
if(event.bucket) {
return
}
let w = event["xaxis.range[1]"] - Math.max(0, event["xaxis.range[0]"])
let layout_ = JSON.parse(JSON.stringify(layout))
if(isNaN(w)) {
sample(soleil)
sample(somme)
layout_.xaxis.autorange = true
layout_.yaxis.autorange = true
event.bucket = soleil.bucket
plotStyle = "min-height:450px"
if(has_plot) {
Plotly!.update('plot', [soleil, somme], layout_)
} else {
Plotly!.newPlot('plot', [soleil, somme], layout_, { responsive: true })
//@ts-ignore
document.getElementById('plot')?.on('plotly_relayout', relayout)
has_plot = true
}
} else {
let sb = soleil.bucket
if(event.bucket) {
w *= event.bucket
} else {
w *= soleil.bucket
}
sample(soleil, w)
sample(somme, w)
let sb_ = soleil.bucket
event["xaxis.range[0]"] *= sb / sb_
event["xaxis.range[1]"] *= sb / sb_
event.bucket = soleil.bucket
layout_.xaxis.range = [
event["xaxis.range[0]"],
event["xaxis.range[1]"]
]
let unite: string;
if(soleil.bucket == 24) {
unite = 'kWh/jour'
} else if (soleil.bucket == 24 * 7) {
unite = 'kWh/semaine'
} else {
unite = 'kWh'
}
layout_.yaxis.title.text = unite
layout_.yaxis.autorange = true
layout_.yaxis.fixedrange = false
plotStyle = "min-height:450px"
if(has_plot) {
Plotly!.update('plot', [soleil, somme], layout_)
} else {
Plotly!.newPlot('plot', [soleil, somme], layout_, { responsive: true })
//@ts-ignore
document.getElementById('plot')?.on('plotly_relayout', relayout)
has_plot = true
}
}
};
function redraw() {
sample(soleil)
sample(somme)
let unite: string
if (soleil.bucket == 24) {
unite = 'kWh/jour'
} else if (soleil.bucket == 24 * 7) {
unite = 'kWh/semaine'
} else {
unite = 'kWh'
}
layout = {
title: 'Autoconsommation',
autosize: true,
automargin: true,
plot_bgcolor: '#fff0',
paper_bgcolor: '#fff0',
font: {
color: darkMode ? '#fff' : '#000',
},
xaxis: {
gridcolor: darkMode ? '#444' : '#bbb',
ticklabeloverflow: 'allow',
ticklabelstep: 4,
tickangle: 45,
},
yaxis: {
title: { text: unite },
gridcolor: darkMode ? '#444' : '#bbb',
color: darkMode ? '#fff' : '#000',
},
showlegend: true,
legend: {
xanchor: 'center',
x: 0.5,
y: -0.4,
orientation: 'h',
},
}
plotStyle = 'min-height:450px'
if (has_plot) {
Plotly!.update('plot', [soleil, somme], layout)
//@ts-ignore
document.getElementById('plot')?.on('plotly_relayout', relayout)
} else {
Plotly!.newPlot('plot', [soleil, somme], layout, {
responsive: true,
})
//@ts-ignore
document.getElementById('plot')?.on('plotly_relayout', relayout)
has_plot = true
}
function redraw() {
sample(soleil)
sample(somme)
let unite: string;
if(soleil.bucket == 24) {
unite = 'kWh/jour'
} else if (soleil.bucket == 24 * 7) {
unite = 'kWh/semaine'
} else {
unite = 'kWh'
}
layout = {
title: "Autoconsommation",
autosize: true,
automargin: true,
plot_bgcolor: "#fff0",
paper_bgcolor: "#fff0",
font: {
color: darkMode ? '#fff': '#000'
},
xaxis: {
gridcolor: darkMode ? '#444': '#bbb',
ticklabeloverflow: 'allow',
ticklabelstep: 4,
tickangle: 45,
},
yaxis: {
title: { text: unite },
gridcolor: darkMode ? '#444': '#bbb',
color: darkMode ? '#fff': '#000',
},
showlegend: true,
legend: {
xanchor: 'center',
x: 0.5,
y: -0.4,
orientation: 'h'
},
}
plotStyle = "min-height:450px"
if(has_plot) {
Plotly!.update('plot', [soleil, somme], layout)
//@ts-ignore
document.getElementById('plot')?.on('plotly_relayout', relayout)
} else {
Plotly!.newPlot('plot', [soleil, somme], layout, { responsive: true })
//@ts-ignore
document.getElementById('plot')?.on('plotly_relayout', relayout)
has_plot = true
}
var dataProd = [
{
values: [Math.round(auto), Math.round(totalProd - auto)],
labels: ['Autoconsommé', 'Surplus'],
marker: { colors: ['#ffbf00dd', '#b81111dd'] },
type: 'pie',
sort: false,
hole: 0.5,
},
]
var dataProd = [{
values: [Math.round(auto), Math.round(totalProd - auto)],
labels: ['Autoconsommé', 'Surplus'],
marker: { colors: ["#ffbf00dd", "#b81111dd"] },
type: 'pie',
sort: false,
hole: .5,
}];
var dataConso = [
{
values: [Math.round(auto), Math.round(totalConso - auto)],
labels: ['Autoproduit', 'Alloproduit'],
marker: { colors: ['#ffbf00dd', '#b81111dd'] },
type: 'pie',
sort: false,
hole: 0.5,
},
]
var dataConso = [{
values: [Math.round(auto), Math.round(totalConso - auto)],
labels: ['Autoproduit', 'Alloproduit'],
marker: { colors: ["#ffbf00dd", "#b81111dd"] },
type: 'pie',
sort: false,
hole: .5,
}];
plotStyle = 'min-height:450px'
Plotly.react(
'autoProd',
dataProd,
{
title: 'Autoconsommation',
font: {
color: darkMode ? '#fff' : '#000',
},
plot_bgcolor: '#fff0',
paper_bgcolor: '#fff0',
autosize: true,
legend: {
orientation: 'h',
},
},
{ responsive: true }
)
Plotly.react(
'autoConso',
dataConso,
{
title: 'Autoproduction',
font: {
color: darkMode ? '#fff' : '#000',
},
plot_bgcolor: '#fff0',
paper_bgcolor: '#fff0',
autosize: true,
legend: {
orientation: 'h',
},
},
{ responsive: true }
)
}
</script>
plotStyle = "min-height:450px"
Plotly.react('autoProd', dataProd, {
title: "Autoconsommation",
font: {
color: darkMode ? '#fff': '#000'
},
plot_bgcolor: "#fff0",
paper_bgcolor: "#fff0",
autosize: true,
legend: {
orientation: "h",
}
}, { responsive: true });
Plotly.react('autoConso', dataConso, {
title: "Autoproduction",
font: {
color: darkMode ? '#fff': '#000'
},
plot_bgcolor: "#fff0",
paper_bgcolor: "#fff0",
autosize: true,
legend: {
orientation: "h",
}
}, { responsive: true });
}
</script>
<form method="POST" action="/api/grain" id="pdl" on:submit={refresh}>
</form>
<form method="POST" action="/api/grain" id="pdl" on:submit={refresh} />
<button type="button" class="btn-close" style="padding:20px;margin:-16px -16px -16px auto" on:click={() => erreur=""} aria-label="Close"></button>
<button
type="button"
class="btn-close"
style="padding:20px;margin:-16px -16px -16px auto"
on:click={() => (erreur = '')}
aria-label="Close" />
<input type="number" class="form-control" placeholder="Consommation Annuelle (kWh)" min="0" step="500" bind:value={pr.conso} on:change={(_ev) => updatePlot(puissance)}/>
<input
type="number"
class="form-control"
placeholder="Consommation Annuelle (kWh)"
min="0"
step="500"
bind:value={pr.conso}
on:change={(_ev) => updatePlot(puissance)} />
<table class="table">
<thead><tr><th>PRM<button type="button" class="btn btn-link align-baseline p-0 ms-2" data-bs-toggle="popover" data-bs-trigger="hover focus" data-bs-content="Un PRM, aussi appelé PDL, est l'identifiant d'un compteur électrique. On peut le trouver sur les factures d'électricité, ou en appuyant sur le bouton + du compteur Linky."><i class="bi bi-question-circle"></i></button></th><th>Prénom</th><th>Nom</th><th></th></tr></thead>
<tbody>
{#each prms as prm, i}
<tr>
<td><input class="form-control" bind:value={prm.prm} type="number" /></td>
<td><input class="form-control" bind:value={prm.nom}/></td>
<td><input class="form-control" bind:value={prm.prenom}/></td>
<td style="width:1%;white-space:nowrap;text-align:center">
<button class="btn btn-link" on:click={(ev) => delPrm(ev, i)}><i class="bi bi-x-circle text-primary"/></button>
</td>
</tr>
{/each}
</tbody>
</table>
<div class="my-3 form-check">
<input class="form-check-input" type="checkbox" id="consentement" bind:checked={consentement}>
<label class="form-check-label" for="consentement">Ces abonnés consentent à ce que j'accède à leurs données</label>
</div>
<table class="table">
<thead
><tr
><th
>PRM<button
type="button"
class="btn btn-link align-baseline p-0 ms-2"
data-bs-toggle="popover"
data-bs-trigger="hover focus"
data-bs-content="Un PRM, aussi appelé PDL, est l'identifiant d'un compteur électrique. On peut le trouver sur les factures d'électricité, ou en appuyant sur le bouton + du compteur Linky."
><i class="bi bi-question-circle" /></button
></th
><th>Prénom</th><th>Nom</th><th /></tr
></thead>
<tbody>
{#each prms as prm, i}
<tr>
<td
><input
class="form-control"
bind:value={prm.prm}
type="number" /></td>
<td
><input
class="form-control"
bind:value={prm.nom} /></td>
<td
><input
class="form-control"
bind:value={prm.prenom} /></td>
<td
style="width:1%;white-space:nowrap;text-align:center">
<button
class="btn btn-link"
on:click={(ev) => delPrm(ev, i)}
><i
class="bi bi-x-circle text-primary" /></button>
</td>
</tr>
{/each}
</tbody>
</table>
<div class="my-3 form-check">
<input
class="form-check-input"
type="checkbox"
id="consentement"
bind:checked={consentement} />
<label class="form-check-label" for="consentement"
>Ces abonnés consentent à ce que j'accède à leurs données</label>
</div>
<button disabled={!consentement} class="mx-2 btn btn-primary" form="pdl">Mettre à jour</button>
<div class="mx-2 spinner-border text-primary" class:d-none={!prm_loading}></div>
<button
disabled={!consentement}
class="mx-2 btn btn-primary"
form="pdl">Mettre à jour</button>
<div
class="mx-2 spinner-border text-primary"
class:d-none={!prm_loading} />
<div class="col-12 col-sm-6 p-0" style={plotStyle} id="autoConso"></div>
<div class="col-12 col-sm-6 p-0" style={plotStyle} id="autoProd"></div>
<div class="col-12 col-sm-6 p-0" style={plotStyle} id="autoConso" />
<div class="col-12 col-sm-6 p-0" style={plotStyle} id="autoProd" />
//@ts-nocheck
import { line, curveLinear, Delaunay, range, scaleLinear, scaleUtc } from 'd3';
// import data from './line-data';
//@ts-nocheck
import {
line,
curveLinear,
Delaunay,
range,
scaleLinear,
scaleUtc,
} from 'd3'
// import data from './line-data';
const marginTop = 100; // the top margin, in pixels
const marginRight = 0; // the right margin, in pixels
const marginBottom = 30; // the bottom margin, in pixels
const marginLeft = 100; // the left margin, in pixels
const inset = 0; // inset the default range, in pixels
const width = 600; // the outer width of the chart, in pixels
const height = 400; // the outer height of the chart, in pixels
const xLabel = ''; // a label for the y-axis
const yLabel = 'Consommation (Wh)'; // a label for the y-axis
const xFormat = ''; // a format specifier string for the y-axis
const yFormat = 'Wh'; // a format specifier string for the y-axis
const horizontalGrid = true; // show horizontal grid lines
const verticalGrid = true; // show vertical grid lines
const colors = ["#b81111", "#ffbf00"]; // fill color for dots && number of colors in fill array MUST match number of subsets in data
const showDots = false; // whether dots should be displayed
const dotsFilled = true; // whether dots should be filled or outlined
const r = 0; // (fixed) radius of dots, in pixels
const strokeWidth = 1; // stroke width of line, in pixels
const strokeOpacity = [0.8, 0.2, 0.8, 0.8]; // stroke opacity of line
const tooltipBackground = 'white'; // background color of tooltip
const tooltipTextColor = 'black'; // text color of tooltip
const strokeLinecap = 'round'; // stroke line cap of the line
const strokeLinejoin = 'round'; // stroke line join of the line
const xScalefactor = width / 150; //y-axis number of values
const yScalefactor = height / 40; //y-axis number of values
const curve = curveLinear; // method of interpolation between points
const xType = scaleUtc; // type of x-scale
const insetTop = 50; // inset from top
const insetRight = inset; // inset from right
const insetBottom = inset; // inset fro bottom
const insetLeft = inset; // inset from left
const xRange = [marginLeft + insetLeft, width - marginRight - insetRight]; // [left, right]
const yType = scaleLinear; // type of y-scale
const yRange = [height - marginBottom - insetBottom, marginTop + insetTop]; // [bottom, top]
const marginTop = 100 // the top margin, in pixels
const marginRight = 0 // the right margin, in pixels
const marginBottom = 30 // the bottom margin, in pixels
const marginLeft = 100 // the left margin, in pixels
const inset = 0 // inset the default range, in pixels
const width = 600 // the outer width of the chart, in pixels
const height = 400 // the outer height of the chart, in pixels
const xLabel = '' // a label for the y-axis
const yLabel = 'Consommation (Wh)' // a label for the y-axis
const xFormat = '' // a format specifier string for the y-axis
const yFormat = 'Wh' // a format specifier string for the y-axis
const horizontalGrid = true // show horizontal grid lines
const verticalGrid = true // show vertical grid lines
const colors = ['#b81111', '#ffbf00'] // fill color for dots && number of colors in fill array MUST match number of subsets in data
const showDots = false // whether dots should be displayed
const dotsFilled = true // whether dots should be filled or outlined
const r = 0 // (fixed) radius of dots, in pixels
const strokeWidth = 1 // stroke width of line, in pixels
const strokeOpacity = [0.8, 0.2, 0.8, 0.8] // stroke opacity of line
const tooltipBackground = 'white' // background color of tooltip
const tooltipTextColor = 'black' // text color of tooltip
const strokeLinecap = 'round' // stroke line cap of the line
const strokeLinejoin = 'round' // stroke line join of the line
const xScalefactor = width / 150 //y-axis number of values
const yScalefactor = height / 40 //y-axis number of values
const curve = curveLinear // method of interpolation between points
const xType = scaleUtc // type of x-scale
const insetTop = 50 // inset from top
const insetRight = inset // inset from right
const insetBottom = inset // inset fro bottom
const insetLeft = inset // inset from left
const xRange = [marginLeft + insetLeft, width - marginRight - insetRight] // [left, right]
const yType = scaleLinear // type of y-scale
const yRange = [height - marginBottom - insetBottom, marginTop + insetTop] // [bottom, top]
// For a single set of data
console.log(data)
if (!('data' in data[0])) {
x = Object.keys(data[0])[0];
y = Object.keys(data[0])[1];
xVals = data.map((el: Record<string, any>) => el[x]);
yVals = data.map((el: Record<string, any>) => el[y]);
colorVals = data.map((_) => 0);
points = data.map((el) => ({
x: el[x],
y: el[y],
color: 0
}));
}
// For data with subsets (NOTE: expects 'id' and 'data' keys)
else {
x = Object.keys(data[0]?.data[0])[0];
y = Object.keys(data[0]?.data[0])[1];
data.forEach((subset, i) => {
subset.data.forEach((coordinate) => {
xVals.push(coordinate[x]);
yVals.push(coordinate[y]);
colorVals.push(i);
points.push(
{
x: coordinate[x],
y: coordinate[y],
color: i
});
});
subsets.push(subset.id);
});
}
// For a single set of data
console.log(data)
if (!('data' in data[0])) {
x = Object.keys(data[0])[0]
y = Object.keys(data[0])[1]
xVals = data.map((el: Record<string, any>) => el[x])
yVals = data.map((el: Record<string, any>) => el[y])
colorVals = data.map((_) => 0)
points = data.map((el) => ({
x: el[x],
y: el[y],
color: 0,
}))
}
// For data with subsets (NOTE: expects 'id' and 'data' keys)
else {
x = Object.keys(data[0]?.data[0])[0]
y = Object.keys(data[0]?.data[0])[1]
data.forEach((subset, i) => {
subset.data.forEach((coordinate) => {
xVals.push(coordinate[x])
yVals.push(coordinate[y])
colorVals.push(i)
points.push({
x: coordinate[x],
y: coordinate[y],
color: i,
})
})
subsets.push(subset.id)
})
}
const I = range(xVals.length);
const gaps = (_d, i) => !isNaN(xVals[i]) && !isNaN(yVals[i]);
const cleanData = points.map(gaps);
const I = range(xVals.length)
const gaps = (_d, i) => !isNaN(xVals[i]) && !isNaN(yVals[i])
const cleanData = points.map(gaps)
const xDomain = [xVals[0], xVals[xVals.length - 1]];
const yDomain = [0, Math.max(...yVals)];
const xScale = xType(xDomain, xRange);
const yScale = yType(yDomain, yRange);
const niceY = scaleLinear().domain([0, Math.max(...yVals)]).nice();
const xDomain = [xVals[0], xVals[xVals.length - 1]]
const yDomain = [0, Math.max(...yVals)]
const xScale = xType(xDomain, xRange)
const yScale = yType(yDomain, yRange)
const niceY = scaleLinear()
.domain([0, Math.max(...yVals)])
.nice()
$: {
lines = [];
colors.forEach((_color, j) => {
const filteredI = I.filter((_el, i) => colorVals[i] === j);
lines.push(chartLine(filteredI));
});
}
$: {
lines = []
colors.forEach((_color, j) => {
const filteredI = I.filter((_el, i) => colorVals[i] === j)
lines.push(chartLine(filteredI))
})
}
const pointsScaled = points.map((el) => [xScale(el.x), yScale(el.y), el.color]);
const delaunayGrid = Delaunay.from(pointsScaled);
const voronoiGrid = delaunayGrid.voronoi([0, 0, width, height]);
const pointsScaled = points.map((el) => [
xScale(el.x),
yScale(el.y),
el.color,
])
const delaunayGrid = Delaunay.from(pointsScaled)
const voronoiGrid = delaunayGrid.voronoi([0, 0, width, height])
const xTicks = xScale.ticks(xScalefactor);
const xTicksFormatted = xTicks.map((el) => (new Date(el*1000).toLocaleDateString()));
const yTicks = niceY.ticks(yScalefactor);
const xTicks = xScale.ticks(xScalefactor)
const xTicksFormatted = xTicks.map((el) =>
new Date(el * 1000).toLocaleDateString()
)
const yTicks = niceY.ticks(yScalefactor)
<svg {width} {height} viewBox="0 0 {width} {height}"
cursor='crosshair'
on:mouseout="{() => dotInfo = null}"
on:blur="{() => dotInfo = null}"
>
<svg
{width}
{height}
viewBox="0 0 {width} {height}"
cursor="crosshair"
on:mouseout={() => (dotInfo = null)}
on:blur={() => (dotInfo = null)}>
<path class="line" fill='none' stroke-opacity={points[dotInfo[1]].color === i ? '1' : '0.1'} stroke={colors[i]} d={subsetLine} stroke-width={strokeWidth} stroke-linecap={strokeLinecap} stroke-linejoin={strokeLinejoin}/>
<circle cx={xScale(points[dotInfo[1]].x)} cy={yScale(points[dotInfo[1]].y)} r={r} stroke={colors[points[dotInfo[1]].color]} fill={dotsFilled} />
<path
class="line"
fill="none"
stroke-opacity={points[dotInfo[1]].color === i
? '1'
: '0.1'}
stroke={colors[i]}
d={subsetLine}
stroke-width={strokeWidth}
stroke-linecap={strokeLinecap}
stroke-linejoin={strokeLinejoin} />
<circle
cx={xScale(points[dotInfo[1]].x)}
cy={yScale(points[dotInfo[1]].y)}
{r}
stroke={colors[points[dotInfo[1]].color]}
fill={dotsFilled} />
<path class="line" fill='none' stroke={colors[i]} d={subsetLine}
stroke-opacity={strokeOpacity[i]} stroke-width={strokeWidth} stroke-linecap={strokeLinecap} stroke-linejoin={strokeLinejoin} />
<path
class="line"
fill="none"
stroke={colors[i]}
d={subsetLine}
stroke-opacity={strokeOpacity[i]}
stroke-width={strokeWidth}
stroke-linecap={strokeLinecap}
stroke-linejoin={strokeLinejoin} />
<g class="y-axis" transform="translate({marginLeft}, 0)" pointer-events='none'>
<path class="domain" stroke="black" d="M{insetLeft}, {marginTop} V{height - marginBottom + 6}"/>
<g
class="y-axis"
transform="translate({marginLeft}, 0)"
pointer-events="none">
<path
class="domain"
stroke="black"
d="M{insetLeft}, {marginTop} V{height - marginBottom + 6}" />
<g class="x-axis" transform="translate(0,{height - marginBottom - insetBottom})" pointer-events='none'>
<path class="domain" stroke="black" d="M{marginLeft},0.5 H{width - marginRight}"/>
<g
class="x-axis"
transform="translate(0,{height - marginBottom - insetBottom})"
pointer-events="none">
<path
class="domain"
stroke="black"
d="M{marginLeft},0.5 H{width - marginRight}" />
<div class="tooltip" style='position:absolute; left:{dotInfo[2].pageX + 12}px; top:{dotInfo[2].pageY + 12}px; pointer-events:none; background-color:{tooltipBackground}; color:{tooltipTextColor}'>
<div
class="tooltip"
style="position:absolute; left:{dotInfo[2].pageX +
12}px; top:{dotInfo[2].pageY +
12}px; pointer-events:none; background-color:{tooltipBackground}; color:{tooltipTextColor}">
.chart-container {
justify-content: center;
align-items: center;
margin-top: 50px;
margin-left: 8
0px;
}
svg {
max-width: 100%;
height: auto;
height: "intrinsic";
margin: auto;
}
path {
fill: "green"
}
.y-axis {
font-size: "10px";
font-family: sans-serif;
text-anchor: "end";
}
.x-axis {
font-size: "10px";
font-family: sans-serif;
text-anchor: "end";
}
.tick text { font-size: 80%; fill: white !important }
.tick {
opacity: 1;
}
.tick-start {
stroke: black;
stroke-opacity: 1;
}
.tick-grid {
stroke: black;
stroke-opacity: 0.2;
font-size: "11px";
color: black;
}
.tick text {
fill: black;
}
.chart-container {
justify-content: center;
align-items: center;
margin-top: 50px;
margin-left: 8 0px;
}
svg {
max-width: 100%;
height: auto;
height: 'intrinsic';
margin: auto;
}
path {
fill: 'green';
}
.y-axis {
font-size: '10px';
font-family: sans-serif;
text-anchor: 'end';
}
.x-axis {
font-size: '10px';
font-family: sans-serif;
text-anchor: 'end';
}
.tick text {
font-size: 80%;
fill: white !important;
}
.tick {
opacity: 1;
}
.tick-start {
stroke: black;
stroke-opacity: 1;
}
.tick-grid {
stroke: black;
stroke-opacity: 0.2;
font-size: '11px';
color: black;
}
.tick text {
fill: black;
}
@media (prefers-color-scheme: dark) {
.y-axis text { fill: white; }
.x-axis text { fill: white; }
.tick-start {
stroke: white;
}
.tick-grid {
stroke: white;
}
.tick text {
fill: white;
}
.domain { stroke: white }
}
@media (prefers-color-scheme: dark) {
.y-axis text {
fill: white;
}
.x-axis text {
fill: white;
}
.tick-start {
stroke: white;
}
.tick-grid {
stroke: white;
}
.tick text {
fill: white;
}
.domain {
stroke: white;
}
}
.tooltip{
border-radius: 5px;
padding: 5px;
box-shadow: rgba(0, 0, 0, 0.4) 0px 2px 4px, rgba(0, 0, 0, 0.3) 0px 7px 13px -3px, rgba(0, 0, 0, 0.2) 0px -3px 0px inset;
opacity: 1;
}
.tooltip {
border-radius: 5px;
padding: 5px;
box-shadow: rgba(0, 0, 0, 0.4) 0px 2px 4px,
rgba(0, 0, 0, 0.3) 0px 7px 13px -3px,
rgba(0, 0, 0, 0.2) 0px -3px 0px inset;
opacity: 1;
}
import Banque from '../../Banque.svelte'
import Simulation from './Simulation.svelte'
import { page } from '$app/stores';
import { assets as a } from '$app/paths';
import { enhance, applyAction } from '$app/forms';
import { onMount } from 'svelte';
import type { SubmitFunction } from '@sveltejs/kit';
import type { Grain } from '../../../helpers'
import * as H from '../../../helpers'
import type { Modal, Offcanvas } from 'bootstrap'
import { email } from '../../../stores'
export let prmsFeature: boolean = false
export let assets: string = a
export let server = "https://coturnix.fr"
type Prm = { prm: number | null, nom: string, prenom: string }
import Banque from '../../Banque.svelte'
import Simulation from './Simulation.svelte'
import { page } from '$app/stores'
import { assets as a } from '$app/paths'
import { enhance, applyAction } from '$app/forms'
import { onMount } from 'svelte'
import type { SubmitFunction } from '@sveltejs/kit'
import type { Grain } from '../../../helpers'
import * as H from '../../../helpers'
import type { Modal, Offcanvas } from 'bootstrap'
import { email } from '../../../stores'
export let prmsFeature: boolean = false
export let assets: string = a
export let server = 'https://coturnix.fr'
type Prm = { prm: number | null; nom: string; prenom: string }
export let data: {
nom: string,
porteur: string,
adresse: string,
tel: string,
id: string,
img?: string,
simulation: Grain.SimulationCommunaute,
guest?: boolean,
prms: Prm[],
email?: string,
}
export let data: {
nom: string
porteur: string
adresse: string
tel: string
id: string
img?: string
simulation: Grain.SimulationCommunaute
guest?: boolean
prms: Prm[]
email?: string
}
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)
}
})
let saveModal_: null | Modal = null
let menu: null | Offcanvas = null
let menuElt: null | HTMLElement = null
let saveModal_: null | Modal = null;
let menu: null | Offcanvas = null;
let menuElt: null | HTMLElement = null
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,
})
}
showSaveModalAfterMenuHide()
menu?.hide()
}
showSaveModalAfterMenuHide()
menu?.hide()
}
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);
};
}
let expert = $page.url.hash == '#expert'
let expert = $page.url.hash == "#expert"
$: 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' : ''
let an = new Date().getFullYear()
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
}
$: investissement = p.puissance
? p.puissance * 1000 * p.ratio + p.enedis
: 0
function onSurfaceChange(ev: Event) {
surface = (ev.target as HTMLInputElement).value
p.puissance = surface / surface_kwc
}
function onPuissanceChange(ev: Event) {
p.puissance = (ev.target as HTMLInputElement).value
surface = p.puissance * surface_kwc
}
$: tarifLocal = (i: number) => H.tarifLocal(p, i)
$: tarifAllo = (i: number) => p.coutElec * Math.pow(1+p.inflationElec/100, i)
$: 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)
$: exploitation = (i: number) =>
p.puissance * p.maintenance * Math.pow(1 + p.inflation / 100, i)
$: resultatFiscal = (i: number) => ebe(i) - amortissement(i) - provisionOnduleurs(i) - interetsDetteSenior(i) - interetsDSRA(i)
$: {
resultatNetData[0] = {
id: '',
data: new Array(N).fill(0).map((_, i) => {
return { x: an + i, y: resultatNet(i) }
}),
}
}
let resultatNetData: { id: string, data: {x:number,y:number}[]}[] = [{id:"",data:[]}]
$: {
resultatNetData[0] = { id: "", data: new Array(N).fill(0).map((_, i) => { return { x: an + i, y: resultatNet(i) }}) }
}
// Synthèse
$: consoMoyenneFoyer = (i: number) => H.consoMoyenneFoyer(p, i)
$: coutElec = () => {
let cout = 0
for(let i = 0; i < N; i++) {
cout += p.coutElec * Math.pow(1 + p.inflationElec / 100, i) * consoMoyenneFoyer(i)
}
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
}
$: 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 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
}
$: 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"
}
}
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
}
$: 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
)
}
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
}
$: economieFoyerMois = fmt(2).format(coutElec_ ? ((coutElec_ - coutElecAuto_) / (coutElec_/(N*12))):0)
$: 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
)
}
<button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#menuoff" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="offcanvas"
data-bs-target="#menuoff"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon" />
<input class="form-check-input" type="checkbox" role="switch" id="expert" bind:checked={expert}>
<label class="form-check-label" for="expert">Niveau expert</label>
<input
class="form-check-input"
type="checkbox"
role="switch"
id="expert"
bind:checked={expert} />
<label class="form-check-label" for="expert"
>Niveau expert</label>
<label class="form-label" for="puissance">Puissance totale (kWc)</label>
<input class="form-control form-control-sm" type="number" id="puissance" min="1" value={p.puissance} on:change={onPuissanceChange} />
<label class="form-label" for="puissance"
>Puissance totale (kWc)</label>
<input
class="form-control form-control-sm"
type="number"
id="puissance"
min="1"
value={p.puissance}
on:change={onPuissanceChange} />
<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} />
<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} />
<label class="form-label" for="autoconso">Taux d'autoconsommation (%)<button type="button" class="btn btn-link align-baseline p-0 ms-2" data-bs-toggle="popover" data-bs-trigger="hover focus" data-bs-content="Pourcentage de la production consommée localement, à valider plus finement dans l'onglet Simulation. C'est la valeur que l'application Coturnix optimise."><i class="bi bi-question-circle"></i></button>
<label class="form-label" for="autoconso"
>Taux d'autoconsommation (%)<button
type="button"
class="btn btn-link align-baseline p-0 ms-2"
data-bs-toggle="popover"
data-bs-trigger="hover focus"
data-bs-content="Pourcentage de la production consommée localement, à valider plus finement dans l'onglet Simulation. C'est la valeur que l'application Coturnix optimise."
><i class="bi bi-question-circle" /></button>
<label class="form-label" for="autoprod">Taux d'autoproduction (%)<button type="button" class="btn btn-link align-baseline p-0 ms-2" data-bs-toggle="popover" data-bs-trigger="hover focus" data-bs-content="Pourcentage des consommations venant de sources locales, à valider plus finement dans l'onglet Simulation."><i class="bi bi-question-circle"></i></button></label>
<label class="form-label" for="autoprod"
>Taux d'autoproduction (%)<button
type="button"
class="btn btn-link align-baseline p-0 ms-2"
data-bs-toggle="popover"
data-bs-trigger="hover focus"
data-bs-content="Pourcentage des consommations venant de sources locales, à valider plus finement dans l'onglet Simulation."
><i class="bi bi-question-circle" /></button
></label>
<label class="form-label" for="prix">Prix d'achat alloproduit (€/kWh)<button type="button" class="btn btn-link align-baseline p-0 ms-2" data-bs-toggle="popover" data-bs-trigger="hover focus" data-bs-content="Ce prix dépend du contrat de fourniture d'électricité du producteur."><i class="bi bi-question-circle"></i></button></label>
<input class="form-control form-control-sm" type="number" step="0.01" min="0" id="coutElec" bind:value={p.coutElec}/>
<label class="form-label" for="prix"
>Prix d'achat alloproduit (€/kWh)<button
type="button"
class="btn btn-link align-baseline p-0 ms-2"
data-bs-toggle="popover"
data-bs-trigger="hover focus"
data-bs-content="Ce prix dépend du contrat de fourniture d'électricité du producteur."
><i class="bi bi-question-circle" /></button
></label>
<input
class="form-control form-control-sm"
type="number"
step="0.01"
min="0"
id="coutElec"
bind:value={p.coutElec} />
<label class="form-label" for="prix">Prix de vente local (€/kWh)<button type="button" class="btn btn-link align-baseline p-0 ms-2" data-bs-toggle="popover" data-bs-trigger="hover focus" data-bs-content="Dans Coturnix, chaque producteur choisit son prix, et Coturnix propose le moins cher au consommateur."><i class="bi bi-question-circle"></i></button></label>
<input class="form-control form-control-sm" type="number" step="0.01" min="0" id="prix" bind:value={p.prix}/>
<label class="form-label" for="prix"
>Prix de vente local (€/kWh)<button
type="button"
class="btn btn-link align-baseline p-0 ms-2"
data-bs-toggle="popover"
data-bs-trigger="hover focus"
data-bs-content="Dans Coturnix, chaque producteur choisit son prix, et Coturnix propose le moins cher au consommateur."
><i class="bi bi-question-circle" /></button
></label>
<input
class="form-control form-control-sm"
type="number"
step="0.01"
min="0"
id="prix"
bind:value={p.prix} />
<label class="form-label" for="inflationElec">Inflation nationale de l'électricité (%)</label>
<input class="form-control form-control-sm" type="number" bind:value={p.inflationElec} min="0" id="inflationElec" />
<label class="form-label" for="inflationElec"
>Inflation nationale de l'électricité (%)</label>
<input
class="form-control form-control-sm"
type="number"
bind:value={p.inflationElec}
min="0"
id="inflationElec" />
<label class="form-label" for="echeances">Durée d'analyse (an)</label>
<input class="form-control form-control-sm" type="number" id="echeances" min="0" bind:value={N}/>
<label class="form-label" for="echeances"
>Durée d'analyse (an)</label>
<input
class="form-control form-control-sm"
type="number"
id="echeances"
min="0"
bind:value={N} />
<label class="form-label" for="apport">Apport initial (€)</label>
<input class="form-control form-control-sm" type="number" id="apport" min="0" step="1000" bind:value={p.apport}/>
<label class="form-label" for="apport"
>Apport initial (€)</label>
<input
class="form-control form-control-sm"
type="number"
id="apport"
min="0"
step="1000"
bind:value={p.apport} />
<label class="form-label" for="interet">Taux d'intérêt(%)</label>
<input class="form-control form-control-sm" type="number" step="0.1" id="interet" min="0" bind:value={p.interet}/>
<label class="form-label" for="interet"
>Taux d'intérêt(%)</label>
<input
class="form-control form-control-sm"
type="number"
step="0.1"
id="interet"
min="0"
bind:value={p.interet} />
<label class="form-label" for="echeances">Nombre d'échéances (en mois)</label>
<input class="form-control form-control-sm" type="number" id="echeances" min="0" bind:value={p.echeances}/>
<label class="form-label" for="echeances"
>Nombre d'échéances (en mois)</label>
<input
class="form-control form-control-sm"
type="number"
id="echeances"
min="0"
bind:value={p.echeances} />
<form id="delForm" method="POST" action="?/del">
</form>
<button class="my-2 me-2 btn btn-primary" on:click={saveModal}>Sauvegarder</button>
<button class="my-2 btn btn-outline-primary" form="delForm">Supprimer</button>
<form id="delForm" method="POST" action="?/del" />
<button
class="my-2 me-2 btn btn-primary"
on:click={saveModal}>Sauvegarder</button>
<button
class="my-2 btn btn-outline-primary"
form="delForm">Supprimer</button>
<a href="#synthese" class="nav-link {syntheseActive}" id="synthese-tab" type="button" role="tab" aria-controls="synthese-tab-pane" aria-selected="true">Synthèse</a>
<a
href="#synthese"
class="nav-link {syntheseActive}"
id="synthese-tab"
type="button"
role="tab"
aria-controls="synthese-tab-pane"
aria-selected="true">Synthèse</a>
<a href="#compte" class="nav-link {compteActive}" id="profile-tab" type="button" role="tab" aria-controls="compte-tab-pane" aria-selected="false">Détails financiers</a>
<a
href="#compte"
class="nav-link {compteActive}"
id="profile-tab"
type="button"
role="tab"
aria-controls="compte-tab-pane"
aria-selected="false">Détails financiers</a>
<a href="#banque" class="nav-link {banqueActive}" id="banque-tab" type="button" role="tab" aria-controls="banque-tab-pane" aria-selected="false">Emprunt</a>
<a
href="#banque"
class="nav-link {banqueActive}"
id="banque-tab"
type="button"
role="tab"
aria-controls="banque-tab-pane"
aria-selected="false">Emprunt</a>
<a href="#expert" class="nav-link {expertActive}" id="expert-tab" type="button" role="tab" aria-controls="expert-tab-pane" aria-selected="false">Mode expert</a>
<a
href="#expert"
class="nav-link {expertActive}"
id="expert-tab"
type="button"
role="tab"
aria-controls="expert-tab-pane"
aria-selected="false">Mode expert</a>
<a href="#simu" class="nav-link {simuActive}" id="prm-tab" type="button" role="tab" aria-controls="prm-tab-pane" aria-selected="false">Simulation</a>
<a
href="#simu"
class="nav-link {simuActive}"
id="prm-tab"
type="button"
role="tab"
aria-controls="prm-tab-pane"
aria-selected="false">Simulation</a>
<div class="tab-pane fade {syntheseActive} {syntheseShow} p-3" id="synthese-tab-pane" role="tabpanel" aria-labelledby="synthese-tab" tabindex="0">
<h3 class="my-3 text-body fs-1 fw-bold ">En un regard, <span class="text-primary">tout</span> votre projet.</h3>
<div
class="tab-pane fade {syntheseActive} {syntheseShow} p-3"
id="synthese-tab-pane"
role="tabpanel"
aria-labelledby="synthese-tab"
tabindex="0">
<h3 class="my-3 text-body fs-1 fw-bold">
En un regard, <span class="text-primary">tout</span> votre
projet.
</h3>
<svg viewBox="{Math.floor(-N*0.05)} {Math.floor(-maxa - margin)} {Math.ceil(N*1.1)} {Math.ceil(maxa-mina + 2 * margin)}" xmlns="http://www.w3.org/2000/svg" width="250px" height="100px" preserveAspectRatio="none">
<path d={traceArray(resultatNet,N)} fill="transparent" stroke-width="2" vector-effect="non-scaling-stroke" stroke="#b71515" />
<svg
viewBox="{Math.floor(
-N * 0.05
)} {Math.floor(
-maxa - margin
)} {Math.ceil(N * 1.1)} {Math.ceil(
maxa - mina + 2 * margin
)}"
xmlns="http://www.w3.org/2000/svg"
width="250px"
height="100px"
preserveAspectRatio="none">
<path
d={traceArray(resultatNet, N)}
fill="transparent"
stroke-width="2"
vector-effect="non-scaling-stroke"
stroke="#b71515" />
<div class="d-flex flex-column justify-content-between text-center ms-3">
<div style="width:250px" class="py-3 my-auto">
<div class="spinner-border ms-3 loading" class:d-none={!pvgis_loading}></div>
<svg class:d-none={pvgis_loading || !maxProd} viewBox="-10 0 270 {maxProd}" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg" width="250px" height="100px">
<div
class="d-flex flex-column justify-content-between text-center ms-3">
<div
style="width:250px"
class="py-3 my-auto">
<div
class="spinner-border ms-3 loading"
class:d-none={!pvgis_loading} />
<svg
class:d-none={pvgis_loading ||
!maxProd}
viewBox="-10 0 270 {maxProd}"
preserveAspectRatio="none"
xmlns="http://www.w3.org/2000/svg"
width="250px"
height="100px">
<svg class="donnee" class:d-none={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
class="donnee"
class:d-none={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" />
<div class="donnee">{N ? format(sum(resultatNet,N)/N) : "0€"}</div>
<div>Bénéfice annuel moyen </div>
<div class="donnee">
{N
? format(sum(resultatNet, N) / N)
: '0€'}
</div>
<div>Bénéfice annuel moyen</div>
<div class="flex-column justify-content-between text-center">
<div class="donnee">{rentabiliteTaux(sum(resultatNet,10))}</div>
<div
class="flex-column justify-content-between text-center">
<div class="donnee">
{rentabiliteTaux(sum(resultatNet, 10))}
</div>
<div class="tab-pane fade {compteActive} {compteShow} p-3" id="compte-tab-pane" role="tabpanel" aria-labelledby="compte-tab" tabindex="0">
<h3 class="my-3 fs-1 fw-bold"><span class="text-primary">Projetez-vous</span> dans votre projet.</h3>
<div
class="tab-pane fade {compteActive} {compteShow} p-3"
id="compte-tab-pane"
role="tabpanel"
aria-labelledby="compte-tab"
tabindex="0">
<h3 class="my-3 fs-1 fw-bold">
<span class="text-primary">Projetez-vous</span> dans votre
projet.
</h3>
<div class="d-flex flex-column my-3">
<div class="tcellt">{an + i}</div>
<div class="tcellt">{resultatNet(i).toFixed(arr)}</div>
</div>
<div class="d-flex flex-column my-3">
<div class="tcellt">{an + i}</div>
<div class="tcellt">
{resultatNet(i).toFixed(arr)}
</div>
</div>
<div class="titreligne tcellt">Autoproduction (€)</div>
<div class="titreligne tcellt">Vente locale (€)</div>
<div class="titreligne tcellt">Vente de surplus (€)</div>
<div class="titreligne tcellt">
Autoproduction (€)
</div>
<div class="titreligne tcellt">
Vente locale (€)
</div>
<div class="titreligne tcellt">
Vente de surplus (€)
</div>
<div class="d-flex flex-column my-4">
<div class="tcellt">{an + i}</div>
<div class="tcellt">{(productionAnnuelle(i) * (p.autoprod * tarifAllo(i) / 100)).toFixed(0)}</div>
<div class="tcellt">{(productionAnnuelle(i) * (autoconso * tarifLocal(i))).toFixed(0)}</div>
<div class="tcellt">{(productionAnnuelle(i) * ((1 - autoconso) * tarifSurplus(i))).toFixed(0)}</div>
<div class="tcellt"> </div>
<div class="tcellt">{chiffreAffaires(i).toFixed(arr)}</div>
</div>
<div class="d-flex flex-column my-4">
<div class="tcellt">{an + i}</div>
<div class="tcellt">
{(
productionAnnuelle(i) *
((p.autoprod * tarifAllo(i)) / 100)
).toFixed(0)}
</div>
<div class="tcellt">
{(
productionAnnuelle(i) *
(autoconso * tarifLocal(i))
).toFixed(0)}
</div>
<div class="tcellt">
{(
productionAnnuelle(i) *
((1 - autoconso) * tarifSurplus(i))
).toFixed(0)}
</div>
<div class="tcellt"> </div>
<div class="tcellt">
{chiffreAffaires(i).toFixed(arr)}
</div>
</div>
<div class="d-flex flex-column my-4">
<div class="tcellt">{an + i}</div>
<div class="tcellt">{exploitation(i).toFixed(arr)}</div>
<div class="tcellt">{turpe(i).toFixed(arr)}</div>
<div class="tcellt">{assurance(i).toFixed(arr)}</div>
<div class="tcellt">{divers(i).toFixed(arr)}</div>
<div class="tcellt">{charges(i).toFixed(arr)}</div>
</div>
<div class="d-flex flex-column my-4">
<div class="tcellt">{an + i}</div>
<div class="tcellt">
{exploitation(i).toFixed(arr)}
</div>
<div class="tcellt">
{turpe(i).toFixed(arr)}
</div>
<div class="tcellt">
{assurance(i).toFixed(arr)}
</div>
<div class="tcellt">
{divers(i).toFixed(arr)}
</div>
<div class="tcellt">
{charges(i).toFixed(arr)}
</div>
</div>
<div class="titreligne tcellt">Taxe foncière</div>
<div class="titreligne tcellt">Cotisation foncière des entreprises</div>
<div class="titreligne tcellt">Excédent brut d'exploitation</div>
<div class="titreligne tcellt">
Taxe foncière
</div>
<div class="titreligne tcellt">
Cotisation foncière des entreprises
</div>
<div class="titreligne tcellt">
Excédent brut d'exploitation
</div>
<div class="d-flex flex-column my-4">
<div class="tcellt">{an + i}</div>
<div class="tcellt">{valeurAjoutee(i).toFixed(arr)}</div>
<div class="tcellt">{accise(i).toFixed(arr)}</div>
<div class="tcellt">{ifer(i).toFixed(arr)}</div>
<div class="tcellt">{taxeFonciere(i).toFixed(arr)}</div>
<div class="tcellt">{cfe(i).toFixed(arr)}</div>
<div class="tcellt">{ebe(i).toFixed(arr)}</div>
</div>
<div class="d-flex flex-column my-4">
<div class="tcellt">{an + i}</div>
<div class="tcellt">
{valeurAjoutee(i).toFixed(arr)}
</div>
<div class="tcellt">
{accise(i).toFixed(arr)}
</div>
<div class="tcellt">
{ifer(i).toFixed(arr)}
</div>
<div class="tcellt">
{taxeFonciere(i).toFixed(arr)}
</div>
<div class="tcellt">
{cfe(i).toFixed(arr)}
</div>
<div class="tcellt">
{ebe(i).toFixed(arr)}
</div>
</div>
<div class="titreligne tcellt">Amortissement</div>
<div class="titreligne tcellt">Intérêts dette senior</div>
<div class="titreligne tcellt">Intérêts DSRA</div>
<div class="titreligne tcellt">Résultat fiscal</div>
<div class="titreligne tcellt">Impôt sur les sociétés</div>
<div class="titreligne tcellt">Résultat net</div>
<div class="titreligne tcellt">
Amortissement
</div>
<div class="titreligne tcellt">
Intérêts dette senior
</div>
<div class="titreligne tcellt">
Intérêts DSRA
</div>
<div class="titreligne tcellt">
Résultat fiscal
</div>
<div class="titreligne tcellt">
Impôt sur les sociétés
</div>
<div class="titreligne tcellt">
Résultat net
</div>
<div class="d-flex flex-column my-4">
<div class="tcellt">{an + i}</div>
<div class="tcellt">{provisionOnduleurs(i).toFixed(arr)}</div>
<div class="tcellt">{amortissement(i).toFixed(arr)}</div>
<div class="tcellt">{interetsDetteSenior(i).toFixed(arr)}</div>
<div class="tcellt">{interetsDSRA(i).toFixed(arr)}</div>
<div class="tcellt">{resultatFiscal(i).toFixed(arr)}</div>
<div class="tcellt">{is(i).toFixed(arr)}</div>
<div class="tcellt">{resultatNet(i).toFixed(arr)}</div>
</div>
<div class="d-flex flex-column my-4">
<div class="tcellt">{an + i}</div>
<div class="tcellt">
{provisionOnduleurs(i).toFixed(arr)}
</div>
<div class="tcellt">
{amortissement(i).toFixed(arr)}
</div>
<div class="tcellt">
{interetsDetteSenior(i).toFixed(arr)}
</div>
<div class="tcellt">
{interetsDSRA(i).toFixed(arr)}
</div>
<div class="tcellt">
{resultatFiscal(i).toFixed(arr)}
</div>
<div class="tcellt">
{is(i).toFixed(arr)}
</div>
<div class="tcellt">
{resultatNet(i).toFixed(arr)}
</div>
</div>
{#if investissement > apport }
<h5 class="my-3">Couverture de la dette</h5>
<div class="d-flex flex-wrap">
<div class="d-flex flex-column my-3">
<div class="titreligne tcellt">Année</div>
<div class="titreligne tcellt">DSCR</div>
{#if investissement > apport}
<h5 class="my-3">Couverture de la dette</h5>
<div class="d-flex flex-wrap">
<div class="d-flex flex-column my-3">
<div class="titreligne tcellt">Année</div>
<div class="titreligne tcellt">DSCR</div>
</div>
{#each Array(Math.ceil(N)) as _, i}
<div class="d-flex flex-column my-3">
<div class="tcellt">{an + i}</div>
<div class="tcellt">
{fmt(2).format(dscr(i))}
</div>
</div>
{/each}
{#each Array(Math.ceil(N)) as _, i}
<div class="d-flex flex-column my-3">
<div class="tcellt">{an + i}</div>
<div class="tcellt">{fmt(2).format(dscr(i))}</div>
</div>
{/each}
</div>
<div class="tab-pane fade {banqueActive} {banqueShow} p-3" id="banque-tab-pane" role="tabpanel" aria-labelledby="banque-tab" tabindex="0">
<h3 class="my-3 fs-1 fw-bold ">Tous <span class="text-primary">les recoins</span> de votre emprunt.</h3>
<Banque dette = {dette} taux={p.interet / 100} duree={p.echeances} bind:interetsAnnuels={interetsAnnuels} bind:remboursementAnnuel={remboursementAnnuel} />
<div
class="tab-pane fade {banqueActive} {banqueShow} p-3"
id="banque-tab-pane"
role="tabpanel"
aria-labelledby="banque-tab"
tabindex="0">
<h3 class="my-3 fs-1 fw-bold">
Tous <span class="text-primary">les recoins</span> de votre
emprunt.
</h3>
<Banque
{dette}
taux={p.interet / 100}
duree={p.echeances}
bind:interetsAnnuels
bind:remboursementAnnuel />
<div class="tab-pane fade {expertActive} {expertShow} py-3" id="expert-tab-pane" role="tabpanel" aria-labelledby="expert-tab" tabindex="0">
<div
class="tab-pane fade {expertActive} {expertShow} py-3"
id="expert-tab-pane"
role="tabpanel"
aria-labelledby="expert-tab"
tabindex="0">
<label class="form-label" for="enedis">Coût de raccordement Enedis</label>
<input class="form-control form-control-sm" type="number" id="enedis" min="0" bind:value={p.enedis}/>
<label class="form-label" for="enedis"
>Coût de raccordement Enedis</label>
<input
class="form-control form-control-sm"
type="number"
id="enedis"
min="0"
bind:value={p.enedis} />
<label class="form-label" for="productible">Productible annuel (kWh/kWc)</label>
<input class="form-control form-control-sm" type="number" id="productible" min="0" bind:value={p.productible}/>
<label class="form-label" for="productible"
>Productible annuel (kWh/kWc)</label>
<input
class="form-control form-control-sm"
type="number"
id="productible"
min="0"
bind:value={p.productible} />
<label class="form-label" for="ratio">Ratio installation (€/W)</label>
<input class="form-control form-control-sm" type="number" id="ratio" min="0" bind:value={p.ratio}/>
<label class="form-label" for="ratio"
>Ratio installation (€/W)</label>
<input
class="form-control form-control-sm"
type="number"
id="ratio"
min="0"
bind:value={p.ratio} />
<label class="form-label" for="degradation">Taux de dégradation PV(%)</label>
<input class="form-control form-control-sm" type="number" id="degradation" min="0" bind:value={p.degradation}/>
<label class="form-label" for="degradation"
>Taux de dégradation PV(%)</label>
<input
class="form-control form-control-sm"
type="number"
id="degradation"
min="0"
bind:value={p.degradation} />
<label class="form-label" for="inflation">Inflation tarif local</label>
<input class="form-control form-control-sm" type="number" id="inflation" min="0" bind:value={p.inflation}/>
<label class="form-label" for="inflation"
>Inflation tarif local</label>
<input
class="form-control form-control-sm"
type="number"
id="inflation"
min="0"
bind:value={p.inflation} />
<div class="tab-pane fade {simuActive} {simuShow} show p-3" id="simu-tab-pane" role="tabpanel" aria-labelledby="simu-tab" tabindex="0">
<div
class="tab-pane fade {simuActive} {simuShow} show p-3"
id="simu-tab-pane"
role="tabpanel"
aria-labelledby="simu-tab"
tabindex="0">
<Simulation id={data.id} server={server} assets={assets} prmsFeature={prmsFeature} bind:prms={data.prms} puissance={p.puissance} bind:prodWeekly={prodWeekly} bind:maxProd={maxProd} bind:pvgis_loading={pvgis_loading} />
<Simulation
id={data.id}
{server}
{assets}
{prmsFeature}
bind:prms={data.prms}
puissance={p.puissance}
bind:prodWeekly
bind:maxProd
bind:pvgis_loading />
<h5 class="modal-title pb-3" id="saveModalLabel">Sauvegarder</h5>
<form method="POST" id="saveForm" action="?/save" use:enhance={save}>
<h5 class="modal-title pb-3" id="saveModalLabel">
Sauvegarder
</h5>
<form
method="POST"
id="saveForm"
action="?/save"
use:enhance={save}>
<label class="form-label" for="nom">Nom du projet</label>
<input class="form-control" type="text" id="nom" name="nom" bind:value={data.nom} required/>
<label class="form-label" for="nom"
>Nom du projet</label>
<input
class="form-control"
type="text"
id="nom"
name="nom"
bind:value={data.nom}
required />
<label class="form-label" for="porteur">Prénom et nom du porteur du projet</label>
<input class="form-control" type="text" id="porteur" name="porteur" bind:value={data.porteur}/>
<label class="form-label" for="porteur"
>Prénom et nom du porteur du projet</label>
<input
class="form-control"
type="text"
id="porteur"
name="porteur"
bind:value={data.porteur} />
<label class="form-label" for="adresse">Adresse</label>
<input class="form-control" type="text" id="adresse" name="adresse" bind:value={data.adresse}/>
<label class="form-label" for="adresse"
>Adresse</label>
<input
class="form-control"
type="text"
id="adresse"
name="adresse"
bind:value={data.adresse} />
<label class="form-label" for="tel">Téléphone</label>
<input class="form-control" type="text" id="tel" name="tel" bind:value={data.tel}/>
<label class="form-label" for="tel"
>Téléphone</label>
<input
class="form-control"
type="text"
id="tel"
name="tel"
bind:value={data.tel} />
<button form="saveForm" class="btn btn-primary">Sauvegarder</button>
<button type="button" class="btn btn-outline-primary" data-bs-dismiss="modal">Annuler</button>
<button form="saveForm" class="btn btn-primary"
>Sauvegarder</button>
<button
type="button"
class="btn btn-outline-primary"
data-bs-dismiss="modal">Annuler</button>
@media (prefers-color-scheme: light) {
nav {
background-color: #fff !important;
}
}
@media (prefers-color-scheme: light) {
nav {
background-color: #fff !important;
}
}
input.prix::-webkit-outer-spin-button,
input.prix::-webkit-inner-spin-button {
/* display: none; <- Crashes Chrome on hover */
-webkit-appearance: none;
margin: 0; /* <-- Apparently some margin are still there even though it's hidden */
}
input.prix::-webkit-outer-spin-button,
input.prix::-webkit-inner-spin-button {
/* display: none; <- Crashes Chrome on hover */
-webkit-appearance: none;
margin: 0; /* <-- Apparently some margin are still there even though it's hidden */
}
import { error } from '@sveltejs/kit';
import type { PageServerLoad, Actions } from './$types';
import { userForm, Grain, save, del } from '../../../helpers';
import { error } from '@sveltejs/kit'
import type { PageServerLoad, Actions } from './$types'
import { userForm, Grain, save, del } from '../../../helpers'
return <Grain.GetProjetResp & { guest?: boolean }> {
nom: "",
id: "",
porteur: "",
tel: "",
adresse: "",
simulation: { ... sim },
return <Grain.GetProjetResp & { guest?: boolean }>{
nom: '',
id: '',
porteur: '',
tel: '',
adresse: '',
simulation: { ...sim },
<p><span class="text-primary align-top"><span class="g">G</span><span class="ra">RA</span>IN</span> est l'outil de simulation photovoltaïque développé par <span class="text-primary align-top"><span class="g">CO</span><span class="ra">TURN</span>IX</span> en 2023. Il est accessible en version gratuite pour tous et en version payante pour les fournisseurs d'installation pour traiter un grand nombre de simulation.</p>
<p>
<span class="text-primary align-top"
><span class="g">G</span><span class="ra">RA</span>IN</span>
est l'outil de simulation photovoltaïque développé par
<span class="text-primary align-top"
><span class="g">CO</span><span class="ra">TURN</span>IX</span> en
2023. Il est accessible en version gratuite pour tous et en version payante
pour les fournisseurs d'installation pour traiter un grand nombre de
simulation.
</p>
<p><span class="text-primary align-top"><span class="g">CO</span><span class="ra">TURN</span>IX</span> a été fondée en 2017.</p>
<p>
<span class="text-primary align-top"
><span class="g">CO</span><span class="ra">TURN</span>IX</span> a
été fondée en 2017.
</p>
<p>Elle offre des services de traitement et analyse de données au service de la performance énergétique.</p><p>Son nom vient du nom latin de la caille des blés. Cet oiseau migrateur est reconnu pour son incroyable capacité à optimiser naturellement chaque dépense d'énergie lors de ses longs vols et chaque intrant au sol pour se charger de la quantité de nourriture exacte dont elle a besoin jusqu'à sa prochaine pause. </p><p> <span class="text-primary align-top"><span class="g"> CO</span><span class="ra">TURN</span>IX</span> a regroupé dans son équipe des spécialistes de l’énergie, des mathématiques, de l’informatique et de la sociologie, ingénieurs et chercheurs, pour concevoir des technologies à la pointe du marché.</p>
<p>
Elle offre des services de traitement et analyse de données au
service de la performance énergétique.
</p>
<p>
Son nom vient du nom latin de la caille des blés. Cet oiseau
migrateur est reconnu pour son incroyable capacité à optimiser
naturellement chaque dépense d'énergie lors de ses longs vols et
chaque intrant au sol pour se charger de la quantité de nourriture
exacte dont elle a besoin jusqu'à sa prochaine pause.
</p>
<p>
<span class="text-primary align-top"
><span class="g"> CO</span><span class="ra">TURN</span>IX</span>
a regroupé dans son équipe des spécialistes de l’énergie, des mathématiques,
de l’informatique et de la sociologie, ingénieurs et chercheurs, pour
concevoir des technologies à la pointe du marché.
</p>
console.log("load")
const token = cookies.get('token')
console.log("token", token)
if(!token || !platform) {
return null
}
try {
console.log("verify token")
const id = await verifyToken(platform.env, token)
console.log("id", id)
if (!id) {
throw error(403, 'Forbidden');
}
const id_ = platform.env.USER.idFromString(id.id)
const identite = await userForm(platform.env, id_, {
Identite: {}
})
return { email: identite.email }
} catch(e) {
console.log("error", e)
return null
console.log('load')
const token = cookies.get('token')
console.log('token', token)
if (!token || !platform) {
return null
}
try {
console.log('verify token')
const id = await verifyToken(platform.env, token)
console.log('id', id)
if (!id) {
throw error(403, 'Forbidden')
}
const id_ = platform.env.USER.idFromString(id.id)
const identite = await userForm(platform.env, id_, {
Identite: {},
})
return { email: identite.email }
} catch (e) {
console.log('error', e)
return null
}
export let donnees: {
projets: number,
puissance: number,
economies: number,
};
let fmt = (n: number) => Intl.NumberFormat('fr-FR', { maximumFractionDigits: n });
export let donnees: {
projets: number
puissance: number
economies: number
}
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
}
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
}
</script>
<div class="pb-3 mb-3 border-bottom border-4 border-primary fs-1 fw-bold bg-cc">{donnees.projets}</div>
<div>Simulations </div>
<div
class="pb-3 mb-3 border-bottom border-4 border-primary fs-1 fw-bold bg-cc">
{donnees.projets}
</div>
<div>Simulations</div>
<div class="flex-column justify-content-between text-center mx-3">
<div class="pb-3 mb-3 border-bottom border-4 border-primary fs-1 fw-bold bg-cc fs-1 fw-bold">{format(donnees.puissance)}</div>
<div>Simulés </div>
<div
class="flex-column justify-content-between text-center mx-3">
<div
class="pb-3 mb-3 border-bottom border-4 border-primary fs-1 fw-bold bg-cc fs-1 fw-bold">
{format(donnees.puissance)}
</div>
<div>Simulés</div>
<div class="pb-3 mb-3 border-bottom border-4 border-primary fs-1 fw-bold bg-cc fs-1 fw-bold">+{Math.round(donnees.economies / 1000)}k€</div>
<div
class="pb-3 mb-3 border-bottom border-4 border-primary fs-1 fw-bold bg-cc fs-1 fw-bold">
+{Math.round(donnees.economies / 1000)}k€
</div>
const marginTop = 30; // the top margin, in pixels
const marginRight = 30; // the right margin, in pixels
const marginBottom = 30; // the bottom margin, in pixels
const marginLeft = 100; // the left margin, in pixels
const inset = 0; // inset the default range, in pixels
const width = 600; // the outer width of the chart, in pixels
const height = 400; // the outer height of the chart, in pixels
const xLabel = ''; // a label for the y-axis
const yLabel = 'Résultat net'; // a label for the y-axis
const xFormat = ''; // a format specifier string for the y-axis
const yFormat = '€'; // a format specifier string for the y-axis
const horizontalGrid = true; // show horizontal grid lines
const verticalGrid = true; // show vertical grid lines
const colors = ["#b81111", "#ffbf00"]; // fill color for dots && number of colors in fill array MUST match number of subsets in data
const showDots = false; // whether dots should be displayed
const dotsFilled = true; // whether dots should be filled or outlined
const r = 0; // (fixed) radius of dots, in pixels
const strokeWidth = 1; // stroke width of line, in pixels
const strokeOpacity = [1]; // stroke opacity of line
const tooltipBackground = 'white'; // background color of tooltip
const tooltipTextColor = 'black'; // text color of tooltip
const strokeLinecap = 'round'; // stroke line cap of the line
const strokeLinejoin = 'round'; // stroke line join of the line
const xScalefactor = width / 180; //y-axis number of values
const yScalefactor = height / 40; //y-axis number of values
const curve = curveLinear; // method of interpolation between points
const xType = scaleLinear; // type of x-scale
const insetTop = 50; // inset from top
const insetRight = inset; // inset from right
const insetBottom = inset; // inset fro bottom
const insetLeft = inset; // inset from left
const xRange = [marginLeft + insetLeft, width - marginRight - insetRight]; // [left, right]
const yType = scaleLinear; // type of y-scale
const yRange = [height - marginBottom - insetBottom, marginTop + insetTop]; // [bottom, top]
const marginTop = 30 // the top margin, in pixels
const marginRight = 30 // the right margin, in pixels
const marginBottom = 30 // the bottom margin, in pixels
const marginLeft = 100 // the left margin, in pixels
const inset = 0 // inset the default range, in pixels
const width = 600 // the outer width of the chart, in pixels
const height = 400 // the outer height of the chart, in pixels
const xLabel = '' // a label for the y-axis
const yLabel = 'Résultat net' // a label for the y-axis
const xFormat = '' // a format specifier string for the y-axis
const yFormat = '€' // a format specifier string for the y-axis
const horizontalGrid = true // show horizontal grid lines
const verticalGrid = true // show vertical grid lines
const colors = ['#b81111', '#ffbf00'] // fill color for dots && number of colors in fill array MUST match number of subsets in data
const showDots = false // whether dots should be displayed
const dotsFilled = true // whether dots should be filled or outlined
const r = 0 // (fixed) radius of dots, in pixels
const strokeWidth = 1 // stroke width of line, in pixels
const strokeOpacity = [1] // stroke opacity of line
const tooltipBackground = 'white' // background color of tooltip
const tooltipTextColor = 'black' // text color of tooltip
const strokeLinecap = 'round' // stroke line cap of the line
const strokeLinejoin = 'round' // stroke line join of the line
const xScalefactor = width / 180 //y-axis number of values
const yScalefactor = height / 40 //y-axis number of values
const curve = curveLinear // method of interpolation between points
const xType = scaleLinear // type of x-scale
const insetTop = 50 // inset from top
const insetRight = inset // inset from right
const insetBottom = inset // inset fro bottom
const insetLeft = inset // inset from left
const xRange = [marginLeft + insetLeft, width - marginRight - insetRight] // [left, right]
const yType = scaleLinear // type of y-scale
const yRange = [height - marginBottom - insetBottom, marginTop + insetTop] // [bottom, top]
let I, xScale, gaps, cleanData, xDomain, yDomain, yScale, niceY, chartLine, pointsScaled, delaunayGrid, voronoiGrid, xTicks, xTicksFormatted, yTicks
let I,
xScale,
gaps,
cleanData,
xDomain,
yDomain,
yScale,
niceY,
chartLine,
pointsScaled,
delaunayGrid,
voronoiGrid,
xTicks,
xTicksFormatted,
yTicks
$: {
// For a single set of data
xVals = []
yVals = []
if (!('data' in data[0])) {
x = Object.keys(data[0])[0];
y = Object.keys(data[0])[1];
xVals = data.map((el: Record<string, any>) => el[x]);
yVals = data.map((el: Record<string, any>) => el[y]);
colorVals = data.map((_) => 0);
points = data.map((el) => ({
x: el[x],
y: el[y],
color: 0
}));
}
// For data with subsets (NOTE: expects 'id' and 'data' keys)
else {
x = Object.keys(data[0]?.data[0])[0];
y = Object.keys(data[0]?.data[0])[1];
data.forEach((subset, i) => {
subset.data.forEach((coordinate) => {
xVals.push(coordinate[x]);
yVals.push(coordinate[y]);
colorVals.push(i);
points.push(
{
x: coordinate[x],
y: coordinate[y],
color: i
});
});
subsets.push(subset.id);
});
}
$: {
// For a single set of data
xVals = []
yVals = []
if (!('data' in data[0])) {
x = Object.keys(data[0])[0]
y = Object.keys(data[0])[1]
xVals = data.map((el: Record<string, any>) => el[x])
yVals = data.map((el: Record<string, any>) => el[y])
colorVals = data.map((_) => 0)
points = data.map((el) => ({
x: el[x],
y: el[y],
color: 0,
}))
}
// For data with subsets (NOTE: expects 'id' and 'data' keys)
else {
x = Object.keys(data[0]?.data[0])[0]
y = Object.keys(data[0]?.data[0])[1]
data.forEach((subset, i) => {
subset.data.forEach((coordinate) => {
xVals.push(coordinate[x])
yVals.push(coordinate[y])
colorVals.push(i)
points.push({
x: coordinate[x],
y: coordinate[y],
color: i,
})
})
subsets.push(subset.id)
})
}
xDomain = [xVals[0], xVals[xVals.length - 1]];
yDomain = [Math.min(...yVals), Math.max(...yVals)];
xScale = xType(xDomain, xRange);
yScale = yType(yDomain, yRange);
niceY = scaleLinear().domain([Math.min(...yVals), Math.max(...yVals)]).nice();
xDomain = [xVals[0], xVals[xVals.length - 1]]
yDomain = [Math.min(...yVals), Math.max(...yVals)]
xScale = xType(xDomain, xRange)
yScale = yType(yDomain, yRange)
niceY = scaleLinear()
.domain([Math.min(...yVals), Math.max(...yVals)])
.nice()
lines = [];
colors.forEach((_color, j) => {
const filteredI = I.filter((_el, i) => colorVals[i] === j);
lines.push(chartLine(filteredI));
});
console.log("lines", lines)
lines = []
colors.forEach((_color, j) => {
const filteredI = I.filter((_el, i) => colorVals[i] === j)
lines.push(chartLine(filteredI))
})
console.log('lines', lines)
pointsScaled = points.map((el) => [xScale(el.x), yScale(el.y), el.color]);
delaunayGrid = Delaunay.from(pointsScaled);
voronoiGrid = delaunayGrid.voronoi([0, 0, width, height]);
pointsScaled = points.map((el) => [
xScale(el.x),
yScale(el.y),
el.color,
])
delaunayGrid = Delaunay.from(pointsScaled)
voronoiGrid = delaunayGrid.voronoi([0, 0, width, height])
<svg {width} {height} viewBox="0 0 {width} {height}"
cursor='crosshair'
on:mouseout="{() => dotInfo = null}"
on:blur="{() => dotInfo = null}"
>
<svg
{width}
{height}
viewBox="0 0 {width} {height}"
cursor="crosshair"
on:mouseout={() => (dotInfo = null)}
on:blur={() => (dotInfo = null)}>
<path class="line" fill='none' stroke-opacity={points[dotInfo[1]].color === i ? '1' : '0.1'} stroke={colors[i]} d={subsetLine} stroke-width={strokeWidth} stroke-linecap={strokeLinecap} stroke-linejoin={strokeLinejoin}/>
<circle cx={xScale(points[dotInfo[1]].x)} cy={yScale(points[dotInfo[1]].y)} r={r} stroke={colors[points[dotInfo[1]].color]} fill={dotsFilled} />
<path
class="line"
fill="none"
stroke-opacity={points[dotInfo[1]].color === i
? '1'
: '0.1'}
stroke={colors[i]}
d={subsetLine}
stroke-width={strokeWidth}
stroke-linecap={strokeLinecap}
stroke-linejoin={strokeLinejoin} />
<circle
cx={xScale(points[dotInfo[1]].x)}
cy={yScale(points[dotInfo[1]].y)}
{r}
stroke={colors[points[dotInfo[1]].color]}
fill={dotsFilled} />
<path class="line" fill='none' stroke={colors[i]} d={subsetLine}
stroke-opacity={strokeOpacity[i]} stroke-width={strokeWidth} stroke-linecap={strokeLinecap} stroke-linejoin={strokeLinejoin} />
<path
class="line"
fill="none"
stroke={colors[i]}
d={subsetLine}
stroke-opacity={strokeOpacity[i]}
stroke-width={strokeWidth}
stroke-linecap={strokeLinecap}
stroke-linejoin={strokeLinejoin} />
<g class="y-axis" transform="translate({marginLeft}, 0)" pointer-events='none'>
<path class="domain" stroke="black" d="M{insetLeft}, {marginTop} V{height - marginBottom + 6}"/>
<g
class="y-axis"
transform="translate({marginLeft}, 0)"
pointer-events="none">
<path
class="domain"
stroke="black"
d="M{insetLeft}, {marginTop} V{height - marginBottom + 6}" />
<g class="x-axis" transform="translate(0,{height - marginBottom - insetBottom})" pointer-events='none'>
<path class="domain" stroke="black" d="M{marginLeft},0.5 H{width - marginRight}"/>
<g
class="x-axis"
transform="translate(0,{height - marginBottom - insetBottom})"
pointer-events="none">
<path
class="domain"
stroke="black"
d="M{marginLeft},0.5 H{width - marginRight}" />
<div class="tooltip" style='position:absolute; left:{dotInfo[2].pageX + 12}px; top:{dotInfo[2].pageY + 12}px; pointer-events:none; background-color:{tooltipBackground}; color:{tooltipTextColor}'>
<div
class="tooltip"
style="position:absolute; left:{dotInfo[2].pageX +
12}px; top:{dotInfo[2].pageY +
12}px; pointer-events:none; background-color:{tooltipBackground}; color:{tooltipTextColor}">
.chart-container {
justify-content: center;
align-items: center;
margin-top: 50px;
margin-left: 8
0px;
}
svg {
max-width: 100%;
height: auto;
height: "intrinsic";
margin: auto;
}
path {
fill: "green"
}
.y-axis {
font-size: "10px";
font-family: sans-serif;
text-anchor: "end";
}
.x-axis {
font-size: "10px";
font-family: sans-serif;
text-anchor: "end";
}
.tick text { font-size: 80%; fill: white !important }
.tick {
opacity: 1;
}
.tick-start {
stroke: black;
stroke-opacity: 1;
}
.tick-grid {
stroke: black;
stroke-opacity: 0.2;
font-size: "11px";
color: black;
}
.tick text {
fill: black;
}
.y-axis .tick text {
text-anchor: end !important;
}
.chart-container {
justify-content: center;
align-items: center;
margin-top: 50px;
margin-left: 8 0px;
}
svg {
max-width: 100%;
height: auto;
height: 'intrinsic';
margin: auto;
}
path {
fill: 'green';
}
.y-axis {
font-size: '10px';
font-family: sans-serif;
text-anchor: 'end';
}
.x-axis {
font-size: '10px';
font-family: sans-serif;
text-anchor: 'end';
}
.tick text {
font-size: 80%;
fill: white !important;
}
.tick {
opacity: 1;
}
.tick-start {
stroke: black;
stroke-opacity: 1;
}
.tick-grid {
stroke: black;
stroke-opacity: 0.2;
font-size: '11px';
color: black;
}
.tick text {
fill: black;
}
@media (prefers-color-scheme: dark) {
.y-axis text { fill: white; }
.x-axis text { fill: white; }
.tick-start {
stroke: white;
}
.tick-grid {
stroke: white;
}
.tick text {
fill: white;
}
.domain { stroke: white }
}
.y-axis .tick text {
text-anchor: end !important;
}
.tooltip{
border-radius: 5px;
padding: 5px;
box-shadow: rgba(0, 0, 0, 0.4) 0px 2px 4px, rgba(0, 0, 0, 0.3) 0px 7px 13px -3px, rgba(0, 0, 0, 0.2) 0px -3px 0px inset;
opacity: 1;
}
.tooltip {
border-radius: 5px;
padding: 5px;
box-shadow: rgba(0, 0, 0, 0.4) 0px 2px 4px,
rgba(0, 0, 0, 0.3) 0px 7px 13px -3px,
rgba(0, 0, 0, 0.2) 0px -3px 0px inset;
opacity: 1;
}
export let remboursement = new Array(duree + 1)
export let remboursementAnnuel = new Array(dureeAns_)
export let crd = new Array(duree + 1)
export let crdAnnuel = new Array(dureeAns_)
export let interets = new Array(duree + 1)
export let interetsAnnuels = new Array(dureeAns_)
export let remboursement = new Array(duree + 1)
export let remboursementAnnuel = new Array(dureeAns_)
export let crd = new Array(duree + 1)
export let crdAnnuel = new Array(dureeAns_)
export let interets = new Array(duree + 1)
export let interetsAnnuels = new Array(dureeAns_)
remboursement = new Array(duree + 1)
crd = new Array(duree + 1)
interets = new Array(duree + 1)
remboursementAnnuel = new Array(dureeAns_)
crdAnnuel = new Array(dureeAns_)
interetsAnnuels = new Array(dureeAns_)
remboursement = new Array(duree + 1)
crd = new Array(duree + 1)
interets = new Array(duree + 1)
remboursementAnnuel = new Array(dureeAns_)
crdAnnuel = new Array(dureeAns_)
interetsAnnuels = new Array(dureeAns_)
crd[0] = dette
remboursement[0] = 0
interets[0] = 0
crdAnnuel[0] = dette
remboursementAnnuel[0] = 0
interetsAnnuels[0] = 0
for(let i = 1; i <= duree; i++) {
if(i <= periodeRemboursementCapital) {
remboursement[i] = 0
} else if (i < nombreEcheancesPeriodeTronquee) {
remboursement[i] = ppmt(
taux * prorataPeriodique,
i - periodeRemboursementCapital,
totalPeriodes,
-dette,
)
} else if (i == nombreEcheances) {
remboursement[i] = crd[i-1]
} else {
remboursement[i] = 0
}
crd[i] = crd[i-1] - remboursement[i]
interets[i] = crd[i-1] * taux * prorataPeriodique
if((i % nombrePeriodesParAn) == 0) {
crdAnnuel[i/nombrePeriodesParAn] = crd[i]
remboursementAnnuel[i/nombrePeriodesParAn] = 0
interetsAnnuels[i/nombrePeriodesParAn] = 0
}
remboursementAnnuel[Math.floor(i/nombrePeriodesParAn)] += remboursement[i]
interetsAnnuels[Math.floor(i/nombrePeriodesParAn)] += interets[i]
}
}
crd[0] = dette
remboursement[0] = 0
interets[0] = 0
crdAnnuel[0] = dette
remboursementAnnuel[0] = 0
interetsAnnuels[0] = 0
for (let i = 1; i <= duree; i++) {
if (i <= periodeRemboursementCapital) {
remboursement[i] = 0
} else if (i < nombreEcheancesPeriodeTronquee) {
remboursement[i] = ppmt(
taux * prorataPeriodique,
i - periodeRemboursementCapital,
totalPeriodes,
-dette
)
} else if (i == nombreEcheances) {
remboursement[i] = crd[i - 1]
} else {
remboursement[i] = 0
}
crd[i] = crd[i - 1] - remboursement[i]
interets[i] = crd[i - 1] * taux * prorataPeriodique
if (i % nombrePeriodesParAn == 0) {
crdAnnuel[i / nombrePeriodesParAn] = crd[i]
remboursementAnnuel[i / nombrePeriodesParAn] = 0
interetsAnnuels[i / nombrePeriodesParAn] = 0
}
remboursementAnnuel[Math.floor(i / nombrePeriodesParAn)] +=
remboursement[i]
interetsAnnuels[Math.floor(i / nombrePeriodesParAn)] += interets[i]
}
}
table {
font-size: 90%;
}
th{
font-size:1rem;
font-weight:bold;
}
td{
padding: 5px 5px;
padding: 5px 7px 5px 10px;
text-align:end;
border:none;
}
table {
font-size: 90%;
}
th {
font-size: 1rem;
font-weight: bold;
}
td {
padding: 5px 5px;
padding: 5px 7px 5px 10px;
text-align: end;
border: none;
}
import { base as b, assets as a } from '$app/paths'
import type { PageData } from './$types';
import { onMount } from 'svelte';
import '../app.scss';
import { email } from '../stores'
import Donnees from './Donnees.svelte'
export let data: PageData;
export let base = b
export let assets: string = a
onMount(() => {
email.set(data.email || null)
})
import { base as b, assets as a } from '$app/paths'
import type { PageData } from './$types'
import { onMount } from 'svelte'
import '../app.scss'
import { email } from '../stores'
import Donnees from './Donnees.svelte'
export let data: PageData
export let base = b
export let assets: string = a
onMount(() => {
email.set(data.email || null)
})
<h1 class="text-uppercase lh-1" style="font-size:4rem;width:50%">No GRAIN,<br/>No gain.</h1>
<h2 class="sub">L'outil <span class="text-primary">gratuit</span> de faisabilité d'autoconsommation.</h2>
<a class="mt-3 btn btn-primary" href="{base}/projet/nouveau">Lancer ma simulation</a>
<h1 class="text-uppercase lh-1" style="font-size:4rem;width:50%">
No GRAIN,<br />No gain.
</h1>
<h2 class="sub">
L'outil <span class="text-primary">gratuit</span> de faisabilité
d'autoconsommation.
</h2>
<a class="mt-3 btn btn-primary" href="{base}/projet/nouveau"
>Lancer ma simulation</a>
<Donnees donnees = {data.donnees}/>
<h1 class="my-5 lh-1 text-center">Simulez <span class="text-primary fw-bold">gratuitement</span> vos <span class="text-primary fw-bold">revenus</span> photovoltaïques.</h1>
<Donnees donnees={data.donnees} />
<h1 class="my-5 lh-1 text-center">
Simulez <span class="text-primary fw-bold">gratuitement</span> vos
<span class="text-primary fw-bold">revenus</span> photovoltaïques.
</h1>
<h2> <span class="text-primary fw-bold">Faisabilité </span>et <span class="text-primary fw-bold">optimisation</span> </h2>
<p> <span class="text-primary fs-5 align-bottom"><span class="logoCol1"> G</span><span class="logoCol2">RA</span>IN</span> vous donne l'ensemble des informations économique de votre projet d'auto-consommation et d'auto-consommation collective pour <span class="text-primary fw-bold">prévoir</span>, <span class="text-primary fw-bold">choisir</span>, <span class="text-primary fw-bold">optimiser</span> votre installation photovoltaïque et son utilisation.
<br/>Partagez une énergie <span class="text-primary fw-bold">moins cher</span>, <span class="text-primary fw-bold">local</span> et <span class="text-primary fw-bold">de saison</span>.
<h2>
<span class="text-primary fw-bold">Faisabilité </span>et
<span class="text-primary fw-bold">optimisation</span>
</h2>
<p>
<span class="text-primary fs-5 align-bottom"
><span class="logoCol1"> G</span><span class="logoCol2"
>RA</span
>IN</span>
vous donne l'ensemble des informations économique de votre projet
d'auto-consommation et d'auto-consommation collective pour
<span class="text-primary fw-bold">prévoir</span>,
<span class="text-primary fw-bold">choisir</span>,
<span class="text-primary fw-bold">optimiser</span>
votre installation photovoltaïque et son utilisation.
<br />Partagez une énergie
<span class="text-primary fw-bold">moins cher</span>,
<span class="text-primary fw-bold">local</span>
et <span class="text-primary fw-bold">de saison</span>.
<h2>Reprenez <span class="text-primary fw-bold">les rennes</span>.</h2>
<p>Avec toutes les informations, simulez le futur de votre production d'énergie et reprennez le pouvoir sur votre énergie.<br/> <span class="text-primary fw-bold"> Simplement*</span>, <span class="text-primary fw-bold">rapidement</span> et <span class="text-primary fw-bold">gratuitement</span>.<br/> Créez votre futur !
<h2>
Reprenez <span class="text-primary fw-bold">les rennes</span>.
</h2>
<p>
Avec toutes les informations, simulez le futur de votre
production d'énergie et reprennez le pouvoir sur votre énergie.<br />
<span class="text-primary fw-bold"> Simplement*</span>,
<span class="text-primary fw-bold">rapidement</span>
et <span class="text-primary fw-bold">gratuitement</span>.<br />
Créez votre futur !
<h2>Et <span class="text-primary fw-bold">ensuite</span> ? </h2>
<p>Ensuite, passez sur <span class="text-primary fs-6 align-bottom"><span class="logoCol1"> CO</span><span class="logoCol2">TURN</span>IX</span> pour partager l'énergie de vos panneaux photovoltaïque avec vos voisins.
<span class="text-primary fs-6 align-bottom"><span class="logoCol1"> CO</span><span class="logoCol2">TURN</span>IX</span> gère aussi les flux financiers entre les participants.
<br/>Oui, <span class="text-primary fw-bold">on fait tout ça.</span>.
<h2>Et <span class="text-primary fw-bold">ensuite</span> ?</h2>
<p>
Ensuite, passez sur <span class="text-primary fs-6 align-bottom"
><span class="logoCol1"> CO</span><span class="logoCol2"
>TURN</span
>IX</span>
pour partager l'énergie de vos panneaux photovoltaïque avec vos voisins.
<span class="text-primary fs-6 align-bottom"
><span class="logoCol1"> CO</span><span class="logoCol2"
>TURN</span
>IX</span>
gère aussi les flux financiers entre les participants.
<br />Oui,
<span class="text-primary fw-bold">on fait tout ça.</span>.
.sub {
font-size: 1.4rem;
font-weight: bold;
margin: 20px 0;
}
.img{
height:calc(max(400px, 100vh - 120px));
background-size: calc(min(75vw, (180/70)*50vh)) calc(min(50vh, (70/180)*75vw));
width: 100%;
background-position:bottom 0px right 0px;
background-repeat:no-repeat;
}
.sub {
font-size: 1.4rem;
font-weight: bold;
margin: 20px 0;
}
.img {
height: calc(max(1200px, 100vh - 120px));
background-size: calc(min(75vw, (180/70) * 50vh))
calc(min(50vh, (70/180) * 75vw));
width: 100%;
background-position: bottom 0px right 0px;
background-repeat: no-repeat;
}
@media not (prefers-color-scheme: dark) {
.card {
background-color:color-mix(in srgb, var(--bs-body-bg), transparent 30%)
}
}
@media not (prefers-color-scheme: dark) {
.card {
background-color: color-mix(
in srgb,
var(--bs-body-bg),
transparent 30%
);
}
}
<a class="nav-link " href="{base}">
<span class="text-primary fs-1 align-middle"><span class="logoCol1"> G</span><span class="logoCol2">RA</span>IN</span>
<img src="{assets}/grain.svg" alt="Coturnix" style="width:30px;height:30px"/>
<a class="nav-link" href={base}>
<span class="text-primary fs-1 align-middle"
><span class="logoCol1"> G</span><span class="logoCol2"
>RA</span
>IN</span>
<img
src="{assets}/grain.svg"
alt="Coturnix"
style="width:30px;height:30px" />
main {
font-family: 'Lato', sans-serif;
flex: 1;
display: flex;
flex-direction: column;
width: 100%;
margin: 0 auto;
box-sizing: border-box;
}
footer {
display: flex;
justify-content: center;
align-items: center;
padding: 8px;
background-color: $primary;
}
main {
font-family: 'Lato', sans-serif;
flex: 1;
display: flex;
flex-direction: column;
width: 100%;
margin: 0 auto;
box-sizing: border-box;
}
footer {
display: flex;
justify-content: center;
align-items: center;
padding: 8px;
background-color: $primary;
}
export async function userForm(env: EnvUser, id: DurableObjectId, body: Grain.CreateProjet): Promise<Grain.CreateProjetResp>
export async function userForm(env: EnvUser, id: DurableObjectId, body: Grain.SaveProjet): Promise<null>
export async function userForm(env: EnvUser, id: DurableObjectId, body: Grain.ListProjets): Promise<Grain.ListProjetsResp>
export async function userForm(env: EnvUser, id: DurableObjectId, body: Grain.DelProjet): Promise<null>
export async function userForm(env: EnvUser, id: DurableObjectId, body: Grain.GetProjet): Promise<Grain.GetProjetResp>
export async function userForm(env: EnvUser, id: DurableObjectId, body: Grain.Cmd): Promise<any> {
let headers = new Headers();
headers.set("Content-Type", "application/json");
let stub = env.USER.get(id);
let x = await (await stub.fetch(
"https://y.coturnix.fr",
{
method: "POST",
export async function userForm(
env: EnvUser,
id: DurableObjectId,
body: Grain.CreateProjet
): Promise<Grain.CreateProjetResp>
export async function userForm(
env: EnvUser,
id: DurableObjectId,
body: Grain.SaveProjet
): Promise<null>
export async function userForm(
env: EnvUser,
id: DurableObjectId,
body: Grain.ListProjets
): Promise<Grain.ListProjetsResp>
export async function userForm(
env: EnvUser,
id: DurableObjectId,
body: Grain.DelProjet
): Promise<null>
export async function userForm(
env: EnvUser,
id: DurableObjectId,
body: Grain.GetProjet
): Promise<Grain.GetProjetResp>
export async function userForm(
env: EnvUser,
id: DurableObjectId,
body: Grain.Cmd
): Promise<any> {
let headers = new Headers()
headers.set('Content-Type', 'application/json')
let stub = env.USER.get(id)
let x = await (
await stub.fetch('https://y.coturnix.fr', {
method: 'POST',
cout += tarifLocal(p, i) * consoMoyenneFoyer(p, i) * p.autoprod / 100
+ p.coutElec * Math.pow(1 + p.inflationElec / 100, i) * consoMoyenneFoyer(p, i) * (100 - p.autoprod) / 100
cout +=
(tarifLocal(p, i) * consoMoyenneFoyer(p, i) * p.autoprod) / 100 +
(p.coutElec *
Math.pow(1 + p.inflationElec / 100, i) *
consoMoyenneFoyer(p, i) *
(100 - p.autoprod)) /
100
export function productionAnnuelle(p: Grain.SimulationCommunaute, i: number){
return p.productible * p.puissance * Math.pow(1-(p.degradation)/100, i)
export function productionAnnuelle(p: Grain.SimulationCommunaute, i: number) {
return p.productible * p.puissance * Math.pow(1 - p.degradation / 100, i)
puissance: number,
economies?: number,
autoconso: number,
autoprod: number,
fraisDivers: number,
prix: number,
apport: number,
interet: number,
echeances: number,
consoMoyenneFoyer: number,
productible: number,
degradation: number,
inflation: number,
ratio: number,
enedis: number,
puissance: number
economies?: number
autoconso: number
autoprod: number
fraisDivers: number
prix: number
apport: number
interet: number
echeances: number
consoMoyenneFoyer: number
productible: number
degradation: number
inflation: number
ratio: number
enedis: number
limites: number[],
prix: number[],
inflation: number,
},
coutElec: number,
inflationElec: number,
maintenance: number,
turpe: number,
turpeInjection: number,
provisionOnduleurs: number,
assurance: number,
divers: number,
ratioDcAc: number,
dureeAmortissement: number,
tauxIS: number,
tauxDSRA: number,
limites: number[]
prix: number[]
inflation: number
}
coutElec: number
inflationElec: number
maintenance: number
turpe: number
turpeInjection: number
provisionOnduleurs: number
assurance: number
divers: number
ratioDcAc: number
dureeAmortissement: number
tauxIS: number
tauxDSRA: number
name?: string,
porteur?: string,
tel?: string,
adresse?: string,
simulation?: SimulationCommunaute,
prms: Prm[],
name?: string
porteur?: string
tel?: string
adresse?: string
simulation?: SimulationCommunaute
prms: Prm[]
id: string,
name?: string,
porteur?: string,
tel?: string,
adresse?: string,
simulation?: SimulationCommunaute,
prms: Prm[],
id: string
name?: string
porteur?: string
tel?: string
adresse?: string
simulation?: SimulationCommunaute
prms: Prm[]
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="%sveltekit.assets%/bootstrap-icons.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@650&family=Roboto:wght@700&display=swap" rel="stylesheet">
<link href="/favicon.png" rel="icon">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="%sveltekit.assets%/bootstrap-icons.css" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Lato:wght@650&family=Roboto:wght@700&display=swap"
rel="stylesheet" />
<link href="/favicon.png" rel="icon" />
static
node_modules
src/simulation_communaute.js
.svelte-kit