From ea61d14250ad22a39f24481e5f3db7e2e6be414b Mon Sep 17 00:00:00 2001 From: olari Date: Wed, 12 May 2021 04:01:12 +0300 Subject: [PATCH] initial --- .gitignore | 1 + analyze.py | 186 +++++++++ backup-script.sh | 5 + foods | 432 ++++++++++++++++++++ godword | 1000 ++++++++++++++++++++++++++++++++++++++++++++++ habits | 3 + open-journal.py | 42 ++ 7 files changed, 1669 insertions(+) create mode 100644 .gitignore create mode 100644 analyze.py create mode 100644 backup-script.sh create mode 100644 foods create mode 100644 godword create mode 100644 habits create mode 100644 open-journal.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4fb4c96 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +**/*.csv diff --git a/analyze.py b/analyze.py new file mode 100644 index 0000000..93c4096 --- /dev/null +++ b/analyze.py @@ -0,0 +1,186 @@ +from pathlib import Path +from datetime import datetime +from collections import Counter +from functools import reduce +import re +import string + +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': 8, + '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]+)') + +total_entries = 0 +total_words = 0 +word_frequency = Counter() + +total_csv = [['day', 'entries', 'words']] +daily_csv = [['day', 'entries', 'words', 'calories']] +entry_csv = [['timestamp', 'words']] +words_csv = [['word', 'count']] + +diet_csv = [[ + 'timestamp', 'name', 'grams', 'calories', 'carbs', 'fat', 'protein', + 'saturated_fat', 'sugar', 'fiber' +]] + +for fpath in sorted((Path.home() / 'workspace' / 'journal').glob('*.md')): + day = fpath.stem + header, *tmp = entry_re.split(fpath.read_text()) + entries = list(zip(tmp[::2], tmp[1::2])) + + daily_entries = len(entries) + daily_words = 0 + daily_calories = 0.0 + + for (timestamp, content) in sorted(entries, key=lambda x: x[0]): + timestamp = int(datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S').timestamp()) + + content = '\n'.join( + part.replace('\n', ' ') + for part in content.split('\n\n') + ) + + for diet in diet_re.finditer(content): + 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 + + + diet_csv.append(( + timestamp, + name, + value, + round(food.get('Energy', 0.0), 2), + round(food.get('Carbs', 0.0), 2), + round(food.get('Fat', 0.0), 2), + round(food.get('Protein', 0.0), 2), + round(food.get('SaturatedFat', 0.0), 2), + round(food.get('Sugar', 0.0), 2), + round(food.get('Fiber', 0.0), 2), + )) + + daily_calories += food.get('Energy', 0.0) + + words = ''.join( + c if c in string.ascii_letters+"'" else ' ' + for c in content.lower() + ).split() + + word_frequency.update(words) + + entry_words = len(words) + daily_words += entry_words + + entry_csv.append([timestamp, entry_words]) + + daily_csv.append([day, daily_entries, daily_words, daily_calories]) + + total_entries += daily_entries + total_words += daily_words + + total_csv.append([day, total_entries, total_words]) + +words_csv += word_frequency.most_common() + +def write_csv(fname, csv): + with open(fname, 'w') as fp: + fp.write('\n'.join(','.join(str(x) for x in row) for row in csv)) + +write_csv('total.csv', total_csv) +write_csv('daily.csv', daily_csv) +write_csv('entry.csv', entry_csv) +write_csv('words.csv', words_csv) +write_csv('diet.csv', diet_csv) diff --git a/backup-script.sh b/backup-script.sh new file mode 100644 index 0000000..915390f --- /dev/null +++ b/backup-script.sh @@ -0,0 +1,5 @@ +#!/bin/bash +apack $1 *.md +rclone copy $1 gdrive:/journal-backup/ +rclone copy $1 prodesk:/home/olari/journal-backup/ +rm $1 diff --git a/foods b/foods new file mode 100644 index 0000000..4f09d73 --- /dev/null +++ b/foods @@ -0,0 +1,432 @@ + +RainbowNoodles +Energy 451kcal +Fat 18g +SaturatedFat 8.6g +Carbs 63g +Sugar 1.7g +Protein 11g +Salt 4.6g + +Banana +Energy 89kcal +Carbs 22.84g +Sugar 12.23g +Fiber 2.6g +Fat 0.33g +Protein 1.09g + +Oil +Energy 828kcal +Fat 92g +SaturatedFat 7g +MonosaturatedFat 57g +PolysaturatedFat 28g + +Egg +Energy 155kcal +Carbs 1.12g +Fat 10.6g +Protein 12.6g + +Milk +Energy 64kcal +Fat 3.5g +SaturatedFat 2.3g +Protein 3.2g +Salt 0.1g + +BellPepper +Energy 31kcal +Protein 1g +Carbs 6g +Sugar 4.2g +Fiber 2.1g +Fat 0.3g + +Flour +Energy 349kcal +Fat 1.4g +SaturatedFat 0.3g +Carbs 71.5g +Sugar 1.7g +Fiber 2.4g +Protein 11.4g +Salt 0.01g + +Salt +Energy 0kcal +Salt 100g + +Cheese +Energy 329kcal +Fat 24g +SaturatedFat 14g +Protein 27g +Salt 1.5g + +Potato +Energy 68kcal +Fat 0.2g +Carbs 13.3g +Protein 1.6g +Fiber 0.8g + +SweetPotato +Energy 86kcal +Carbs 20g +Fiber 3g +Sugar 4.2g +Protein 1.6g + +Salad +Energy 10kcal +Fat 0.2g +SaturatedFat 0g +Carbs 1g +Sugar 0.5g +Protein 1.1g + +SaladDressing +Energy 259kcal +Fat 22.3g +SaturatedFat 1.5g +Carbs 14g +Sugar 10.8g +Protein 0.4g +Salt 0.99g + +PeasCornPepper +Energy 85kcal +Fat 0.7g +SaturatedFat 0.2g +Carbs 12g +Sugar 2.4g +Fiber 5.5g +Protein 4.9g +Salt 0.07g + +Muesli +Energy 391kcal +Fat 10.9g +SaturatedFat 3.9g +Carbs 61.9g +Sugar 26.7g +Fiber 6g +Protein 8.4g +Salt 0.08g + +Margarine +Energy 630kcal +Fat 70g +SaturatedFat 20g +UnsaturatedFat 35g + +PickleSlices +Energy 54kcal +Sugar 12.1g +Salt 1g + +Ketchup +Energy 102kcal +Carbs 23.2g +Sugar 22.8g +Protein 1.2g +Salt 1.8g + +WhiteBread +Energy 253kcal +Fat 2.5g +SaturatedFat 0.3g +Carbs 45g +Sugar 1.1g +Fiber 6.1g +Protein 9.4g +Salt 1.1g + +DarkBread +Energy 242kcal +Fat 1.3g +SaturatedFat 0.2g +Carbs 43.6g +Sugar 1.4g +Fiber 11.7g +Protein 8.2g +Salt 1.1g + +KauraTyynyt +Energy 254kcal +Fat 4.1g +SaturatedFat 0.5g +Carbs 39g +Sugar 0.8g +Fiber 6.6g +Protein 12g +Salt 1.1g + +BiscuitRings +Energy 541kcal +Fat 30.1g +SaturatedFat 14.8g +Carbs 61.8g +Sugar 23.1g +Protein 4.6g +Salt 0.48g + +SobaChili +Energy 218kcal +Fat 9.3g +SaturatedFat 4.4g +Carbs 27.4g +Sugar 6g +Protein 4.9g +Salt 2.3g + +CocaCola +Energy 42kcal +Carbs 10.6g +Sugar 10.6g + +Pasta +Energy 348kcal +Fat 1.7g +SaturatedFat 0.4g +Carbs 67g +Sugar 2.5g +Fiber 4g +Protein 13g + +SaskiaPeach +Energy 16kcal +Sugar 4g + +GelatelliVeganIceCream +Energy 342kcal +Fat 21.3g +SaturatedFat 16g +Carbs 34.3g +Sugar 24.2g +Protein 2.3g + +BrownRice +Energy 371kcal +Fat 2g +SaturatedFat 0.5g +Carbs 77g +Fiber 8.7g +Protein 7.1g + +SojaRouha +Energy 77kcal +Carbs 6.2g +Sugar 3.15g +Protein 12.21g +Salt 1.34g + +MonsterEnergy +Energy 47kcal +Sugar 11g + +MousseCherry +Energy 535kcal +Fat 36.4g +SaturatedFat 21.2g +Carbs 41.4g +Sugar 31.4g +Protein 6.5g + +FoodCream +Energy 161kcal +Fat 15g +SaturatedFat 10g +Carbs 4.7g +Sugar 3.7g + +Honey +Energy 64kcal +Carbs 17g +Sugar 17g + +Coffee +Energy 0kcal + +Oatmeal +Energy 68kcal +Fat 1.4g +Carbs 12g +Sugar 0.5g +Fiber 1.7g +Protein 2.4g + +VahvlitortTallinn +Energy 505kcal +Fat 51g +Carbs 40g +Sugar 25g +Protein 6g + +TaffelJuustoSnaks +Energy 550kcal +Fat 33g +SaturatedFat 6.2g +Carbs 51g +Sugar 3.6g +Protein 10g +Salt 1.8g + +FakeChicken +Energy 142kcal +Fat 5g +SaturatedFat 0.5g +Carbs 11.3g +Sugar 1.57g +Protein 13.14g +Salt 0.39g + +SourCream +Energy 139kcal +Fat 12g +SaturatedFat 6.7g +Carbs 4g +Sugar 4g +Protein 2.8g +Salt 0.1g + +WhiteBeansTomatoSauce +Energy 105kcal +Protein 4g +Carbs 18g +Sugar 2g + +CherryTomatoes +Energy 18kcal +Carbs 3.92g +Sugar 2.62g +Fiber 1.2g +Protein 0.88g +Fat 0.2g + +BerryMustikaVaarika +Energy 85kcal +Carbs 13g +Sugar 7.2g +Fiber 4.7g +Protein 0.95g + +VanilliIceCream +Energy 160kcal +Fat 6.3g +SaturatedFat 4.1g +Carbs 22.5g +Sugar 19.9g +Protein 3.2g +Salt 0.12g + +Cocoa +Energy 373kcal +Fat 2.9g +SaturatedFat 1.5g +Carbs 78.6g +Sugar 76.6g +Protein 4.8g +Salt 0.31g + +Sugar +Energy 400kcal +Carbs 100g +Sugar 100g + +KeishaCandy +Energy 553kcal +Fat 35g +SaturatedFat 18g +Carbs 47g +Sugar 45g +Protein 8.1g +Salt 0.13g + +ProteinSpaghetti +Energy 350kcal +Fat 2.5g +SaturatedFat 0.6g +Carbs 66g +Sugar 3.7g +Fiber 7.5g +Protein 12g + +PastaSauce +Energy 61kcal +Fat 1.9g +SaturatedFat 0.2g +Carbs 9.2g +Sugar 5.7g +Protein 1.3g +Salt 1.27g + +--- + +Omlette +BellPepper 50g +Cheese 25g +Egg 180g +Flour 25g +Milk 80g +Oil 25g +Salt 2g + +MashedPotato +Margarine 40g +Milk 180g +Potato 1000g +TOTAL 1300g + +Blov +BrownRice 600g +Ketchup 250g +Oil 50g +SojaRouha 300g +PeasCornPepper 225g +TOTAL 2460g + +RoastedVeggies +Oil 100g +Potato 1000g +SweetPotato 450g + +MilkSoup +Margarine 30g +Milk 500g +Oil 25g +Pasta 350g +Sugar 10g +TOTAL 1315 + +Pancake +Egg 120g +Milk 600g +Oil 50g +Sugar 12g +Flour 300g + +CreamPotatoes +Cheese 170g +FoodCream 450g +Oil 50g +Potato 1500g + +FakeChickenVeggies +FakeChicken 250g +Oil 50g +PeasCornPepper 225g + +OmletteWithoutMilk +Cheese 25g +Egg 180g +Flour 25g +Milk 80g +Oil 25g + +ProteinSpaghettiBolognese +ProteinSpaghetti 500g +PastaSauce 500g +TOTAL 1640g diff --git a/godword b/godword new file mode 100644 index 0000000..9496e14 --- /dev/null +++ b/godword @@ -0,0 +1,1000 @@ +a +ability +able +about +above +accept +according +account +across +act +action +activity +actually +add +address +administration +admit +adult +affect +after +again +against +age +agency +agent +ago +agree +agreement +ahead +air +all +allow +almost +alone +along +already +also +although +always +American +among +amount +analysis +and +animal +another +answer +any +anyone +anything +appear +apply +approach +area +argue +arm +around +arrive +art +article +artist +as +ask +assume +at +attack +attention +attorney +audience +author +authority +available +avoid +away +baby +back +bad +bag +ball +bank +bar +base +be +beat +beautiful +because +become +bed +before +begin +behavior +behind +believe +benefit +best +better +between +beyond +big +bill +billion +bit +black +blood +blue +board +body +book +born +both +box +boy +break +bring +brother +budget +build +building +business +but +buy +by +call +camera +campaign +can +cancer +candidate +capital +car +card +care +career +carry +case +catch +cause +cell +center +central +century +certain +certainly +chair +challenge +chance +change +character +charge +check +child +choice +choose +church +citizen +city +civil +claim +class +clear +clearly +close +coach +cold +collection +college +color +come +commercial +common +community +company +compare +computer +concern +condition +conference +Congress +consider +consumer +contain +continue +control +cost +could +country +couple +course +court +cover +create +crime +cultural +culture +cup +current +customer +cut +dark +data +daughter +day +dead +deal +death +debate +decade +decide +decision +deep +defense +degree +Democrat +democratic +describe +design +despite +detail +determine +develop +development +die +difference +different +difficult +dinner +direction +director +discover +discuss +discussion +disease +do +doctor +dog +door +down +draw +dream +drive +drop +drug +during +each +early +east +easy +eat +economic +economy +edge +education +effect +effort +eight +either +election +else +employee +end +energy +enjoy +enough +enter +entire +environment +environmental +especially +establish +even +evening +event +ever +every +everybody +everyone +everything +evidence +exactly +example +executive +exist +expect +experience +expert +explain +eye +face +fact +factor +fail +fall +family +far +fast +father +fear +federal +feel +feeling +few +field +fight +figure +fill +film +final +finally +financial +find +fine +finger +finish +fire +firm +first +fish +five +floor +fly +focus +follow +food +foot +for +force +foreign +forget +form +former +forward +four +free +friend +from +front +full +fund +future +game +garden +gas +general +generation +get +girl +give +glass +go +goal +good +government +great +green +ground +group +grow +growth +guess +gun +guy +hair +half +hand +hang +happen +happy +hard +have +he +head +health +hear +heart +heat +heavy +help +her +here +herself +high +him +himself +his +history +hit +hold +home +hope +hospital +hot +hotel +hour +house +how +however +huge +human +hundred +husband +I +idea +identify +if +image +imagine +impact +important +improve +in +include +including +increase +indeed +indicate +individual +industry +information +inside +instead +institution +interest +interesting +international +interview +into +investment +involve +issue +it +item +its +itself +job +join +just +keep +key +kid +kill +kind +kitchen +know +knowledge +land +language +large +last +late +later +laugh +law +lawyer +lay +lead +leader +learn +least +leave +left +leg +legal +less +let +letter +level +lie +life +light +like +likely +line +list +listen +little +live +local +long +look +lose +loss +lot +love +low +machine +magazine +main +maintain +major +majority +make +man +manage +management +manager +many +market +marriage +material +matter +may +maybe +me +mean +measure +media +medical +meet +meeting +member +memory +mention +message +method +middle +might +military +million +mind +minute +miss +mission +model +modern +moment +money +month +more +morning +most +mother +mouth +move +movement +movie +Mr +Mrs +much +music +must +my +myself +name +nation +national +natural +nature +near +nearly +necessary +need +network +never +new +news +newspaper +next +nice +night +no +none +nor +north +not +note +nothing +notice +now +n't +number +occur +of +off +offer +office +officer +official +often +oh +oil +ok +old +on +once +one +only +onto +open +operation +opportunity +option +or +order +organization +other +others +our +out +outside +over +own +owner +page +pain +painting +paper +parent +part +participant +particular +particularly +partner +party +pass +past +patient +pattern +pay +peace +people +per +perform +performance +perhaps +period +person +personal +phone +physical +pick +picture +piece +place +plan +plant +play +player +PM +point +police +policy +political +politics +poor +popular +population +position +positive +possible +power +practice +prepare +present +president +pressure +pretty +prevent +price +private +probably +problem +process +produce +product +production +professional +professor +program +project +property +protect +prove +provide +public +pull +purpose +push +put +quality +question +quickly +quite +race +radio +raise +range +rate +rather +reach +read +ready +real +reality +realize +really +reason +receive +recent +recently +recognize +record +red +reduce +reflect +region +relate +relationship +religious +remain +remember +remove +report +represent +Republican +require +research +resource +respond +response +responsibility +rest +result +return +reveal +rich +right +rise +risk +road +rock +role +room +rule +run +safe +same +save +say +scene +school +science +scientist +score +sea +season +seat +second +section +security +see +seek +seem +sell +send +senior +sense +series +serious +serve +service +set +seven +several +sex +sexual +shake +share +she +shoot +short +shot +should +shoulder +show +side +sign +significant +similar +simple +simply +since +sing +single +sister +sit +site +situation +six +size +skill +skin +small +smile +so +social +society +soldier +some +somebody +someone +something +sometimes +son +song +soon +sort +sound +source +south +southern +space +speak +special +specific +speech +spend +sport +spring +staff +stage +stand +standard +star +start +state +statement +station +stay +step +still +stock +stop +store +story +strategy +street +strong +structure +student +study +stuff +style +subject +success +successful +such +suddenly +suffer +suggest +summer +support +sure +surface +system +table +take +talk +task +tax +teach +teacher +team +technology +television +tell +ten +tend +term +test +than +thank +that +the +their +them +themselves +then +theory +there +these +they +thing +think +third +this +those +though +thought +thousand +threat +three +through +throughout +throw +thus +time +to +today +together +tonight +too +top +total +tough +toward +town +trade +traditional +training +travel +treat +treatment +tree +trial +trip +trouble +true +truth +try +turn +TV +two +type +under +understand +unit +until +up +upon +us +use +usually +value +various +very +victim +view +violence +visit +voice +vote +wait +walk +wall +want +war +watch +water +way +we +weapon +wear +week +weight +well +west +western +what +whatever +when +where +whether +which +while +white +who +whole +whom +whose +why +wide +wife +will +win +wind +window +wish +with +within +without +woman +wonder +word +work +worker +world +worry +would +write +writer +wrong +yard +yeah +year +yes +yet +you +young +your +yourself diff --git a/habits b/habits new file mode 100644 index 0000000..fb56c5a --- /dev/null +++ b/habits @@ -0,0 +1,3 @@ +take vitamins +weigh yourself +exercise diff --git a/open-journal.py b/open-journal.py new file mode 100644 index 0000000..a55ad44 --- /dev/null +++ b/open-journal.py @@ -0,0 +1,42 @@ +from subprocess import run, Popen, DEVNULL +from datetime import datetime +from pathlib import Path +import random +import sys + +current_date = datetime.now().strftime('%Y-%m-%d') +current_time = datetime.now().strftime('%H:%M:%S') + +journal_path = Path.home() / 'workspace' / 'journal' + +target_page = journal_path / f'{current_date}.md' + +script_path = Path(__file__).parent + +habits = '\n'.join([f'[-] {x}' + for x in (script_path / 'habits').read_text().strip().split('\n')]) + +words = (script_path / 'godword').read_text().strip().split('\n') +godword = '\n'.join(' '.join(random.choice(words) + for a in range(10)) for _ in range(2)) + +if not target_page.exists(): + Popen( + ['bash', str(script_path / 'backup-script.sh'), current_date+'.zip'], + cwd=str(journal_path), stdout=DEVNULL, stderr=DEVNULL + ) + + target_page.write_text(f'''\ +# {target_page.stem} + +Godword: +{godword} + +Habits: +{habits} +''') + +with open(target_page, 'a') as fp: + fp.write(f'\n{current_date} {current_time} ') + +run(['nvim', str(target_page), '+'])