final commit

This commit is contained in:
olari
2021-05-24 05:37:47 +03:00
parent bdaeb1fb95
commit 0e1fd8b4a9
5 changed files with 362 additions and 0 deletions

View File

@@ -129,6 +129,8 @@ diet_csv = [[
'saturated_fat', 'sugar', 'fiber'
]]
output = open('diet', 'w')
for fpath in sorted((Path.home() / 'workspace' / 'journal').glob('*.md')):
day = fpath.stem
header, *tmp = entry_re.split(fpath.read_text())
@@ -143,6 +145,7 @@ for fpath in sorted((Path.home() / 'workspace' / 'journal').glob('*.md')):
daily_sugar = 0.0
for (timestamp, content) in sorted(entries, key=lambda x: x[0]):
ts_str = timestamp
timestamp = int(datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S').timestamp())
content = '\n'.join(
@@ -152,8 +155,11 @@ for fpath in sorted((Path.home() / 'workspace' / 'journal').glob('*.md')):
for diet in diet_re.finditer(content):
value, name = diet.groups()
output.write(f'{ts_str} {name} {value}\n')
value = float(value.removesuffix('g'))
if name in recipes:
food = recipes[name]
@@ -171,6 +177,7 @@ for fpath in sorted((Path.home() / 'workspace' / 'journal').glob('*.md')):
print(f'ERROR: Invalid diet entry: {content}')
continue
diet_csv.append((
timestamp,

70
foods
View File

@@ -1,4 +1,32 @@
Apple
Energy 52kcal
Fat 0.2g
Carbs 14g
Fiber 2.4g
Sugar 10g
Protein 0.3g
HarkisRouheseos
Energy 335kcal
Fat 3.1g
SaturatedFat 0.3g
Carbs 26g
Sugar 3.7g
Fiber 12g
Protein 47g
Salt 1.0g
HazelnutIcecream
Energy 288kcal
Fat 18g
SaturatedFat 5.6g
Carbs 27g
Sugar 24g
Fiber 1.1g
Protein 4.0g
Salt 0.17g
CheesePizza
Energy 210kcal
Fat 5.3g
@@ -129,6 +157,15 @@ Fiber 2.4g
Protein 11.4g
Salt 0.01g
GrahamFlour
Energy 330kcal
Fat 3.0g
SaturatedFat 0.5g
Carbs 56g
Sugar 0.8g
Fiber 13g
Protein 14g
Salt
Energy 0kcal
Salt 100g
@@ -554,6 +591,12 @@ Carbs 1.5g
Protein 22.0g
Salt 2.7g
Salmon
Energy 208kcal
Fat 13g
SaturatedFat 3.0g
Protein 20g
---
Omlette
@@ -590,6 +633,10 @@ FakeChicken 250g
Oil 40g
PeasCornPepper 225g
OilVeggies
Oil 30g
PeasCornPepper 220g
MashedPotato
Margarine 40g
Milk 180g
@@ -633,6 +680,11 @@ FoodCream 450g
Oil 50g
Potato 1500g
CreamPotatoes2
Cheese 200g
FoodCream 450g
Potato 1020g
ProteinSpaghettiBolognese
ProteinSpaghetti 500g
PastaSauce 500g
@@ -666,7 +718,25 @@ Oil 20g
SaladDressing 65g
TOTAL 1675g
PastaSalad2
TricolorePasta 500g
Salad 270g
Oil 30g
SaladDressing 100g
TOTAL 1675g
ProteinShake
SkimMilk 400g
ProteinPowder 60g
MashedPotato2
Margarine 20g
Potato 760g
Milk 300g
VegeKotlet
Oil 45g
HarkisRouheseos 180g
Milk 240g
Egg 65g
GrahamFlour 60g

105
parse.py Normal file
View File

@@ -0,0 +1,105 @@
from datetime import datetime, timedelta
from pathlib import Path
from subprocess import run
from typing import Union
import sys
import re
JOURNAL_PATH = '/Users/olari/workspace/journal'
entry_re = re.compile(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}')
def get_daily_file_paths() -> list[Path]:
return list(sorted(Path(JOURNAL_PATH).glob('*.md')))
def resolve_relative_time_expression(now: datetime, expr: str) -> datetime:
weekdays = [
'monday', 'tuesday', 'wednesday', 'thursday',
'friday', 'saturday', 'sunday'
]
if expr == 'today':
return now
elif expr == 'tomorrow':
return now + timedelta(days=1)
elif expr == 'yesterday':
return now - timedelta(days=1)
elif expr in weekdays:
return now - timedelta(days=now.weekday()) + weekdays.index(expr)
else:
return None
def parse_godword(content: str) -> list[str]:
return content.split()
def parse_habits(content: str) -> dict[str, bool]:
return {
line[4:]: line[1] == 'x'
for line in content.splitlines()
}
header_modules = {
'godword': (None, parse_godword),
'habits': (None, parse_habits),
}
def parse_module(content: str) -> tuple[str, Union[list, dict]]:
name, *content = content.splitlines()
name = name.removesuffix(':').lower()
content = '\n'.join(content)
_, parse = header_modules[name]
return name, parse(content)
def parse_header(header):
title, *modules = header.split('\n\n')
title = title.removeprefix('# ')
return {
'title': title,
'modules': dict(parse_module(module) for module in modules)
}
def parse_timestamp(timestamp):
return datetime.strptime('%Y-%m-%d %H:%M:%S')
def parse_entry(entry):
return {
}
def parse_file(fpath):
header = {}
entries = []
buf = []
with open(fpath) as fp:
for i, line in enumerate(fp):
if entry_re.match(line):
if not header:
header = parse_header('\n'.join([c.strip() for c in buf]))
header['line'] = i
else:
entries.append(parse_entry('\n'.join(buf)))
buf = [line]
else:
buf.append(line)
result = {
'header': header,
'entries': entries,
}
breakpoint()
return result
def parse_journal():
return {
info['header']['title']: info
for fpath in get_daily_file_paths()[-5:]
for info in parse_file(fpath)
}
import json
open('journal.json', 'w').write(json.dumps(parse_journal()))

29
search.py Normal file
View File

@@ -0,0 +1,29 @@
from pathlib import Path
from subprocess import run
import re
import sys
entry_re = re.compile(r'^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})', re.MULTILINE)
matches = []
for fpath in sorted((Path.home() / 'workspace' / 'journal').glob('*.md')):
header, *tmp = entry_re.split(fpath.read_text())
entries = list(zip(tmp[::2], tmp[1::2]))
for (timestamp, content) in sorted(entries, key=lambda x: x[0]):
content = '\n'.join(
part.replace('\n', ' ')
for part in content.split('\n\n')
)
if sys.argv[1].lower() in content.lower().split():
matches.append((timestamp, content))
buf = ''
for (ts, c) in matches:
c = c.replace('\n', ' ').strip()
buf += (f'[[{ts}]] {c}')[:80] + '\n'
run(['nvim', '-'], input=buf.encode('utf-8'))

151
summary.py Normal file
View File

@@ -0,0 +1,151 @@
from pathlib import Path
from datetime import datetime
from collections import Counter
from functools import reduce
import re
import string
import sys
def parse_foods_file():
path = Path.home() / 'projects' / 'open-journal' / 'foods'
text = path.read_text()
foods, recipes = text.split('---')
def parse_macro(macro):
if macro == '...':
return ('INVALID', 0.0)
name, value = macro.split()
value = float(value.removesuffix('g').removesuffix('kcal'))
return (name, value)
foods = {
macros[0]: dict(parse_macro(macro) for macro in macros[1:])
for macros in [food.split('\n') for food in foods.strip().split('\n\n')]
}
def combine_values(fst, snd):
result = fst.copy()
for k,v in snd.items():
if k in fst:
result[k] += v
else:
result[k] = v
return result
def evaluate_ingredients(ingredients):
result = {}
total_weight = 0.0
for ingredient in ingredients:
k,v = parse_macro(ingredient)
if k == 'TOTAL':
result[k] = v
break
else:
total_weight += v
food = foods[k]
for kk,vv in food.items():
if kk not in result:
result[kk] = 0.0
result[kk] += vv * (v/100.0)
if 'TOTAL' not in result:
result['TOTAL'] = total_weight
return result
recipes = {
ingredients[0]: evaluate_ingredients(ingredients[1:])
for ingredients in [
recipe.split('\n') for recipe in recipes.strip().split('\n\n')
]
}
def get_calories_from_macros(mm):
calories = 0.0
for k,v in mm.items():
calories += v * {
'Carbs': 4,
'Fat': 9,
'Protein': 4
}.get(k, 0.0)
return calories
#for k,v in foods.items():
# print(round(v.get('Energy') - get_calories_from_macros(v)), k)
return foods, recipes
foods, recipes = parse_foods_file()
entry_re = re.compile(r'^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) ', re.MULTILINE)
diet_re = re.compile(r'@diet (\d+g) ([a-zA-Z]+)')
current_day = list(sorted((Path.home() / 'workspace' /
'journal').glob('*.md')))[-1]
header, *tmp = entry_re.split(current_day.read_text())
entries = list(zip(tmp[::2], tmp[1::2]))
daily_grams = 0.0
daily_calories = 0.0
daily_protein = 0.0
for (timestamp, content) in sorted(entries, key=lambda x: x[0]):
content = '\n'.join(
part.replace('\n', ' ')
for part in content.split('\n\n')
)
has_printed = False
entry_calories = 0.0
entry_protein = 0.0
for diet in diet_re.finditer(content):
if not has_printed:
print(f'-- {timestamp}')
has_printed = True
value, name = diet.groups()
value = float(value.removesuffix('g'))
if name in recipes:
food = recipes[name]
if value == 0.0:
value = food['TOTAL']
food = {k: v*(value/food['TOTAL']) for k,v in food.items()}
elif name in foods:
if value == 0.0:
value = 100
food = {k: v*(value/100.0) for k,v in foods[name].items()}
else:
breakpoint()
print(f'ERROR: Invalid diet entry: {content}')
continue
protein = round(food.get('Protein', 0.0), 2)
calories = round(food.get('Energy', 0.0), 2)
entry_calories += calories
entry_protein += protein
print(f'{name:<20} {value:<6}g, {calories:<6}kcal, {protein:<6}g protein')
if has_printed:
entry_calories = round(entry_calories, 2)
entry_protein = round(entry_protein, 2)
print(f'-- TOTAL: {entry_calories}kcal, {entry_protein}g protein')
print()
daily_calories += entry_calories
daily_protein += entry_protein
print(f'-- DAILY TOTAL ({daily_calories}kcal, {daily_protein}g protein)')