Skip to Content
Personal Insights

The ABAP Detective Gets His Meal

It was a Tuesday, I recall, when the meal ticket got punched. I don’t mean someone kicked the bucket, I mean I got a case. Out of the cheesy bleu, the authorities swung by my back garden, asking me to look into a different kettle of fish than I was used to. Not a code violation, a cookbook case. A food-off not a one-off. Hopefully the food isn’t off.

Case background: food-off

It all started years ago, in the wanted post Cooking and Software Efficiency Randolf Eilenberger starts out the first course talking about developer diets, myth or not. A good read still, very much about process (or procedurals, as the cops call them) not so much about the food itself. Food, being the video challenge laid down in the charging documents.

In the morgue files (the newspaper kind, not the cemetery ones) my mind drifted back to an unsolved case, as far as I can tell, where my friend Craig Cmehil asked the community to come up with recipe data and access means. 2009 something was the citation: comment-86689. Then, memory chips tickling again, I stumbled on my own case notes, when I was with the force, “How To Cook With Logic.” Boy was I a wet behind the ears rookie code investigator that day.

The Logic post dealt with application software to store and retrieve recipes, created in the PC DOS era, and as happens, created an elementary data definition language for food preparation. Today it’d be XML, but back then it was plain text, keywords, and specific columns and content. Since that case was from 2009 (a lifetime ago in the data world, not so long civilization wise) I dusted off the folder structures and read-me files, trying to fire up the application engine for one more flight. Alas, time and operating system flavors move on, and the MealMaster code won’t rise.

Checked on http://www.ffts.com/mmformat.txt to find the technical specs for the recipes. If any were added to the live database on the old system and never exported, well, that’s just lost files in the evidence room. It happens, you know. But I have a hundred of so recipes from my Aunt Shirley’s 3by5 box, and now I’ve inherited my Mom’s set. As we’ll see, these old files are often handwritten, telling a story of how and when the evidence of good eating was collected.

 

Some pictures now while I finish my flashback recovery…

 

Above is a data recovery attempt using a freeware recipe application called “Gourmet” [ GitHub ].

 

Apple Crisp

In this view, ingredients are on the right and instructions on the left. Not how I normally see family data layout formats but eminently digestible. This is a pi shot.

 

Compare the Apple Crisp recipe through Gourmet to this one from the Meal-Master manual.

Carrot Cake

I’d say the DOS roots of the old code shines through the user interface for keystroke actions, and for the “Courier” type font. Bizarrely, in their own manual a menu goes from 80 columns to maybe 160, making that text less than user friendly. The faint lines separating the Gourmet view help keep the viewers eye focused where needed.

 

 

Mrs. Bowlings Baked Beans, also pi. Though it’s an in joke.

 

image

 

Meal’s (my grandmother) Dumplings

Code or data aspects as clues

The three main leads I had amounted to beans. I mean literal beans, not the metaphorical ones. Only one was typed, so there was no way to match the impressions. I’m no handwriting analyst but I’d say enough matches are visible as to be proof. Maybe not enough for a district attorney. But I digress.

  • A Baked Lima Beans

  • B Baked Beans, Southern Style
  • C Baked Beans

On the topic of “user interface” a key component of reproducible recipes is understandability (not a word, so I cheat). In example A we’ve got a title on the top, ingredients on the left, and steps on the right. A classic clean interface, complexity visible at a glance and return to position easy enough given the small number of additives and processing.

Example B also has title, ingredients and steps, with the more “magazine like” layout of 2 columns for the ingredients and wide columns for the steps. Easy on the eye, and if were typed consistently, lent itself to be sucked into the gigaverse of cooking sites (e.g. Recipe Cottage).

The last, while typed, is not in a machine digestible format as others I’ve seen. The ingredients and steps overlap, as one would describe a recipe verbally (I mean, who recites the shopping list and then talks about the pan flips?). And for the coup de grace, a can of tomato soup. Andy Warhol smiles.

In a brief flashback to 1915, we have this bean recipe from the Suffrage Cookbook (reference below):

Note the lined up ingredients, in this case heavily indented rather than left-aligned. Fractions for amounts but no abbreviations so less likely to mix up a teaspoon with a tablespoon. If you noticed there are no temperatures listed here, you’re a deputy health inspector now. Before you could easily own your own gauge, oven values were listed as slow, warm, etc.

Back to the data refresh. My brain is getting like scrambled eggs. I needed to refresh my app store account. Or something like that. In my day, you went to the corner drug store and got your pulp magazine detective training manuals, and your aspirins for those days when the caseload runs into overtime.

I liked what I saw with Gourmet. Mainly because it was the only code I could find on the NetBSD pkgsrc tree that mentioned MealMaster. The build went pretty easy as they say (also note the mention of “1 and 2 column” formats as standard data definitions):

$ cd /usr/pkgsrc/databases/gourmet

Gourmet Recipe Manager is a manager, editor, and organizer for
recipes. It currently has support for MealMaster(tm) and
MasterCook(tm) import, including 1 and 2 column MealMaster recipes and
plain text and XML MasterCook(tm). It can also export and import an XML
format of its own (the DTD is included here for your interest) which I
developed for an earlier recipe program in emacs-lisp. It also allows
you to export recipes as MealMaster(tm), HTML, RTF or Plain Text.
Then the trouble started 

$ /usr/pkg/bin/gourmet help 
Loading gnomeprint failed: 
trying wx 
importing wxprinter 
Loading wx failed: trying lpr 
** (gourmet:3189): WARNING **: 00:06:20.276: expected enumeration type GtkTextDirection, but got GtkDirectionType instead 
** (gourmet:3189): WARNING **: 00:06:20.294: expected enumeration type GtkTextDirection, but got GtkDirectionType instead Traceback (most recent call last): File "/usr/pkg/lib/python2.7/site-packages/gourmet/GourmetRecipeManager.py", 
line 957, in importg self.import_multiple_files(ifiles) File "/usr/pkg/lib/python2.7/site-packages/gourmet/GourmetRecipeManager.py", 
line 1044, in import_multiple_files import_source=string.join([os.path.split(f)[1] for f in filenames],", ") File "/usr/pkg/lib/python2.7/site-packages/gourmet/GourmetRecipeManager.py", 
line 1094, in run_import display_errors=display_errors) File "/usr/pkg/lib/python2.7/site-packages/gourmet/GourmetThreads.py", 
line 24, in __init__ self.name = name File "/usr/pkg/lib/python2.7/threading.py", 
line 971, in name assert self.__initialized, "Thread.__init__() not called" AssertionError: Thread.__init__() not called $

 

“Well, it was like this officer, I fed the standard text file to the application and it, well, died. I had no idea!”

Switching to Windows instead of UNIX, the gourmet just mainly worked as it should. That’s the picture above, running a recovery from a 2009 data export.

The leads on other food formats.

 

 

 

 

 

 

Bland, but functional main user screen:

The “Source” data column heading led me to believe I could easily improve my own database of recipes by flagging from which family member the code, er, index card came from. However, the space below that title is unusable, and on individual edits those are greyed out. Perhaps a premium feature, or just oh, yeah, unimplemented feature.

I wanted to cover all bases, so I tried a Linux flavor on Raspberry Pi. Then I had to break for coffee and, um, TastyKakes. Again, easy install steps.

$ sudo apt install gourmet
Reading package lists… Done

[…]

$

It reads and writes data like a good bot, but among the coffee grounds and eggshells was this message typed on a 3 part carbon form:

 File "/usr/lib/python2.7/dist-packages/gourmet/plugin_loader.py", line 278, in get_plugins

 

Augh. Python 2 has been sent down the river, making this case a flimsy one. Anything happens to tip one corner of the stack of containers, and down it goes.

They say never read your reviews. Or is it your own code comments, or what, something to do with fortune cookies. But you have to check the tea leaves at times, and this paid off, in spades.

Or so I thought.

   note the `--database-url` option

I had to look. Curiosity is not just a cat trait. Oh, nice, a MYSQL interface!

by default is something like 

  sqlite:///~/.gourmet/recipes.db

but could also be e.g. 

mysql://gourmetrecipe: ...

 

Well, shot myself in the foot with that hope. A dash of pepper, nothing to sneeze or cry about like onions.

ImportError: No module named MySQLdb

 

Anyway, my notes on the only database that works shows SQL Lite:

$ file .gourmet/recipes.db 
.gourmet/recipes.db: SQLite 3.x database, last written using SQLite version 3027002

As my former Lieutenant Columbo used to say, oh, just one more thing. A good user interface to an app that must be dead simple to use while multitasking, what about the chain of custody, I mean the table of content like a 3 by 5 box is organized sometimes by “tab separators” that say things like “Salad”. In current use, there are categories, and each recipe can be in none, one, or more than one. A list of suspect categories is in order, as well as app logic to produce indexes, shopping lists, pantry checks, whatever.

A final case note on the “Units Of Measure” gang. Anyone who orders online, or even non-automated transactions like phone or verbal orders, getting units right is critical. Was that 1 egg, or 1 dozen eggs called for?

The “spec” fails us here, as the source code is buried in an MSDOS executable,

Positions 9-10 contain one of the valid Meal-Master unit of measure codes, 
including blanks. (see list in program).


Now we are in a pickle. Can only derive valid values from existing text dumps. Or, check out the new sheriff in town to see what dish they recommend.

Let’s see what else is on the um menu. Right, food names.

CREATE TABLE pantry_xref (
    description           character varying( 512) NOT NULL,
    nbd_no                character varying(   8)     NULL,
    fdc_id                character varying(  10)     NULL,
    upc                   character varying(  16)     NULL,
    note                  character varying( 256)     NULL,
  primary key (description)
)
;

The Pantry_XRef is from my own case studies, looking to feed a shopping tool based on ingredients rather than starting with a desired outcome and listing from that. I researched the Food and Drug Administration, the Department of Agriculture and related sites to find out how food contents are measured and specified. Unsurprisingly, I found 3 different (publicly available) database formats from the government. To keep straight an NBD from an FDC, there are code comments. At the data layer.

-- COMMENT ON COLUMN Products.nbd_no IS '8-digit Nutrient Database
-- Number (NDB) that uniquely identifies a food item. Links to the
-- Nutrient file and the Serving Size file.';

One original lead on the breadcrumb trail:

For the database, we shall be using the usda (USDA The US Department of Agriculture’s public domain food and nutrient database) which you can download from http://[REDACTED]/projects/dbsamples/

Government (US) food link: ndb.nal.usda.gov

(The suggested citation is: U.S. Department of Agriculture, Agricultural Research Service. FoodData Central, 2019. fdc.nal.usda.gov)

 

Finding the next meal

Eventually, I found suspects in the original treatise, either 5 or 6. Maybe if the times permitted, I’d round them up on a TechEd forum, and pass the dessert plate around to pick the best. Tastes change though and here we are in a virtual diner.

And the nominees are:

Blueberries

OK, not much prep here. I like it.


MMMMM----- Recipe via Meal-Master (tm)

Title: Blueberries
Categories: Fruits

Blueberries

Chill.

Eat.

MMMMM

Award: Best of Show! {Performance Award}

 

I will line up the usual, I mean, current suspects in the same manner, skipping to the final course of data and skipping over the pretty menu pictures.

Sugar Snap Peas


MMMMM----- Recipe via Meal-Master (tm)

Title: Sugar Snap Peas

Peas, Snap, Sugar

Shucks, just eat them raw?

MMMMM

Award: Best Short! {Writing Award}

 

Panka Encrusted Shrimp


MMMMM----- Recipe via Meal-Master (tm)

Title: Panka Shrimp
Categories: Seafood
Cooktime: 20 minutes
Preparation Time: 1 week

1 Panka
12 Shrimp
1 dl Flour
1/8 Pepper
1/8 Salt
4 Eggs
1 qt Sunflower oil
Thai hot spice


First, build an oven

Dredge

Deep fry

Drain


MMMMM


Award: Best Technical Achievement! {Set Design Award}

Great Northern Beans


MMMMM----- Recipe via Meal-Master (tm)

   Title: Great Northern Beans
Cooktime: 1/2 day
Preparation Time: 1 day
Categories: American, Side dish

     1    Beans, Great Northern
          Onions
          Brown sugar
          BBQ sauce (optional)
          Ketchup (optional)
       mg Cinnamon
          Nutmeg


  Soak
  
  Simmer 9 to 10 hours.
  
  Spice
  

MMMMM


Award: Best Presentation Layer! {Documentary Award}

(while editing this one I noticed that “pound” showed up under “p” alphabetically, but as “lb.” Deep apologies to the rest of the world for using “English” measurements in my recipes).

 

 


MMMMM----- Recipe via Meal-Master (tm)

Title: Oranges
Preparation Time: 1 minute
Categories: Fruits

Orange


Peel and eat.

Spit seeds.


MMMMM

Award: Best Edible Trees! {Craft Award}

 

Finally…


MMMM----- Recipe via Meal-Master (tm)

Title: Malaguetta with Pork Chop
Cooktime: 1/2 hour
Preparation Time: 1 hour
Categories: Meat

Malaguetta Chilies
250 g Rice
Potatoes
Grilled onions
Lime
250 g Pork chop


Cook them both together.

Then you feel better.


MMMMM

 

Award: Best Technical Chops! {Production Award}

ob cit.. (obligatory citations and certifications)

Sorry for the M word. It is embedded in the legacy data standard, and I’ll do my best to get hip with the XML speak.

 

Other dangling links:

UPC and food: http://product-open-data.com/gtin/0074030203007

DB reference: postgresonline.com/journal/archives/88-Fusion-Charts-and-PostgreSQL-Part-1-Database-Analysis-of-USDA-DB.html

GITs:

https://github.com/topics/usda-national-nutrient-database

https://github.com/Adyg/usdanl-sr28-postgresql

https://github.com/Adyg/usdanl-sr28-postgresql/raw/master/usda_sr28.sql

USDA (Agriculture)

https://www.ars.usda.gov/northeast-area/beltsville-md-bhnrc/beltsville-human-nutrition-research-center/nutrient-data-laboratory/docs/

https://fdc.nal.usda.gov/fdc-datasets/FoodData_Central_branded_food_csv_2019-04-02.zip

https://fdc.nal.usda.gov/fdc-datasets/FoodData_Central_csv_2019-04-02.zip

(might be stale heh heh heh)

OTHER

https://world.openfoodfacts.org/product/0011196652515/winter-blend-white-rose

 

 

Free E Books from Project Gutenberg:

The Suffrage Cookbook http://www.gutenberg.org/ebooks/26323

 

4 Comments
You must be Logged on to comment or reply to a post.
  • My name in here and many cool recipes!   I would say that’s win!

    It did however, lead me to craving  Apple Crisp.   Now something I’ll have to do over the weekend.  Or as you know it would be one of my favorites Blueberry pie.  Now that is a simple recipe.

     

    • Ha! I thought about whether or not I should tag you in the post, so that is resolved.

      Next challenge – ABAPgit recipe codebase…

       

  • As non native English speaker, it was extremely hard to go through the whole post, but I’ve managed to do so 🙂

    Glad to be a part of the gang that did the videos and it was fun making it. Hope to see more peers doing this next time 😉