Haloscan comments to WordPress – the nitty gritty.

As I mentioned in the previous episode, I recently had to move more than 8000 comments from my old comment system, Haloscan, and import them into WordPress. Haloscan served me well back in the day, but they are going away, and all my more recent comments are in the WordPress system anyway. Nice to have them all in one place.

The process turned out to be pretty easy. I found a script for importing comments from a different system, modified it, modified it some more, found a fundamental problem with it, fixed that, and in the end not much of code remained from the example, except the part where the WordPress logo is displayed on the screen. I assume that part came from the code the guy copied to make the code that I copied.

Along the way I learned a couple of things. PHP is a pretty flexible language, but running a loop that sets up 8500 data structures and runs 25500 database queries exposes PHP’s primary weakness: memory management. The whiz kids who invented PHP designed it for a load/compile/execute/exit-and-clean-up flow. Memory allocated during execution is cleaned up when the program is done running (usually when the Web page is delivered). When you try to do heavy lifting with PHP, you have to start paying attention to getting your memory back before the traditional clean-up time.

The code I started with did a direct database query to add the comment to the comments table, but that got things out of sync with other tables. (The posts table keeps track of the number of comments that apply to it, presumably for performance reasons.) I dug into the core WordPress code and found the method they call to post comments, and I made my code call that function. I have no idea what all the bookkeeping chores are that function does, and really I don’t care as long as they get done.

I didn’t worry about performance too much at first (after all, it only has to run once), but one of the database queries I did was really expensive (scanning all the posts for a specific set of characters). Even running on my local server it was slow, and I knew that if I tried something like that on my actual Web host alarms would go off and they’d shut me down for a while. I did a little optimization on that front, and it was enough.

The following script has some Muddle-specific code in it, but it might come in handy for others who need to move Haloscan comments to a new system. The part that parses Haloscan XML is pretty generic and would work for anyone, the part that saves the comments might be useful as a guide as well. The main difference others will have to deal with is where to get proper post_id based on the thread field in the XML. In my case I had a link in each blog episode back to the Haloscan thread.

The HTML bit in the middle of the file is not essential; but it puts a nice WordPress logo on the screen when the script starts up. I inherited that from the script I started with.

NOTE: While this script has code in it specific to me, I am available to customize it for others who need to move their code from Haloscan into another environment, or, for that matter, from any structured source into WordPress. Drop me a line!

<?php
 
if (!file_exists('../wp-config.php')) die("There doesn't seem to be a wp-config.php file. You must install WordPress before you import any comments.");
require('../wp-config.php');
 
function saveCommentToWP($comment, $dbRef, &$postThreads) {
    //echo "here's where the comment save happens <br/><br />";
    $thread = $comment['thread'];
    $postID = $postThreads[$thread];
    if (!isset($postThreads[$thread])) {
        $query = "SELECT * FROM wp_posts WHERE post_content LIKE '%".$thread."%' AND post_status='publish'";
        $postID = $dbRef->get_var($query, 0);
        $postThreads[$thread] = $postID ? $postID : 0;
        if ($postThreads[$thread] == 0)
            echo ("<br />Thread $thread has no post!");
        else
            echo "<br />Thread $thread";
        flush();       // got to have real-time updates!
    }
 
    if ($postID && $postID != 0) {
        $userId = $comment['email'] == 'vikingjs@mac.com' ? 1 : 0;
 
        //set up the data the way wp_insert_comment expects it.
        $wp_commentData = array();
        $wp_commentData['comment_post_ID'] = (int) $postID;
        $wp_commentData['user_id'] = (int) $userId;
        $wp_commentData['comment_parent'] = 0;
        $wp_commentData['comment_author_IP'] = $comment['ip'];
        $wp_commentData['comment_agent'] = 'Haloscan';
        $wp_commentData['comment_date'] = $comment['datetime'];
        $wp_commentData['comment_date_gmt'] = $comment['datetime'];
        $wp_commentData['comment_approved'] = '1';
        $wp_commentData['comment_content'] = $comment['text'];
        $wp_commentData['comment_author'] = $comment['name'];
        $wp_commentData['comment_author_email'] = $comment['email'];
        $wp_commentData = wp_filter_comment($wp_commentData);
 
        $comment_ID = wp_insert_comment($wp_commentData);
 
        //echo ("<strong>saved comment $comment_ID</strong>");
    }
 
    // try to reclaim some memory
    unset($wp_commentData);
    unset($comment);
}
 
header( 'Content-Type: text/html; charset=utf-8' );
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<title>WordPress &rsaquo; Import Comments from RSS</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style media="screen" type="text/css">
    body {
        font-family: Georgia, "Times New Roman", Times, serif;
        margin-left: 20%;
        margin-right: 20%;
    }
    #logo {
        margin: 0;
        padding: 0;
        background-image: url(http://wordpress.org/images/logo.png);
        background-repeat: no-repeat;
        height: 60px;
        border-bottom: 4px solid #333;
    }
    #logo a {
        display: block;
        text-decoration: none;
        text-indent: -100em;
        height: 60px;
    }
    p {
        line-height: 140%;
    }
    </style>
</head><body> 
<h1 id="logo"><a href="http://wordpress.org/">WordPress</a></h1> 
 
<?php
 
// Bring in the data
$reader = new XMLReader();
if ($reader->open('export-8.xml')) {
    $postThreads = array();
    $thread = '';
    while ($reader->read()) {
        //echo "<br />read node type: ".$reader->nodeType.';     '.$reader->name.': '.$reader->value;
        if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'thread') {
            $thread = $reader->getAttribute('id');
        }
        if ($thread) {
            if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'comment') {
                // begin building comment
                $comment = array('thread' => $thread);
                $reader->read();
                while ( !($reader->nodeType == XMLReader::END_ELEMENT && $reader->name == 'comment') ) {
                    if ($reader->nodeType == XMLReader::ELEMENT) {
                        $property = $reader->name;
                        $reader->read(); // assumes text element following element tag has the data
                        $comment[$property] = $reader->value;
                    }
                    $reader->read();
                }
                saveCommentToWP($comment, $wpdb, $postThreads);
            }
        }
    }
    $reader->close();
}
 
?>
 
 
</body>
</html>

3

In with the Old

I got a message today that Haloscan is closing down. That is the service that provided refreshingly spam-free comments on my old blog. A year ago I finally abandoned iBlog for WordPress, and I’m glad I did. At the time, however, I didn’t want to tackle moving the old comments over into the new system. In my conversion I embedded a link into each of the old episodes to the legacy comment system, and left it at that.

It is fortunate I found out about Haloscan when I did. Another week and 8500 comments would have been lost forever. That’s a big part of the underlayer of this blog, the part people sink gradually into as they hang around more, and they realize that this isn’t just about me. There are some pretty interesting conversations, observations, poems, and even stories in those comments. With the timer running I set to work to get the comments out of Haloscan and into WordPress.

The move turned out to be pretty straightforward. (Simpler, perhaps, than it had been to put the links into the posts.) I’ll go into the technical details in an episode tomorrow, but for now, why don’t you pop into the archives for 2004 or so and find an old episode with good comments? Maybe you’ll find something interesting someone said once. Maybe you’ll see the name of someone you haven’t thought of in a while. Maybe you’ll see something you want to comment on, even.

The Pinnacle of Human Achievement

I might have mentioned bacon lollipops a while back; I’m too lazy to go look. But now there’s this!

Caffeinated Maple Bacon Lollipops!

The copy in the announcing email read thusly:

Dear Everyone:

For years, mankind has looked up to the stars and asked, “Why is bacon so awesome? And can it be improved?”

While we here at Lollyphile can’t answer the former without slipping into flowery prose, we are confident in answering the latter. Yes. Yes, it can be improved: it can also be a stimulant. The equation looks like this:

(organic, sustainably farmed bacon) + (Vermont maple syrup) + (the caffeine equivalent of two cups of coffee) = Caffeinated Maple Bacon Lollipops

Caffeinated Maple-Bacon Lollipops!

We’re really, genuinely proud of these lollipops. Not like the normal newsletter or press release “We are proud to offer…” proud, but like the genuine, “Hey lookit this thing my child can do exceptionally well” proud. Really proud. And excited.

Now isn’t that something? (No, at this time I do not get a commission for lollipop purchases.)

A Literature Question

As one who aspires to the title ‘writer’, it is important that I read. There’s no better teacher than a well-written story. Toward that end I’ve been digging back into books that have stood the test of time, stories that everyone in the world has read except me. Pride and Prejudice and Zombies is one I’ve been meaning to get to for a while.

I have a question, though. In this version, Elizabeth Bennett is a young lady from the lower portions of the upper class, and she’s reasonably attractive, quick of wit, and a bit of a snippy bitch (many of her most pointed insults almost got past me, delivered as they were with subtlety and nuance that only upper-crust English can summon). Plus, she’s one hell of a zombie slayer. Her entire brood of sisters are quite accomplished at deanimating the undead.

She has caught the eye of more than one gentleman, but her zombie slaying is considered unladylike by some, and her first marriage proposal comes with the assumption that she will stop slaying zombies. Naturally she rebels at the mere idea.

I never read Pride and Prejudice (some sort of hackneyed subset of the version I’m reading), but I can’t help wondering how much of the zombie content is invented and how much is paraphrasing what was already there in the version Jane Austen did without assistance. Zombie-slaying of course wasn’t in the abridged version, but was there something else instead, something non-zombie-slaying Elizabeth would be loath to give up? Lady Catherine de Bourgh is renowned for her zombie slaying, and so is her daughter. What claim to fame do they have in the first draft?

1

Happy Ought-to Ought-to Day!

It’s a special day on the muddled calendar, although the name is based on that old-fashioned calendar that many people insist on using even today. It’s February twoth, or as valued bloggcomm member and new blogger Jesse pointed out, 02/02, pronounced aught-two aught-to (rhymes with ought to ought to).

The day forms a nice partner with January twoth, a deadline to measure progress on the new year’s projects. (I really should have mentioned it back then.) My list of ought-to’s is a long one this year, starting with kick-starting the writing and reading more. Wouldn’t hurt to get a blog episode up now and then as well. I really need to get the muddled calendar displaying correctly as well, and get the sweet voting working again, and do something about Jer’s Software Hut…

What ought you to do today?

1

A Quick Health Question

Three days a week I work out. It’s about 50-50 aerobic and resistance training, starting with thirty minutes of rowing machine and treadmill, followed by crunches and weights. It feels pretty good to have done it.

After working out we generally spend a few minutes with my sweetie’s folks, then we drive home. I’d estimate it’s at least half an hour between the end of the workout and our arrival home. Each time, on the way up the stairs to our apartment, I get a massive head rush.

Anyone know what’s causing it? Should I worry? When I was younger I had low blood pressure, but last time it was measured my blood pressure was on the high side. I haven’t lost a significant amount of weight, but I think I’m in better shape.

Any insight or wacky theories are welcome. Thanks!

A Job I’m Glad I Don’t Have

As you might be able to tell from the paucity of episodes here at MR&HBI, I’ve rejoined the ranks of the employed. My writing has taken a real beating, so today I’m going to spend some time writing about work. You don’t have to thank me, it’s what I do.

I don’t mind writing software; I’m pretty good at it and I can make pretty decent money doing it. I would much rather write code than dig ditches, for instance, and luckily for me the world has decided that making Web sites is worth more than roadside drainage. (Before you go and say, “that’s because it takes skill and training to make a Web site, but anyone could dig a ditch’, ask yourself – could you dig ditches for a living? If the economy were turned upside-down, that ditch-digger living in his nice house would say, ‘anyone can make a living sitting on their ass in front of a computer, but I dig ditches. I’m glad things are the way they are, is all I’m saying.)

My current job sends me dangerously into territory I don’t much like, however, and that’s the area known as Information Technology. It’s not really a good name for the job, which is about setting up computers and keeping them running. It’s less about making things and more about making things work.

Last night, for instance, I moved the Web product I’m working on to a different server and it didn’t work. Naturally I assumed the problem was in my code (it had worked on that server in the past), so it was several hours later that I discovered that for reasons I still don’t know, the server failed when it tried to compress very large messages. Just *poof* no response beyond the number 500 (something went wrong). To make things more fun the server was specifically set up to not write out a lot of error messages to its log. I turned off the compression feature (with a hammer) and things worked again. Five hours or so spent to add seven characters to a PHP file, to make things work the same way they already did on other servers. Welcome to the world of IT.

I think the original intention of the phrase information technology referred to the the information that would be stored, manipulated, and distributed by machines. What the I really stands for is the vast store of arcane crap you have to know to do that job well. What line of the php.ini file to modify if you want zlib output buffering and utf-8 character encoding. How to set up all the computers in an office to use a local domain name server first. That’s the information in IT.

The worst thing about having an IT job is this, however: When you’re doing a good job, no one notices. When a company is running smoothly, that’s a sign that the IT department can be downsized. There are no problems! What are those guys doing all day? Having things not happen as part of your job description makes for tricky times when you do your job well. Of course, when something does go wrong people know just where to find you.

So if you work in a company that has people on payroll working to keep your technology humming along, cut them a little slack. Someone’s got to do that stuff; be glad it’s not you. I do enough IT now to know that I’d rather let someone else have the pleasure.

You Know it has to Happen

I’m waiting for the commercial that has:

“I’m Steve Jobs, and Windows 7 was my idea.”

An Important Science Question Investigated

I give this to you without comment:

The Airspeed Velocity of an Unladen Swallow.

MacPorts and GIMP

Preamble for those here by the grace of Google: Yes, I do eventually get around to talking about Gimp in this episode. Short version: it works but takes hours. Anyway, on with the show!

Setting up a new computer can be a tedious task; there are all kinds of settings and programs and files and whatnot that need to be passed from old to new. When you work with Web development things can get even more cumbersome, as one finds oneself descending deep into the world of IT. There are programs to install that all have to talk to each other, and configuration files to be tweaked. Many of the applications that are required have no user interface of their own, they simply run in the background and answer requests from other applications.

I found myself facing (for the third time in three months) the need to install the latest Apache (and set up virtual hosts), PHP, Pear, MySQL server, PHP email addons, Propel, and on and on. For many of these items, the instructions for installations go something like:

1) Download the source code
2) Configure the build
3) Compile the application

And the instructions go on from there. For most of the above there are shortcuts, and probably-recent-enough versions of some things come built-in with the Mac OS, but when you install it yourself you can get everything where you want it and avoid conflicts. Still, this can be a long, tedious, pain in the butt to get going. And when you install something and it doesn’t play well with the others, finding that one line in the secret config file that’s causing the problem can be a real pain.

Enter MacPorts. MacPorts is a project that has developed a system that does all the steps of the installation for you, and puts everything in standard places so everything else installed with MacPorts can find it and talk to it. There’s still some configuration to do (tell PHP where the database server’s socket is, and set passwords for instance), but overall things are much simpler, and there are very good instructions out there for tweaking and troubleshooting MacPort installs. Since the person writing the instructions knows where all the files are in the standard install, instructions can be much more specific.

With MacPorts installing php 5.3.1 was a simple matter of typing “sudo port install php5” and letting the MacPort system do the rest. Hooray! Setting up a server is suddenly much simpler.

As an aside, MySQL didn’t work when I used MacPorts to install it on a previous machine. Don’t know why. Ran the install, followed the instructions, nothing. After a few hours banging my head against it, I went and got the excellent binary installer. It worked without a hitch. This time around I didn’t bother with the MacPorts version at all.

Anyway, thanks to MacPorts, I was able to get a complete development system up with nary a hitch, in a fraction of the time. Knowing where all the config files were this time around helped as well. I found several useful links on the Web, particularly from HiveLogic and my new buddy Danilo Stern-Sapad who took a little grammar rant from me with grace.

On that note, I read the phrase “How to setup…” so many times in so many places it’s amazing I still have teeth.

Edited to add: I have now written my own tutorial which does into greater detail than the above, and includes a works-every-time MySQL install.

Last night I realized I hadn’t installed GIMP on this computer yet. GIMP is an open-source graphics program that wishes it rivaled Photoshop but it doesn’t really. It’s free, however, and when you consider the incredible amount of work that went into it, you have to be impressed. I don’t do a whole lot with graphics, so GIMP is usually adequate for my needs.

When I went to the Web site for GIMP I found a couple of options for installation, including MacPorts. Just type “sudo port install gimp” into the terminal and that’s that. Pretty sweet.

One thing about a program like GIMP: it’s really a collection of a bazillion smaller parts. Many of those parts require other bits to work. When you run a traditional installer, all the parts are already there and they’re already tied together in a neat bundle. MacPorts does things a little differently; each part knows what parts it depends on to work, so when you say “install gimp” it first looks at the parts gimp needs, then at the parts those parts depend on, and so forth. You get to watch (if you choose to pay attention) the parade of all the little pieces as they’re installed, each the product of an individual or small group of people who have allowed their work to be exploited for free.

For GIMP, the list of dependencies goes very deep. I watched as X11 was installed. X11 is already on my computer, but ok, this is MacPorts and they keep their own realm and that way they can update parts without worrying about how that will affect non-MacPort installations. It’s redundant, but that’s why God made big hard drives.

Then I saw Python 2.6 install. Later, Python 2.5 went by. One of the little pieces seems to depend on an earlier version of Python. This probably means the person in charge of that bit just hasn’t updated it recently. On the installation went. After a while the Gnu Compiler Collection came down the pipe. gcc is a collection of compilers for building programs, and I watched as gcc was built… using the gcc already installed on my machine. Hm. And what’s this? Fortran! Yep, somewhere in the great tree of dependencies (maybe ‘root system’ would be a better term), someone decided that a Fortran compiler was necessary to run GIMP.

Actually, that’s not quite fair; the piece that loaded the Fortran compiler might need it for other tasks not related to GIMP. Just because GIMP uses a library doesn’t mean that’s the only use for it. Still, I ended up with a lot of stuff I don’t need. It’s all invisible and I’d never know it was there if I hadn’t watched the install (which took hours), so it’s not a disaster or anything. And next time I need Fortran I’m ahead of the curve!

Time slipped past, the install continued. I went to bed. When I got up this morning to check if the build was finished, I discovered there had been an error. Yep, the MacPort version of gimp-app doesn’t currently compile on 64-bit operating systems. All that other stuff that was installed? Python 2.6 and Python 2.5, the Gnu Compiler Collection (including Fortran), libgnome and libbonoboui and tkl and tk and gd2 and dozens of other things I don’t know what are, they’re still there, waiting to be useful in some way.

Edited to add: The compile bug has been fixed; I recently used MacPorts to install Gimp on my 64-bit laptop. It took a long, long, time, but now it works just fine.

1

AiA: White Shadow – Episode 12

Our story so far: Allison is an American high-school student who has transferred to a private prep school in Japan. She is a transfer student, and in this Japan, that means she will be the cause of upheaval and strife. Although she really doesn’t understand what’s going on around her most of the time, she is starting to understand White Shadow, a computer virus that can infect the human brain. Or something like that. It seems Allison is pretty good with computers, and may be the person to stop the scourge. Those around her sort of take this for granted. She’s a transfer student, after all.

Last night the virus got into the video system of a local dance club, and the results were horriffic. Allison has decided to investigate, and she has been joined by her friends. As soon as they entered the building, however, they were confronted by a man with a gun. While he was talking, Alice simply vanished.

If you would like to read from the beginning, the entire story is here.

“Damn! Find her! She must not escape!” The man with the gun gestured frantically. Spotlights stabbed through the darkness all around the group, and from the shadows men emerged slowly, menacingly, clad in the heavy rubberized suits of the Institute, faces invisible behind reflective glass. Each bore a wicked-looking rifle, raised and ready to fire as they swayed back and forth, sweeping their headlamps around the night club.

Ruchia fought down a rising sense of panic. She might have lost it completely but Seiji was holding on to her arm, his touch reassuring. He was standing completely still, staring at the man who had stopped them, his face a mask of pure rage. Yet he held himaelf, one hand on Ruchia’s arm, the other on Tasuke’s shoulder. It looked like Tasuke was about ready to attack the nearest Institute man, if Seiji wasn’t holding her back. Ruchia wished she had a little of her friend’s courage.

Kaneda was just standing there, looking around himself in confusion, as if he had just awakened out of a dream to find himself there.

The man who had first accosted them strode up to Ruchia and shouted down into her face. He was a big man, with broad shoulders, who wore his silk suit jacket like a military uniform, his tie knotted with absolute precision. His black hair was cut short. “Where’s the other one?” he screamed.

Ruchia cowered before the man’s anger, grateful for the support from Seiji. Her knees were shaking. “What other one?”

“The other girl, stupid! the one who was standing right next to you!” Ruchia could feel the man’s spittle on her face.

“T-t-tasuki? She’s right there.”

“Not her, stupid! The other one!”

Ruchia felt the tears welling up in her eyes. What was this crazy old man talking about?

“What the heck are you talking about?” challenged Seiji. “We’re all right here!”

“Don’t play stupid with me! There were five of you!”

Tasuke jumped into the fray. “What are you, stupid? Can’t you even count?”

One of the shambling hulks in the Institute suits stepped to the side of his leader. “Uh, sir?” His voice came through a tinny speaker on his chest. “We’ve double-checked the surveillance cams. There were only these four.”

“What?!”

“Just the four, sir.”

“Damn! That can’t be!”

“I’m sorry, sir, but…”

“Damn that White Shadow!”

What the heck is he talking about? Ruchia wondered. Anyone could see that there were four of us when we came in. She looked at her friends to see if they might have some idea what this guy’s problem was. She thought that Kaneda was about to say something, but then he thought better of it. He went back to looking confused.

Ruchia had a bad feeling as the man looked them over. He was deciding what to do with them, she was sure. She found herself wishing that Allison were there. This was definitely transfer-student sort of trouble. Ruchia wondered why they had even agreed to meet Allison here.

“Wrap ’em up,” the man said. “Let’s get them back to the institute. They might be contaminated.”

“Hey! You can’t do that!” Tasuke protested. “We’re fine!”

The big man smiled grimly as the institute men in their protective suits closed in around the four of them. “I will be the judge of that.”

Ruchia screamed, Tasuke struggled and kicked, Seiji shouted in defiance, but it made no difference.

“You can’t do this!” Seiji shouted. “Where are you taking us?”

As they pulled a heavy black hood over her head, Ruchia thought she heard Kaneda say, “To the room with no doors.” She heard a thud and Kaneda grunted.

“Kaneda!” Ruchia called. “Kaneda! Are you OK?” He didn’t answer. Hands were on her now, cold, impersonal, heavily gloved hands, grabbing her arms, her legs, her chest, wrapping aroung her middle and lifting her up as if she weighed nothing. She screamed, she kicked, to no effect. She had never felt so vulnerable as the hands moved over her body. “Help me,” she sobbed, but no one answered.

From a catwalk high above the floor of the discotheque Allison watched as her friends were bundled up. Her gut wrenched when she heard Ruchia’s piteous plea for help, and her blood boiled when they hit Kaneda over the head to silence him.

Allison had been wise to get there early, to slip in unnoticed and conceal herself. Had she even suspected that the institute would take her friends, however, she never would have done it. Now it was her fault they were in trouble, and it was going to be up to her to get them out.

But what was the institute? She had guessed that White Shadow came from there, but now it seemed like they were actually fighting against it. Did that make them her allies? Her gut replied with a resounding ‘no’. Perhaps they had a common enemy, but that didn’t make them friends.

Now the Institute had taken her friends. To the room with no doors, Kaneda had said, before they pummeled him into silence. What did that mean? Allison didn’t know, but she suspected White Shadow might.

The three men sat in the grass beneath a mighty tree. They wore their monk’s robes carelessly, exposing their knobby legs and sometime more, causing more than one passerby to avert their gaze with a stricken expression. They sat in order of height; on the lap of the middle monk there was a laptop computer. All three stared at the screen with rapt attention, the colors from the screen lighting up their faces in a steady progression through the spectrum.

“It’s terrible,” the tall one said.

“It’s wonderful,” the short one agreed.

“What are we looking at again?” the one in the middle asked.

“It’s a computer virus,” the short one said.

“It’s God,” the tall one said, nodding in agreement.

“Truth,” the short one said.

“Lies,” the tall one agreed.

“It’s making my lap sweaty,” the middle one said, lifting up the computer.

“That’s what she said!” the other two said in unison. The broke out laughing.

“Next time,” the one in the middle said, “we need to find someone else to be the straight man.”

“Next time…” the tall one said.

“Next time…” the short one said.

“That Seiji boy was fun,” the middle one said.

“Very serious young man.”

“Wouldn’t know a joke if it suffocated him in his sleep.”

“I hope they haven’t killed him yet.”

The three men nodded solemnly, then began to laugh.

Happy January 2th! Uh, whoops…

January twoth is a holiday in the Muddled Calendar, first suggested by Mr7k a few years back. He pointed out that January first is hardly the time to be getting a start on the new year, what with the aftermath of New Year’s Eve to contend with, and all the sporting events on television to watch. No, much better to have January twoth, New Year’s Day (observed), set aside for all the getting-off-on-the-right-foot activities.

This morning I thought it would be nice to post a short episode here and to spend a little time getting my own year started on a positive note. Then I noticed that January twoth was yesterday. Huh.

1

Making Truffles

The insides and the outsides

The insides and the outsides

There is a thread in my life, a theme that plays out time and again. It is a small part of who I am, a constituent in the definition of ‘Jerry’. This bit of Jerryness is manifest often, and was apparent on the Night of Truffles. Simply put, there is a gap (sometimes quite large) between my image of what I want to achieve and my ability to achieve it.

Take drawing, for instance. On the occasions I have set drawing implement to paper, my mind has produced vast scapes of color and light, form and structure, of a depth that could stir the most jaded soul. What comes out on the paper is, well, not that.

Topping off the Truffles

Topping off the Truffles

And so we come to the task for the evening: painting melted chocolate into the molds, so that it can be filled with different chocolate stuff and then covered with chocolate. It is important to avoid thin spots in the chocolate, lest the structural integrity of the truffle be undermined. Too thick, and the ratio of crunchy outside to smooth inside is lost. The walls of chocolate must reach the top of the mold in even thickness.

Of course, getting the chocolate thickness exactly right isn’t really that big of a deal. It’s not that hard. Yet, as I stood there using a kitchen knife to distribute the chocolate, there was always the platonic ideal of the truffle, haunting me, rendering my sorry efforts inadequate. As a result, the light of my life produced about two truffle shells for every one I made.

That's a keeper!

That's a keeper!

Then came the measuring of the inside goop into the shells. “This is really easy,” the beacon who guides my heart said. “You just have to fill them almost to the top, but leave enough space so the chocolate on top can seal up with the sides.” Yes, but exactly how much wiggle room does that leave me? I was a little better with this task, and occasionally even recognized that the tiny amounts of filling I was adding and removing couldn’t possibly make the slightest difference. In my gut roiled the fear of producing a truffle that cracked or leaked or was otherwise unsightly. When you consider how yummy the thing was going to be no matter what happened, it might seem like a lot of worry over very little. Still, the Ideal Truffle loomed, superimposed by my imagination over each still-incomplete confection.

Not All the Truffles

Not All the Truffles

The next phase of production was best done by two people: the chocolate-topper and the sprinkler. I was elected sprinkler and happily so. My sweetie laid the molten chocolate over the tops of the truffles, then handed them off to me, and I sprinkled peppermint and toffee fragments into the still-soft chocolate. I managed to make this more difficult than necessary (each truffle had to have a good distribution of fragment sizes, and the peppermint looked better with red stripes showing), but not debilitatingly so. (Crushing the hard candy had it’s own uncertainties. Fragments too large? Too much dust?)

Eighty-eight truffles later, it was time to start again.

Ultimately, all the worry was for naught; the truffles came out quite lovely, and tasty like crazy. A few even approached the Ideal Truffle.

1

Pfeffernüsse!

It’s been a week since we made these lovely balls of yum, so I’m just going to let the pictures tell the story.

Rolling out the blobs

Rolling out the blobs

My main job: rolling the rough blobs of dough into little spheres and laying them out on the cooking-stones.

 

The kitchen smelled great!

The kitchen smelled great!

Looking lovely in the oven.

 

Keeping the assembly line moving

Keeping the assembly line moving

They bake quickly, so it’s important to keep the stones moving from station to station in a constant rotation. 44 Pfeffernüses per sheet.

 

Some (but not all) of the cookies.

Some (but not all) of the cookies.

We made rather a lot of them. It was a couple of days later when my sweetie applied the powdered sugar coating.

The best part: naturally we had to eat the ones that broke apart during powdered sugar application. It’s all about quality control, you know.

An open letter to the retard driving a white compact car on Highway 17 in dense fog with no lights

You, sir, are a fucking retard.

Sincerely,
Jerry