Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Be more explicit documenting Dr. Syntax's objects #9

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 138 additions & 45 deletions dr.syntax/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,64 +9,159 @@ Dr. Syntax (in America known as Syntax, M.D.)
is an object model, and file layout
for representing recipes, ingredients, and shopping lists.

Examples are shown in JSON format, and the `nosebag` project will continue to
use JSON, but Dr. Syntax is format agnostic as long as the object can be
serialised and deserialised intact.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might add something like:

Where necessary, the serialisations can be referred to as "Syntax JSON" or "syntax.json", "Syntax TOML" or "syntax.toml", and so on.


## Object model

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need something at the top of this section which talks about ontology + recipe list + recipes before it gets into the details.

### Recipes

Each recipe is represented as a core object and optional additional media.
The central properties of each recipe are two lists:

* recipe ingredients, which:
* reference an ingredient by name (which may not exist,
in which case it is treated as if an ingredient of that name exists
with no other defined properties)
* have an optional quantity which are either a naked
positive number, meaning an amount without unit, or contain:
* an amount
* a unit
* optional notes that provide advice on how to modify the amount
required (such as "more if they are small")
* an optional property of 'optional', meaning that the ingredient can be
omitted
* an optional prep instruction
* an optional note (distinct from the quantity note), which can be used
to express a preference; for instance, you could indicate a preferred
variety
* steps, each of which is a narrative of the task to be accomplished

Recipes also have a name, an optional "serves" property to represent how many
people this recipe will feed, and zero or more attributes (such as "gluten
free"), which are used for searching and filtering.

Prep instructions for ingredients are implicit steps that all come before
the first recipe step.

### Ingredients
### The list of known ingredients — `ontology.json`

Stored serialised as `ontology.json`, the ontology is an object containing
an abstraction of foodstuff used in recipes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"an object listing the foodstuffs used in recipes"? Yes, it's an abstraction, but I'm not sure saying that makes things clearer.


```javascript
{
"ingredients": [
{
"name": "carrot",
"group": "vegetable",
"attributes": [
"meat free",
...
]
},
...
]
}
```

Each ingredient is an object, containing:

* `name` — _required_, the unique, singular name of the foodstuff, by
convention lower cased (ie "carrot" not "Carrots")
* `group` — _optional_, the unique, singular name of the grouping of the
foodstuff, also by convention lower cased (ie "spice" not "Spices")
* `attributes` — _optional_, an array of strings which represents aspects of the
ingredient, such as "dairy" or "meat" that could be used for searching
and filtering

Groups represent a phase of shopping where similar items are collected
together, such as an aisle or area in a supermarket, or visiting different
shops.

Ingredients are the abstraction of the food stuff used in recipes. So
"carrot" rather than "100g carrots". The names of ingredients are unique,
and by convention are singular and lower-cased.

Ingredients also have an optional group, referenced by name, and zero or
more attributes (such as "meat") which are used for searching and filtering
recipes.
### The list of recipes — `recipes.json`

### Groups
Stored serialised as `recipes.json`, the list of recipes is an array of
strings that represent the directory relative to the location storing both
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since nosebag can work over HTTP, it's not necessarily the directory. Perhaps just a note that "equivalent things happen" under HTTP? Or "path"?

`recipes.json` and `ontology.json` under which the recipe serialisation can be
found.

Groups represent a phase of your shopping, and may be thought of as aisles
of a supermarket, or different shopkeepers. They have a name, which like
ingredients are unique, singular, and lower-cased. For example, "vegetable",
or "spice".
```javascript
{

## File layout
"recipes": [
"bacon-hash",
"cauliflower-fritter-lime-sauce",
...
]
}
```


### A recipe — `<dir>/recipe.json`

The recipe core object is serialised as JSON, and stored as `recipe.json`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's no longer the case that Dr. Syntax is always JSON, this should be updated.

alongside additional media files for that recipe. (Media files are
referenced using either a relative URL, meaning their leaf filename, or an
absolute URL if the media files are stored elsewhere such as on Wikipedia.)

Ingredients and groups are serialised as one JSON object, stored as
`ontology.json`.
```javascript
{
"name": "Mashed potatoes",
"serves": "2",
"attributes": [
"gluten free",
...
],
"ingredients": [
{
"name": "large potato",
"quantity": 4,
"prep": "cut into 1-inch cubes",
"notes": "Preferably Maris Piper or other floury potato."
},
...
],
"steps": [
{
"task": "Heat water in a large pan until boiling.",
},
...
],
}
```

The **recipe object** contains:

* `name` — _required_, a string containing the name of the recipe (this does not
have to be unique within a collection of recipes)
* `ingredients` - _required_, an array of ingredient objects (see below)
* `steps` — _required_, an array of step objects (see below)
* `serves` — _optional_, a string representing how many people this recipe will feed
* `attributes` — _optional_, an array of strings which represent aspects of
this recipe (such as "gluten free") which can be used for searching and
filtering


The **ingredient object** contains:

* `name` — _required_, a string containing the name of the ingredient to
reference from the ontology (which may not exist, in which case it is
treated as if an ingredient of that name exists with no other defined
properties)
* `quantity` — _optional_, an object which contains:

```javascript
{
"amount": 300,
"unit": "g",
}
```

* `amount` — _required_, a positive integer
* `unit` — _optional_, a string representing the unit of which _amount_ is
needed
* `notes` — _optional_, a string containing advice on how to adjust the amount if
necessary (eg "more if they are small")

If both `unit` and `notes` are not needed, the object can be collapsed to a
positive integer (eg requiring 2 onions has no new unit to be expressed).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what the word "new" is doing here?

* `prep` — _optional_, a string containing directions on how to prepare the
ingredient before making the recipe (eg "finely chopped")
* `notes` — _optional_, a string containing advice on the ingredient (such as
a preferred variety, acceptable substitutions, things to look out for when
purchasing, etc)
* `optional` — _optional_, a boolean value set to `true` if the ingredient is
not strictly necessary, such as a garnish or extra herbs/spices

The **step object** contains:

* `task` — _required_, a string containing the narrative description of a step
in making the recipe


When interpreting a recipe object, these are the keys Dr. Syntax has imbued
with meaning. Other keys can exist in the object for private use, but note
that this specification may be expanded later which could introduce
incompatibilities. There is as yet no explicit extension model.

Prep instructions for ingredients are implicit steps that all come before
the first recipe step.


## Doctor Syntax recommends that

Expand All @@ -91,7 +186,5 @@ Ingredients and groups are serialised as one JSON object, stored as
tools to suggest ways of scheduling the steps of multiple recipes you need
to cook at once, such as for a dinner.

* group and ingredient names are singular and lower-cased.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we keep this advice for ingredient names, noting that while they may not appear in the ontology, they should still follow the convention that the ontology itself uses.


* "large potato" as an ingredient can be more useful than "potato" with a
quantity unit of "large".