Skip to content

Instantly share code, notes, and snippets.

@sli
Last active December 29, 2015 11:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save sli/7663011 to your computer and use it in GitHub Desktop.
Save sli/7663011 to your computer and use it in GitHub Desktop.
A parser for eJuice Me Up recipes.
class Recipe(object):
def __init__(self, recipe):
self.__data = {
'nicotine_base':0,
'nicotine_target':0,
'amount':0,
'cut':0,
'target_pg':0,
'target_vg':0,
'unknown_a':0,
'unknown_b':0,
'base_pg_percent':0,
'base_vg_percent':0,
'drops_per_ml':0,
'notes':''
}
recipe = recipe.split('\n')
self.__data['nicotine_base'] = int(recipe[0])
self.__data['nicotine_target'] = int(recipe[1])
self.__data['amount'] = int(recipe[2])
self.__data['cut'] = int(recipe[3])
self.__data['target_pg'] = int(recipe[14])
self.__data['target_vg'] = int(recipe[15])
self.__data['unknown_a'] = int(recipe[16])
self.__data['unknown_b'] = int(recipe[17])
self.__data['base_pg_percent'] = int(recipe[18])
self.__data['base_vg_percent'] = int(recipe[19])
self.__data['drops_per_ml'] = int(recipe[30])
self.__data['notes'] = '\n'.join(recipe[46:]).rstrip()
self.__flavors = FlavorList(recipe)
def __getattr__(self, name):
if name == 'flavors':
return self.__flavors
elif name in self.__data.keys():
return self.__data[name]
else:
raise AttributeError
def __repr__(self):
return '<Recipe>'
def __dir__(self):
return sorted(set(dir(super(Recipe, self)) + self.__data.keys()))
# Handles a list of Flavor objects
class FlavorList(object):
def __init__(self, recipe):
self.__flavors = (
Flavor((recipe[9], recipe[4], recipe[20], recipe[25], recipe[31])),
Flavor((recipe[10], recipe[5], recipe[21], recipe[26], recipe[32])),
Flavor((recipe[11], recipe[6], recipe[22], recipe[27], recipe[33])),
Flavor((recipe[12], recipe[7], recipe[23], recipe[28], recipe[34])),
Flavor((recipe[13], recipe[8], recipe[24], recipe[29], recipe[35])),
Flavor((recipe[37], recipe[36], recipe[38], recipe[39], recipe[40])),
Flavor((recipe[42], recipe[41], recipe[43], recipe[44], recipe[45])),
)
def __getitem__(self, index):
return self.__flavors[index]
# Holds the data for a single flavor
class Flavor(object):
def __init__(self, flavor):
self.__data = {
'name':'',
'percent':0,
'pg_percent':0,
'vg_percent':0,
'flavorless':False
}
self.__data['name'] = flavor[0]
self.__data['percent'] = int(flavor[1])
self.__data['pg_percent'] = int(flavor[2])
self.__data['vg_percent'] = int(flavor[3])
self.__data['flavorless'] = bool(int(flavor[4]))
def __getattr__(self, name):
return self.__data[name]
def __dir__(self):
return sorted(set(dir(super(Flavor, self)) + self.__data.keys()))
# Load up a recipe and return a Recipe object
def load_recipe(fn):
fcons = open(fn, 'r').read()
return Recipe(fcons)
if __name__ == '__main__':
import sys
if len(sys.argv) < 2:
print 'Usage: ejuice.py <recipe filename>'
sys.exit(1)
else:
r = load_recipe(sys.argv[1])
print r
@zengargoyle
Copy link

Line 18: Line separator is '\r\n' (0x0d 0x0a), maybe this doesn't matter in Python?

Line 30: Notes are multi-line

$ cat -n White\ Rabbit2.rec
    42  0
    43  by: Brenda
    44  100
    45  0
    46  0
    47  Line 1 of Notes
    48  Line 2 of Notes
    49  Line 3 of Notes

Line 74: 'flavorless' is '0 PG / 0 VG' flag (to turn off the PG+VG=100 constraint)

@zengargoyle
Copy link

Maybe in the array of flavors, prune out the '0%' entries, if there's text in the flavor name field and the percentage is 0, then move it to notes. This breaks round-trip-ability but makes for a better recipe (IMHO, not having 0% 'empty' flavors and having the 'by: Somebody' or 'Menthol to taste' type of things moved to Notes is a good thing).

@sli
Copy link
Author

sli commented Dec 4, 2013

You're right about the multiline notes thing. I actually wrote this, then updated eJuice to the most recent version. The one I developed against didn't support notes at all, so it was a bit of an afterthought. I'll fix that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment