objs = {
try {
class Node {
constructor(name, def, nodeDeps, frame) {
this.name = name
this.def = def
this.nodeDeps = nodeDeps
this.frame = frame
this.attrs = frame.scope
this.attrStrings = {}
Object.entries(this.attrs).forEach(([k, v]) => {
if (v !== undefined) {
this.attrStrings[k] = v.toString ? v.toString() : v
}
})
}
}
let base = new Frame(
"base",
MathExpr.compileBlock(`
varunitcost = 0
varcostrate = (sum(deps.varcost) + varunitcost) / varunit
usage = 1 varunit
varcost = dot(usage, varcostrate)
fixedcost = 0
fixedunit = 1
fixedcostself = 0
fixedcost = (sum(deps.fixedcost) + fixedcostself) / fixedunit`
),
{
deps: NewArrayProxy([]),
})
console.log("base", base)
let exprs = {
// power: { attrs: {varunitcost: '0.1 usd / hour', varunit: 'kW'} },
// computer: { deps: {power: {usage: '1 kW'}}, attrs: {fixedcostself: '50 usd / measure'}},
// // sysadmin: { attrs: {fixedcostself: '200000 usd / year'} },
// webserver: {
// deps: {
// // computer: { usage: '1 second' },
// // sysadmin: {},
// },
// },
// visit: { deps: {webserver: {usage: '1 second'}} }
tea: { deps: {hotwater: {usage: '100 mL'}} },
hotwater: { deps: {kettle: {usage: '2 kettle minute'}, water: {}}, attrs:{varunit: 'L'}},
water: { attrs: {varunitcost: '0.1 usd', varunit: 'L'} },
kettle: { deps: {power: {usage: '1 kW'} }},
power: { attrs: {varunitcost: '0.1 usd / hour', varunit: 'kW'} },
}
// Evaluate expressions in attrs and dep overrides
let nodeDepIndex = {}
Object.entries(exprs).forEach(([nodeName, nodeDef]) =>
nodeDepIndex[nodeName] = Object.keys(nodeDef.deps || {})
)
let nodeOrder = toposort(Object.keys(nodeDepIndex), node => nodeDepIndex[node])
let nodes = {}
nodeOrder.forEach(nodeName => {
let nodeDef = exprs[nodeName]
let attrExprs = Object.entries(nodeDef.attrs || {}).map(([name, src]) => MathExpr.compile(name, src))
let nodeDeps = {}
Object.entries(nodeDef.deps || {}).forEach(([depName, depOverrideDef]) => {
depOverrideDef = depOverrideDef || {}
let depOverrideExprs = Object.entries(depOverrideDef).map(([name, src]) => MathExpr.compile(name, src))
let depNode = nodes[depName]
nodeDeps[depName] = depNode.frame.cloneAndOverride(
`${nodeName}.dep < ${depName}`, depOverrideExprs, {})
})
let depsProxy = NewArrayProxy(
Object.values(nodeDeps).map(dep => dep.scope)
)
console.log(nodeName, "depsProxy", depsProxy, nodeDeps)
let scope = {deps: depsProxy}
if (!attrExprs.some(expr => expr.name === "varunit")) {
if (!math.type.Unit.isValuelessUnit(nodeName)) {
math.createUnit(nodeName)
}
scope.varunit = math.unit(nodeName)
// scope.usage = math.multiply(1, scope.varunit)
}
let frame = base.cloneAndOverride(nodeName, attrExprs, scope)
nodes[nodeName] = new Node(nodeName, nodeDef, nodeDeps, frame)
})
console.log("nodeOrder", nodeOrder)
// S.root(d => {
// invalidation.then(d)
// })
return nodes
} catch (e) {
console.log(e)
throw e
}
}