There are knowns, known unknowns, and unknown unknowns
July 21, 2018 3:44 PM Subscribe
I want to build a website that displays information based on multiple layers of user input (so it needs a database). I'll have a (future) designer do a pretty front end, but I want to get the back end structure right from the beginning. I don't know what I need to know to build this. I do know SQL, HTML, CSS and a smattering of Python and javascript. I need to know more.
The basic structure will be something like this. Assume everyone coming to this site has a pet. (The subject matter isn't really pets, this is just a clearer analogy.) Each question can take the user down a different decision tree but the results may overlap (e.g. a long-haired dog and a long-haired cat might both get a result about the best way to brush your pet). The choices for each question will be discrete, not free text fields.
There's no timeframe for this project and it's not paid work. I would like to get some sort of working prototype to see if an organization thinks it's worth pursuing. I'd rather get it right than slap something together. Is there a course that would walk me through something close to this? Would Python get me all or most of the way there?
The basic structure will be something like this. Assume everyone coming to this site has a pet. (The subject matter isn't really pets, this is just a clearer analogy.) Each question can take the user down a different decision tree but the results may overlap (e.g. a long-haired dog and a long-haired cat might both get a result about the best way to brush your pet). The choices for each question will be discrete, not free text fields.
> Do you have a cat, dog, or other pet?
> cat
> Does it have long hair or short hair?
> long
> From one to ten, how much of an asshole is your cat, 10 being the worst?
> 9
> Do you have carpet, wood, or tile floors?
> carpet
> Would it be expensive to replace?
> Yes
Result: Your cat is likely to puke on your expensive carpet out of sheer spite. Here is an article about cat vomit and what you can do.
There's no timeframe for this project and it's not paid work. I would like to get some sort of working prototype to see if an organization thinks it's worth pursuing. I'd rather get it right than slap something together. Is there a course that would walk me through something close to this? Would Python get me all or most of the way there?
I want to build a website that displays information based on multiple layers of user input (so it needs a database).
Technically--and this is not to say you shouldn't check out a back-end framework here if such a thing interests you--but if the only saved part of this is the decision-tree part and you don't need to store what people have answered past the point where you give them a result, you can do this in front-end JavaScript only. A front-end-only quiz (that only displayed a single question at a time but actually all loaded on a single page and presented a grade at the end) was one of the things I did for my first front-end course, and this is a little more complex than that but it doesn't sound like it's much so.
posted by Sequence at 4:05 PM on July 21, 2018 [3 favorites]
Technically--and this is not to say you shouldn't check out a back-end framework here if such a thing interests you--but if the only saved part of this is the decision-tree part and you don't need to store what people have answered past the point where you give them a result, you can do this in front-end JavaScript only. A front-end-only quiz (that only displayed a single question at a time but actually all loaded on a single page and presented a grade at the end) was one of the things I did for my first front-end course, and this is a little more complex than that but it doesn't sound like it's much so.
posted by Sequence at 4:05 PM on July 21, 2018 [3 favorites]
I would do the following:
posted by hoyland at 4:14 PM on July 21, 2018
- read about database normalization if it's not something you're familiar with already (it's something that feels very counterintuitive to me, so I often resist it and end up starting to reinvent it myself only to realise it's what I resisted in the first place)
- write a text-based version in Python with hard-coded data (maybe only a tiny subset) and no DB
- read some tutorials on Flask or Django (my bias is towards Flask, especially for small projects)
- build an api (the functions from your text-based prototype that retrieve things from the database will probably correspond to the end points)
- now worry about the frontend
posted by hoyland at 4:14 PM on July 21, 2018
If it's really just going to display information in the manner you describe (as opposed to collecting and storing information) I'd think you'd want to use existing software for something like interactive fiction which similarly can display text or images following a series of choices, such as Twine, and just adjust the styling to fit your needs.
The optimum approach is going to depend on the number of possible endpoints. For a relatively small number of endpoints, say a number in the dozens, you could just do a bunch of interlinked flat hand-made HTML pages; in the intermediate range you could do a single web page with a bunch of javascript plumbing working off of a large javascript array, which Twine is an off-the-shelf version of, or alternatively you could still do flat HTML pages but use something like a Python script to automatically generate and interlink them en masse if there are going to be hundreds or thousands of endpoints; or, if there are going to be so many endpoints that Twine or a similar approach in a single web page would become unwieldly and sluggish, that's when you'd need to go to a more robust heavy-footprint solution backed by a database.
For your example in the OP you'd compute the maximum number of endpoints by multiplying the number of options at each step, so: 3 (cat|dog|other) × 2 (long|short) × 10 × 3 (carpet|wood|tile) × 2 (yes|no) = 360, minus the number of branches that consolidate back down to the same endpoint. Perhaps some facets can reduce the number of endpoints further—if, for example, the only real impact of the asshole-osity value (9 in the example) is to display a derived sentence on the final page stating something like, "Your carpet has been 90% destroyed by cat puke" then small snippets of script can probably handle storing the value and formatting the final message, effectively reducing the number of endpoints further.
One factor to consider is how much traffic you want the web site to be able to handle. For high traffic sites you'd probably want to stick to a solution with flat HTML files or a single javascript-heavy page because scaling up a database-backed web application can get complicated.
posted by XMLicious at 5:35 PM on July 21, 2018 [3 favorites]
The optimum approach is going to depend on the number of possible endpoints. For a relatively small number of endpoints, say a number in the dozens, you could just do a bunch of interlinked flat hand-made HTML pages; in the intermediate range you could do a single web page with a bunch of javascript plumbing working off of a large javascript array, which Twine is an off-the-shelf version of, or alternatively you could still do flat HTML pages but use something like a Python script to automatically generate and interlink them en masse if there are going to be hundreds or thousands of endpoints; or, if there are going to be so many endpoints that Twine or a similar approach in a single web page would become unwieldly and sluggish, that's when you'd need to go to a more robust heavy-footprint solution backed by a database.
For your example in the OP you'd compute the maximum number of endpoints by multiplying the number of options at each step, so: 3 (cat|dog|other) × 2 (long|short) × 10 × 3 (carpet|wood|tile) × 2 (yes|no) = 360, minus the number of branches that consolidate back down to the same endpoint. Perhaps some facets can reduce the number of endpoints further—if, for example, the only real impact of the asshole-osity value (9 in the example) is to display a derived sentence on the final page stating something like, "Your carpet has been 90% destroyed by cat puke" then small snippets of script can probably handle storing the value and formatting the final message, effectively reducing the number of endpoints further.
One factor to consider is how much traffic you want the web site to be able to handle. For high traffic sites you'd probably want to stick to a solution with flat HTML files or a single javascript-heavy page because scaling up a database-backed web application can get complicated.
posted by XMLicious at 5:35 PM on July 21, 2018 [3 favorites]
This sounds a fun project! Agreed with above that you should try an initial version in static html/js/css. You could host it on an s3 bucket for cheap with cloudfront as cdn. Perhaps a single page in js to do the decision tree, then redirect to a static page (generate offline from a template?) for each result / article?
You could add a backend later as required with some REST calls.
posted by JonB at 11:37 PM on July 21, 2018 [1 favorite]
You could add a backend later as required with some REST calls.
posted by JonB at 11:37 PM on July 21, 2018 [1 favorite]
Seconding XMLicious that generating static html might be a good way to go, especially to get a mockup built quickly. Your data is really a tree structure, or possibly a finite state machine. A database is a fine place to store data, but it forces you to think in terms of rows of data and relations. HTML and XML can better model tree structures and finite state machines.
Here's a program, using Haskell list comprehensions, that generates the names of the 360 html files that would model your example, and with a few hours work (need to brush up on tree unfolds), one could make a program that generates the contents of those files.
qa =
[ (["cat","dog","other"],"Do you have a cat, dog, or other pet?")
, (["long","short"],"Does it have long hair or short hair?")
, (map show [1..10], "From one to ten, how much of an asshole is your cat, 10 being the worst?")
, (["carpet","wood","tile"],"Do you have carpet, wood, or tile floors?")
, (["Yes","No"],"Would it be expensive to replace?")
]
-- Result: Your cat is likely to puke on your expensive carpet out of sheer spite. Here is an article about cat vomit and what you can do.
t = [a1++a2++a3++a4++a5++".html" | a1< - fst$qa!!0,
a2< - fst$qa!!1, a3< - fst$qa!!2, a4< - fst$qa!!3, a5< - fst$qa!!4 ]
Each file can be as simple as:
< h t m l >
Do you have carpet, wood, or tile floors?
< a href="catlong9carpet.html">carpet
< a href="catlong9wood.html">wood
< a href="catlong9tile.html">tile
< / h t ml>
Here's a zip file of a few html files that implement your example, with only one path filled in (the path you gave). Start with index.html
posted by cyclicker at 12:33 AM on July 26, 2018
Here's a program, using Haskell list comprehensions, that generates the names of the 360 html files that would model your example, and with a few hours work (need to brush up on tree unfolds), one could make a program that generates the contents of those files.
qa =
[ (["cat","dog","other"],"Do you have a cat, dog, or other pet?")
, (["long","short"],"Does it have long hair or short hair?")
, (map show [1..10], "From one to ten, how much of an asshole is your cat, 10 being the worst?")
, (["carpet","wood","tile"],"Do you have carpet, wood, or tile floors?")
, (["Yes","No"],"Would it be expensive to replace?")
]
-- Result: Your cat is likely to puke on your expensive carpet out of sheer spite. Here is an article about cat vomit and what you can do.
t = [a1++a2++a3++a4++a5++".html" | a1< - fst$qa!!0,
a2< - fst$qa!!1, a3< - fst$qa!!2, a4< - fst$qa!!3, a5< - fst$qa!!4 ]
Each file can be as simple as:
< h t m l >
Do you have carpet, wood, or tile floors?
< a href="catlong9carpet.html">carpet
< a href="catlong9wood.html">wood
< a href="catlong9tile.html">tile
< / h t ml>
Here's a zip file of a few html files that implement your example, with only one path filled in (the path you gave). Start with index.html
posted by cyclicker at 12:33 AM on July 26, 2018
« Older where to go in continental US in mid-August? | Indoor sinkhole under by basement tile floor? Newer »
This thread is closed to new comments.
posted by snoogles at 3:51 PM on July 21, 2018 [5 favorites]