You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 11 Next »

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

[evaluation]

Reflection

[reflection]

  • No labels