abrobbins90 / groceries

Menu Organizer
1 stars 1 forks source link

Meal Node Architecture #19

Open abrobbins90 opened 4 years ago

abrobbins90 commented 4 years ago

The current meal node stores all recipe information inside the current info property. This should be replaced with properties that are specific to the meal node.

abrobbins90 commented 4 years ago

Proposed architecture for meal node: The main property unique to MealNode is recipe. This will be an array with at least one entry, composed of objects of a new class, RecipeSection.

RecipeSection represents a section of the recipe (shocking, I know). This might consist of a preparation to a meal, or the making of a sauce, etc. This object is composed of a name, a header, and an array of objects of a new class called RecipeTasks.

RecipeTasks represent a single instruction, such as mixing eggs and milk, or chopping onions. Essentially, there is a hierarchy of 3 levels, representing the whole recipe, its sections, and the specific tasks. In any of these 3 sections, there may exist a defined ingredient quantity. By default, they are attached to the MealNode, where they are essentially unassigned. If there is just 1 tsp of salt in a recipe, with no more info, then <MealNode>.ingrQuan[<salt ID>] = <quantity definition>. If however, it is specified that section 2, task 1 is to add this salt, then the same object will instead be: <MealNode>.recipe[1].task[0].ingrQuan[<salt ID>] = <quantity definition>

The ingredient quantities will also be defined with a data structure, given by class quantity. At its core, it's just a simple object with an amount and unit property. Later on it can be expanded to allow easy addition of quantities. It can also be linked to a multiplicative factor for the meal for multiplying the quantities. So many possibilities!

Overall, this architecture accomplishes the following:

  1. The 3-level hierarchy allows the recipe to be split up very easily. On the front-end, this can help the user split up the recipe as they wish and keep things looking a lot better. Different sections could be expanded or highlighted for example. This would lay the framework to highlight or collect ingredients and quantities when needed. More importantly, it provides flexibility. The user need not use any of this. If the user leaves it at 1 section (default), they can type everything into the header without using the tasks. This would be equivalent to the current layout.
  2. On the backend, this hierarchy allows operations to happen at the necessary level. The MealNode can easily access all the instructions or ingredient quantities below it, etc. The required level of specificity or generality will always be accessible. Ingredients can be divided up and organized. Whether this is manual or there is any automatic recognition of where ingredients go, they can be moved and stored in their native task or section.
  3. The saving and loading of these levels of abstraction can all be handled at the local level. The MealNode can output a single dictionary representing all of its data. So on the server side, it stores this as it would anything else.
MareoRaft commented 4 years ago

A lot of good stuff, but of course I only talk about the stuff that doesn't make sense to me...

I'm confused about 3. Are you saying that the backend is still storing the recipe as a single string, as opposed to an array of instructions?

side note: In the case that the backend is storing an array of instructions, will the DB be capable of performing a text search on all the recipes? We might want that ability for the future.

What will the GUI look like for instructions? Does the user get a separate box per instruction? I'm sortof worried that half the users will not use the feature, and then if any new functionality we want to add depends on the users using this feature, we will not be able to provide it to them.

I feel like it may be more of the computer's job to parse and interpret the recipe, not the user's. This sounds like a job for neural networks (regexs)

abrobbins90 commented 4 years ago

For the backend, I'm saying that it stores everything in a single dictionary. This dictionary will contain the instructions at multiple levels of the dictionary. The actual "instruction" field will only be at the task level, but the "header" field is provided at the section level as an open area the user may freely type without any of the task organization. For example: mealnode.recipe = [ {name: '', header: 'Pre-heat oven to 400F\nThis recipe serves 4 people\nThis is my favorite meal ever',tasks:[]}, {name: 'Prep', header: '', tasks: [{instruction: 'Dice onions'}, {instruction: 'Chop peppers'}]}, ... ]

So to your point, yes my thoughts for how it is natively stored would put the instruction texts in a bunch of places, making searching more difficult. However I think we can solve that. As with all things there are trade offs. This data structure will be more powerful as it natively stores lots of information and structure. We can either search through the structure when necessary, or we can also store a flattened version for other uses on the server. For a given meal, this would be very easy. And data could be stored in any form desired.

For the GUI, I'm thinking to break it up identically to the underlying architecture. So the page will start with a text box like it has now. There can be space for a title, but it can be non-obtrusive if the user doesn't want a title. At the bottom of a section, within the box, can be a "+ Task" sign to add a task. And below the box can be a "+ Section" to add another section. I use a Wiki plugin at work in one program that actually has a similar hierarchy with a really nice GUI. The buttons to add their equivalent to sections or tasks are invisible or very dim until you mouse over, so the whole space is very clean, yet functional. I have that in mind. The actual tasks, when available, will be shown as numbered. Tasks and sections can be reordered with drag and drop, and there can be an X to the right to delete as well.

I'm not worried about users not using this. Again, I'm trying to keep in mind that they don't have to use it. If they want to type everything in a single header of a section (i.e. no structure whatsoever), then that's fine. That will be equivalent to the current instructions box (just a text box).

And as for the computer vs the user's job, I think we could write some "smart" programs to try and parse a recipe and automatically break it up into sections and tasks. Then the user can just write their recipe quickly and then press the "Auto-parse" button and correct any mistakes as needed. But I'm also thinking we could have shortcuts, like when you press Enter within a task, it automatically makes another task. That would be easy! I know it would be nice for the user to write any old garbage down and think that we'll parse it beautifully, but that feels impractical to me. I like the idea of having a middle step where they can attempt to auto-parse it. And then if they're happy with it (provide confirmation), our various features can then more confidently work with the result. Maybe some features will not be so complicated. For example, I want to automatically assign ingredients to their respective locations. This shouldn't be too hard, since it's a simple search. And it doesn't matter how the user structures things either. Every level will have that functionality.

MareoRaft commented 4 years ago

Cool beans. I like the idea of auto-numbering tasks, since doing that manually is a pain (especially if you add a new task in the middle after-the-fact)