🖋️ Améliore la page de documentation de publicode

- Ajoute le tuto
- Rend tous les exemples executables
pull/945/head
Johan Girod 2020-03-24 17:50:18 +01:00
parent 815ff255ee
commit 0f1ca13b7f
18 changed files with 436 additions and 361 deletions

View File

@ -1,5 +1,5 @@
// Page listing the engine's currently implemented mecanisms and their tests
import knownMecanims from 'Engine/known-mecanisms.yaml'
import mécanismes from 'Engine/mecanisms.yaml'
import { fromPairs, has, toPairs } from 'ramda'
import React from 'react'
import './Mecanisms.css'
@ -24,7 +24,7 @@ export default function Mecanisms() {
partageant le code de mecanisms.test.js
</p>
<ul id="mecanisms">
{toPairs(knownMecanims).map(([name, data]) => (
{toPairs(mécanismes).map(([name, data]) => (
<li key={name}>
{name}
{suites[name] == null ? (

View File

@ -1,11 +0,0 @@
import React from 'react'
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter'
import yaml from 'react-syntax-highlighter/dist/cjs/languages/hljs/yaml'
import style from 'react-syntax-highlighter/dist/cjs/styles/hljs/tomorrow'
SyntaxHighlighter.registerLanguage('yaml', yaml)
export default ({ source }) => (
<SyntaxHighlighter language="yaml" style={style}>
{source}
</SyntaxHighlighter>
)

View File

@ -1,7 +1,7 @@
import { ThemeColorsContext } from 'Components/utils/colors'
import { SitePathsContext } from 'Components/utils/withSitePaths'
import Value from 'Components/Value'
import knownMecanisms from 'Engine/known-mecanisms.yaml'
import mecanisms from 'Engine/mecanisms.yaml'
import { findRuleByDottedName, findRuleByNamespace } from 'Engine/rules'
import { isEmpty } from 'ramda'
import React, { Suspense, useContext, useState } from 'react'
@ -28,7 +28,7 @@ import './Rule.css'
let LazySource = React.lazy(() => import('./RuleSource'))
export default AttachDictionary(knownMecanisms)(function Rule({ dottedName }) {
export default AttachDictionary(mecanisms)(function Rule({ dottedName }) {
const currentExample = useSelector(state => state.currentExample)
const flatRules = useSelector(flatRulesSelector)
const valuesToShow = !useSelector(noUserInputSelector)

View File

@ -3,7 +3,7 @@ import rules from 'Publicode/rules'
import React from 'react'
import emoji from 'react-easy-emoji'
import { Rule } from 'Types/rule'
import ColoredYaml from './ColoredYaml'
import PublicodeHighlighter from '../ui/PublicodeHighlighter'
type RuleSourceProps = Pick<Rule, 'dottedName'>
@ -17,7 +17,7 @@ export default function RuleSource({ dottedName }: RuleSourceProps) {
Code source <br />
<code>{dottedName}</code>
</h2>
<ColoredYaml source={safeDump(source)} />
<PublicodeHighlighter source={safeDump(source)} />
</div>
)
}

View File

@ -0,0 +1,21 @@
import React from 'react'
import emoji from 'react-easy-emoji'
import { PrismLight as SyntaxHighlighter } from 'react-syntax-highlighter'
import yaml from 'react-syntax-highlighter/dist/esm/languages/prism/yaml'
import style from 'react-syntax-highlighter/dist/esm/styles/prism/atom-dark'
SyntaxHighlighter.registerLanguage('yaml', yaml)
export default ({ source }) => (
<div css="position: relative; margin-bottom: 1rem">
<SyntaxHighlighter language="yaml" style={style}>
{source}
</SyntaxHighlighter>
<a
href={`https://publi.codes/studio?code=${encodeURIComponent(source)}`}
css="position: absolute; bottom: 5px; right: 10px; color: white !important;"
>
{emoji('⚡')} Lancer le calcul
</a>
</div>
)

View File

@ -31,10 +31,11 @@ button {
blockquote {
background: var(--lighterColor);
border-radius: 0.6em;
padding: 1.2em 1em 0.4em;
margin: 0.6em;
color: #333;
border-radius: 0.3rem;
padding: 1rem;
padding-bottom: 0.6rem;
margin: 1rem 0;
color: var(--darkerColor);
}
.ui__.answer-group {

View File

@ -1,3 +1,4 @@
import PublicodeHighlighter from 'Components/ui/PublicodeHighlighter'
import React from 'react'
import emoji from 'react-easy-emoji'
import ReactMarkdown, { ReactMarkdownProps } from 'react-markdown'
@ -31,6 +32,15 @@ type MarkdownProps = ReactMarkdownProps & {
className?: string
}
const CodeBlock = ({ value, language }) =>
language === 'yaml' ? (
<PublicodeHighlighter source={value} />
) : (
<pre>
<code>{value}</code>
</pre>
)
export const Markdown = ({
source,
className = '',
@ -40,7 +50,12 @@ export const Markdown = ({
<ReactMarkdown
source={source}
className={`markdown ${className}`}
renderers={{ link: LinkRenderer, text: TextRenderer, ...renderers }}
renderers={{
link: LinkRenderer,
text: TextRenderer,
code: CodeBlock,
...renderers
}}
{...otherProps}
/>
)

View File

@ -1,16 +1,29 @@
# Publicode
Publicode est un langage déclaratif pour encoder les algorithmes d'intérêt
public. Il permet de réaliser des calculs généraux tout en fournissant une
explication permettant de comprendre et de documenter ces calculs.
Publicode est adapté pour modéliser des domaines métiers complexes pouvant être
décomposés en règles élémentaires simples (comme la législation socio-fiscale,
un bilan carbone, un estimateur de rendement locatif, etc.). Il permet de
décomposés en règles élémentaires simples (comme la [législation socio-fiscale](https://github.com/betagouv/mon-entreprise/tree/master/publicode),
[un bilan carbone](https://github.com/laem/futureco-data/blob/master/co2.yaml),
un estimateur de rendement locatif, etc.).
Il permet de
générer facilement des simulateurs web interactifs où l'on peut affiner
progressivement le résultat affiché, et explorer une documentation du calcul.
## Formule basiques
## Projets phares
- [mon-entreprise.fr](https://mon-entreprise.fr/simulateurs) : utilise publicode
pour spécifier l'ensemble des calculs relatifs à la législation socio-fiscale
en France. Le site permet entre autre de simuler une fiche de paie complète,
de calculer les cotisations sociales pour un indépendant ou encore connaître
le montant du chômage partiel. Les règles sont publiées sous la forme d'une
[bibliothèque de calcul autonome](https://mon-entreprise.fr/intégration/bibliothèque-de-calcul), libre de droit.
- [futur.eco](https://futur.eco/) utilise publicode pour calculer les bilans
carbone d'un grand nombre d'activité, plats, transport ou biens.
## Principe de base
La syntaxe de Publicode est basée sur le langage
[Yaml](https://en.wikipedia.org/wiki/YAML). Un fichier Publicode contient une
@ -32,8 +45,6 @@ prix total:
formule: 5 * prix d'un repas
```
> [Lancer le calcul](https://publi.codes/studio?code=prix%20d'un%20repas%3A%0A%20%20formule%3A%2010%0A%0Aprix%20total%3A%0A%20%20formule%3A%205%20*%20prix%20d'un%20repas)
Il s'agit d'un langage déclaratif : comme dans une formule d'un tableur le `prix total` sera recalculé automatiquement si le prix d'un repas change. L'ordre de
définition des règles n'a pas d'importance.
@ -53,12 +64,12 @@ prix total:
formule: nombre de repas * prix d'un repas
```
> [Lancer le calcul](https://publi.codes/studio?code=prix%20d'un%20repas%3A%0A%20%20formule%3A%2010%20%E2%82%AC%2Frepas%0A%0Anombre%20de%20repas%3A%0A%20%20formule%3A%205%20repas%0A%0Aprix%20total%3A%0A%20%20formule%3A%20nombre%20de%20repas%20*%20prix%20d'un%20repas)
Le calcul est inchangé mais on a indiqué que le "prix d'un repas" s'exprime en
`€/repas` et que le "nombre de repas" est un nombre de `repas`. L'unité du prix
total est inférée automatiquement comme étant en `€`. (`€/repas` \* `repas` =
`€`) Ce système d'unité permet de typer les formules de calcul et de rejeter
`€`)
Ce système d'unité permet de typer les formules de calcul et de rejeter
automatiquement des formules incohérentes :
```yaml
@ -77,8 +88,6 @@ prix total:
# La formule de "prix total" est invalide.
```
> [Lancer le calcul](https://publi.codes/studio?code=prix%20d'un%20repas%3A%0A%20%20formule%3A%2010%20%E2%82%AC%2Frepas%0A%0Anombre%20de%20repas%3A%0A%20%20formule%3A%205%20repas%0A%0Afrais%20de%20r%C3%A9servation%3A%0A%20%20formule%3A%201%20%E2%82%AC%2Frepas%0A%0Aprix%20total%3A%0A%20%20formule%3A%20nombre%20de%20repas%20*%20prix%20d'un%20repas%20%2B%20frais%20de%20r%C3%A9servation)
Dans l'exemple ci-dessus Publicode détecte une erreur car les termes de
l'addition ont des unités incompatibles : d'un côté on a des `€` et de l'autre
des `€/repas`. Comme dans les formules de Physique, cette incohérence d'unité
@ -90,10 +99,37 @@ prix total:
formule: nombre de repas * (prix d'un repas + frais de réservation)
```
> [Lancer le calcul](<https://publi.codes/studio?code=prix%20d'un%20repas%3A%0A%20%20formule%3A%2010%20%E2%82%AC%2Frepas%0A%0Anombre%20de%20repas%3A%0A%20%20formule%3A%205%20repas%0A%0Afrais%20de%20r%C3%A9servation%3A%0A%20%20formule%3A%201%20%E2%82%AC%2Frepas%0A%0Aprix%20total%3A%0A%20%20formule%3A%20nombre%20de%20repas%20*%20(prix%20d'un%20repas%20%2B%20frais%20de%20r%C3%A9servation)>)
> **Attention :** Il ne faut pas insérer d'espace autour de la barre oblique dans
> les unités, l'unité `€ / mois` doit être notée `€/mois`
> **Attention:** Il ne faut pas insérer d'espace autour de la barre oblique dans
> les unités, l'unité ~`€ / mois`~ doit être notée `€/mois`
### Conversion
Publicode converti automatiquement les unités si besoin.
```yaml
salaire:
formule: 1500 €/mois
prime faible salaire:
applicable si: salaire < 20 k/an
formule: 300€
```
On peut forcer la conversion des unités via la propriété `unité`, ou la notation suffixé `[...]`
```yaml
salaire:
unité: €/mois
formule: 3200
salaire annuel:
formule: salaire [k€/an]
```
**Conversions disponibles :**
- `mois` / `année` / `jour`
- `€` / `k€`
## Titre, description et références
@ -149,25 +185,34 @@ spécifique par mécanisme.
Par exemple on a un mécanisme `barème`:
```yaml
revenu imposable:
formule: 54126 €
impôt sur le revenu:
formule:
barème:
assiette: revenu imposable
tranches:
- taux: 0%
plafond: 9807
plafond: 9807
- taux: 14%
plafond: 27086
plafond: 27086
- taux: 30%
plafond: 72617
plafond: 72617
- taux: 41%
plafond: 153783
plafond: 153783
- taux: 45%
```
La syntaxe hiérarchique de Yaml permet d'imbriquer les mécanismes :
```yaml
prime . fixe:
formule: 1000€
prime . taux du bonus:
formule: 20%
prime:
formule:
somme:
@ -175,15 +220,9 @@ prime:
- produit:
assiette: fixe
taux: taux du bonus
prime . fixe:
formule: 1000€
prime . taux du bonus:
formule: 20%
```
**[Voir la liste des mécanismes](https://github.com/betagouv/mon-entreprise/blob/master/publicode/mecanism.md)**
**[Voir la liste des mécanismes existants](/mécanismes)**
## Applicabilité
@ -204,8 +243,6 @@ prime de vacances:
formule: 200€
```
> [Lancer le calcul](https://publi.codes/studio?code=date%20de%20d%C3%A9but%3A%20%0A%20%20formule%3A%2012%2F02%2F2020%0A%20%20%0Aanciennet%C3%A9%20en%20fin%20d'ann%C3%A9e%3A%0A%20%20formule%3A%20%0A%20%20%20%20dur%C3%A9e%3A%0A%20%20%20%20%20%20%20depuis%3A%20date%20de%20d%C3%A9but%0A%20%20%20%20%20%20%20jusqu'%C3%A0%3A%2031%2F12%2F2020%0A%0Aprime%20de%20vacances%3A%0A%20%20applicable%20si%3A%20anciennet%C3%A9%20en%20fin%20d'ann%C3%A9e%20%3E%201%20an%0A%20%20formule%3A%20200%E2%82%AC)
Ici si l'ancienneté est inférieure à un an la prime de vacances ne sera pas
applicable. Les variables non applicables sont ignorées au niveau des mécanismes
(par exemple le mécanisme `somme` comptera une prime non applicable comme valant

View File

@ -1,219 +0,0 @@
# Liste et description des différents mécanismes compris par le moteur.
# La description peut être rédigée en markdown :-)
une possibilité:
type: enum
inversion numérique:
type: numeric
description: |
La formule de calcul de cette variable n'est pas connue, souvent elle n'a même pas de sens. Mais le mécanisme `inversion` indique qu'elle peut être _estimée_ à partir de l'un des _objectifs_ listés sous l'attribut `avec`. Il faut alors renseigner une valeur cible pour cet objectif.
Voilà comment ça marche : on va donner à la variable une valeur au hasard, calculer _l'objectif_, puis grâce à des calculs savants améliorer notre choix jusqu'à ce que l'écart entre le calcul et la valeur cible devienne satisfaisant.
Concrètement, si l'on demande au moteur (même indirectement) la valeur d'une variable qui a pour formule une inversion, il va vérifier qu'une des possibilités d'inversion a bien une valeur calculée ou saisie, et procéder à l'inversion décrite plus haut à partir de celle-ci. Sinon, ces possibilités d'inversions seront listées comme manquantes.
une de ces conditions:
type: boolean
description: |
C'est un `ou` logique.
Contient une liste de conditions.
Renvoie vrai si l'une des conditions est vraie.
toutes ces conditions:
type: boolean
description: |
C'est un `et` logique.
Contient une liste de conditions.
Renvoie vrai si toutes les conditions vraies.
variations:
type: numeric
description: |
Contient une liste de conditions (`si`) et leurs conséquences associées (`alors`).
Pour la première condition vraie dans la liste, on retient la valeur qui lui est associée.
Si aucune condition n'est vraie, alors ce mécanisme renvoie implicitement `non applicable`
Exemple:
```
- si: age < 18 ans
alors: 'mineur'
- sinon: 'majeur'
```
Ce mécanisme peut aussi être utilisé au sein d'un mécanisme compatible, tel que la produit ou le barème.
Exemple (TVA):
```
produit:
assiette: total hors taxe
variations:
- si: restauration
alors:
taux: 10%
- sinon:
taux: 20%
```
produit:
type: numeric
description: |
C'est une multiplication un peu améliorée, très utile pour exprimer les cotisations.
Sa propriété `assiette` est multipliée par un pourcentage, `taux`, ou par un `facteur` quand ce nom est plus approprié.
La multiplication peut être plafonnée : ce plafond sépare l'assiette en deux, et la partie au-dessus du plafond est tout simplement ignorée. Dans ce cas, elle se comporte comme une barème en taux marginaux à deux tranches, la deuxième au taux nul et allant de `plafond` à l'infini.
le maximum de:
type: numeric
description: |
Renvoie la valeur numérique de la liste de propositions fournie qui est la plus grande.
Il est conseillé de renseigner une description de chaque proposition par exemple quand elles représentent des méthodes de calcul alternatives.
le minimum de:
type: numeric
description: |
Renvoie l'élément de la liste de propositions fournie qui a la plus petite valeur.
Ces propositions doivent avoir un mécanisme de calcul ou être une valeur numérique.
Il est conseillé de renseigner une description de chaque proposition par exemple quand elles représentent des méthodes de calcul alternatives parmi lesquelles il faut en choisir une.
somme:
type: numeric
description: |
C'est tout simplement la somme de chaque terme de la liste.
arrondi:
type: numeric
description: |
On arrondi à l'euro le plus proche
recalcul:
type: numeric
description: >-
Relance le calcul d'une règle dans une situation différente de la situation
courante. Permet par exemple de calculer le montant des cotisations au
niveau du SMIC, même si le salaire est plus élevé dans la situation
actuelle.
##########################################
# Ce qu'on appelle aujourd'hui des RuleProp
# Et qui deviendront des mécanismes classiques normalement par la suite #TODO
formule:
description: |
C'est la formule de calcul d'une variable. Elle renvoie une valeur numérique ou un 'non', exprimant le fait que la variable n'est pas applicable, ce qui vaut implicitement 0.
Cette doit faire appel à fera appel à des mécanismes de calcul : par exemple `produit`, le plus commun pour les variables de type `Cotisation`.
applicable si:
description: |
Décide si la règle est applicable pour la situation saisie.
> Une cotisation sociale peut ne concerner que les salariés au statut cadre. Elle ne sera pas à verser pour un non cadre
La formule de calcul peut donc être ignorée, quel que soit son montant.
Peut être accompagnée du mécanisme 'non applicable si'.
non applicable si:
description: |
Décide si la règle n'est applicable pour la situation saisie.
> Un contrat CDD peut entraîner une majoration spécifique. Cette majoration est 'non applicable si' le contrat est un CDI.
La formule de calcul peut donc être ignorée, quel que soit son montant.
Peut être accompagnée du mécanisme 'applicable si'.
rend non applicable:
description: |
Permet de désactiver l'application de certaines règles pour la situation saisie.
> Ce mécanisme est utile pour encoder les régimes d'exceptions (par exemple le [régime des impatriés](/documentation/contrat-salarié/régime-des-impatriés)) sans avoir à modifier la définition des règles de base.
barème:
type: numeric
description: >-
C'est un barème en taux marginaux, mécanisme de calcul connu son utilisation
dans le calcul de l'impôt sur le revenu.
L'assiette est décomposée en plusieurs tranches, qui sont multipliées par un
taux spécifique.
Les tranches sont souvent exprimées sous forme de facteurs d'une variable
que l'on appelle `multiplicateur`, par exemple `1 x le plafond de la
sécurité sociale`.
grille:
type: numeric
description: >-
C'est un barème sous la forme d'une grille de correspondance. C'est le
mécanisme de calcul de l'impôt neutre, aussi appelé impôt non personnalisé.
Il est composé de tranches qui se suivent. Il suffit de trouver l'assiette
qui correspond à la tranche, et de selectionner le montant associé à
l'assiette.
taux progressif:
type: numeric
description: >-
Ce mécanisme permet de calculer un taux progressif. On spécifie pour chaque
tranche le plafond et le taux associé. Le taux effectif renvoyé est calculé
en lissant la différence de taux entre la borne inférieure et supérieure de
l'assiette
> Par exemple, si nous nous avons les tranches suivantes :
- taux: 50% / plafond: 0
- taux: 100% / plafond: 1000
> Pour une assiette de 500, le taux retourné sera 75%, car il correspond au
taux situé à la moitié de la tranche correspondante.
composantes:
type: numeric
description: |
Beaucoup de cotisations sont composées de deux parties qui partagent la méthode de calcul mais diffèrent par des paramètres différents.
Pour ne pas définir deux variables presque redondantes, on utilise le mécanisme de composante. Il se comportera comme une somme dans les calculs, mais son affichage sur les pages /règle sera adapté.
Il est même possible, pour les mécanismes `barème` et `produit` de garder en commun un paramètre comme l'assiette, puis de déclarer des composantes pour le taux.
> L'exemple le plus courant de composantes, c'est la distinction part employeur, part salarié (ex. retraite AGIRC).
allègement:
type: numeric
description: |
Permet de réduire le montant d'une variable.
Très utilisé dans le contexte des impôts.
encadrement:
type: numeric
description: |
Permet d'ajouter un plafond et/ou un plancher à une valeur.
durée:
type: numeric
description: |
Permet d'obtenir le nombre de jours entre deux dates
synchronisation:
type: object
description: |
Pour éviter trop de saisies à l'utilisateur, certaines informations sont
récupérées à partir de ce que l'on appelle des API. Ce sont des services
auxquels ont fait appel pour obtenir des informations sur un sujet précis.
Par exemple, l'État français fournit gratuitement l'API géo, qui permet à
partir du nom d'une ville, d'obtenir son code postal, son département, la
population etc.
Ce mécanismes `synchronisation` permet de faire le lien entre les règles de
notre système et les réponses de ces API.

View File

@ -2,33 +2,11 @@ import { decompose } from 'Engine/mecanisms/utils'
import variations from 'Engine/mecanisms/variations'
import { convertNodeToUnit } from 'Engine/nodeUnits'
import { inferUnit, isPercentUnit } from 'Engine/units'
import {
any,
equals,
evolve,
is,
map,
max,
mergeWith,
min,
path,
pluck,
reduce,
toPairs
} from 'ramda'
import { any, equals, evolve, is, map, max, mergeWith, min, path, pluck, reduce, toPairs } from 'ramda'
import React from 'react'
import 'react-virtualized/styles.css'
import { typeWarning } from './error'
import {
collectNodeMissing,
defaultNode,
evaluateArray,
evaluateNode,
evaluateObject,
makeJsx,
mergeAllMissing,
parseObject
} from './evaluation'
import { collectNodeMissing, defaultNode, evaluateArray, evaluateNode, evaluateObject, makeJsx, mergeAllMissing, parseObject } from './evaluation'
import Allègement from './mecanismViews/Allègement'
import { Node, SimpleRuleLink } from './mecanismViews/common'
import InversionNumérique from './mecanismViews/InversionNumérique'
@ -463,7 +441,7 @@ export let mecanismReduction = (recurse, k, v) => {
export let mecanismProduct = (recurse, k, v) => {
if (v.composantes) {
//mécanisme de composantes. Voir known-mecanisms.md/composantes
//mécanisme de composantes. Voir mécanismes.md/composantes
return decompose(recurse, k, v)
}
if (v.variations) {

View File

@ -0,0 +1,308 @@
une de ces conditions:
description: >-
C'est un `ou` logique.
Contient une liste de conditions.
Renvoie vrai si l'une des conditions est applicable.
retourne: Booléen
exemples:
base:
age:
formule: 17 ans
mineur émancipé:
formule: oui
peut voter:
formule:
une de ces conditions:
- age > 18 ans
- mineur émancipé
toutes ces conditions:
description: >-
C'est un `et` logique.
Contient une liste de conditions.
Renvoie vrai si toutes les conditions sont applicables.
argument:
- '*'
- ...
produit:
description: >-
C'est une multiplication un peu améliorée, très utile pour exprimer les
cotisations.
Sa propriété `assiette` est multipliée par un pourcentage, `taux`, ou par un
`facteur` quand ce nom est plus approprié.
La multiplication peut être plafonnée : ce plafond sépare l'assiette en
deux, et la partie au-dessus du plafond est tout simplement ignorée. Dans ce
cas, elle se comporte comme une barème en taux marginaux à deux tranches, la
deuxième au taux nul et allant de `plafond` à l'infini.
argument:
assiette: Valeur à multiplier
taux: Taux à appliquer
facteur: Facteur multiplicatif
plafond: Plafond au dessus duquel le taux appliqué est nul
exemples:
base:
cotisation:
formule:
produit:
assiette: 2000 €/mois
taux: 5%
assiette plafonnée:
plafond sécurité sociale:
formule: 3000 €/mois
assiette cotisation:
formule: 15000 €/mois
chômage:
formule:
produit:
assiette: assiette cotisation
plafond: 400% * plafond sécurité sociale
taux: 4%
variations:
description: >-
Contient une liste de conditions (`si`) et leurs conséquences associées
(`alors`).
Pour la première condition vraie dans la liste, on retient la valeur qui lui
est associée.
Si aucune condition n'est vraie, alors ce mécanisme renvoie implicitement
`non applicable`
Ce mécanisme peut aussi être utilisé au sein d'un mécanisme compatible, tel qu'un produit ou un barème.
arguments:
- si: condition à vérifier
alors: consequence évaluée si la condition est vrai
- ...
- sinon: consequence évaluée si aucune des conditions précédente n'était applicable
exemples:
base:
taux réduit:
formule: oui
taux allocation familiales:
formule:
variations:
- si: taux réduit
alors: 3.45%
- sinon: 5.25%
dans un produit:
assiette cotisation:
formule: 2300 €/mois
taux réduit:
formule: oui
allocation familiales:
formule:
produit:
assiette: assiette cotisation
variations:
- si: taux réduit
alors:
taux: 3.45%
- sinon:
taux: 5.25%
somme:
description: >-
C'est tout simplement la somme de chaque terme de la liste. Si un des terme
n'est pas applicable, il vaut zéro.
On peut aussi retrancher des valeurs avec l'opérateur unaire `-`
arguments:
- '*'
- ...
exemples:
base:
somme:
- 15.89
- 12% * 14 €
- (-30 €)
terme non applicable:
a:
formule: 50
b:
applicable si: non
formule: 20
somme:
formule:
somme:
- a
- b
- 40
le maximum de:
description: >-
Renvoie la valeur numérique de la liste de propositions fournie qui est la
plus grande.
Pour ajouter un plancher à une valeur, préférer l'utilisation du
mécanisme `encadrement`.
le minimum de:
description: >-
Renvoie la valeur numérique de la liste de propositions fournie qui est la
plus petite.
Pour plafonner une valeur, préférer l'utilisation du mécanisme `encadrement`.
arrondi:
description: >-
Arrondi à l'entier le plus proche, ou à une précision donnée.
exemples:
base:
arrondi:
formule:
arrondi:
valeur: 12.45
décimales: 1
régularisation:
description: >-
Permet de régulariser progressivement un calcul de cotisation en fonction de
variables numérique mensuelle cumulée.
Ce mécanisme spécifique est utilisé pour le calcul des cotisations
mensuelles.
arguments:
règle: règle à régulariser
valeurs cumulées:
- liste de variables cumulée mensuellement pour calculer la régularisation. Doit être
numérique, et avoir une unité `/mois`
exemples:
base:
brut:
formule:
somme:
- 2000 €/mois | du 01/01/2020 | au 31/05/2020
- 4000 €/mois | du 01/06/2020 | au 31/12/2020
plafond:
formule: 3000 €/mois
cotisation:
formule:
régularisation:
règle:
produit:
assiette: brut
plafond: plafond
taux: 10%
valeurs cumulées:
- brut
- plafond
cotisation en mai:
formule: cotisation | du 01/05/2020 | au 31/05/2020
cotisation en juin:
formule: cotisation | du 01/06/2020 | au 30/06/2020
cotisation en novembre:
formule: cotisation | du 01/11/2020 | au 30/11/2020
recalcul:
description: >-
Relance le calcul d'une règle dans une situation différente de la situation
courante. Permet par exemple de calculer le montant des cotisations au niveau du
SMIC, même si le salaire est plus élevé dans la situation actuelle.
barème:
description: C'est un barème en taux marginaux, mécanisme de calcul connu son utilisation
dans le calcul de l'impôt sur le revenu.
L'assiette est décomposée en plusieurs tranches, qui sont multipliées par un
taux spécifique.
Les tranches sont souvent exprimées sous forme de facteurs d'une variable
que l'on appelle `multiplicateur`, par exemple `1 x le plafond de la
sécurité sociale`.
grille:
description: >-
C'est un barème sous la forme d'une grille de correspondance. C'est le
mécanisme de calcul de l'impôt neutre, aussi appelé impôt non personnalisé.
Il est composé de tranches qui se suivent. Il suffit de trouver l'assiette
qui correspond à la tranche, et de selectionner le montant associé à
l'assiette.
taux progressif:
description: >-
Ce mécanisme permet de calculer un taux progressif. On spécifie pour chaque
tranche le plafond et le taux associé. Le taux effectif renvoyé est calculé
en lissant la différence de taux entre la borne inférieure et supérieure de
l'assiette
> Par exemple, si nous nous avons les tranches suivantes :
- taux: 50% / plafond: 0
- taux: 100% / plafond: 1000
> Pour une assiette de 500, le taux retourné sera 75%, car il correspond au
> taux situé à la moitié de la tranche correspondante.
composantes:
description: >-
Beaucoup de cotisations sont composées de deux parties qui partagent la
méthode de calcul mais diffèrent par des paramètres différents.
Pour ne pas définir deux variables presque redondantes, on utilise le
mécanisme de composante. Il se comportera comme une somme dans les calculs,
mais son affichage sur les pages /règle sera adapté.
Il est même possible, pour les mécanismes `barème` et `produit` de garder en
commun un paramètre comme l'assiette, puis de déclarer des composantes pour
le taux.
> L'exemple le plus courant de composantes, c'est la distinction part
employeur, part salarié (ex. retraite AGIRC).
allègement:
description: >-
Permet de réduire le montant d'une variable.
Très utilisé dans le contexte des impôts.
encadrement:
description: Permet d'ajouter un plafond et/ou un plancher à une valeur.
durée:
description: Permet d'obtenir le nombre de jours entre deux dates
synchronisation:
description: Pour éviter trop de saisies à l'utilisateur, certaines informations sont
récupérées à partir de ce que l'on appelle des API. Ce sont des services
auxquels ont fait appel pour obtenir des informations sur un sujet précis.
Par exemple, l'État français fournit gratuitement l'API géo, qui permet à
partir du nom d'une ville, d'obtenir son code postal, son département, la
population etc.
Ce mécanismes `synchronisation` permet de faire le lien entre les règles de
notre système et les réponses de ces API.
inversion numérique:
description: >-
La formule de calcul de cette variable n'est pas connue, souvent elle n'a
même pas de sens. Mais le mécanisme `inversion` indique qu'elle peut être
_estimée_ à partir de l'un des _objectifs_ listés sous l'attribut `avec`. Il
faut alors renseigner une valeur cible pour cet objectif.
Voilà comment ça marche : on va donner à la variable une valeur au hasard,
calculer _l'objectif_, puis grâce à des calculs savants améliorer notre
choix jusqu'à ce que l'écart entre le calcul et la valeur cible devienne
satisfaisant.
Concrètement, si l'on demande au moteur (même indirectement) la valeur d'une
variable qui a pour formule une inversion, il va vérifier qu'une des
possibilités d'inversion a bien une valeur calculée ou saisie, et procéder à
l'inversion décrite plus haut à partir de celle-ci. Sinon, ces possibilités
d'inversions seront listées comme manquantes.

View File

@ -20,7 +20,7 @@ export default function parse(parse, k, v) {
// Barème en taux marginaux.
if (v.composantes) {
//mécanisme de composantes. Voir known-mecanisms.md/composantes
//mécanisme de composantes. Voir mécanismes.md/composantes
return decompose(parse, k, v)
}
if (v.variations) {

View File

@ -17,7 +17,7 @@ import {
export default function parse(parse, k, v) {
if (v.composantes) {
//mécanisme de composantes. Voir known-mecanisms.md/composantes
//mécanisme de composantes. Voir mécanismes.md/composantes
return decompose(parse, k, v)
}
if (v.variations) {

View File

@ -11,7 +11,7 @@ import {
export default function parse(parse, k, v) {
if (v.composantes) {
//mécanisme de composantes. Voir known-mecanisms.md/composantes
//mécanisme de composantes. Voir mécanismes.md/composantes
return decompose(parse, k, v)
}
if (v.variations) {

View File

@ -19,7 +19,7 @@ export const Header = ({ noSubtitle, sectionName = '' }) => (
</Link>
{!noSubtitle && (
<p css="max-width: 28rem; margin: 0 auto; font-size: 120%">
Un nouveau langage pour les algorithmes d'intérêt public.
Le langage pour les algorithmes d'intérêt public.
</p>
)}
</header>

View File

@ -1,9 +1,6 @@
import exemple1 from '!!raw-loader!./exemples/bareme-ir.yaml'
import exemple2 from '!!raw-loader!./exemples/douche.yaml'
import ColoredYaml from 'Components/rule/ColoredYaml'
import { Markdown } from 'Components/utils/markdown'
import publicodeReadme from 'Engine/README.md'
import React, { useEffect } from 'react'
import emoji from 'react-easy-emoji'
import { Link } from 'react-router-dom'
import { Header } from './Header'
export default function Landing() {
@ -21,67 +18,11 @@ export default function Landing() {
document.body.appendChild(css)
})
return (
<div className="app-content ui__ container" css="margin-bottom: 2rem">
<div className="app-content ui__ container" css="margin: 2rem 0">
<Header />
<h2>Pourquoi ?</h2>
<p>
Certains algorithmes sont bien trop importants pour être maintenus dans
une boîte noire, souvent privée, que seuls les développeurs expérimentés
peuvent comprendre.
</p>
<p>
{' '}
C'est notamment le cas d'une bonne partie de la loi, qui spécifie en
français des règles... et charge à d'autres de les implémenter
librement.
</p>
<p>
La plateforme <em>publicodes</em> fusionne documentation et
implémentation en partant d'un code simple. Ajouter une règle de calcul,
c'est déployer sans effort sur le Web la page de documentation
correspondante, lisible par tout citoyen.
</p>
<br />
<p>Pour aller plus loin:</p>
<ul>
<li>
<a href="https://github.com/betagouv/publicodes/wiki">
{emoji('📖 ')} Lire la documentation
</a>
</li>
<li>
<Link to="/studio"> Essayer le langage </Link>
</li>
</ul>
<h2>Projets phares</h2>
<h3>
La sécurité sociale et les impôts -{' '}
<a href="https://mon-entreprise.fr">mon-entreprise.fr</a>
</h3>
<div className="ui__ card">
<ColoredYaml source={exemple1} />
</div>
<Link to="/studio?exemple=bareme-ir" className="ui__ button small">
Lancer le calcul
</Link>
<p>
En plus du site Web, Mon-entreprise est disponible comme une{' '}
<a href="https://mon-entreprise.fr/intégration/bibliothèque-de-calcul">
bibliothèque de calcul autonome
</a>
.
</p>
<h3>
L'impact climatique de nos gestes du quotidien - &nbsp;
<a href="https://futur.eco">futur.eco</a>
</h3>
<div className="ui__ card">
<ColoredYaml source={exemple2} />
</div>
<Link to="/studio?exemple=douche" className="ui__ button small">
Lancer le calcul
</Link>
<br />
<Markdown source={publicodeReadme} />
</div>
)
}

View File

View File

@ -134,6 +134,10 @@ module.exports.commonLoaders = ({ legacy = false } = {}) => {
{
test: /\.ne$/,
use: [babelLoader, 'nearley-loader']
},
{
test: /\.md$/,
use: ['raw-loader']
}
]
}