A Django site.
September 26, 2008

Hans Fugal
no nic
The Fugue :
» Bread PDF Update

I've updated my bread/sourdough PDF to reflect the recipe and methods I have settled on.

The bread recipe didn't really change, though I adjusted a few minor details in wording, etc. The sourdough pancakes recipe is completely new—the one from Joe Pastry which is so much better than the one I came up with. The biscuit recipe is the old biscuit recipe from the old sourdough cards that my family got with our start. I don't know if that source has a name or author, but I do have scanned images at http://hans.fugal.net/sourdough/. The consensus of all who eat these biscuits is that they must be served at Thanksgiving dinner in Heaven.

biscuits1 biscuits2

September 19, 2008

Hans Fugal
no nic
The Fugue :
» IMMS

So Apple added this Genius thing to iTunes recently. Not being the type to get excited about new iPod styles, it looks like the most interesting thing they could come up with this year. I gave it a try. I am not impressed.

I think it's because I've been spoiled. 5 years ago I was using what I still consider to be the peak of intelligent listening software, IMMS. Genius isn't half as cool as IMMS was then, and while IMMS hasn't made any quantum leaps in coolness, quite a few rough edges have been rounded off in the meantime.

I've been living in a sort of IMMS drought the past couple of years, since I switched to using a laptop primarily. Namely, an Apple laptop. This Genius release spurred me on to rectify that situation. If the best Apple could do was generate a 25-song playlist based on statistics gathered from other people the hopes of someone else hacking up an iTunes plugin to do IMMS or something like it dwindled to obscurity.

The bane of IMMS is, ironically, its most compelling feature. IMMS is cool because you don't have to do anything. It pays attention to your listening habits, and analyzes the audio, and makes intelligent decisions for you when you turn on random. 4 years ago I would show up to work and be in a Depeche Mode mood, so I'd manually queue up a Depeche Mode song or two and the whole day I'd be treated to complementary music. If the occasional happy song slipped through, I just skipped it and IMMS took the hint. Don't underestimate the amazing wow factor of a computer apparently reading your mind.

But this focus on simple non-obtrusive UI has been its biggest technical struggle. Media players are now a dime a dozen, and few of them have the plugin and UI sophistication to support IMMS' modus operandi. IMMS was developed originally as a plugin for XMMS and even then ugly workaround hacks were required. Then someone wrote a queue control patch for XMMS, and if you patched your XMMS you were in heaven. Oh, did I mention that still almost no other media players even have queue functionality, let alone let the plugins control the queue? Then when you consider the set of media players usable on OS X the situation gets laughable.

Somewhere in the middle MPD came along. It fit my situation well because the speakers over on the desktop were a lot nicer than the ones in my laptop. But queues it has not and nobody seems to care. Von bravely came up with an IMMS hack for MPD, but it was too hacky for me—too much like the old XMMS days before the queue control patch (incidentally, queue control is part of XMMS proper now as of version 1.2.11).

So I suffered along with manual or truly random music listening. Until now.

Recently I looked into this again for the desktop, and I was delighted to discover that one of the many XMMS descendants has finally solved the XMMS bitrot without throwing the baby out with the bathwater. Audacious is as cool as XMMS ever was and as modern as your favorite modern player (unless you measure modern by klunky iTunes-like screen-wasting music browsers). What's more, the imms plugin for it is right there in the Ubuntu repository. Just apt-get install imms-audacious and enable the plugin and you're off and running. So I set it up and… didn't use it. As in, we rarely listen to music on the desktop because nobody really sits there for very long. So finally earlier this week I hammered out a simple remote control using Audacious' dbus interface. That's another post, once I knock off a few other TODO points.

Feeling on a roll and feeling left out when at school, I decided to get an IMMS solution on my laptop, running OS X Leopard (10.5.4). I'll spare you the agonizing play-by-play and give you the shortest path to success: install Audacious and then IMMS. Actually the really shortest path is to install XMMS and then IMMS, because XMMS is in MacPorts. But it's the old version of XMMS without queue control, and doesn't have CoreAudio support (you have to use the JACK output plugin) so I don't recommend that.

To install Audacious, install its dependencies (mostly using MacPorts), then build it and its plugins. Installing its dependencies is the hardest part because it's difficult to locate libmcs and libmowgli (they're not where the README says they are, and Google is less than helpful). I just ended up stealing the *.orig.tar.gz files from the Ubuntu packages (apt-get source -d libmcs1 libmowgli). There is one patch you need for the plugins.

 src/CoreAudio/audio.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

Index: audacious-plugins-1.5.1/src/CoreAudio/audio.c
===================================================================
--- audacious-plugins-1.5.1.orig/src/CoreAudio/audio.c  2008-09-19 12:08:01.000000000 -0600
+++ audacious-plugins-1.5.1/src/CoreAudio/audio.c   2008-09-19 12:10:28.000000000 -0600
@@ -326,7 +326,12 @@ gint osx_get_output_time(void)
 {
        gint retval;

-        retval = output_time_offset + ((output_total * sample_size * 1000) / output.bps);
+        if (output.bps == 0)
+        {
+            printf("Avoiding divide by zero in osx_get_output_time()\n");
+            retval = 0;
+        } else
+            retval = output_time_offset + ((output_total * sample_size * 1000) / output.bps);
        retval = (int)((float)retval / user_pitch);

        //printf("osx_get_output_time(): time is %d\n",retval);

Next you need to install IMMS. This is a bit more involved, but should be straightforward with these patches. I'll put them here and talk about each in turn.

First, a missing include for mkdir()

 immsd/immsd.cc |    1 +
 1 file changed, 1 insertion(+)

Index: imms-3.1.0-rc4/immsd/immsd.cc
===================================================================
--- imms-3.1.0-rc4.orig/immsd/immsd.cc  2008-03-02 18:54:06.000000000 -0700
+++ imms-3.1.0-rc4/immsd/immsd.cc   2008-09-19 08:05:58.000000000 -0600
@@ -2,6 +2,7 @@
 #include <errno.h>
 #include <signal.h>
 #include <unistd.h>
+#include <sys/stat.h>

 #include <iostream>
 #include <sstream>

Then, a workaround due to OS X not having an initstate_r() (which I incidentally couldn't find in the current Linux manpages on Ubuntu or Debian either). This patch may not apply cleanly by itself, you may need to apply your cognitive reasoning.

configure.ac         |    3 +++
immsconf.h           |    3 +++
immsconf.h.in        |    3 +++
immscore/immsutil.cc |    9 +++++++++
4 files changed, 18 insertions(+)

Index: imms-3.1.0-rc4/immscore/immsutil.cc
===================================================================
--- imms-3.1.0-rc4.orig/immscore/immsutil.cc    2008-03-02 18:54:06.000000000 -0700
+++ imms-3.1.0-rc4/immscore/immsutil.cc 2008-09-19 08:13:29.000000000 -0600
@@ -27,6 +27,7 @@ int imms_random(int max)
{
    int rand_num;
    static bool initialized = false;
+#ifndef INITSTATE_BUG
    static struct random_data rand_data;
    static char rand_state[256];
    if (!initialized)
@@ -36,6 +37,14 @@ int imms_random(int max)
        initialized = true;
    }
    random_r(&rand_data, &rand_num);
+#else
+    if (!initialized)
+    {
+        srandom(time(0));
+        initialized = true;
+    }
+    rand_num = random();
+#endif
    double cof = rand_num / (RAND_MAX + 1.0);
    return (int)(max * cof);
}
Index: imms-3.1.0-rc4/configure.ac
===================================================================
--- imms-3.1.0-rc4.orig/configure.ac    2008-03-02 18:54:06.000000000 -0700
+++ imms-3.1.0-rc4/configure.ac 2008-09-19 08:17:58.000000000 -0600
@@ -68,6 +68,9 @@ else
    AC_MSG_RESULT([yes])
fi

+AC_DEFINE(INITSTATE_BUG,, [initstate_r is buggy])
+
+
AC_CHECK_LIB(z, compress,, [with_zlib=no])
AC_CHECK_HEADERS(zlib.h,, [with_zlib=no])
if test "$with_zlib" = "no"; then
Index: imms-3.1.0-rc4/immsconf.h
===================================================================
--- imms-3.1.0-rc4.orig/immsconf.h  2008-09-19 08:05:31.000000000 -0600
+++ imms-3.1.0-rc4/immsconf.h   2008-09-19 08:18:23.000000000 -0600
@@ -121,6 +121,9 @@
/* Define to 1 if you have the <zlib.h> header file. */
#define HAVE_ZLIB_H 1

+/* initstate_r is buggy */
+#define INITSTATE_BUG /**/
+
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "mag@luminal.org"

Index: imms-3.1.0-rc4/immsconf.h.in
===================================================================
--- imms-3.1.0-rc4.orig/immsconf.h.in   2008-09-19 07:48:52.000000000 -0600
+++ imms-3.1.0-rc4/immsconf.h.in    2008-09-19 08:16:32.000000000 -0600
@@ -120,6 +120,9 @@
/* Define to 1 if you have the <zlib.h> header file. */
#undef HAVE_ZLIB_H

+/* initstate_r is buggy */
+#undef INITSTATE_BUG
+
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT

This patch is just so libpcre can be found

build/Makefile |    1 +
1 file changed, 1 insertion(+)

Index: imms-3.1.0-rc4/build/Makefile
===================================================================
--- imms-3.1.0-rc4.orig/build/Makefile  2008-03-02 18:54:06.000000000 -0700
+++ imms-3.1.0-rc4/build/Makefile   2008-09-19 12:25:05.000000000 -0600
@@ -18,6 +18,7 @@ libimmscore.a: $(call objects,../immscor
libmodel.a: $(call objects,../model) svm-similarity-data.o
        $(AR) $(ARFLAGS) $@ $(filter %.o,$^)

+immstool-LIBS=`pcre-config --libs`
immstool: immstool.o libmodel.a libimmscore.a 
training_data: training_data.o libmodel.a libimmscore.a 
train_model: train_model.o libmodel.a libimmscore.a

Linking shared libraries on OS X is so much different from on Linux that there is almost always a need to do a patch something like this.

rules.mk |    5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

Index: imms-3.1.0-rc4/rules.mk
===================================================================
--- imms-3.1.0-rc4.orig/rules.mk    2008-09-19 09:04:13.000000000 -0600
+++ imms-3.1.0-rc4/rules.mk 2008-09-19 12:25:50.000000000 -0600
@@ -14,9 +14,8 @@ link = $(CXX) $(filter-out %.a,$1) $(fil
%.o: %.c; $(call compile, $(CC), $<, $@, $($*-CFLAGS) $(CFLAGS) $($*-CPPFLAGS) $(CPPFLAGS))
%: %.o; $(call link, $^ $($*-OBJ) $(LIBS), $@, $($*-LIBS) $(LDFLAGS))
%.so:
-   $(CXX) $^ $($*-OBJ) $($*-LIBS) $(LIBS) \
-       $(LDFLAGS) \
-            -shared -Wl,-z,defs,-soname,$@ -o $@
+   gcc -flat_namespace -undefined suppress -o $@ -bundle $^ $($*-OBJ) $($*-LIBS) $(LIBS) \
+       $(LDFLAGS) -o $@

%-data.o: %
        $(OBJCOPY) -I binary -O $(OBJCOPYTARGET) -B $(OBJCOPYARCH) --rename-section .data=.rodata,alloc,load,readonly,data,contents $< $@

This final patch fixes IMMS to use the proper interface for audacious (seems like this would have to be done anywhere?)

clients/audacious/audaciousinterface.c |  177 +++++++++++++++++++++++++++++++++
clients/audacious/rules.mk             |    2 
2 files changed, 178 insertions(+), 1 deletion(-)

Index: imms-3.1.0-rc4/clients/audacious/audaciousinterface.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ imms-3.1.0-rc4/clients/audacious/audaciousinterface.c   2008-09-19 15:30:21.000000000 -0600
@@ -0,0 +1,177 @@
+#include <gtk/gtk.h>
+
+#ifdef BMP
+#include <bmp/configdb.h>
+#include <bmp/util.h>
+#include <bmp/plugin.h>
+#elif AUDACIOUS
+#include <audacious/configdb.h>
+#include <audacious/util.h>
+#include <audacious/plugin.h>
+#endif
+#include "immsconf.h"
+#include "cplugin.h"
+
+
+int use_xidle = 1;
+int poll_tag = 0;
+
+GtkWidget *configure_win = NULL, *about_win = NULL, *xidle_button = NULL;
+
+gint poll_func(gpointer unused)
+{
+    imms_poll();
+    return TRUE;
+}
+
+void read_config(void)
+{
+    ConfigDb *cfgfile;
+
+    if ((cfgfile = cfg_db_open()) != NULL)
+    {
+        cfg_db_get_int(cfgfile, "imms", "xidle", &use_xidle);
+        cfg_db_close(cfgfile);
+    }
+}
+
+void init(void)
+{
+    imms_init();
+    read_config();
+    imms_setup(use_xidle);
+    poll_tag = gtk_timeout_add(200, poll_func, NULL);
+}
+
+void cleanup(void)
+{
+    imms_cleanup();
+
+    if (poll_tag)
+        gtk_timeout_remove(poll_tag);
+
+    poll_tag = 0;
+}
+
+void configure_ok_cb(gpointer data)
+{
+    ConfigDb *cfgfile = cfg_db_open();
+
+    use_xidle = !!GTK_TOGGLE_BUTTON(xidle_button)->active;
+
+    cfg_db_set_int(cfgfile, "imms", "xidle", use_xidle);
+    cfg_db_close(cfgfile);
+
+    imms_setup(use_xidle);
+    gtk_widget_destroy(configure_win);
+}  
+
+#define ADD_CONFIG_CHECKBOX(pref, title, label, descr)                          \
+    pref##_frame = gtk_frame_new(title);                                        \
+    gtk_box_pack_start(GTK_BOX(configure_vbox), pref##_frame, FALSE, FALSE, 0); \
+    pref##_vbox = gtk_vbox_new(FALSE, 10);                                      \
+    gtk_container_set_border_width(GTK_CONTAINER(pref##_vbox), 5);              \
+    gtk_container_add(GTK_CONTAINER(pref##_frame), pref##_vbox);                \
+                                                                                \
+    pref##_desc = gtk_label_new(label);                                         \
+                                                                                \
+    gtk_label_set_line_wrap(GTK_LABEL(pref##_desc), TRUE);                      \
+    gtk_label_set_justify(GTK_LABEL(pref##_desc), GTK_JUSTIFY_LEFT);            \
+    gtk_misc_set_alignment(GTK_MISC(pref##_desc), 0, 0.5);                      \
+    gtk_box_pack_start(GTK_BOX(pref##_vbox), pref##_desc, FALSE, FALSE, 0);     \
+    gtk_widget_show(pref##_desc);                                               \
+                                                                                \
+    pref##_hbox = gtk_hbox_new(FALSE, 5);                                       \
+    gtk_box_pack_start(GTK_BOX(pref##_vbox), pref##_hbox, FALSE, FALSE, 0);     \
+                                                                                \
+    pref##_button = gtk_check_button_new_with_label(descr);                     \
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pref##_button), use_##pref); \
+    gtk_box_pack_start(GTK_BOX(pref##_hbox), pref##_button, FALSE, FALSE, 0);   \
+                                                                                \
+    gtk_widget_show(pref##_frame);                                              \
+    gtk_widget_show(pref##_vbox);                                               \
+    gtk_widget_show(pref##_button);                                             \
+    gtk_widget_show(pref##_hbox);
+
+void configure(void)
+{
+    GtkWidget *configure_vbox;
+    GtkWidget *xidle_hbox, *xidle_vbox, *xidle_frame, *xidle_desc; 
+    GtkWidget *configure_bbox, *configure_ok, *configure_cancel;
+
+    if (configure_win)
+        return;
+
+    read_config();
+
+    configure_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+    gtk_signal_connect(GTK_OBJECT(configure_win), "destroy",
+            GTK_SIGNAL_FUNC(gtk_widget_destroyed), &configure_win);
+    gtk_window_set_title(GTK_WINDOW(configure_win), "IMMS Configuration");
+
+    gtk_container_set_border_width(GTK_CONTAINER(configure_win), 10);
+
+    configure_vbox = gtk_vbox_new(FALSE, 10);
+    gtk_container_add(GTK_CONTAINER(configure_win), configure_vbox);
+
+    ADD_CONFIG_CHECKBOX(xidle, "Idleness", 
+#ifdef BMP
+            "Disable this option if you use BEEP on a dedicated machine",
+#elif AUDACIOUS
+            "Disable this option if you use Audacious on a dedicated machine",
+#endif
+            "Use X idleness statistics");
+
+    /* Buttons */
+    configure_bbox = gtk_hbutton_box_new();
+    gtk_button_box_set_layout(GTK_BUTTON_BOX(configure_bbox), GTK_BUTTONBOX_END);
+    gtk_button_box_set_spacing(GTK_BUTTON_BOX(configure_bbox), 5);
+    gtk_box_pack_start(GTK_BOX(configure_vbox), configure_bbox, FALSE, FALSE, 0);
+
+    configure_ok = gtk_button_new_with_label("Ok");
+    gtk_signal_connect(GTK_OBJECT(configure_ok), "clicked",
+            GTK_SIGNAL_FUNC(configure_ok_cb), NULL);
+    GTK_WIDGET_SET_FLAGS(configure_ok, GTK_CAN_DEFAULT);
+    gtk_box_pack_start(GTK_BOX(configure_bbox), configure_ok, TRUE, TRUE, 0);
+    gtk_widget_show(configure_ok);
+    gtk_widget_grab_default(configure_ok);
+
+    configure_cancel = gtk_button_new_with_label("Cancel");
+    gtk_signal_connect_object(GTK_OBJECT(configure_cancel), "clicked",
+            GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(configure_win));
+    GTK_WIDGET_SET_FLAGS(configure_cancel, GTK_CAN_DEFAULT);
+    gtk_box_pack_start(GTK_BOX(configure_bbox), configure_cancel, TRUE, TRUE, 0);
+    gtk_widget_show(configure_cancel);
+    gtk_widget_show(configure_bbox);
+    gtk_widget_show(configure_vbox);
+    gtk_widget_show(configure_win);
+}
+
+void about(void)
+{
+    if (about_win)
+        return;
+
+    about_win =
+#ifdef AUDACIOUS
+        audacious_info_dialog(
+#else
+        xmms_show_message(
+#endif
+            "About IMMS",
+            PACKAGE_STRING "\n\n"
+            "Intelligent Multimedia Management System" "\n\n"
+            "IMMS is an intelligent playlist plug-in for BPM" "\n"
+            "that tracks your listening patterns" "\n"
+            "and dynamically adapts to your taste." "\n\n"
+            "It is incredibly unobtrusive and easy to use" "\n"
+            "as it requires no direct user interaction." "\n\n"
+            "For more information please visit" "\n"
+            "http://www.luminal.org/wiki/index.php/IMMS" "\n\n"
+            "Written by" "\n"
+            "Michael \"mag\" Grigoriev <mag@luminal.org>",
+            "Dismiss", FALSE, NULL, NULL);
+
+    gtk_signal_connect(GTK_OBJECT(about_win), "destroy",
+            GTK_SIGNAL_FUNC(gtk_widget_destroyed), &about_win);
+}
Index: imms-3.1.0-rc4/clients/audacious/rules.mk
===================================================================
--- imms-3.1.0-rc4.orig/clients/audacious/rules.mk  2008-03-02 18:54:06.000000000 -0700
+++ imms-3.1.0-rc4/clients/audacious/rules.mk   2008-09-19 15:28:17.000000000 -0600
@@ -7,7 +7,7 @@ libaudaciousimms-LIBS = $(AUDACIOUSLDFLA
audaciousinterface-CPPFLAGS=$(AUDACIOUSCPPFLAGS)
audplugin-CPPFLAGS=$(AUDACIOUSCPPFLAGS)

-audaciousinterface.o: bmpinterface.c
+audaciousinterface.o: audaciousinterface.c
        $(call compile, $(CC), $<, $@, $($*-CFLAGS) $(CFLAGS) $($*-CPPFLAGS) $(CPPFLAGS))

AUDACIOUSDESTDIR=""

Phew. And that's not all. When you build IMMS you need to have OBJDUMP=gobjdump if you're using the default binutils variant from MacPorts, and this patch:

 rules.mk   |    2 +-
 vars.mk    |    6 +++---
 vars.mk.in |    1 +
 3 files changed, 5 insertions(+), 4 deletions(-)

Index: imms-3.1.0-rc4/rules.mk
===================================================================
--- imms-3.1.0-rc4.orig/rules.mk        2008-09-19 08:49:43.000000000 -0600
+++ imms-3.1.0-rc4/rules.mk     2008-09-19 16:17:33.000000000 -0600
@@ -19,7 +19,7 @@ link = $(CXX) $(filter-out %.a,$1) $(fil
             -shared -Wl,-z,defs,-soname,$@ -o $@

 %-data.o: %
-       objcopy -I binary -O $(OBJCOPYTARGET) -B $(OBJCOPYARCH) --rename-section .data=.rodata,alloc,load,readonly,data,contents $< $@
+       $(OBJCOPY) -I binary -O $(OBJCOPYTARGET) -B $(OBJCOPYARCH) --rename-section .data=.rodata,alloc,load,readonly,data,contents $< $@

 # macros that expand to the object files in the given directories
 objects=$(sort $(notdir $(foreach type,c cc,$(call objects_$(type),$1))))
Index: imms-3.1.0-rc4/vars.mk
===================================================================
--- imms-3.1.0-rc4.orig/vars.mk 2008-09-19 09:03:05.000000000 -0600
+++ imms-3.1.0-rc4/vars.mk      2008-09-19 15:07:44.000000000 -0600
@@ -5,8 +5,8 @@ INSTALL = /opt/local/bin/ginstall -c
 prefix = /usr
 PREFIX = $(prefix)
 OBJCOPY = gobjcopy
-OBJCOPYTARGET = 
-OBJCOPYARCH = 
+OBJCOPYTARGET = mach-o-le
+OBJCOPYARCH = i386
 exec_prefix = ${prefix}
 bindir = ${exec_prefix}/bin
 datadir = ${prefix}/share
@@ -15,7 +15,7 @@ VPATH = ../immscore:../analyzer:../model
 ARFLAGS = rs

 SHELL = bash
-PLUGINS = libxmmsimms.so
+PLUGINS = libxmmsimms.so libaudaciousimms.so
 OPTIONAL = immsremote analyzer

 GLIB2CPPFLAGS=`pkg-config glib-2.0 --cflags`
Index: imms-3.1.0-rc4/vars.mk.in
===================================================================
--- imms-3.1.0-rc4.orig/vars.mk.in      2008-03-02 18:54:06.000000000 -0700
+++ imms-3.1.0-rc4/vars.mk.in   2008-09-19 16:17:24.000000000 -0600
@@ -4,6 +4,7 @@ VERSION = @PACKAGE_VERSION@
 INSTALL = @INSTALL@
 prefix = @prefix@
 PREFIX = $(prefix)
+OBJCOPY = @OBJCOPY@
 OBJCOPYTARGET = @OBJCOPYTARGET@
 OBJCOPYARCH = @OBJCOPYARCH@
 exec_prefix = @exec_prefix@

Finally, make install doesn't finish the job.

cp build/libaudaciousimms.so /usr/local/lib/General/imms.impl

Well I think that's all the information you need, though it may not go smoothly. Hopefully we can get this all worked into IMMS proper and the 3.1.0 release will just work. If you use linux give Audacious+IMMS a try—it's easy and painless. If you think Audacious is for sissies, learn about the queue and the jump feature and try out IMMS for a week or two before you pass final judgement.

Oh, two final notes: Installing Torch can be a real pain and Audacious keyboard shortcuts don't work well with the gtk2 +quartz variant in MacPorts, so you want to stick with X11 gtk2. Oh, and though Audacious has a Last.fm plugin I haven't yet been able to figure out how to get it to stay enabled.

September 11, 2008

Hans Fugal
no nic
The Fugue :
» Touch Typing

Steve Yegge has posted an funny, irreverent, and above all excellent argument for touch typing. I highly recommend it even if you do touch type.

I am downright flabbergasted by some of the comments though. There are hunt-and-peck folks defending their inability to touch type as lifestyle choice based on the belief that they will get RSI. People justifying typing slow because it saves them from wasting time chatting or writing long emails. There are some interesting claims from 2–4 finger typists that they can type without looking at 70wpm (this is certainly possible), and choosing not to learn to touch type the "right way" because it will give them RSI (this is certainly ludicrous).

Typing is a vital skill if you work in IT, especially programming. Of this there is no doubt, rationalizing strangers aside. I simply cannot imagine being stuck typing at 10wpm or less. It would be like being stuck behind a pair of tractors on the freeway going 20 mph. For the rest of your life.

Last I checked I type about 65 wpm on average. I could probably go faster, but I never have felt the need. I can type as fast as I think when programming. If I were a stream-of-consciousness novelist or a secretary, I could probably make use of a faster typing speed. As it is, 60–70wpm seems to be a sweet spot for me.

I'd like to discuss the ridiculous RSI claims. Yes, if you type all day without breaks you can get RSI. There are certain things you can do to mitigate or exacerbate this for a given amount of typing and typing speed. If you tried to go lightning fast all the time you might hasten the onset of RSI. But I argue that the absolute worst thing you can do if you're afraid of RSI is to not touch type. RSI means Repetitive Stress Injury, from repetitively performing certain motions until your body starts to break down. Smaller more relaxed motions are less stressful on your body than large stiff motions. If you touch type well, your hands are relaxed, your fingers float over the keys, and movement is minimal. Of course you still need to take care—take breaks, spend some time thinking without typing or drawing pictures on paper, proper nutrition, etc. But the biggest thing you can do to prevent RSI is to have proper form. And maybe learn dvorak (I still use qwerty because I find sysadmin and programming to be tedious with dvorak, but I don't spend most of my time actually typing).

On the other hand, if you hunt and peck 24/7 guess how much more movement—repetitive movement—your body is enduring? Ever heard of tennis elbow? RSI isn't the exclusive privilege of touch typists. If you type slow enough that you can't possible get RSI, you are irrelevant. If you type fast enough to be productive but don't have good form, you are setting yourself up for RSI. If you're RSI-prone or just paranoid, go learn dvorak now or find a job that doesn't require much typing.

I'd add to Steve's exhortation to learn to touch type, that if you do touch type but you feel your form is off, you have low accuracy, or you feel that your fingers are stiff, do some conscientious practice. Focus on accuracy and relaxation first, then speed. Enhancing your typing skills is a great benefit if you spend a lot of time typing, although learning to touch type in the first place is obviously a much bigger payoff.

Let's continue to learn from musicians: correct form (including relaxed posture and keep those wrists off the keyboard/desk), accuracy, then speed.

August 28, 2008

Gabriel Gunderson
gundy
gundy dot org
» More work stuff

Wow, landing contract work can be time consuming. Sometimes it takes more work to find the contracts than to fill the commitments. In the last couple weeks I was able to land a few good deals and get few solid leads, but I had to let a big one fall through so I could attend an out-of-state family funeral.

I think I’ve pretty much decided against the full-time employment route. Contract work has been fun so far, but it’ll probably be a month or two before the flow of contracts becomes more or less steady. With that in mind, I’m starting to think that in the long run I’d rather sell a product than my time. I guess I’ll keep looking for contract work, meanwhile revisiting some of the business plans I’ve drawn up in the past…

I noticed that there will be a few voip-related tracks at UTOSC tomorrow. If you’re going to be there want to talk shop on open-source telephony, I’m game.

A big thanks to those that have reached out with employment and contract leads. I’m sincerely grateful. Make no mistake, no matter what entrepreneurial schemes I come up with, I’ll still need any work I can get. After all, I’ve still got mouths to feed. ;)

August 15, 2008

Gabriel Gunderson
gundy
gundy dot org
» Putting on a brave face

Scary and exciting. That’s how I would describe my new occupational path. I’m going to be accepting contracting work while I look for a more stable arrangement (read: get-a-job). I want to be able to look around and get to know some of the many businesses in the valley that have need of a Linux sysadmin/programmer before I make the choice to join one of them. I don’t want to be overly needy when searching for the right fit.

Anyway, if anyone has advice on job searching, contracting, resume building, networking or has any other general advice they would like to share, I’m all ears.

I also feel like I need to get plugged back in. I’ve been pretty heads down for the last year and a half. I haven’t been hanging out on IRC, blogging, posting to mailing lists, attending local user/business groups, volunteering or developing my skills. Heck, I haven’t even been logged into IM more then a handful of times during that period.

Along those lines (getting plugged back in)…

I’m changing over my IM contact to gabe@gundy.org using Jabber (XMPP). Feel free to add me to your buddies if you use Google Talk or another Jabber service. If we already chat using my old account, you’ll notice a change sometime later today.

It’s also a good time for me to breath life into my LinkedIn profile. If you and I have worked, played, studied or chilled together, send me a LinkedIn invite so I can keep in touch and see what others are up to. BTW, I don’t do “social web” stuff very often, but LinkedIn is one service that I find useful.

Lastly, if you (or anyone you know) has need of an experienced Linux sysadmin, drop a line. I can do just about anything, but I mostly enjoy and work with Linux, Asterisk, PostgreSQL, MySQL, Python, Mono, C#, Bash, IPTables, Django, Postfix, Mailman, Apache, Subversion, Django, FreeSWITCH and all things Open Source.

Thanks and I’ll be seeing more of you!

August 11, 2008

Hans Fugal
no nic
The Fugue :
» Hipster Redux

I've talked about the Hipster PDA a few times. I finally stabilized on a system that works for me. I've been using it steadily for months with no major changes now, so I thought I'd share with you.

My brief foray into the hipmod was fun, but too restrictive and small in the end. I understand others enjoy it though, so I'm glad I did it.

I find the classic hipster with a few modifications works best. My biggest beef with the original hipster is that it falls apart and it's not very user-friendly. That binder clip had to go. So I got some binding rings (½" I think, but the exact size isn't critical) and use a standard 3-hole punch to punch 2 holes in the index cards, and bind it with 2 rings. This makes a more book-like planner, which nicely folds over on itself.

Now, those rings can be pesky to open and close so I decided not to. I snip a little cut from the edge of the cards I want to be removeable to the holes. They stay in but will come right out and go right in without struggle.

I also like to print some forms (as you've seen). These I just print on regular paper and trim to size with a guillotine then hole punch (no snips, that works best on cardstock).

I made front and back covers out of a cereal box and duct tape, and even a pen holder out of duct tape. I'll post a picture soon so you can see.

My planner consists of a few reference pages I printed out (including a circle of fifths, a few airport kneeboards, performance data for my favorite planes, and morse code… anything you can find a PDF for.), my weekly calendar/todo list pages, and a bunch of index cards that I use for notes, moments of inspiration, or whatever else they come in handy for. Oh, and a paperclip to mark the current week. I only have to reprint/refill the weekly pages about once every 3 months or so.

For printing things, I wrote a script that automates some of what I mentioned in previous posts.

July 30, 2008

Hans Fugal
no nic
The Fugue :
» Use a balloon to estimate RV

So it's been awhile since I estimated my residual lung volume (RV), and I figured it was time to do it again.

I'm a big guy, so my lungs hold a lot of air. When you're blowing all your air into containers in the bathtub, and you're ⅔ or more exhaled, is not the best time for pausing to move your straw to another container—or worse, refilling the container. This time I decided to use a balloon.

I took a deep breath, exhaled maxmially into the balloon, then blew the rest into the container through a straw. (Wait, did he just say "the rest" after "maximally exhaled"?) I heard that. Yes, you can't exhale all of your air because the pressure in the balloon is higher than atmospheric pressure. In my case, I had another 400ml of air.

Then I emptied the air out of the balloon into the container. This is easy and leisurely once you figure out the trick, but it can seem next to impossible at first. Hint: don't try to submerge the balloon. If you grab the lip of the balloon mouth only, and avoid pinching the neck, you can control the air flow very well. There, I had measured my vital lung capacity (VC).

It worked great, and compared with the last circus event when I measured VC it was much easier.

Now I had to figure out how to get from VC to RV. The clown who wrote http://hans.fugal.net/density kind of left this step vague. I've remedied that and added a page to my spreadsheet. For the curious, my RV is up from 2.0 liters to 2.2 liters, and a total lung capacity of 8.2 liters.

July 29, 2008

Hans Fugal
no nic
The Fugue :
» %BF Nomogram

Remember that system I came up with for calculating body fat percentage using a gallon jug in a swimming pool? I always let the computer do the calculations for me—I have a little script that I run that updates my weight graph. But not everyone is as geeky as that, and formula is not that simple, and when you add units conversion in it gets downright hairy.

I finally figured out how to generate a nomogram. Now you have no excuses.

July 4, 2008

Von Fugal
no nic
ATOM von Fugal
» On Gay Rights and Gay Marriage

The blogosphere is rife with discussion on gay marriage and the LDS Church’s involvement in California. I would like to do my part in the battle for family. I pray this post will have positive effect in that battle, however modest it might be.

First of all, I’ve already said how I feel about group rights. Gays don’t have rights. Human beings have rights. Gays happen to be human beings. Good, we’re on the same page.

That said, this isn’t really about gay rights as much as it is about gay marriage, but it brings me to my first point.

Marriage is not a right.

For all the talk about gay rights you can mostly chalk it up to human rights that need to transcend prejudice. In other words, instead of clamoring for “gay rights” they should instead be insisting that they be afforded the already existing human rights. Gay marriage, on the other hand, is a prime example of a group inventing new rights so they can feel the same as everyone else regardless of their decisions. It’s like a people with dreadlocks inventing a right to lay their heads on your table simply because you don’t mind another person without dreadlocks doing it.

Marriage is fundamental to society.

This is entirely incident to marriage not being a right, but is yet a powerful argument against the thought that marriage should be a right. Marriage is the very institution by which children have parents, both mother and father. It is the core of the fundamental unit of society—family.

Marriage involves more than the couple.

Intimate relations are not just about consenting adults having a good time. There is ever present the possibility of new life. This new life has rights just the same. It has needs, physical, emotional, spiritual.

Husband and wife have a solemn responsibility to love and care for each other and for their children. “Children are an heritage of the Lord” (Psalms 127:3). Parents have a sacred duty to rear their children in love and righteousness, to provide for their physical and spiritual needs, to teach them to love and serve one another, to observe the commandments of God [etc.]

Children are entitled to birth within the bonds of matrimony, and to be reared by a father and a mother who honor marital vows with complete fidelity.

The Family: A Proclamation to the World

It is because of this sticky situation that marriage is instituted. The very purpose of marriage is to give children stable homes, to assure where possible that when children are created they have a mother and a father. Once you realize this, you realize that gay marriage isn’t the only thing you ought to be worried about. Fornication, adultery and divorce come to mind. Alas, this post is about gay marriage. Indeed, homosexual relations cannot result in offspring, so the very reasons for instituting marriage don’t even apply to the deviants. Yet they insist they have a right to marry. Again I propose it’s merely about them feeling the same as everyone else, regardless of their personal choices. It’s validation, nothing more.

Government should be involved in marriage.

Many of my libertarian friends throw around the idea that government should step out of marriage completely, leaving it a private and religious matter concerning only those involved. This is one of few places where I diverge from the libertarian camp (though not necessarily libertarian ideals). As stated previously, marriage inherently involves more than the parties involved. It involves family and new life; it involves society as a whole. It is in the interests of everyone involved (and everyone is involved, who among us was not born of a mother and a father?) and we should take every opportunity to encourage marriage over promiscuity and counseling over divorce. We should take every opportunity to afford children the privilege of being born into the marriage relation, and where that’s not possible to be adopted into such (no, I’m not saying single parents should give up their children, though they shouldn’t be discouraged to do so). The government is the vehicle by which the people are governed. Whereas the people deem it in society’s interest to afford children the opportunity to develop under the guidance of bonded mother and father, encouraged to stay together, for better or for worse, in sickness and in health, thus is born the state sanctioned institution of marriage.

6 comments

June 6, 2008

Jason Hall
jayce^
Jayce^
» Food Storage Commentary

This message is actually some commentary to reply to a recent posting by a "Hoser That's Not My Brother".  Since he decided to take his food-snobbery into an area that I care more than a little about, I thought I'd give a few opinions.  Please go read his bit first, and then come back here and this will make a lot more sense.  Actually, from other discussions, much of what I have to say is in agreement with the hoser, but I do hope to clarify some points, and give my opinion on others.

Starting off, there is much confusion in the food storage world, and he's right, what to store must come from you.  "Store what you eat, and eat what you store," is an oft-repeated mantra that is very correct. Just blindly following some list will get you in big trouble if you ever need that food.  You probably won't know how to use it, and it will likely give you serious problems shortly after eating.  The provident living website is a great resource for very basic elements of storage, but it is just a starting point.  Along with that, it's a good starting point for the information you need in actually using your storage in an efficient manner.

For me, I think one of the most important things to start out with though is by asking yourself the question, "Why food storage?".  I too have gone through some inter-job difficulties before where the bit of storage we had was a lifesaver for us, but there could be more.  Maybe you want to be ready for WTSHTF aka TEOTWAWKI, maybe you just know that food bought now (well, better last fall) was a great way to beat inflation, and the stock market (often by double digit percentages).  Whatever the case, how much, and what you need to store will change with that definition.  Me, I figure if I'm prepared for the absolute worst case that I don't think will ever happen, then I'll feel pretty good if I just get laid off without job prospects again.  Hope for the best, prepare for the worst.

Now, to review by category:

Grains
Yes, it is a lot of wheat to keep around, but then again, they don't call it the staff of life for nothing.  Try going without bread for a week or so, and see how you feel.  Sure you can say you did the atkins things before, but let's also look at some other factors.  First, given a situation where you really *need* to use your storage.  There is a good chance that your physical activity level is going to be changing a bit.  Be it heavy stress, to just plain walking a lot more, your body will be needing those carbs quick.  Also the fiber content will be very helpful in combating bad side effects of your stress levels, and other dietary changes.  One word of caution though, do ease into using real whole-wheat (even from store-bought whole wheat flour), or you will have some serious issues to contend with.  Wheat itself can also be used to cultivate simple meat-substitutes (hey, if you're really starving), and as stated, its protein content is necessary for making breads from other cereals.  Besides all of the above stated, your grains are some of your absolute *cheapest* ways to augment just how much food you have stored, heck even at today's way inflated prices you can get sealed buckets of hard wheat for $23 or so for 45#.  Add to that the fact that stored properly it has the longest stable shelf life of any food storage item, you should make sure you have a good amount of wheat and cereals in stock.

But it is smart to mix up your cereals some.  Get a couple of types of rice, maybe some softer wheat (cake flour, etc), Rye, Corn, Oats, and others.  you'll always want some variety in your diet, and hey, you can always just experiment with new breads too.

Oh, and do get a mill/wheat grinder.   Get a powered one first, and a hand mill second. It's amazing how much better bread is with fresh flour.  With a powered one you're more likely to use your wheat right now, saving yourself money, getting much better breads, and just getting healthier.  Added bonus, your house smells much nicer.

Fats and Oils

Yes embrace the necessity of Fats.  Well, I know I've never needed to tell a chef that, but I'll just back you up on that one.  For basic storage of oils, I can answer one good reason for shortening over standard vegetable oil.  Shelf life.  Based on it's nature, it tends to have a longer time before it goes rancid.  You have to be careful about how long you keep your oil around, which is one reason it doesn't tell you to keep too much.  Most people would buy some Costco sized mega-container, and it would all spoil before it was even opened, much less the problems it would have if opened.  I'll agree on the PB too, it's something we can't have enough of, and have no trouble rotating through (in fact tend to over do that :) )

Legumes

Dry beans are important for food storage, because as any Brasilian (and really any Latin American) will tell you, it's food.  It's cheap food, and combined, beans and rice bring out some wonder-twin powers in each other.  They combine to form more complete proteins which most of us will be lacking in a crappy situation because we won't have nearly the amount of meat we're used to.  With he dry beans, yes, choose most any you like, and get some variety (and learn how to use them).  Get the other dry or canned, as you would use them, but variety is good.  Dried soup mix can be the basic soups you see, largely for spices, but more often refers to a Soup Base, that the canneries used to have.  Was a simple soup/stock that was designed for mixing things in.  Stock has great nutrition, even dried, and makes it much easier to use so much of this dried food.

Sugars

Actually, I wouldn't lower it at all.  Now part of why this seems so high is based on the targeted usages for your food storage.  It's expected that if you're smart enough to be storing food, you'll probably have a garden too.  You'll see that sugar disappear the first time you make jam.  Don't forget your body will likely be craving some things that can sooth a sweet tooth while you change diets, and adding to that, most people can really do with the stress relief of their favorite desert.

As for the kool-aid, if you've read this far I'd think you're drinking some :) .  Actually one of the biggest reasons for the powdered drink mix is for water storage.  Depending on how much, and how you've stored it, or what your filtration method and storage is, you can wind up with some funky flavors.  It may be clean, but might taste quite off, and a little flavor will help you keep hydrated, which is pretty key in this area.  Same thing camping, that mountain stream water aint always that refreshingly crisp :)

I actually think I'd want more of the honey and molasses though.  We have a lot of good recipes using them.

Milk

How could you even question "other".  As a chef this should be seen as too little, without even trying.  Sweetened condensed milk is a good one, along with evaporated milk.  But let's be even more obvious:

  • Cheese - Serious comfort food, excellent enzyms and good storage.  Freeze dried, Canned "queso", or *real* canned cheese (that stuff is quite good, and amazing storage).  Or if you have "wine cellar" type qualities, keep some cheese wheels around, they'll just get better tasting, and you know you'll rotate through them.
  • Yogurt - Important dairy, will work wonders for your digestion, especially if not feeling well.  But how do you store it? Well, you can get cultures that will store well, and learn to make your own!
  • Soy Milk - yeah, it's worthwhile to have :)
  • UHT milk - Boxed milk, stores for a year or so.  Parmalat is famous for this.
As for powdered milk, I have a strong aversion to it from having to drink it too often when we lived overseas.  The texture is too different for my main staple food :)  However, the morning-moos variety is better than others, and I have recently found Nido which is dried whole milk!  yes, that helps the texture a ton.  You can find it in small cans in the latin foods section of Wally World to try it out, just don't buy the Nido Kinder (compare ingredients between the two to get a good idea).

There are some good ideas on how you can use powdered milk too, for making things like cheese/yogurt and more.  Those could help you out.

Cooking Essentials

Seasonings Seasonings Seasonings!  You've got a lot of 'basic foods', you'll want to spice them up.  Dried, whole, etc, and get your herb garden running.

Oh, and as for the salt, as mentioned with the sugars, just think of having to do some pickling.  Oh, and tanning, since I'm sure *everybody* will be running out trying to do some of that :)

Water

This is of course something that we can't be without, but always think is the last thing that we will not have.  Possibly, but I'd rather be prepared.  I go with the 2gal per person, since I think if I ever really need it, it'll be in the summer here, and I know I'll need more.  Plus I like to be clean, meaning more than the minimum.

As for bleach, it loses its real potency starting after about 6 months, so check as to how much you store.  You can get good dried chlorine too, good to keep around, and lasts longer.

Summary

There are great books that can help with this subject, and plenty of crappy ones too.  I can suggest a few, and love to help friend get ready for the best or worst of times.

April 21, 2008

Hans Fugal
no nic
The Fugue :
» Token Bucket of Life

When it comes down to it, the secret of productivity is to just do it. In our line of work, it's not as simple as you're either chopping a tree down or you're not. So it's easy to get distracted on tangential or unrelated tasks and trains of thought. If I didn't know people personally who somehow manage to avoid this trap most of the time, I'd think it was impossible. For the rest of us, I present a nifty trick.

Grab two condiment bowls, shot glasses, rolls of tape, whatever. Now grab some glass "stones", some pebbles, some M&Ms, whatever. The former are buckets. The latter are tokens. Put all the tokens into bucket A.

Now for every hour you work (really), move a token from bucket A to bucket B. Do this every day for a week and keep a tally. This will show you how much time you are working and how much time you are squandering. It will be depressing. Don't let your boss see.

Now decide how much time you will permit yourself to squander. You might feel that should be 0, or maybe you feel you deserve an hour a day. No matter what you feel it should be, make a realistic goal at this point. It's just like physical excercise you know. So figure out the ratio between work time and play time. 4:1 makes the math convenient, so let's take that ratio. Now, for every hour you work you bring a token from A to B. It represents 4 quarter hours in bucket A, but only 1 quarter hour in bucket B. That is, you get to play 15 minutes for every token you have in B. Think of it as a bank account. If you don't got no tokens in the play bucket, you work. If you do, you might keep working because you're in the zone. But you might play, because you have the tokens to do so. So play, and play guilt free. The guilt-free recreation is as important as anything here. If you can't bring yourself to give yourself permission to play at work, then split it up between stuff you hate and stuff you enjoy. You do enjoy some aspect of your work, no?

This is just a slightly-modified token bucket scheme, like that used in network shaping (e.g. Quality of Service). When I first came up with it, I was inspired by "token economics" which was suggested for potty training. When I had the system going for a day or two, and was working on a QoS presentation, it dawned on me that what I had here was a token bucket. That makes it all the more cool.

What good is it? I think it's an effective tool for a couple of reasons: it's simple, unobtrusive, and authoritative. It keeps you accountable, both to it and to yourself, and to anyone who looks on that knows what it means. It doesn't nag you, nor is it susceptible to your rationalizations. It's easy to reset or set aside when it doesn't apply (when a deadline looms and you don't have time to play at all). The only habit you need to get into is checking your account before playing. But if you fail to remember, you can always adjust the totals retroactively, in which case although you may have overdrawn you will still see the state of affairs, and have an opportunity for introspection.

Now if you'll excuse me, my play bucket just ran out.

March 20, 2008

Jason Hall
jayce^
Jayce^
» Making a Splash

What a night, after my team paintball practice, I had to run down to the American Fork pool to help my brothers' ward scout group learn basic kayak safety. They've decided that they are doing a kayak high adventure at lake Powell this year. So my brother and I brought down two of the kayaks, and started with the basics of entry, seating, control, and water escape. It's been a few years, so the demo of water re-entry was a little scary, but I did it. jayce_and_jeremy_teaching_kayaking.jpg It was great to get the boats back in some water (and quite warm at that), and we'll be getting quite a few more chances to take these guys out to practice this summer so they can get the feel for kayaking before their trip. And yes, these aren't tiny little whitewater kayaks. :) 19' Seda Glider, and a 17' Necky

February 13, 2008

Jason Hall
jayce^
Jayce^
» Moving Right Along

Yes, I'm moving on.  It's time for me to go to a new place, so I'm starting to troll along with my resume for anything interesting.  I won't go into my reasons here, as I am still employed :) but would like to find something new.

If for some reason you are reading this and don't know what I do, or what I'm good at, wow, I'm surprised :) but here goes a little.

I'm a very experienced Perl programmer,with previous experience in the usuals (C, C++), but those are pretty outdated in terms of experience.  The larger part of my experience and background is in dealing with Billing and Finance applications, and large scale replicating site/cms tools.  I'm a core developer on the Freeside billing system,  and heavily involved with the local Open Source community.  Go ahead, check out the resume - http://halls.lug-nut.com/jayce/resume.html

January 16, 2008

Von Fugal
no nic
ATOM von Fugal
» Inflation? Recession? Another Great Depression?

Pretty scary stuff. I don’t think that we necessarily will face another great depression. We are, however, really on the verge of a recession (which is just a specific level being reached in the current trend we’re already in). Inflation is absolutely happening quite consistently. And I do think another great depression is completely within our grasp if we really want it, and wanting it may very well be no more than being content with the current trend.

I have felt the effects of this poor money management in very real ways. Gas is an obvious example which I’m sure we all feel, monthly grocery costs rise, you can even see it in vending machines and laundromats. The price just goes up and up, never down. Tuition is more imposing year after year after year, with no end in sight. Will the next generation be able to afford college? If they do manage to “afford” it, will they ever pay off the debt in their lifetime? I wonder if my youngest brother will even be able to afford it.

Ron Paul is the ONLY candidate I’m aware of whose platform is less government, less spending, less inflation, less debt, less war, less interference in our personal lives, all in all, LESS INSANITY.

Anyway, here’s the article that prompted my rant.
http://www.downsizedc.org/blog/2008/jan/14/protect_your_money
I’ve seen similar figures from other sources.

And if you don’t know who Ron Paul is, or especially if you’ve heard of him and your knee-jerk reaction is “lunatic” (thanks to our glorious media), please check out his website. (please also note that those donations are from common folk, not big lobbyists).

1 comment

November 9, 2007

Jason Hall
jayce^
Jayce^
» 25 Skills

Found this article on Popular Mechanics recently: 25 Skills Every Man Should Know

Use it as a scorecard, where did you wind up?  I do like that it is updated to include concepts such as backing up your drive.

October 8, 2007

Hans Fugal
no nic
The Fugue :
» Cost of Bread

How much does it cost to bake a loaf of bread? Or put another way, how much money might you save baking your own bread (which will taste better anyway)? These figures will give you a ballpark idea. As always, I'm following my recipe.

  • 425 grams of King Arthur Unbleached All-Purpose Flour: about 60 cents
  • 8 grams of kosher salt: about 1.5 cents
  • Sourdough culture and water (practically free)
  • Preheat (my) oven with baking stone and dutch oven to 450°: 20 minutes at 2585 watts at 11.482 cents/kWh = 10 cents (I leave the baking stone in because I'm too lazy to take it out. Actually, it's 6 unglazed clay tiles, but that's another story)
  • Heating element on during bake, including restoring heat lost when oven door open (yes, I watched the little light with a stopwatch): 10 minutes = 5 cents

Total cost: about 75 cents for a 1½ lb loaf of absolutely terrific artisan sourdough bread. You'll pay 4–5 times that for bread that's not nearly as good (nor as good for you) at the grocery store. So if you save say $2 per loaf you might be able to buy yourself a used iPod after a year. Then again, you might eat 4 times as much bread…

The take-home lesson here is never let anyone give you a guilt trip for baking bread. It costs under 25¢ in electricity, and even if you place a high price tag on pollution it is dwarfed by your air conditioner, refrigerator, etc. One very real issue is baking in the middle of the day in the summer, either making the A/C work that much harder or making you that much hotter. This is mostly a concern in places like Las Cruces where lunatics like myself live. Most of you will have air conditioners that can handle it just fine, though it would be interesting to figure what that cost would be (if you do so, let me know).

October 6, 2007

Von Fugal
no nic
ATOM von Fugal
» Walls and Blocks and Beasts! Oh My!

Some people were poking around for the beast game on #utah today. So I dug up ye olde code and got it to compile without so much as installing some libs and adding a #include. That’s promising, I haven’t touched that code in 4+ years. Anyway it compiles but when you run it the screen is all garbage. #utah says it probably has to do with sfms. I don’t have a hint of time to do anything with it right now, but here I post it anyway in a darcs repo for the whole world to enjoy.

Some history on the project, you can stop reading now if you hate history. This was the first major thing I ever worked on. Before this it was writing a few graphics routines in BASIC for my friends game “Target”. It was then I drew the best ever 8×8 pixel rendition of an angry green blob. Wish I still had that… Prodding the time machine along… My brother Jacob and I set out to clone our good friend beast around 1997-8 in C++. He did all the work at first, with me watching intently and asking such questions as “what does that do?” and “why do it like that?”. Before the end I was writing as much code as he (or at least so I remember it). We had a good ol’ time playing it. When I returned from my mission in 2003 I did a rewrite to port it to linux using ncurses. At some point I also added some fancy self-preservation AI to the beasts. I’m really not sure if the AI stuff is in this version of the code I dug up; I hope it is.

1 comment

September 29, 2007

Hans Fugal
no nic
The Fugue :
» Total Heart Rate Training

I’m still swimming. This may be the longest I’ve stuck with any exercise program (excluding things thrust upon me like basketball practice or getting out of bed). Naturally, being the technical sort that I am, I want to make sure I’m using this exercise time efficiently, so I picked up Total Heart Rate Training by Joe Friel at the bookstore (and put it down before I left—reading it over several visits while my son played with the Thomas trains). This is an informative book with lots of information, but it’s not for the weak of heart—literally or figuratively. The book is written by and for obsessive-compulsive athletes (the most common variety is known as triathlete). You have to be absolutely bonkers to follow this book religiously. But it can be useful to the thinking fitness swimmer, with a grain of salt.

The first problem with this book is precision. Not a lack thereof but an overabundance and misunderstanding of it. In physics, or any practical math, you can get in trouble by giving more significant digits than your measurements warrant. You can fool yourself and others into thinking you have more precision than you do, which leads people to jump to incorrect conclusions and make silly and/or dangerous decisions. Heart rate monitors will give you absurdly accurate heart rate measurements. But I posit that you can’t measure how that maps to your body’s metabolism (the zones) with anywhere near that accuracy, at least not while exercising. What’s more, as a swimmer anyway, you can only check the monitor during rests at the end of the pool, where it’s just as convenient to take your pulse with the pace clock (it takes 6 seconds to get ±5 bpm). The heart rate charts in the appencides are what really give it away, though. Running, Biking, Swimming, etc. each have their own 2-page chart with some 60-odd entries on where the zones begin and end, to the nearest bpm. If that doesn’t sound absurd by itself, take a look at this graph I made from the swimming chart:

Swimming Heart Rate Zones

They say a picture is worth a thousand words. Notice how the relationship is almost completely linear. I’m no exercise scientist, but how much do you want to bet the body is not so perfectly conformant? I bet it varies depending on the day, conditions, what you ate, etc. There might even be some nonlinearities. So we have a chart with a bunch of numbers and no graph, that is overly precise.

That wouldn’t be so bad on its own, but the author actively disparages traditional measures and formulas for being too inaccurate, when of course the reason they are too inaccurate is that they are too precise. The most obvious example is that your maximum heart rate is 220 minus your age. This gives you a bpm, but really it’s only good to within 10 or 20 bpm. He rightly says that this is not accurate. But he says it’s as likely to be way wrong as not, because it’s a statistical measurement. i.e. it’s a bell curve. Hello, 95% confidence of being within 2 standard deviations hardly qualifies as “as likely as not” to be outside. If he really wanted to convince me he would have stated the confidence intervals and said just how far off from that number you are likely to be. Then he would have compared that error with the error in pinpointing the zones in exercise. I think we’d find that maximum heart rate, while not perfect, isn’t as bad as all that.

While being absurdly precise and complicated (to the delight of obsessive compulsive triathletes everywhere), this book is also somewhat lacking in rigor and logic. Besides the examples above, there’s an issue I blogged about previously: the so-called fat-burning zone. As you may recall, the fact is that your body burns more fat per calorie when in an aerobic metabolism. This leads people to call the aerobic zone the fat-burning zone. People get lazy and forget to put in the disclaimer that you have to work longer to burn as many calories, which leads to confusion. Trainers and self-righteous OC athletes retaliate by pointing out that you burn more calories per time unit by working out harder—up into anaerobic, and so “the fat-burning zone is a myth”. Well it’s not a myth, it’s perfectly valid if you’re willing to work out longer. Instead of elucidating the topic with clarity and stating both sides of the issue without bias, the author falls squarely, if not extremely, on the myth side.

Still, there is a lot of good information in here on how the body works, what’s going on in the various zones, in which zones you can best spend your exercise time in order to achieve your goals (the information for a fitness swimmer is in there, if a bit hidden behind the triathlete-like goals). Numbers that are useful if you take into account that they are too precise, etc.

I’ll give you an oversimplified summary of what I learned in the book. Referring to that graph above (by the way, I had no control on which colors were used—they’re just GNUPlot’s default colors), notice that the x axis is the lactate threshold. He claims that LT is a better base point than maximum heart rate, because you can directly observe it without killing yourself. Sounds good to me.

At the border of zones 1 and 2, aerobic respiration accounts for almost all of the energy produced. Aerobic respiration primarily uses fat and is much more efficient, but less powerful, than anaerobic respiration. If you’re fit you can stay in zone 2 all day long.

At the border of zones 4 and 5, enough anaerobic respiration is happening that various easily-observable changes occur, and the exercise benefits change too (especially those related to heart). Oversimply put, training above LT will train for speed in shorter (non-endurance) races, and also do various good things for your heart.

At the border of zones 5b and 5c, almost no aerobic respiration is occuring—it’s all anaerobic. This is because you’re demanding more power than aerobic respiration can keep up with. Anaerobic respiration is done not from fat stores but from stuff stored in the muscles themselves (for immediate access and powerful energy). There’s only so much of this fuel, so you run out of steam quickly above LT, but especially up here. This is sprinting stuff, and you can rarely keep it up long enough to even measure heart rates much into zone 5c.

For me, I am going to aim at increasing my LT and staying mostly in zones 2 and 4, (apparently zone 3 is a waste—little more benefit than zone 2 but requiring a lot more recovery) but doing interval training shooting up into the above-LT zones, mostly for the heart benefits. I figure that will meet my goals best, i.e. I will enjoy the exercise more and not leave the pool exhausted, I will burn more fat per calorie, and the interval training will give me enough edge to keep things interesting and improve my cardiovascular health (not to mention increase LT—doing intervals with sufficient rest to “cycle” the heart rate from low to high and back to low is one good way to do that). And I’m going to do it by taking my pulse with the pace clock periodically, and paying attention to how my body feels and how hard I’m breathing.

Of course, the most important thing is to keep on just doing it, and that’s going well because I’m enjoying learning the Total Immersion swimming method, and I’m finaly getting into the more interesting drills. It won’t be too long until I graduate to swimming again, at which point I’ll review that book. I’m looking forward to seeing if I can swim a 500m in under 10 minutes with ease. That’s something I had to do regularly as a lifeguard and even though I was more fit then (or at least less fat) I always struggled with swimming 500m non-stop, and my times were usually 10-12 minutes. If I can swim a 500m with ease in under 10 minutes in my current shape, it will be a testament to the TI method. Stay tuned!

August 31, 2007

Hans Fugal
no nic
The Fugue :
» The Heart Rate Chasm

My Swimming Book makes the following claim: if you work out at lower (but still aerobic) intensity you burn more fat per calorie than if you work out at higher intensities. Note that it says per calorie, which means you have to work out longer. A rough guideline is to go the same distance as you would at the higher intensity.

Unfortunately he doesn't give any references and no numbers or graphs. One is left wanting more information. But if you try to google that topic you will find two camps yelling at each other from across a great chasm.

Group 1 says keep your heart rate down in the fat-burning zone. Group 2 says group 1 is a bunch of fools and that although the ratio may be higher you burn more fat by working at a higher intensity because you burn more calories. The amusing thing is that neither side ever cites any references whatsoever, nor gives any concrete numbers. Neither side gives due diligence to pointing out that you can burn the same amount of fat either by working easy-but-long or hard-but-fast. Calorie burn rate (time) and intensity are a tradeoff, but to the two groups there is no compromise.

Finally I found a white paper with solid logic and numbers and graphs. (Still not enough references, but at least there are some.) Check out the graph on page 8 which confirms what I suspected: there is a point of diminishing returns. Choosing Zone 2 over Zone 1 is a no brainer. Choosing Zone 3 over Zone 2 looks marginally smart. Choosing Zone 4 over Zone 3 (when fat loss is the only consideration) is silly—you use more calories to burn the same amount of fat. Of course there are lots of reasons to go into Zones 3 and 4, like training for races, cardiovascular health, building more muscle, and burning off the extra helping you had at breakfast. But if you're looking to burn fat efficiently, It looks like roughly 70% of maximum heart rate (220 minus your age, as an estimate) is the point of diminishing returns, and a good aim.

Now, that said, there is a lot of variance in the fat burning range. In fact, the whole point of that white paper is to teach you how to increase that anaerobic threshhold so that you can burn a higher fat percentage at higher intensities, effectively raising that point of diminishing returns and allowing you to burn more fat per minute. This is another thing the TI book said you could do but didn't give enough details for my taste.

Of course, let it not be forgotten that the thing that makes the most difference is actually getting up off your duff and into the pool.

August 24, 2007

Hans Fugal
no nic
The Fugue :
» Body Density Measurement Uncertainty

A couple days back I posted my idea for measuring body density and estimating body fat. Dad, who has a set of skinfold calipers gave it a try and gave me comparative results, and asked the question on everbody's mind: just how accurate is it, especially with that pretty blatant guess at residual lung volume?

So I took some time to learn how to account for uncertainty and take a stab at pinning a confidence interval on the technique. First of all, I didn't realize how complicated uncertainty propogation is. Partial derivatives, squares and square roots, etc. Luckily, I came across some lecture or presentation notes detailing a sequential perturbation method (instead of an analytical method). I could have talked Jacob into walking me through the partial derivatives, but this method is easy to code and a find in and of itself. Read about it in this PDF.

I coded up the formula and ran some test data through it. Here's the equation again for review: ρ = m / ((m + mc)/ρw - (va + vc + vr)) Here's the values and uncertainty I attribute to each variable:

  • m = 121.29 ±0.02 kg
  • ρw = 0.997 ±0.001 kg/l
  • va = 1.13 ±ٍ0.01 l
  • vr = 1.87 ±0.5 l
  • mc = 0 ±0.02 kg
  • vc = 0 ±0.01 l

I didn't actually use a counterbalance, but I included the uncertainty in measuring its mass and volume as if I had, just for completeness. As suspected, vr has the largest uncertainty. I calculated the uncertainty if vr were magically accurate, and found that the uncertainty was 0.0014 kg/l. This translates to about 0.65% body fat with Siri's equation (ignoring the uncertainty inherent in that equation, which is a constant bias accross measurements for one person on any given day).

Note that I give ρw this time, instead of whisking it away with a magical 1 kg/l. I picked an average value between 72°F and 84°F (most pools are in this range), with an uncertainty (due to water temperature) of about 0.001 kg/l. If you use 1 kg/l instead you are introducing a bias of about 0.9% body fat. So I was wrong about that being insignificant.

Now, I found a better estimate (why better? because it seems to come from a more reputable source than Wikipedia) for residual lung volume: vr = RV = 0.24 VC. So I may have overestimated my RV last time by ½ liter. (Update: I think that must be a typo on that page, they probably mean 24% or 28% of total capacity instead. This fits in much better with the rest of the literature that I have found, e.g. Quanjer and Paoletti.) That seems like a generous uncertainty measure for RV, too. With that uncertainty factored in, we get an uncertainty of about 2.1% body fat, or about 5% is you are on the slight side of average (the less you weigh, the more difference that 1/2 liter makes).

So, Dad, let's bump your score up by about 1% for the density of water and then tack an uncertainty of 2% onto it, you have a body fat of 26.3% ±2%. I'm no expert on using calipers, but one paper's abstract indicates that the skinfold method uncertainty is about 3%. I've seen 10% tossed around casually too, but have no reliable source to back that up. That puts the two methods within the appropriate reach of eachother, which is heartening. It's interesting to note that BMI is overestimating Dad's fat, because he's more lean than the average couch potato. Imagine the difference if the subject were someone completely nuts, like a young triathlete, who has body fat of about 15%. Even better, if you are such a nut you could do the experiment and post your results (and BMI) here as a comment for us to see.

August 20, 2007

Hans Fugal
no nic
The Fugue :
» Measure Your Body Density

When you try to lose weight, what you are really trying to do is lose fat. Weighing yourself is a first approximation of your progress, but a better indicator is your body fat percentage (%BF). Unfortunately, measuring %BF can be expensive and/or difficult. It doesn't need to be so. All you need is a body of water (e.g. a swimming pool), a gallon jug, and your bathroom scale.

One of the most accurate ways to measure body fat is hydrostatic weighing. You are weighed underwater and on land, and your body's density is determined. Then body fat is estimated from the measured density. This is the same basic technique that we will use, but we don't require an underwater scale or special tank.

First the how, then I'll give you the physics. Get in the pool and exhale all the air you can, and allow yourself to sink. You will sink unless you're particularly obese. Take note of the sensation of sinking. Then do the same thing but with your lungs full. Take note of the sensation of floating. Now, we want to reach the point of neutral buoyancy when your lungs are empty, where you are neither sinking nor floating. You will be weightless under the water. Take the gallon jug and hold it under the water, then exhale completely. If the jug is full of air, you will probably float (unless you are quite lean, in which case you'll need two jugs). Keep adding water and repeating until you reach neutral buoyancy. If you sink, add air (pour out some water). If you float, add water. Once you've found the magic amount of water, use this equation to calculate your body density (ρ):

rho=m/(m liters/kg - v_\text{air}))

where m is your mass (what the scale tells you), v is the volume of you and your buoy combined, and vair is the volume of air in your buoy. If you have ¾ gallon of water in your gallon jug, then vair is ¼ gallon. ρw=1 kg/liter for all the precision we need.

Once you have density, you may like to estimate your body fat. The equation for that is Siri's equation, which says

This equation assumes your lungs are completely empty, which they can't be, so we need to introduce a term for the residual volume of your lungs. This is about ¼ of your total lung capacity, or ⅓ of your vital lung capacity. You can measure your vital lung capacity with a balloon or a by blowing air through a straw into an inverted container filled with water. The average residual lung capacity for an american male is 1.2 liters; mine is about 1.9 liters. So we can adjust the formula for density as follows:

rho=m/(m/rho<em>w - v</em>a - v_r)w - va - v_r)" />w - va - v_r)"/>

If you do this experiment you will probably find that your estimated %BF is not too far from your BMI, which is a statistical tool for estimating %BF. It can be wildly inaccurate for statistical outliers (e.g. people who are actually in shape), but it's easy to calculate and a decent sanity check in this case.

Here's what's going on. We're using Archimedes' principle: the buoyant force on a submerged object is equal to the weight of the fluid displaced. When the buoyant force balances the force of gravity, we have neutral buoyancy. The buoyant force is expressed as F_b = -rho_w v g. Substitute weight for the buoyant force and solve for the volume of the body (v = vbody + vair), then substitute that into the definition of density (m/v), and you get the formula I gave you above (if you consider the mass of air and the gallon jug as negligible). I glossed over that—if you'd like me to go into more detail say so in the comments.

If you're particularly obese and don't sink when you exhale completely, then all is not lost. You just need some counterbalance. The modified equation is:

rho = m<em>b / ((m</em>b + m<em>c)/rho</em>w - v<em>a - v</em>c)b / ((mb + mc)/rhow - va - vc)">c)">b / ((mb + mc)/rhow - va - vc)">c)">.

You can find the volume of your counterbalance by taking a cue from Archimedes and measuring displacement.

About accuracy: the biggest variable in this process is how much air is left in your lungs. You will find with practice that you are able to exhale more air, which will lower your %BF estimation, as if by magic. However it always overestimates and once you figure out how to completely exhale will be very consistent. Siri's equation is the next place to look—it basically takes the density of fat and the density of muscle and ignores bone mass and density, what you ate for lunch, etc. It will also almost certainly overestimate %BF. The astute reader will wonder about air compression in the milk jug. I measured this and found that when the jug is held within a foot or so from the surface, it does compress. However, the amount it compresses conveniently offsets the extra capacity of the jug (they don't pack milk spilling over the brim of the jug, after all). All in all I think it's accurate within a few percentage points for %BF, gives you an upper bound (i.e. you are free to brag about the number you get, even if it may be slightly high), and is more accurate than BMI.

December 15, 2006

Von Fugal
no nic
ATOM von Fugal
» Stick it to 'The Man'

In a world frought with restrictive employment agreements how is a prospective employee to protect himself? I believe the reason there are so many undesirable terms is because job seekers are too eager for that next big break or that shiny big company they can put on their resumé. If the companies couldn’t get any bites on these contracts then they would stop mandating them. It’s up to us as the fresh meat on the market to take a stand and decline oppressive agreements. Patience is key. There are plenty of jobs out there and with enough searching and patience I believe you can find a mode of employ that’s not only unrestrictive but that’s mutually beneficial. Seek out that employer you can build a symbiotic relationship with. Work with someone whose goals and values you can make your own. You will be much happier. As such you will be more productive and make your employer happier as well. Dare to love your job, not just what you do, but how you do it and under what terms as well.

0 comments