jkjk not final

This commit is contained in:
olari
2021-05-28 04:13:27 +03:00
parent 0e1fd8b4a9
commit 3aef7c4133
7 changed files with 308 additions and 98 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
**/*.csv **/*.csv
.ipynb_checkpoints/ .ipynb_checkpoints/
__pycache__/

View File

@@ -7,80 +7,7 @@ import string
import sys import sys
def parse_foods_file(): from common import 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() foods, recipes = parse_foods_file()
@@ -144,6 +71,8 @@ for fpath in sorted((Path.home() / 'workspace' / 'journal').glob('*.md')):
daily_fat = 0.0 daily_fat = 0.0
daily_sugar = 0.0 daily_sugar = 0.0
output.write(f'-- {day}\n')
for (timestamp, content) in sorted(entries, key=lambda x: x[0]): for (timestamp, content) in sorted(entries, key=lambda x: x[0]):
ts_str = timestamp ts_str = timestamp
timestamp = int(datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S').timestamp()) timestamp = int(datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S').timestamp())

82
common.py Normal file
View File

@@ -0,0 +1,82 @@
from pathlib import Path
from datetime import datetime
def parse_timestamp(timestamp):
return datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S')
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

24
extract_toc.py Normal file
View File

@@ -0,0 +1,24 @@
from subprocess import run
import sys
outline = run(
['mutool', 'show', sys.argv[1], 'outline'],
capture_output=True
).stdout.decode('utf-8')
indent = 0
last_quote_index = 0
for line in outline.splitlines():
quote_index = line.find('"')
hash_index = line.find('#')
if quote_index > last_quote_index:
indent += 1
elif quote_index < last_quote_index:
indent -= 1
last_quote_index = quote_index
title = line[quote_index+1:line.find('"', quote_index+1)].strip()
page = int(line[hash_index+1:line.find(',', hash_index+1)])
print(f'{"#"*indent} {title} ({page})')

70
foods
View File

@@ -1,4 +1,34 @@
ProteinRakha
Energy 67kcal
Fat 0.2g
SaturatedFat 0.1g
Carbs 6g
Sugar 5.9g
Protein 10g
Salt 0.06g
Water
Energy 0kcal
KaneliKorppu
Energy 359kcal
Fat 6.6g
SaturatedFat 0.5g
Carbs 65g
Sugar 23g
Fiber 4g
Protein 8g
Salt 0.5g
Broccoli
Energy 34kcal
Fat 0.4g
Carbs 7g
Fiber 2.6g
Sugar 1.7g
Protein 2.8g
Apple Apple
Energy 52kcal Energy 52kcal
Fat 0.2g Fat 0.2g
@@ -7,6 +37,16 @@ Fiber 2.4g
Sugar 10g Sugar 10g
Protein 0.3g Protein 0.3g
BeanitHarkis
Energy 206kcal
Fat 10g
SaturatedFat 1g
Carbs 9g
Sugar 0.9g
Fiber 6.1g
Protein 16g
Salt 1.3g
HarkisRouheseos HarkisRouheseos
Energy 335kcal Energy 335kcal
Fat 3.1g Fat 3.1g
@@ -246,6 +286,16 @@ Sugar 22.8g
Protein 1.2g Protein 1.2g
Salt 1.8g Salt 1.8g
WholeGrainBread
Energy 255kcal
Fat 5g
SaturatedFat 0.5g
Carbs 41g
Sugar 4g
Fiber 7g
Protein 8g
Salt 1g
WhiteBread WhiteBread
Energy 253kcal Energy 253kcal
Fat 2.5g Fat 2.5g
@@ -740,3 +790,23 @@ HarkisRouheseos 180g
Milk 240g Milk 240g
Egg 65g Egg 65g
GrahamFlour 60g GrahamFlour 60g
RoastedVeggies2
Broccoli 300g
Oil 70g
Potato 1000g
SweetPotato 300g
BeanitHarkisVeggies
Oil 60g
BeanitHarkis 250g
PeasCornPepper 200g
Ketchup 100g
TOTAL 760g
Pancake
SkimMilk 430g
Water 300g
Oil 30g
Flour 430g
Sugar 20g

View File

@@ -43,7 +43,7 @@ header_modules = {
'habits': (None, parse_habits), 'habits': (None, parse_habits),
} }
def parse_module(content: str) -> tuple[str, Union[list, dict]]: def parse_header_module(content: str) -> tuple[str, Union[list, dict]]:
name, *content = content.splitlines() name, *content = content.splitlines()
name = name.removesuffix(':').lower() name = name.removesuffix(':').lower()
content = '\n'.join(content) content = '\n'.join(content)
@@ -55,16 +55,25 @@ def parse_header(header):
title = title.removeprefix('# ') title = title.removeprefix('# ')
return { return {
'title': title, 'title': title,
'modules': dict(parse_module(module) for module in modules) 'modules': dict(parse_header_module(module) for module in modules)
}
def parse_diet(content):
pass
def parse_content(content):
content = content.strip()
return {
'blocks': [b.replace('\n', ' ') for b in content.split('\n\n')]
} }
def parse_timestamp(timestamp): def parse_timestamp(timestamp):
return datetime.strptime('%Y-%m-%d %H:%M:%S') return datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S')
def parse_entry(entry): def parse_entry(entry):
return { return {
'timestamp': int(parse_timestamp(entry[:19]).timestamp()),
'content': parse_content(entry[19:]),
} }
def parse_file(fpath): def parse_file(fpath):
@@ -73,33 +82,29 @@ def parse_file(fpath):
buf = [] buf = []
with open(fpath) as fp: for i, line in enumerate(fpath.read_text().splitlines()):
for i, line in enumerate(fp):
if entry_re.match(line): if entry_re.match(line):
if not header: if not header:
header = parse_header('\n'.join([c.strip() for c in buf])) header = parse_header('\n'.join([c.strip() for c in buf]))
header['line'] = i
else: else:
entries.append(parse_entry('\n'.join(buf))) entries.append(parse_entry('\n'.join(buf)))
buf = [line] buf = [line]
else: else:
buf.append(line) buf.append(line)
result = { return {
'header': header, 'header': header,
'entries': entries, 'entries': entries,
} }
breakpoint() def parse_journal():
result = {}
for fpath in get_daily_file_paths()[-5:]:
info = parse_file(fpath)
result[info['header']['title']] = info
return result 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 import json
open('journal.json', 'w').write(json.dumps(parse_journal())) open('journal.json', 'w').write(json.dumps(parse_journal()))

99
progress.py Normal file
View File

@@ -0,0 +1,99 @@
import sys
from collections import defaultdict
from datetime import datetime, timedelta
import math
from common import parse_timestamp
content = open(sys.argv[1]).read().strip()
"""
* Total hours
* Hours today
* Hours this week
* Percentage completed
* Pages completed
* Estimated hours to completion
* Estimated completion date
"""
lines = content.splitlines()
i = 0
current_chapter = ''
result = defaultdict(float)
total_chapters = 0
completed_chapters = 0
today = datetime.now().replace(hour=0,minute=0,second=0,microsecond=0)
this_week = today - timedelta(days=7)
total_hours = 0.0
day_hours = 0.0
week_hours = 0.0
oldest_timestamp = datetime.now()
while i < len(lines):
line = lines[i].strip()
if line.startswith('#'):
current_chapter = line[line.find(' ')+1:]
total_chapters += 1
elif line.startswith('@start'):
start = parse_timestamp(line.removeprefix('@start '))
if start < oldest_timestamp:
oldest_timestamp = start
i += 1
line = lines[i].strip()
end = parse_timestamp(line.removeprefix('@stop '))
delta = end - start
hours = delta.seconds / 60 / 60
result[current_chapter] += hours
total_hours += hours
if start > this_week:
week_hours += hours
if start > today:
day_hours += hours
elif line.startswith('@done'):
completed_chapters += 1
i += 1
#from pprint import pprint
#pprint(dict(result), sort_dicts=False)
num_days = (datetime.now() - oldest_timestamp).days or 1
hours_per_day = total_hours / num_days
hours_per_chapter = total_hours / completed_chapters
hours_to_completion = hours_per_chapter * (total_chapters - completed_chapters)
days_to_completion = math.ceil(hours_to_completion / hours_per_day)
completion_date = datetime.now() + timedelta(days=days_to_completion)
completion_percentage = completed_chapters/total_chapters*100
print(f'Started on: {oldest_timestamp.strftime("%Y-%m-%d")}')
print(f'Progress: [{completed_chapters}/{total_chapters}] ({round(completion_percentage, 2)}%)')
print(f'Total: {round(total_hours, 2)}h')
print(f'Week: {round(week_hours, 2)}h')
print(f'Day: {round(day_hours, 2)}h')
print(f'Hours per day: {round(hours_per_day, 2)}h')
print(f'Hours to completion: {round(hours_to_completion, 2)}h')
print(f'Completion date: {completion_date.strftime("%Y-%m-%d")}')