From 7ec220244e21d6d5d73b75f39ac7c02f57e6d0c6 Mon Sep 17 00:00:00 2001 From: cyfraeviolae Date: Wed, 8 Jan 2025 21:30:36 -0500 Subject: init --- .gitignore | 2 + README.md | 3 + index.html | 384 +++++++++++++++++++++++++++++++++++++++++++++++++++++ static/favicon.ico | Bin 0 -> 318 bytes static/script.js | 240 +++++++++++++++++++++++++++++++++ static/styles.css | 5 + wordlist.txt | 367 ++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 1001 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 index.html create mode 100644 static/favicon.ico create mode 100644 static/script.js create mode 100644 static/styles.css create mode 100644 wordlist.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..085876a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.ipynb_checkpoints +node_modules diff --git a/README.md b/README.md new file mode 100644 index 0000000..972604a --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Travelwords + +A list of words to learn when travelling. diff --git a/index.html b/index.html new file mode 100644 index 0000000..d48c599 --- /dev/null +++ b/index.html @@ -0,0 +1,384 @@ + + + + Travelwords + + + + + + + +
+
+ +
+

+ The peripatetic sorcerer Roseacrucis has teleported you to a + foreign land. In order to communicate, you must learn the following + words and phrases in the local language, allowing you to + communicate, though perhaps with poor grammar. +

+ +
+ + + + + diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000..4e0f88c Binary files /dev/null and b/static/favicon.ico differ diff --git a/static/script.js b/static/script.js new file mode 100644 index 0000000..d8dbf77 --- /dev/null +++ b/static/script.js @@ -0,0 +1,240 @@ +"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('/static/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') + let 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: 3, + tmlim: Number.parseInt(document.getElementById('limit').value), + } + } + return {ingredients, lp, recipes} +} diff --git a/static/styles.css b/static/styles.css new file mode 100644 index 0000000..4442223 --- /dev/null +++ b/static/styles.css @@ -0,0 +1,5 @@ +.ingredient { + display: inline-block; + margin-right: 5px; + margin-bottom: 5px; +} diff --git a/wordlist.txt b/wordlist.txt new file mode 100644 index 0000000..b3f8a19 --- /dev/null +++ b/wordlist.txt @@ -0,0 +1,367 @@ +
  • Pronouns
  • +
  • I
  • +
  • you
  • +
  • he
  • +
  • she
  • +
  • it
  • +
  • we
  • +
  • you all
  • +
  • they
  • +
  • +
  • Verbs (conjugated for I and you)
  • +
  • be
  • +
  • buy
  • +
  • can
  • +
  • cannot
  • +
  • clean
  • +
  • come
  • +
  • could
  • +
  • do
  • +
  • drive
  • +
  • explain
  • +
  • finish
  • +
  • go
  • +
  • hear
  • +
  • leave
  • +
  • like
  • +
  • listen
  • +
  • live
  • +
  • love
  • +
  • pay
  • +
  • read
  • +
  • return
  • +
  • say
  • +
  • sell
  • +
  • should
  • +
  • sing
  • +
  • sit
  • +
  • stand
  • +
  • study
  • +
  • talk
  • +
  • think
  • +
  • try
  • +
  • visit
  • +
  • wait
  • +
  • walk
  • +
  • want
  • +
  • write
  • +
  • +
  • Time
  • +
  • after
  • +
  • before
  • +
  • day after tmw
  • +
  • day before yesterday
  • +
  • early
  • +
  • good evening
  • +
  • good morning
  • +
  • good night
  • +
  • hour
  • +
  • minute
  • +
  • now
  • +
  • second
  • +
  • today
  • +
  • tomorrow
  • +
  • tonight
  • +
  • week
  • +
  • yesterday
  • +
  • +
  • Questions
  • +
  • are you closed
  • +
  • are you open
  • +
  • can you do
  • +
  • can you make
  • +
  • do you have x
  • +
  • how much
  • +
  • how old are you
  • +
  • i am from __
  • +
  • is it permitted
  • +
  • what
  • +
  • what is this
  • +
  • what is your name
  • +
  • when
  • +
  • when do you close
  • +
  • when do you open
  • +
  • where
  • +
  • where are you from
  • +
  • where do you live
  • +
  • who
  • +
  • why
  • +
  • +
  • Adjectives
  • +
  • amazing
  • +
  • angry
  • +
  • bad
  • +
  • big/large
  • +
  • boring
  • +
  • close
  • +
  • cold
  • +
  • cool
  • +
  • delicious
  • +
  • different
  • +
  • difficult
  • +
  • easy
  • +
  • famous
  • +
  • far
  • +
  • first
  • +
  • good
  • +
  • happy
  • +
  • hot
  • +
  • hot
  • +
  • late
  • +
  • medium
  • +
  • near
  • +
  • next
  • +
  • normal
  • +
  • okay
  • +
  • old
  • +
  • perfect
  • +
  • popular
  • +
  • previous
  • +
  • sad
  • +
  • second
  • +
  • similar to/like
  • +
  • small
  • +
  • strange
  • +
  • surprising
  • +
  • tired
  • +
  • vegetarian
  • +
  • very good
  • +
  • young
  • +
  • +
  • Numbers
  • +
  • one
  • +
  • two
  • +
  • three
  • +
  • four
  • +
  • five
  • +
  • six
  • +
  • seven
  • +
  • eight
  • +
  • nine
  • +
  • ten
  • +
  • eleven
  • +
  • twelve
  • +
  • thirteen
  • +
  • fourteen
  • +
  • fifteen
  • +
  • sixteen
  • +
  • seventeen
  • +
  • eighteen
  • +
  • nineteen
  • +
  • twenty
  • +
  • twenty-one
  • +
  • thirty
  • +
  • forty
  • +
  • fifty
  • +
  • sixty
  • +
  • seventy
  • +
  • eighty
  • +
  • ninety
  • +
  • one hundred
  • +
  • one hundred and one
  • +
  • one thousand
  • +
  • ten thousand
  • +
  • +
  • Adverbs
  • +
  • actually
  • +
  • always
  • +
  • fortunately
  • +
  • here
  • +
  • most
  • +
  • never
  • +
  • often
  • +
  • probably
  • +
  • quickly
  • +
  • rarely
  • +
  • slowly
  • +
  • some
  • +
  • sometimes
  • +
  • there
  • +
  • truthfully
  • +
  • unfortunately
  • +
  • usually
  • +
  • +
  • Directions
  • +
  • down
  • +
  • east
  • +
  • left
  • +
  • north
  • +
  • right
  • +
  • south
  • +
  • straight
  • +
  • turn
  • +
  • up
  • +
  • west
  • +
  • +
  • Phrases
  • +
  • anything is fine
  • +
  • both are fine
  • +
  • don't worry about it, no problem
  • +
  • excuse me
  • +
  • for here
  • +
  • for one (restaurant)
  • +
  • for two
  • +
  • go ahead
  • +
  • goodbye
  • +
  • hello
  • +
  • help
  • +
  • here you go
  • +
  • i am from
  • +
  • i don't understand
  • +
  • i don't want
  • +
  • i understand
  • +
  • i want
  • +
  • i want this (at restaurant)
  • +
  • i want to
  • +
  • i want to go
  • +
  • it doesn't matter/anything is ok
  • +
  • it is not permitted
  • +
  • it is permitted
  • +
  • my name is
  • +
  • nice to meet you
  • +
  • please
  • +
  • see you later
  • +
  • sorry
  • +
  • takeaway
  • +
  • thank you
  • +
  • that is not the case
  • +
  • that is the case
  • +
  • +
  • Nouns
  • +
  • (nth) floor of a building
  • +
  • a glass of (wine, etc)
  • +
  • adult
  • +
  • airplane
  • +
  • airport
  • +
  • animal
  • +
  • bad weather
  • +
  • bags/luggage
  • +
  • bar
  • +
  • beer
  • +
  • bicycle
  • +
  • bike
  • +
  • bird
  • +
  • boy
  • +
  • boyfriend
  • +
  • breakfast
  • +
  • building
  • +
  • bus
  • +
  • bus station
  • +
  • car
  • +
  • cash
  • +
  • cat
  • +
  • child
  • +
  • city
  • +
  • club
  • +
  • coffee
  • +
  • company
  • +
  • country
  • +
  • credit card
  • +
  • dinner
  • +
  • dog
  • +
  • drink
  • +
  • eggs
  • +
  • everyone
  • +
  • everything
  • +
  • eyes
  • +
  • fish
  • +
  • food
  • +
  • garbage
  • +
  • girl
  • +
  • girlfriend
  • +
  • glass (of wine, water, etc)
  • +
  • glasses
  • +
  • good weather
  • +
  • hair
  • +
  • hand
  • +
  • head
  • +
  • hobbies
  • +
  • holiday
  • +
  • home
  • +
  • hometown
  • +
  • house
  • +
  • human
  • +
  • husband
  • +
  • ice
  • +
  • inside
  • +
  • keys
  • +
  • language
  • +
  • lock
  • +
  • lunch
  • +
  • man
  • +
  • mathematics
  • +
  • me
  • +
  • meat
  • +
  • menu
  • +
  • money
  • +
  • month
  • +
  • music
  • +
  • music
  • +
  • name
  • +
  • napkin
  • +
  • outside
  • +
  • phone
  • +
  • phone number
  • +
  • place
  • +
  • rain
  • +
  • rental
  • +
  • restaurant
  • +
  • rice
  • +
  • school
  • +
  • seafood
  • +
  • stairs
  • +
  • station
  • +
  • the check
  • +
  • thing
  • +
  • toilet
  • +
  • train
  • +
  • train station
  • +
  • trash
  • +
  • united states
  • +
  • wife
  • +
  • wine
  • +
  • woman
  • +
  • word
  • +
  • work
  • +
  • +
  • colors
  • +
  • black
  • +
  • blue
  • +
  • green
  • +
  • orange
  • +
  • red
  • +
  • white
  • +
  • yellow
  • +
  • +
  • utility words
  • +
  • a few
  • +
  • all
  • +
  • almost
  • +
  • also
  • +
  • and
  • +
  • anything
  • +
  • at
  • +
  • because
  • +
  • both
  • +
  • but
  • +
  • enough
  • +
  • if
  • +
  • in
  • +
  • less
  • +
  • many
  • +
  • more
  • +
  • no
  • +
  • nothing
  • +
  • of
  • +
  • of
  • +
  • one of something
  • +
  • or
  • +
  • then
  • +
  • therefore
  • +
  • towards
  • +
  • two of something
  • +
  • with
  • +
  • without
  • +
  • yes
  • +
  • yet
  • +
  • (negation)
  • -- cgit v1.2.3