176 lines
4.6 KiB
JavaScript
176 lines
4.6 KiB
JavaScript
import R from 'ramda'
|
|
import removeDiacritics from '../utils/remove-diacritics'
|
|
|
|
|
|
import { createSelector } from 'reselect'
|
|
import {variablesSelector} from './selectors'
|
|
import traversalGuide from './traversalGuide'
|
|
|
|
/* AIM : Parse all the variables and extract their references to other variables.
|
|
Rank the results by count. */
|
|
|
|
// Use http://regexr.com/ to understand and write regexps !!
|
|
|
|
let credits = 3 // 5 complex variables
|
|
|
|
// let GETAdHocVariable = id =>
|
|
// new Promise((resolve, reject) =>
|
|
// setTimeout(() =>
|
|
// resolve(
|
|
// Math.random() > 0.6 && credits ?
|
|
// credits -- && {calls: ['myVar' + Math.random(), 'myVar2' + Math.random()]}
|
|
// : 'myInputVariable' + Math.random()
|
|
// ),
|
|
// Math.random() * 2000 + 1000
|
|
// )
|
|
// )
|
|
|
|
let GETAdHocVariable = name =>
|
|
new Promise(resolve =>
|
|
window.fetch('https://api.openfisca.fr/api/1/variables/?name=' + name.trim().replace(/\s/g, '_'))
|
|
.then(res => res.json())
|
|
.then(json => {
|
|
let {error, variables} = json
|
|
if (error && JSON.stringify(error).indexOf('Variable does not exist') + 1){
|
|
resolve('TODO ' + name)
|
|
}
|
|
if (variables) {
|
|
let {name, formula} = variables[0]
|
|
if (formula && formula['input_variables']) {
|
|
resolve({calls: formula['input_variables']})
|
|
} else {
|
|
resolve(name)
|
|
}
|
|
}
|
|
})
|
|
)
|
|
|
|
|
|
async function getAdHocVariables(id) {
|
|
let variable = await GETAdHocVariable(id)
|
|
if (R.is(String, variable))
|
|
return variable
|
|
else
|
|
return Promise.all(
|
|
variable.calls.map(getAdHocVariables)
|
|
)
|
|
}
|
|
|
|
// Returns a list of list of used variables
|
|
// recursive function
|
|
let findUsedVariables = (variables, schema, toAnalyse) =>
|
|
/*TODO
|
|
If instruction of GET call -> return Promise
|
|
1) input var OK return string
|
|
2) call to other variables -> list of promises
|
|
*/
|
|
R.cond([
|
|
[R.isNil, () => []],
|
|
[R.has('adHoc'), ({id}) => getAdHocVariables(id)],
|
|
// The traversal of variables has found a parsable variable attribute.
|
|
// Parse it to extract variables
|
|
[R.is(Function), extractor =>
|
|
R.pipe(
|
|
extractor,
|
|
R.unless(R.isArrayLike, R.of),
|
|
R.map(R.cond([
|
|
[R.is(String), name => findVariables(variables, name)],
|
|
[R.is(Object), tags => findVariables(variables, null, tags)]
|
|
])),
|
|
R.unnest,
|
|
R.map(
|
|
/*TODO
|
|
if instruction of GET call findUsedVariables(GET CALL)
|
|
*/
|
|
R.cond([
|
|
[R.has('adHoc'), adHocSpec => findUsedVariables(variables, adHocSpec)],
|
|
[R.is(String), R.identity],
|
|
[R.T, found => findUsedVariables(variables, traversalGuide, found)]
|
|
])
|
|
)
|
|
)(toAnalyse)
|
|
],
|
|
// Walk the graph using the guiding object until you find a parsable attribute
|
|
[R.is(Object), traversalObject =>
|
|
R.toPairs(traversalObject).reduce(
|
|
(res, [key, value]) => {
|
|
return toAnalyse[key] != null ?
|
|
[...res, ...findUsedVariables(variables, value, toAnalyse[key])] :
|
|
res
|
|
}, []
|
|
)],
|
|
[R.T, () => []]
|
|
])(schema)
|
|
|
|
|
|
let calculableVariables = createSelector(
|
|
[variablesSelector],
|
|
R.pipe(R.pluck('calculable'), R.unnest)
|
|
)
|
|
|
|
/************************************
|
|
Functions to find variables */
|
|
|
|
let findVariablesByName = name =>
|
|
R.filter(variable => removeDiacritics(variable.variable) == name)
|
|
|
|
let findVariablesByTags = tags =>
|
|
R.filter(R.pipe(
|
|
R.prop('tags'),
|
|
R.whereEq(tags)
|
|
))
|
|
|
|
let findVariables = (variables, name, tags) =>
|
|
R.pipe(
|
|
variables => R.is(String, name)
|
|
? findVariablesByName(name)(variables)
|
|
: variables,
|
|
variables => R.is(Object, tags)
|
|
? findVariablesByTags(tags)(variables)
|
|
: variables,
|
|
R.cond([
|
|
[ R.isEmpty, () => variableNotFound(name)],
|
|
[ (variables) => R.is(String, name) && variables.length > 1,
|
|
() => variableNameCollision(name, tags)],
|
|
[ R.T,
|
|
R.identity]
|
|
]),
|
|
)(variables)
|
|
|
|
let variableNotFound = name =>
|
|
// Should do a query to openfisca web api
|
|
({adHoc: true, id: name})
|
|
|
|
let variableNameCollision = (name, tags) =>
|
|
`More than one variable corresponds to this name, tags tuple : ${name}, ${tags}`
|
|
|
|
/*****************************************/
|
|
|
|
let accum = [] //aaw
|
|
|
|
setTimeout(() => console.log(R.countBy(R.identity)(accum)), 10000)
|
|
|
|
let resolvePromisesRec =
|
|
R.pipe(
|
|
R.unless(R.isArrayLike, R.of),
|
|
R.map(R.cond([
|
|
[R.is(Promise), p => p.then(resolvePromisesRec)],
|
|
[R.is(String), string => accum.push(string)]
|
|
]))
|
|
)
|
|
|
|
export let usedVariables = createSelector(
|
|
[state => state.rootVariables, calculableVariables],
|
|
(roots, variables) => {
|
|
// get all variables from these roots, rec !
|
|
return R.compose(
|
|
// R.uniq,
|
|
resolvePromisesRec,
|
|
R.flatten,
|
|
R.map(rootObject => findUsedVariables(variables, traversalGuide, rootObject)),
|
|
R.map(root => findVariables(variables, removeDiacritics(root))[0])
|
|
)(roots)
|
|
|
|
}
|
|
)
|