summaryrefslogtreecommitdiff
path: root/script.js
diff options
context:
space:
mode:
authorcyfraeviolae <cyfraeviolae>2021-07-04 23:58:55 -0400
committercyfraeviolae <cyfraeviolae>2021-07-04 23:58:55 -0400
commitf09e3205cffadcde1753e09a148a27f1cb8c6264 (patch)
tree7debee575bfdb7c2888614ecfe8edb3224cb66bb /script.js
parent89ebed9500296180bf3b880b1e2aebe9ed7bc566 (diff)
static
Diffstat (limited to 'script.js')
-rw-r--r--script.js240
1 files changed, 0 insertions, 240 deletions
diff --git a/script.js b/script.js
deleted file mode 100644
index ba26dac..0000000
--- a/script.js
+++ /dev/null
@@ -1,240 +0,0 @@
-"use strict";
-
-var ingredientsm = {}
-var allIngredients = []
-for (let recipe of allRecipes) {
- for (let ingredient of recipe.ingredients) {
- if (ingredient.special) {
- continue
- }
- if (!ingredientsm[ingredient.ingredient]) {
- allIngredients.push(ingredient.ingredient)
- ingredientsm[ingredient.ingredient] = 1
- }
- }
-}
-allIngredients.sort()
-var ingredientsLookup = {}
-for (let [idx, ingredient] of allIngredients.entries()) {
- ingredientsLookup[ingredient] = idx
-}
-
-var globret = undefined;
-
-window.addEventListener('load', function(evt) {
- glpkPromise.then(function(glpk) {
-
- const worker = new Worker('./node_modules/glpk.js/glpk-worker.js')
- worker.onerror = (err) => { console.log(err) }
- worker.onmessage = (evt) => {
- if (evt.data.initialized) {}
- if (evt.data.result) {
- hide(document.getElementById('waiting'))
- show(document.getElementById('solution'))
- renderSolution(glpk, evt.data, globret)
- }
- }
-
- document.getElementById('optimal').addEventListener('click', function(evt) {
- evt.preventDefault()
- window.globret = constructILP(glpk)
- solveILP(worker, globret)
- })
- })
-})
-
-
-function renderSolution(glpk, sol, ret) {
- let ingredients = ret.ingredients
- let recipes = JSON.parse(JSON.stringify(ret.recipes))
- let res = []
- let batches = []
- let origbatch = []
- for (let [r, recipe] of recipes.entries()) {
- if (recipe.length == 0) {
- origbatch.push(r)
- }
- }
- for (let [varname, on] of Object.entries(sol.result.vars)) {
- if (!on) { continue }
- if (!varname.startsWith('y')) { continue }
- let y = Number.parseInt(varname.split('_')[1])
- if (res.indexOf(y) != -1) { continue }
- res.push(y)
- let batch = []
- for (let [r, recipe] of recipes.entries()) {
- if (recipe.length == 1 & recipe[0] == y) {
- batch.push(r)
- }
- }
- for (let [r, recipe] of recipes.entries()) {
- recipes[r] = recipe.filter(it => it != y)
- }
- batches.push(batch)
- }
- let ol = document.createElement('ol')
-
- let li = document.createElement('li')
- li.appendChild(document.createTextNode('On-hand'))
- if (origbatch.length) {
- let ul = document.createElement('ul')
- drinks = origbatch.map(b => allRecipes[b].name).join(', ')
- let sli = document.createElement('li')
- sli.appendChild(document.createTextNode(drinks))
- ul.appendChild(sli)
- li.appendChild(ul)
- }
- ol.appendChild(li)
-
- for (let [idx, y] of res.entries()) {
- let batch = batches[idx]
- let li = document.createElement('li')
- li.appendChild(document.createTextNode(ingredients[y]))
- if (batch.length) {
- let ul = document.createElement('ul')
- let drinks = batch.map(b => allRecipes[b].name).join(', ')
- let sli = document.createElement('li')
- sli.appendChild(document.createTextNode(drinks))
- ul.appendChild(sli)
- li.appendChild(ul)
- }
- ol.appendChild(li)
- }
- document.getElementById('solution').innerHTML = ''
- let desc = document.createElement('p')
- if (sol.result.status == glpk.GLP_UNDEF) {
- desc.appendChild(document.createTextNode('Error: Failed to find feasible solution. Try increasing time limit.'))
- } else if (sol.result.status == glpk.GLP_FEAS) {
- desc.appendChild(document.createTextNode(`Found feasible solution of score ${-sol.result.z}.`))
- } else if (sol.result.status == glpk.GLP_INFEAS) {
- desc.appendChild(document.createTextNode('Error: Did not find feasible solution.'))
- } else if (sol.result.status == glpk.GLP_NOFEAS) {
- desc.appendChild(document.createTextNode('Error: Problem has no feasible solution.'))
- } else if (sol.result.status == glpk.GLP_OPT) {
- desc.appendChild(document.createTextNode(`Found optimal solution of score ${-sol.result.z}.`))
- } else if (sol.result.status == glpk.GLP_UNBND) {
- desc.appendChild(document.createTextNode('Error: Problem is unbounded.'))
- }
- document.getElementById('solution').appendChild(desc)
- if (sol.result.status == glpk.GLP_FEAS || sol.result.status == glpk.GLP_OPT) {
- document.getElementById('solution').appendChild(ol)
- }
-}
-
-let hide = e => e.style.display = 'none';
-let show = e => e.style.display = 'inline-block';
-
-function solveILP(worker, ret) {
- let seconds = Number.parseInt(document.getElementById('limit').value)
- document.getElementById('waiting').innerHTML = seconds + ' seconds...'
- hide(document.getElementById('solution'))
- show(document.getElementById('waiting'))
- let incrSeconds = () => {
- document.getElementById('waiting').innerHTML = seconds + ' seconds...'
- seconds--
- }
- setInterval(incrSeconds, 1000)
- worker.postMessage(ret.lp)
-}
-
-function constructILP(glpk) {
- let skip = Object.values(document.querySelector('form')).reduce((obj, field) => {
- if (field.getAttribute('x-ingredient') && field.checked) {
- obj[field.getAttribute('x-ingredient')] = 1
- }
- return obj
- }, {})
-
- let ingredientsset = {}
- let recipes = []
-
- for (let recipe of allRecipes) {
- for (let ingredient of recipe.ingredients) {
- if (ingredient.special) { continue }
- if (skip[ingredientsLookup[ingredient.ingredient]]) { continue }
- ingredientsset[ingredient.ingredient] = 1
- }
- }
- let ingredients = Object.keys(ingredientsset)
-
- for (let recipe of allRecipes) {
- let x = []
- for (let ingredient of recipe.ingredients) {
- if (ingredient.special) { continue }
- if (skip[ingredientsLookup[ingredient.ingredient]]) { continue }
- x.push(ingredients.indexOf(ingredient.ingredient))
- }
- recipes.push(x)
- }
- let n_ingredients = ingredients.length
-
- let makeStepR = (step, r) => `r${step}_${r}`
- let makeStepY = (step, y) => `y${step}_${y}`
-
- let jsonvars = []
- for (let step = 0; step < n_ingredients; step++) {
- for (let [r, recipe] of recipes.entries()) {
- jsonvars.push({name: makeStepR(step, r), coef: -1})
- }
- }
- let jsonobjective = {
- direction: glpk.GLP_MIN,
- vars: jsonvars,
- }
- let jsonconstraints = []
- for (let step = 0; step < n_ingredients; step++) {
- let vars = []
- for (let y = 0; y < n_ingredients; y++) {
- vars.push({name: makeStepY(step, y), coef: 1})
- }
- jsonconstraints.push({vars, bnds: {type: glpk.GLP_FX, lb: step+1}})
- }
- for (let y = 0; y < n_ingredients; y++) {
- for (let step = 0; step < n_ingredients - 1; step++) {
- jsonconstraints.push({
- vars: [{name: makeStepY(step+1, y), coef: 1}, {name: makeStepY(step, y), coef: -1}],
- bnds: {type: glpk.GLP_LO, lb: 0}
- })
- }
- }
- for (let [r, recipe] of recipes.entries()) {
- for (let step = 0; step < n_ingredients; step++) {
- let total = []
- for (let y of recipe) {
- total.push({name: makeStepY(step, y), coef: -1})
- }
- total.push({name: makeStepR(step, r), coef: 1})
- jsonconstraints.push({
- vars: total,
- bnds: {type: glpk.GLP_LO, lb: (-recipe.length + 1)}
- })
- for (let y of recipe) {
- jsonconstraints.push({
- vars: [{name: makeStepR(step, r), coef: 1}, {name: makeStepY(step, y), coef: -1}],
- bnds: {type: glpk.GLP_UP, ub: 0}
- })
- }
- }
- }
- let binaries = []
- for (let y = 0; y < n_ingredients; y++) {
- for (let step = 0; step < n_ingredients; step++) {
- binaries.push(makeStepY(step, y))
- }
- }
- for (let r = 0; r < recipes.length; r++) {
- for (let step = 0; step < n_ingredients; step++) {
- binaries.push(makeStepR(step, r))
- }
- }
- let lp = {
- objective: jsonobjective,
- subjectTo: jsonconstraints,
- binaries,
- options: {
- msglev: 2,
- tmlim: Number.parseInt(document.getElementById('limit').value),
- }
- }
- return {ingredients, lp, recipes}
-}