Design

Our final design is not very different from our design after GR4. On the front page, some of the symbols for restrictions changed, as seen below. Originally, we were planning on using symbols such as cheese and meat to designate different restrictions; we settled on using letters that are commonly used to designate restrictions.

(click for high-res)

Selecting restriction buttons still works as before. The custom button’s textbox now has autocomplete. Originally the custom button’s slide out bar slid downwards from the custom button. It now slides to the right. This was changed after paper prototyping feedback.

(click for high-res)

Below is the results page. Originally no recipe would be displayed after a search, but we changed it to show the top recipe by default after a search.

(click for high-res)

A mini-search bar was added to make it easier to correct searching errors. Previously, during paper prototyping, it was necessary to go back to the homepage to search again.

The original recipe and the substituted ingredients can be toggled using this button. This has been the same for the whole process.

When the substitutions are present, the old ingredients are crossed out.

Additional substitution information can be found by hovering over the tooltip. This is one of the few things that still confused users during our last round of user testing as sometimes they didn’t realize that they could hover to attain more information.

There is a loading screen with this animation.

Overall, since the website idea was straightforward, we successfully implemented a simple user interface. We received good user feedback, primarily during paper prototype testing, and we integrated suggestions into our interface.

Implementation

Our website is hosted on scripts.mit.edu. The two pages of the site (the front page and the search results page) are served as static HTML, CSS, and Javascript directly through Apache. We use FastCGI to provide a dynamic endpoint for fetching recipe results. This FastGCI script is written in Ruby. It uses Sinatra, a Ruby microframework for building web applications, as well as ActiveRecord, an object relational mapper. Our database is stored in MySQL, hosted by Amazon’s Relational Database Service. The schema of the database is illustrated below:

Our website uses Bootstrap as a CSS framework. The front page includes an autocomplete widget in the “Custom” form to complete the names of ingredients. Because we only have a couple thousand ingredients, we can serve them all to the client, and search through them in javascript. Instead of creating a dynamic endpoint to generate this data on-the-fly, we created a script that generates a JSON file with all of the ingredients that we run any time we update the database. We then serve that JSON as a static file, loaded asynchronously once the rest of the home page is loaded. This minimizes server load (becuase the JSON doesn’t need to be generated for each client), and perceived latency (because the rest of the page loads before the JSON is requested). Finally, the homepage stores the user’s dietary restrictions in persistent cookie, saving user preferences automatically without the need for user accounts.

The search results page is a static HTML file with a simple loading animation. Because this is served directly through Apache, it can be loaded very quickly to provide feedback to the user as we search the database. We first use MySQL full-text search to find relevant recipes. For each recipe, we identify which ingredients violate the user’s dietary restrictions, and then use our substitutions table to find appropriate substitutions. We then serve up these results as JSON, and they are rendered client-side.

Our substitution data was generously provided by Chun-Yuen Teng, Yu-Ru Lin, and Lada A. Adamic, from the data used for their paper, “Recipe recommendation using ingredient networks". To determine which ingredients violate which restrictions, we tagged each of our ingredients by hand, using an internal web-based tool we built (at http://vegitu.de/tagger, but it doesn’t list any ingredients anymore, as they’ve all been tagged). The recipes themselves are from http://www.nibbledish.com/, a website that hosts Creative Commons-licensed recipes. Using Python, we wrote a crawler with Mechanize to find recipe pages, parsed the HTML with BeautifulSoup, and then used a number of heuristics to parse the ingredients list and populate our database with structured versions of the recipes.

All code we wrote is public on GitHub: https://github.com/benweissmann/vegitude.

Evaluation

We conducted our user tests on three people, each from a different segment of the targeted population. Categories in our target user group are vegans, vegetarians, and non-restricted persons who cook for friends with restrictive dietary needs. We briefed each individual with a general description of the problem that Vegitude is trying to solve and the manner in which it solves it. Following that, we gave each individual three or four tasks based on a scenario centered around the segment of the user population that they are in. Each task touched on a different capability of the website, making sure that each user could successfully learn how to utilize all of Vegitude’s capabilities naturally, without being told or shown how to do so. Here is the link to the user briefing and tasks.

After conducting these user tests, we discovered a couple of interesting usability problems for us to tackle:

  • Tooltips use ambiguous at first sight
  • Minor severity

The tooltips that accompany substitutions (on the left of them) can be pretty ambiguous at first sight. One of our users did not naturally think of checking the tooltip next to vegetable oil (a substitution for butter) in order to find alternative substitution for butter. One way to solve this problem might be to add in some natural instruction to the page to explain that more information on the substitutions and the ingredients they substitute might be found through the tooltips.

  • The search seems fairly slow
  • Minor severity

One of our users mentioned that the search seems fairly slow and, although we have a search page animation, it runs for such a long time on most searches that it can be tiring. One idea we had to solve this issue is to actually use a dedicated searching library, such as Lucene, in order to find our information, instead of the mySQL search that we currently use.

  • Substitutions based on usage is hard 
  • Major severity; luckily, this isn't a class on backend, so it is actually more of a minor severity for our purposes

It turns out that actually finding appropriate substitutions for particular ingredients in certain recipes can be difficult, as their use in a recipe can vary. One of our users pointed this out and it is a reasonable worry. We have looked into this and figured that, unless we can find a better ingredient substitute database, we will probably have to create an algorithm or go through by hand and specify the type of substitutions for particular ingredients in different kinds of recipes.

Reflection

Reflecting on the past project, I think that our organization during this project was pretty swell; We all contributed very heavily to the project and came out with a very nicely designed product that both has a reasonable use, as well as an easy-to-learn interface.

We learned a lot throughout this project, from using Bootstrap to create appealing layouts, to creating a database to store structured recipe data, to using python to crawl recipe websites and extract structured data from free-form text.

We used our prototyping stages effectively. While the overall design is similar to the original paper prototype, we fine-tuned colors and sizes and added additional features (such as the mini-search on the results page) based on the feedback we received from our heuristic evaluations.

If we were to do anything differently, it would have to create documentation at an earlier stage, and to update this documentation so we could use it as a tool for collaboration and coordination.

  • No labels