jsled / brew-journal

homebrew journaling

This URL has Read+Write access

brew-journal / TODO
100644 569 lines (505 sloc) 19.704 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
-*- org -*-
* Concepts
** Future Steps
*** Notes
Future steps are used a couple of ways:
- to schedule out a whole brew session, with rough times, &c.
- to schedule transition points in a fermentation session
  - to establish calendar/task/reminder entries
 
 
When operating with a mix of future and realized steps; let's assume a
time-stamped mix of future (f_) and real (r_) events:
 
   [f_0, f_5, f_10, f_15] | 4 future steps
-> [r_1, f_5, f_10, f_15] | realize the first step, about the right time
-> [r_1, r_12, f_10, f_15] | realize the second step *after* the future 3rd step
 
 
At this point, it seems that next_step is f_10, but with its time adjusted to
be equal to the value of r_12.
 
 
Another option is that the second transition "pushes" the timestamps of the
other future steps out by the same amount; thus, that last transition would
instead effect:
 
-> [r_1, r_12, f_17, f_22]
 
This is most useful for a brew session which has its events scheduled at
fixed offsets from each other, where a slip should "cascade" to other
events. E.g., if the mash starts 25 minutes late, it still takes an hour,
and all subsequent steps (the boil, hop additions, &c.) should get
pushed out 25 minutes. However, on a different scale, there is no need for a
cascade. If the mash/pitch happens 1 or 5 or even 12 hours later, I'm
probably still racking next Saturday, and kegging in 3 weeks.
 
What's the threshold?
 
- change steps on the same (literal) day
- change steps within the next N (=6?) hour window
- change steps until the inter-step distance is N (=6?) hours
- change steps while the magnitude of change is a fraction of the inter-step delta.
 
I like the the inter-step distance test, maybe with a threshold of 12 hours
or so.
 
Note that "push" and "pull" are the same, above. We should probably say
"adjust" instead.
 
----------
 
Now, what about intermediate non-Future steps that get inserted, but are part
of the Step-relation depgraph? For instance, we create future steps for
'strike' and 'boil', but then actually record realized steps for the
intervening 'mash' and 'sparge' steps?
 
If the immediately next Future step is in the (multi-level) tree of future
steps possible from the newly-added Step, we're in one of two situations:
 
- the new step is intentionally "splitting" the time the steps were
  allocating.
 
- the new step represents a delay, and the future steps should be pushed out;
  but it's not clear by how much, except if we take some "standard" schedules
  into account, where possible.
 
I don't think it's possible to handle this without being clever, and perhaps
too clever. So, don't.
 
 
Now, if the new Realized step is (topologically and temporally) *after* the
first Future scheduled step, then we have a problem. E.g., we have:
 
    [r_strike, f_mash, r_boil(new)]
 
We have a few options:
 
- ignore the "missed" Future step. Don't consider it as a valid next step.
- Error/force the realization of the missed step.
- silently realize the missed step with its existing timestamp
  - maybe only iff its timestamp "makes sense" given the previous and
    currently-realized steps?
 
Next Steps
----------
 
At any given point, the most recently realized step "suggests" a set of
potential 'next' steps that can be taken. Elements of this set may or may
not align with any temporally-next Future Steps. If they do, then that
Future step should be taken as the Next step, and used in its place, though
this is a function of the user interface to a large degree.
 
"future" vs. future
-------------------
 
What is the essence of "future" steps? They haven't happened, yet.
 
*** Use Cases
***** Historical Entry
 
- entry_date >> date
- dates are sequentially entered
- Step.date is all that matters
- there are never "future" steps
 
***** Immediate Entry
 
- entry_date ~~ date
- items are sequentially entered
- Step.date is all that matters
- "now" used as default for .date, value for .entry_date
- there are never "future" steps
 
***** Forward Planning
 
- entry_date << date
- items are sequentially entered
- Step date is all that matters
 
***** Forward Planning with After-The-Fact Fixup
 
- entry_date << date *and* entry_date > date
 
*** Use Cases redux
 
(basic future steps case)
- in the past, enter future steps; update future steps to "now", sequentially
 
- in the past, enter future steps; in the future, update now-past steps and now-future steps
 
- in the past, enter future steps; in the far-future, update all-now-past steps
 
* Todo
** bugs, misc
*** TODO cascading /recipe/{id}/hops/hops/hops/… in the case of ingredient add failure
*** TODO no way to add a fermentable (e.g., honey) added at flame-out.
*** TODO unable to add "5 g" of apple must for cider recipes (no volume adds for fermentables)
*** TODO dingeema-uncovered None-safety issues
 
- Brew with Recipe
  - Recipe with no name (${brew.recipe.name})
  - Recipe with no Style (${recipe.style.name}
 
- audit all those chained expressions in templates
 
*** TODO no logging on dreamhost, which is annoying
- error logging
- access logging
- activity logging (new recipe, new brew, &c.)
  - do this as a feed, instead
*** TODO user profile should require existing password for password change; use django form validation/cleaning routines
*** TODO to add: Fruit/"Other"
(08:42:34 PM) djensen: I think you need 'Other' for fruit
*** DONE lack of timezone handling
    CLOSED: [2009-09-29 Tue 20:23]
http://code.google.com/p/django-timezones/
http://www.djangosnippets.org/snippets/183/
http://pypi.python.org/pypi/pytz/
 
for egg in lib/*.egg; do export PYTHONPATH=$(pwd)/${egg}:$PYTHONPATH; done;
 
*** DONE to add: Citra hops
    CLOSED: [2009-09-21 Mon 22:28]
(08:39:22 PM) djensen: need to add Citra hops
(08:39:38 PM) djensen: not that I've seen it the home brew shop yet
*** DONE recipes should list/link their authors
    CLOSED: [2009-07-29 Wed 21:05]
*** DONE std.fmt.date.ymdhm should omit the 'hm' if the hour is exactly midnight.
    CLOSED: [2009-03-30 Mon 22:48]
*** DONE "shopping list" shows up for brews with any future steps.
    CLOSED: [2009-03-30 Mon 22:13]
*** DONE need for some sort of "other fruit", so adding straight oranges doesn't need to be listed as adding "orange zest"
    CLOSED: [2009-03-30 Mon 20:53]
*** DONE dreamhost'ed admin/ site media serving.
    CLOSED: [2009-03-18 Wed 21:52]
*** DONE move to django 1.0
    CLOSED: [2008-12-26 Fri]
See http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges
*** DONE move to a defined/modern genshi release?
    CLOSED: [2008-12-26 Fri]
*** DONE login/new-account failures don't have standard form behavior; wrong password has no feedback
    CLOSED: [2008-12-26 Fri]
*** DONE 500/404 page handling
    CLOSED: [2008-12-17 Wed 21:48]
Mostly on public/production site.
 
http://docs.djangoproject.com/en/dev/howto/error-reporting/#howto-error-reporting
(seems to be in 1.0 only?)
 
http://docs.djangoproject.com/en/dev/topics/http/views/#returning-errors
 
urlconf:
handler404 = 'app.views.custom_404'
handler500 = 'app.views.custom_500'
*** DONE brew step volume only allows one sigdigit, making '3.75 g' not acceptable. :(
    CLOSED: [2008-12-17 Wed 20:41]
*** DONE adding hop without boil time -> 500?
    CLOSED: [2008-08-31 Sun 18:32]
*** DONE /user/{user}/brew/{id}?type={type} doesn't work.
*** DONE with validation error on step addition, the form is correctly populated, but collapsed
** weirdness
*** when journaling after racking to secondary, is it entered as primary-ferm or secondary-ferm?
Maybe Steps should strictly be "transitions" or "activtives", not just states
of being.
** shitty things
*** recipe_new() is a bit too busy for comfort
*** toggled <div> py:attrs style form mumble
** tests
*** TODO front-to-back-script
- create new user, fail
- correct mistake, success
- login, fail
- login success
- create recipe
- create brew from recipe
- update brew steps
  - mostly in order
  - go back and correct some mistakes
- setup future brew
- advance clock forward
- check "future" steps
- advance clock forward
- transition future step to current step
- add steps "in real time"
- update old brew
  [- the idea here is a combined brew-day where the carboy for brew A is
     being vacated for the current brew B]
- advance clock forward
- update brew
*** recipe editing
**** TODO add grain: happy, sad
***** sad
- absurd units
  - missing values
  - wrong values
- OOB units
**** TODO add hop: happy, sad
**** TODO add yeast: happy, sad
**** TODO add adjunct: happy, sad
*** brew editing
**** TODO schedule steps, test 'next step' computations
**** TODO future steps:
- check dashboard reflects changes appropriately
- check future steps
  - changing future date
  - changing future date -> "now"
  - changing future date -> "a few seconds ago"
  - changing future date -> way in the past
  - "realize" a future dated step with other future dated steps
    - follow-on effect on "next step" logic
**** TODO changes to steps, impact
*** creating a brew impacts
**** TODO shopping list
** major
*** calendaring
**** encourage future steps visually … how?
***** when adding a 'pitch' step, prompt to add future steps for 'ferm1' and 'ferm2'
***** when adding 'starter', prompt for 'strike-water', 'ferm1', 'ferm2', &c.…
**** if a "future" action gets updated in time, what happens to other future actions after it?
***** nothing
***** they're moved forward in time by the same delta-T they had before the update (nifty, but maybe wrong.)
****** then make it some policy of the type of future step? Ferm vs. keg vs. …?
***** make them all immediately after the new step.
**** "standard" ferm schedules?
***** 1 wk primary, 2 wk secondary
***** style-based?
**** DONE next step types += first future step for update
**** DONE add step form takes into account first future step
**** DONE add "future" sub-body to table
***** visually/functionally distinct how?
*** shopping list
**** TODO better shopping list
***** TODO [#N] collapse ingredients (hops esp.) in same brew
***** TODO [#N] sum ingredient amounts
***** TODO [#S] better ordering
***** table display?
***** TODO [#W] probably actually want to model "need to buy" or "don't need to buy" states.
**** http://beeradvocate.com/forum/read/1102362#1102497
*** computed values
**** efficiency
***** DONE [#N] need: grains + gravity readings + volume reading
***** TODO [#N] efficiency tracker (based on 'system'?)
***** TODO [#S] "?mumble?" vs. "brewhouse" efficiency
**** alc/vol
***** TODO [#S] estimated: fn(grains, efficiency, yeast.attenuation)
***** DONE [#N] actual: FG - OG
**** OG
***** DONE [#S] estimated: fn(grains, efficiency)
      CLOSED: [2009-09-21 Mon 22:39]
***** actual: gravity at 'pitch'
**** FG
***** TODO [#S] estimated: fn(grains, est_OG, yeast.attenuation)
***** actual: latest post-'pitch' gravity reading
**** IBU
***** DONE [#W] estimated: fn(hop schedule)
      CLOSED: [2009-09-21 Mon 22:39]
***** actual: none
**** SRM
***** DONE [#W] estimated: fn(grains)
      CLOSED: [2009-09-21 Mon 22:39]
***** TODO [#W] actual: none (manual entry)
**** BU:GU
**** timing
***** brew day
***** fermentation
**** mash chart/schedule
***** planned
***** actual
*** achievements
**** meta
***** user must be able to turn this off, but defaults to on
***** user must be able to decline [?]
****** "first keg", but we've been kegging for a while, and are working backwards in entry.
***** future brews should show user what achievements will be earned.
**** achievements
***** firsts/technique
****** "First Brew! Welcome! :)"
****** "First Brew in ${style}"
****** First {Ale,Lager,Common,Brett,Cider,Mead,Bragot}
****** First {1.060,70,80,90,100,} OG brew
****** first {single-infusion,decoction} mash
****** mash-out with your bad self!
****** first {cont.sparge, batch sparge, oat sparge, >25% wheat sparge}
****** first dry-hopping
****** first fruit
****** first smoke
****** first oak/wood
***** journeyman
****** x{50|100} gallons brewed
****** {10,25,50,100,150,…} brews complete
****** Brewing for {1,2,3,…} years.
****** self-roasted malt
***** perfection/technique
****** {75,80,85,90,95,>95} efficiency
****** competition awards
****** BJCP scoring
***** height
****** {6,7,9,10,11,12,13,15} abv
****** "Hop Bomb!": >100 IBU brewed
****** 60, 90, 120 minute boil
***** random
****** "Session ": 3-4% abv
****** "most novel ingredient"
****** selection of weird ingredients
******* honey
******* grains of paradise
******* cinnamon
****** "Weird!"
******* ale grain profile, lager yeast
******* ? what else...?
***** series
****** 5 >{70,80,90}% efficiency in a row.
****** >{1,2,5} gal/week brewed for this year.
***** site-wide
****** longest {{primary,second} fermentation,conditioning}
****** these need to be "rescinded".
*** form validation
**** visual (see Yahoo patterns)
**** client-side validation
**** DONE actual submission logic
*** visual design
**** logo/identity
***** typeface-based
***** beer mug ring/stain
***** graph paper = journal
**** how wide are tables normally? 90%? 80%?
**** steal "Actions" table from <https://launchpad.net/bzr-rebase>
***** recipe actions?
***** brew actions?
**** brew next steps list: only show most likely, hide rest behind "(more…)"
*** recipe browse/search
**** browsing
**** searching
***** structured, by ingredient/style/&c.
*** user addition of recipe components
*** alerts
**** "keg now!"
**** "rack this week?"
*** comments
**** OpenID support
*** widget-style embedding
**** brew overview
**** upcoming brews
*** recipe input features
**** DONE regular browser
**** clone from other URL
***** use the following style of the Google Reader "note this URL" bookmarklet for on-the-web recipe induction:
 
       javascript:
       var b=document.body;
       var GR________bookmarklet_domain='http://www.google.com';
       if(b&&!document.xmlVersion){
       void(z=document.createElement('script'));
       void(z.src='http://www.google.com/reader/ui/link-bookmarklet.js');
       void(b.appendChild(z));
       }
       else{}
 
**** star from other URL
**** parse block of text
*** keyboard navigation
**** j/k should navigate between displayed table rows, jumping between tables.
**** 'g {location}' paradigm?
**** '?' overlay
*** printable journal pages
**** long-term storage/archiving
*** import/export
*** add 'equipment'/'rig'
** minor
*** DONE better integration of genshi
    CLOSED: [2009-09-21 Mon 23:00]
see http://www.djangosnippets.org/snippets/97/
*** TODO compute strike/sparge water volume from recipe, mash type, desired water/grist ratio
*** TODO /recipe/ shouldn't 404.
*** TODO add time counter for some steps (primary/secondary fermentation)
*** TODO some sort of markdown/wikiformatting/CRLF-><br/> for notes
*** TODO be able to (re-)associate a recipe with a Brew
*** TODO use django `get_absolute_url`, `permalink` methods
*** focus improvements
**** TODO profile form after new user creation
**** /user/{user}
***** TODO next action
**** /recipe/{id}/{text}
***** DONE top actions
***** DONE edit details -> :input:first
***** DONE add -> first form elt
***** TODO GET after POST of {grain, hop, …} -> [add] button on same form.
*** /recipe/{id}
**** TODO show all brew instances of recipe
***** by: authoring user, viewing user, all users
**** DONE add "clone", "brew" ui options
*** /user/{user}/brew/{id}/ should have brew- or recipe-name in URL
*** starring recipes
**** TODO make AJAX-y
*** recipe editing
**** pre-select units fields
***** TODO same as the last-used units in the item-class
***** TODO based on user prefs
**** TODO Should have a place for boil-length, expected efficiency
- noticed while entering saison automné recipe/brew details from notes … was
  the 90 minute boil intentional or a side effect of the brew-day?
- What other things should be part of the recipe?
*** improve user profile
**** TODO preferences
***** DONE default recipe type (extract, partial-mash, all-grain)
***** TODO default units (english/metric)
**** TODO identity links in profile to other fora
***** beeradvocate
***** tastybrew
***** ?others?
***** other web urls
*** step addition
**** de-emphasise unrelated entry fields in any given step-type.
**** better form layout, anyways
*** google crawling
**** is there anything private?
**** TODO add reasonable robots.txt
*** model cleanups
**** Brew
***** add brew name?
***** Notes
****** add differentiated, timestampped, author'd notes
******* this approaches Comments, where Brew.brewer = Comment.author is a bit special.
**** Hops
***** TODO type: {bittering, flavor, aroma}
***** TODO class: {german, american, british, …}
***** TODO notes: "floral, citrusy, &c."
**** Adjunct
***** TODO some way for an adjunct to be not in the boil (e.g., "secondary", "keg", &c.)
*** signup
**** TODO username character restrictions, confirmation
**** TODO existing username check?
**** TODO naughtyness check?
**** TODO verification
*** better auth
**** OpenID (maybe for comments only?)
**** verification
**** forgot password
**** forgot username
*** TODO user-friendly field values ("gl" -> "gallon(s)")
*** add data
**** adjuncts
**** more yeasts
***** generic yeasts
***** dry yeasts (Safale, Windsor, &c.)
***** Wyeast: wine, distiller, cider, mead, sake, VSS archives
***** White Labs
*** TODO paginated views
**** historical brews
**** all authored recipes
*** system logging
**** per request/timing accesslog (add to page footer, too)
**** general system: startup, shutdown, resource util, &c.
**** auth-related
*** refactor rendering
**** starred-recipe table on /user/jsled/ and /user/jsled/recipe/
*** auth
**** general 'edit-controls-for-authorized-editor'
***** /user/{user}/ -> starred, recipe actions, controls
**** generic 'auth-user-must-match-object-owner' during POST handling
**** superuser support all around
*** user interface
**** auto-complete text fields for style, grain, hops...
**** step addition
***** if the brew knows the mash grains, then it can compute strike and sparge water volumes, absorption, &c.
*** TwoLevelSelectWidget
**** cleanup, review
**** use for
***** TODO [#S] hops
****** TODO [#S] extend Hops model for regional, functional groupings
***** TODO [#N] adjuncts
*** step type constraint
**** DONE break out step options based on current state of brew instance
**** better step_type modeling dervied to options,constraints,labels,&c.
*** deletion
**** recipe
**** brew
* Colors
 
Base green: rgb(34, 140, 34) (#228C22)
 
<http://wellstyled.com/tools/colorscheme2/index-en.html#>, triad:
 
green: #228C22
dark: #186218
light: #CFFFCF
bright: #9EFF9E
 
purple: #8C2272
dark: #62184F
light: #FFCFF3
bright: #FF9EE7
 
brown: #8C4C22
dark: #623518
light: #FFE2CF
bright: #FFC59E
 
 
<http://www.easyrgb.com/index.php?X=HARM#Result>:
nice blue/purple/grey: #6977B0
nice soft green: #75B368
 
* Resources
** http://www.beersmith.com/GrainList.htm
** Testing
*** http://ericholscher.com/blog/2008/aug/14/using-mock-objects-django-and-python-testing/ - datetime.datetime monkey patching
*** http://www.voidspace.org.uk/python/weblog/arch_d7_2008_07_26.shtml - module monkey patching as decorator
* git notes
 
git fetch
git rebase remotes/origin/master
 
* Thanks, Google Cache
 
This is for the … weizen?
 
date step volume temp gravity (corrected) notes
2008-06-13 00:00 make starter 800 ml
2008-06-21 12:50 dough-in 5 gl 151 f overshot mash temp, needed more water to cool.
2008-06-21 13:20 mash
2008-06-21 13:50 mash 151 f
2008-06-21 13:51 1st runnings, start 1.064
2008-06-21 14:05 1st runnings, end 1.054
2008-06-21 14:20 2nd runnings, start 1.031
2008-06-21 16:15 pitch 5 gl 1.037
2008-06-29 13:30 kegged 1.009
2008-06-21 12:35 strike water 4.5 gl 170 f