MacBook, defective by design banner

Put the knife down and take a green herb, dude.

One feller's views on the state of everyday computer science & its application (and now, OTHER STUFF) who isn't rich enough to shell out for

FOR ENTERTAINMENT PURPOSES ONLY!!! Back-up your data and always wear white.
URLs I want to remember:
* Atari 2600 programming on your Mac
* joel on software (tip pt)
* Professional links: resume, github, paltry StackOverflow * Regular Expression Introduction (copy)
* The hex editor whose name I forget
* JSONLint to pretty-ify JSON
* Using CommonDialog in VB 6 * Free zip utils
* that hardware vendor review site I forget about is here * Regex Tester
* Read the bits about the zone * Find column in sql server db by name
* Giant ASCII Textifier in Stick Figures (in Ivrit) * Quick intro to Javascript
* Don't [over-]sweat "micro-optimization" * Parsing str's in VB6
* .ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture); (src) * Break on a Lenovo T430: Fn+Alt+B
email if ya gotta, RSS if ya wanna RSS, ¢ & Δ if you're keypadless
Thursday, August 25, 2016

Tire Kingdom ad for Buy 2 get 2 free!!1!

One thing that's bugged me a little is the penchant for tire places to have great buy three, get one free tire deals, but recently Tire Kingdom blew them all out of the water with its BOGO replacement: Buy two, get two free deal.

I don't get it. Either we're getting robbed when we buy a single tire -- which, I'm afraid to admit, I've been trained to do over long decades of watching a particular role model do the same -- or there's something fishy about these BTGO and now BTGT offers.

There isn't a ton of red tape on the Tire Kingdom deal. Here it is:

For a limited time, buy two select tires, and get two free when you purchase our Value Installation Package on all four tires
Valid on purchase of select in-stock tires. Purchase of Value Installation Package at regular price required on all four tires. Charge for additional parts/service if needed. Plus up to 10% shop fee based on non-discounted retail price not to exceed $35 (where permitted). Local, state and/or tire disposal fees where applicable. In instances of a staggered fitment vehicle, the purchase combination must include four (4) qualifying products. Discount will be taken off the lowest-priced tires. Not valid with other discount offers. Eligibility may vary depending on tire size and model

Okay, so we've got a shop fee for 10% of the tire, which is a little high. It's fair to say that we're only getting a 90-95% break in the freebees.

But the only super serious issue here is "when you purchase our Value Installation Package on all four tires". At its worst, we might something like this post suggests they found:

Buy 2 tires, get 2 free..

2 tires, installed, costs $465, and that's if you only buy the 2 and don't get the other 2.

Now, if you get the 2 free and get those installed, it's $950.

But let's pretend installation fees aren't the scam for a second. What's going on? I think I figured it out.

Tire places : Zombies :: Used Tires : Brains

I recently had a nail in the wall/edge of the tread of a tire, and dropped it off loose to my usual tire place to get a replacement. Got a call later that they only had one new tire in stock at that size... and one used tire.

I kinda wanted a nicer tire with a longer warranty than they were offering, but didn't want to wait carless for the two or three days it'd take to come in. I also had, pre-nail, four fairly old tires, with one bald enough that it really did need replacing soon. Naturally, this one with the nail was one of the tires with a decent amount of tread left. But it couldn't be repaired because of the nail's placement, so off it went.

(Did I rotate the tires? No, I'm afraid I didn't, so one was much worse than the others, I'm afraid.)

Against my better judgement, I went with the used tire, pretending that I'd only use it until I got all four tires in to one of those crazy buy 3 get 1 deals. That is, I was, in my mind, replacing trash with trash until I could get all the trash out.

Used price: $55 + installation New price: $110 + installation

Apparently margins on new tires at retail aren't great, but the margins on these used tires are. Why? Because when they replace all four tires, the shop gets a ton of good, free used tires from you. I started getting suspicious that the tires on my car that I thought looked okay really were okay, and later decided to replace the bald tire with a brand new one.

When I went in recently to repair a busted radiator, my local shop gave me this as part of their generic vehicle checklist:

image showing tire wear on my tires

So tell me which was...

  1. The new tire
  2. The used tire I'd recently purchased
  3. The first and second four year-old tires that are left.


  1. New Tire: Right front, exactly where you guessed.
  2. "New" Used: Right rear! As bad as my worst remaining old tire!
  3. Four-year old tires: Both lefts!
    • One painfully better than my "new" used.
    • Of course the one I'd replaced was a rear tire that looked just as good...

So if I'd gone ahead and gotten four tires just to replace the bald right front, pre-nail, I would've given that tire company at least two great used tires, and probably a third they could've used too. That's $110-$165 at retail I would've handed right back, plus installation fees, to the tire company. That is, I've already given them back more than the free tire they'd "give" me. Plus that fourth tire cost them less than the $110 retail price. Plus I'd pay them installation on that "free" tire that.

Your car is a veritable gold mine of resalable used tires to tire companies. That's one reason why they want to entice you to install all at once, which also means likely replacing a few early. If you rotate tires and drive them all equally down to the nubs, congratulations. You win with this deal.

I'm betting that's the minority position. ;^)

Labels: , ,

posted by ruffin at 8/25/2016 12:13:00 PM
Wednesday, August 24, 2016

Perhaps the most important Visual Studio trick to know about the Immediate Window: To print something with all the newlines and carriage returns "invoked", so to speak, you suffix the string in question with ,nq.

Say you're debugging some SQL. This isn't horribly useful...

String with linebreaks rendered in immediate window

It's all on one line with \r\ns all over the place.

Let's try it again with ,nq afterwards...

SQL formatted without carriage returns and newlines

For some reason, I've got the SQL indented like mad (okay, okay, it's so it lines up in Visual Studio. This is a quick and dirty utility service that has embedded SQL), but you get the point. It's actually legible with the ,nq suffix.

I could've sworn I'd posted this before, but couldn't google it up in my own blog in a minute or less, so here we go again, proper keywords attached.

Labels: ,

posted by ruffin at 8/24/2016 10:46:00 AM
Tuesday, August 23, 2016

FLAC file playing in Windows Groove

Hello, kudos to Windows. Groove Player is playing FLAC format out of the box, as advertised, apparently.

I'm not an audio snob, but I sure do enjoy downloading free and legal shows from etree. They're usually in FLAC format now (no more shn, I don't think), and not having to convert them is wonderful. And it's nice not having to load a new codec to get things to play like I did on macOS for so long (thank you for years of use, Perian).

I've gotten to the point that I enjoy using the Windows Groove player okay. It's so much more straightforward than iTunes now, and its Metro style/UWP GUI is a huge improvement over Windows Media Player. Lighter-weight, less resource hogging software is good, though I'm afraid it's going to keep creeping up as they try to sell more and more stuff (lots of streaming stuff in "Your Groove" now). FLAC support just adds to the enjoyment.

Labels: , , ,

posted by ruffin at 8/23/2016 06:01:00 PM

from a google search while writing this

comments from 9to5 Mac

From Vesper's own release notes:

We three at Q Branch — Dave, John, and Brent — are greatly appreciative of everyone who has used and said good things about Vesper. We love this app. But the time has come to say goodbye. We thank you, sincerely, for your support and enthusiasm.

From Brent Simmon's blog here:

I loved working on Vesper. It was one of the great software-making experiences of my life. We’d get on a roll and it was wonderful.

And now it hurts to turn it off, but it’s time.

... and here...

The code is all Objective-C. It’s an iOS 6 app with just enough changes to keep it working on iOS 7 and beyond. It knows nothing about size classes, presentation controllers, and so on. Doesn’t even use auto layout. It’s not an example of how you’d write an app these days.

Belief inside Q Branch: if we had started with a Mac app rather than an iOS app, Vesper would have been much more successful. That wasn’t clear at the time we started, though (Dec. 2012).

... and from the same post as above, describing what comes next for Simmons...

This is the last app on the App Store where I wrote all (or almost all) of the code. Odds are excellent that there will never be another app written largely by me on any app store.
I’m working on new stuff from Ranchero Software. I had planned two apps, but I think it’s going to be just one, just because two takes too much time. So I picked the one I’m more passionate about.

It’s a Mac app...

And then that will be my app. The thing I work on for the next 10 or so years, until I retire. That’s the plan. (To be clear, though, I don’t plan to leave my day job, which I love.)

What happened?

  • "time to say goodbye"
  • "but it's time [to turn it off]"

These quotes aren't helpful.

  • "if we had started with a Mac app... Vesper would have been much more successful."

This might be useful. Sounds like the app wasn't making much money.

If it's a client-side only app, that's no big deal. It costs you very little (your Apple developer account cost) to keep something on the app store.

There are two problems with Vesper, however.

  1. They're syncing everything into their own cloud service.
    • This costs money every hour it's open.
    • Syncing images (size) can be a bear.
  2. The code isn't particularly easy to maintain.
    • See "It's an iOS 6 app... It knows nothing about size classes [etc]..."

The first means it's costing them money today (EDIT: Gruber adds that they were also paying licensing fees for the font. He's removed that portion from his post, but it was originally there). The second means it's going to cost them a disproportionate amount of time to improve the app tomorrow.

If today and tomorrow are overly expensive, it might be foldin' time.

Post Mortem Results?

Here's my guess at what happened.

  • They're stuck with a crappy codebase (we all write some)
  • Vesper has high server fees relative to new income
  • It's a poorly chosen app category where there's too much competition
  • Related to the previous: Nobody's buying
  • Most importantly: The app's not stellar. Great design, decent start, not yet stellar.

It's amazing to think that folks with the name recognition, at least in Apple circles, of Wiskus, Simmons, and Gruber could fail, but they did. To Gruber's credit, he didn't pimp Vesper much at all on The Talk Show or, iirc, Daring Fireball a few months after release. But he didn't do the app any favors with that restraint either. Wear your own shirt.

I heard that Gruber was using Vesper on his Mac in the iOS emulator. I think that tells you something pretty important right there.

I think you can also piece together from Simmons' final statements that he wasn't interested in writing a notes app for the Mac, and I'd guess that this provides the three a good escape narrative. "If we'd only made a Mac app..." I'd counter with, "If that's a good market, why not do it now?" And if the syncing code works well, it's done, man. You're 50% of the way to a notes app already (sync and much of your design is done)!

Again, I don't think Simmons is interested in writing a notes app for the Mac. But I think the real answer is that a great Mac notes app wouldn't have saved them, even if the coding time was zero.

Good, but not great

Vesper was good, but not great. It was, unfortunately, buggy. There were a number of times that I couldn't see and/or add images in one screen orientation. Sometimes cursors would jump around. Sometimes I couldn't enter text. It's a notes app. That's bad.

The idea -- the design -- of Vesper was great. It wasn't a great app. Mediocre apps, regardless of design, tend to fail if they're not maintained and improved. Vesper's had how many updates since 2013?

Revisiting The Marco Effect

I think the most important take home here is that The Marco Effect is greatly overestimated.

That is, if Marco's apps were no good, he probably wouldn't stay in business. Heck, if Marco's stuff was decent, even solid, it might not be worth making.

If Marco had the same reach as The Talk Show and Daring Fireball, picked the wrong app, and that app was only "okay", they wouldn't be worth his time.

Vesper shows me we don't give Marco enough credit. It also tells me app dev is a very tough gig.

A cynic might say that Wiskus-Gruber-Simmons simply didn't want to "stick it out" (certainly they could cover even server-side losses for a while), or that 33% of the cash from decent is much less than 100%, or that Overcast is a labor of love & doesn't make tons of cash either (actually, Overcast does quite well), but I still see Marco being undervalued here. His apps do better because of both (business speak alert!) product-market fit and quality.

Nice of them to let us dump our stuff before it disappears, natch. ;^)

Edit: Tell me what you really think

Ouch. The reviews have turned pretty nasty.

Customer Reviews

Oh well.

A good example of why subscription services are bad and why extremely expensive apps are bad. And this seems to be both. A $10 app for a service that is now closing and will be completely unusable. And if you haven't logged in for a while, you may have missed the closing notification and you'll be too late to recover important or invaluable data. I discovered this via Apps Gone Free. That's how I heard of it today and checked it out. Sad to see all of this.

About time you pulled the plug

Nice waste of money this app was. I bought it years ago based on the promises of one of the most opinionated, self promoting guys on the Internet. Turns out John Gruber & pals were a lot of talk & very little action. This app was abandoned almost immediately after it was released. Let this be a warning to others not to bother with promises of snake oil like this in the future.

I agree with those who are unhappy. Thank Gawd I didn't have to pay.

There are several other note apps that are much better and have mush better functionality.
No way to add to an existing note. No way to unarchive a note, and the list goes on of deficiencies.
Sync is discontinued.
Pull the plug, call it a day.

Edit #2: Gruber weighs in, a little

Must've missed it yesterday, or it came in later than I catch up on RSS, but Gruber says he's going to do his own postmortem in a bit:

I’m working on a postmortem — or maybe more of a eulogy — but for now, I can’t express my feelings any better than those two short paragraphs from Brent.

Will be interesting to see how candid he is. I'd like Jared Sinclair, Marco Arment-level candidness, but I'll guess we'll take what we get.

Labels: , , , , ,

posted by ruffin at 8/23/2016 11:18:00 AM
Monday, August 22, 2016

Tell you what, being an independent shop has its drawbacks. One is that it's hard to be good at design and zeroes and ones. There are certainly people great at both, but it's much fewer than those who are really good at just one or the other. That's nearly a truism.

That means it's taken me days to get my website looking presentable over and above my cheaping out and using a template for the site.

One of the biggest issues for me was trying to get a grid of application features to look good in both desktop and mobile modes. I've got a pretty common set of three features and an image for each. On the desktop, the bootstrap grid arrangement is simple enough:

Desc 1

Desc 2

Desc 3

Image 1

Image 2

Image 3

But when I go to mobile, I want the order to change fairly drastically.

What I want

What Bootstrap Does
by Default when small viewpoint

Image 1

Desc 1

Desc 1

Desc 2

Image 2

Desc 3

Desc 2

Image 1


Probably makes more sense with numbers...







Changes into...

What I want

What Bootstrap Does
by Default










That's kind of an extreme change.

First attempted solution

I wasted a lot of time trying bootstrap push and pull. Look at this answer, for instance.

So basically in a 3 column layout of any web page the "Main Body" appears at the "Center" and in "Mobile" view the "Main Body" appears at the "Top" of the page. This is mostly desired by everyone with 3 column layout.

<div class="container">
    <div class="row">
        <div id="content" class="col-lg-4 col-lg-push-4 col-sm-12">
        <h2>This is Content</h2>
        <p>orem Ipsum ...</p>

        <div id="sidebar-left" class="col-lg-4  col-sm-6 col-lg-pull-4">
        <h2>This is Left Sidebar</h2>
        <p>orem Ipsum...</p>

        <div id="sidebar-right" class="col-lg-4 col-sm-6">
        <h2>This is Right Sidebar</h2>
        <p>orem Ipsum.... </p>

Look at the first col-sm-12 class. That means the next two divs end up on new rows, right? So I can count on pulling my images back a row or two, and pushing my descriptions to fit, right?

Wrong. After fiddling around a while, pushes seem to simply push off to the right of the viewable row. And this question pretty much confirms it.

Second solution

Since that question suggests that we can't push and pull, I figured I'd take one of these more complicated options. They boil down to...

  1. Hide at different view "grid tiers"
  2. Use JavaScript event handlers to catch resizing

The first makes more sense I think, though you end up having to duplicate code.

I ended up with code like what's below. What's important to note is that the first row is hidden-sm-down, so it's not visible in small or smaller tiers. Then I've got extra lines -- the description text -- repeated in the next row in divs that are hidden-md-up.

It does get the effect I want, even if it's not DRY.

<div class="row hidden-sm-down">
    <div class="feature-desc col-md-4 ">
        Tools to help you learn Markdown. <!--- <<< This'll be repeated -->
    <div class="feature-desc col-md-4">
        Keyboard shortcuts once you're a pro. <!-- and this. -->
    <div class="feature-desc col-md-4">
        Easy Actions make editing effortless. <!-- and this too. -->

<div class="row">
    <div class="col-md-4">
        <img class="col-image" src="./resources/toolbar350x55.png" alt="toolbar showing a few of MarkUpDown's commands" />
        <div class="hidden-md-up"> <!-- \/\/\/ =====REPEATED!!!===== -->
            <ul><li>Tools to help you learn Markdown.</li></ul>
    <div class="col-md-4">
        <img class="col-image" src="./resources/keystrokes.gif" alt="Just a few of MarkUpDown's keystroke commands" />
        <div class="hidden-md-up"> <!-- \/\/\/ =====REPEATED!!!===== -->
            <ul><li>Keyboard shortcuts once you're a pro.</li></ul>
    <div class="col-md-4">
        <img class="col-image" src="./resources/clipboardUrlInsert.gif" alt="Animation of smart clipboard insertion with urls" />
        <div class="hidden-md-up"> <!-- \/\/\/ =====REPEATED!!!===== -->
            <ul><li>Easy Actions make editing effortless.</li></ul>

<div style="height:15px" class="row hidden-sm-down">

I don't like it, though I don't even know that it isn't what a bootstrap master would do to get the same effect. I do know that any idealistic setup seems to go completely out of the window once your use case gets complicated enough, whether with conventional code or with CSS.


Here's a chart of the different "down" and "up" classes to hide your stuff, though it's from the version 4 alpha...

Extra small devices Portrait phones (<544px) Small devices Landscape phones (≥544px - <768px) Medium devices Tablets (≥768px - <992px) Large devices Desktops (≥992px - <1200px) Extra large devices Desktops (≥1200px)
.hidden-xs-down Visible Visible Visible Visible
.hidden-sm-down Visible Visible Visible
.hidden-md-down Visible Visible
.hidden-lg-down Visible
.hidden-sm-up Visible
.hidden-md-up Visible Visible
.hidden-lg-up Visible Visible Visible
.hidden-xl-up Visible Visible Visible Visible

Labels: , ,

posted by ruffin at 8/22/2016 11:37:00 AM
Thursday, August 18, 2016

So here's a fun RapidWeaver 7 bug...

Meta refresh on RapidWeaver header for a page

If you have a meta refresh tag and take a look at the preview of the page (say you want to check if your link works, or just want to check the "Hold on! Redirecting in a few!" text), the refresh is going to happen, even if you swap back to view the page's code.

That is, I can change the refresh time to ten or fifteen seconds so I can view the page, preview what I've got, go back into html edit mode, and then the code I'm looking at will go to the new page 10-15 seconds after I previewed the page.

Hint: If I'm on an html edit page, you can kill the refresh.

I've used RapidWeaver before. Skipped 6, but used 5 a lot, especially for class syllabi (when I TA'd), conference sites (see a, ahem, common theme? har har), even my own business site, which is what I'm "redesigning" now.

I like the app a lot, but it's still so danged rough around the edges. The html editor is not where I'd want to spend my time editing. There's no autocomplete of tags, no real html-friendly actions at all. The Markdown editor isn't good at all -- mostly just a text area for typing Markdown. What's worse, the Markdown parser isn't complete. I've had it miss links when translating into html, and that's just plain inexcusable.

I've often said these what amount to RAD tools will get you 80% to done in no time flat, but the remaining 20% will take you five times as long as it should've, ultimately netting you a loss in productivity. That's not the case with RapidWeaver. It essentially lets you passively partner with website designers, and gives you complete control over your html, which some hosts that support themes ultimately don't. So I get to skip most of the design overhead in developing a good looking website, which would take me weeks to months. But I'm still fighting with this app for days on days to do that last 20% easily.

Labels: ,

posted by ruffin at 8/18/2016 09:08:00 AM
Wednesday, August 17, 2016

Man. I tried to create responsive images today, and it was more trouble than I would've expected.

I think the biggest problem for me was a long detour through srcset. If all you're interested in is making sure a different image is presented on mobile, what you really want to use is picture.

Here's an example:

  <source media="(max-width: 500px)" srcset="./resources/mudSmall.png">
  <source media="(max-width: 1000px)" srcset="./resources/mudMedium.png">
  <source media="(min-width: 1001px)" srcset="./resources/mudLarge.png">
  <img src="./resources/mudLarge.png" alt="Responsive screenshot of MarkUpDown">

That's it.

Excellent, though not quite great, tutorial on creating responsive images here at MDN.

Biggest win? Now my screenshot changes when I tip my phone from portrait to landscape and back. Observe!

Landscape on iOS (iPhone 5 size)

landscape view on iOS

Portrait on iOS (iPhone 5 size)

portrait view on iOS

RapidWeaver Theme Removes ALL br Tags. Rly.

Now to figure out how to get that content centered for mobile portrait in the RapidWeaver theme I'm using (called Offroad). Hit a really nasty snag today where whoever made the theme -- a pack-in for the RapidWeaver application, no less -- decided they'd erase all br tags from your pages on the site. No, honestly. Some theme designer thought this code was a good idea:

if (
    $(".site-logo img").width(t / 2),
    $(".thumbnail-wrap, .thumbnail-frame").attr("style", ""), 
) { //...

Can you spot it? Of course you can. It's the $("br").remove(). WTFBBQ, man?

I changed it a bit to make it less invasive, but still, REMOVING EVERY br TAG PROGRAMMATICALLY IS A CODE SMELL, FOLKS. I'm not bitter. ;^)

if (
    $(".site-logo img").width(t / 2),
    $("br").not(".site-content-inner br").remove(), // <<< EDIT MADE HERE! -RUF
    $(".thumbnail-wrap, .thumbnail-frame").attr("style", ""), 
) { // ...

Everything seems happier now.

Labels: , ,

posted by ruffin at 8/17/2016 08:08:00 PM
Friday, August 12, 2016

From ESPN:

"We just haven't seen the explosiveness and the production that we'd seen the first four months of last year,'' manager Joe Girardi said. "This is not just this year. It happened in August and September of last year, and when you get to a certain age, whenever you struggle, the first thing they're going to ask, is he too old?"

I don't think it's [just] age.

Tell me this: Do you get drug tested when you're suspended? How long before the benefits of juicing disappear after you've stopped taking them? The math seems pretty simple here.

That said, I would've loved to see him grab four HRs in four ABs tonight and walk off with the most insane 700 HRs in history. Guess he'll settle for a double and a third of an inning at third, which was a classy move by the Yankees (though them letting him play shortstop for that third would've impressed me more).

Labels: ,

posted by ruffin at 8/12/2016 11:47:00 PM

When you write pretty much any code dealing with text, you get used to viewing raw bytes. Probably the most annoying part of it all, once you get your head around Unicode, is dealing with newlines in a tolerant, cross-platform fashion.

From today's Wikipedia:

0x9B? Good heavens. And if "OverDose On Arrival" isn't stuck in your head somewhere, you haven't really parsed text yet in your programming career. To these, you might also add 0D0D0A from an apparent Notepad bug.

The most annoying part is probably that you can't easily treat newline characters as any fixed number of bytes when you're dealing with crossplatform text. And you should probably always assume you're dealing with crossplatform text.

So when I'm breaking things down into informal test cases, I often shove the parsing code I'm writing into a testing console app project to see what's going on. Why I never did the below before when dealing with newlines, I have no idea.

public static void NLWriteLine(string toWrite, bool bookend = true)
    if (bookend)
        toWrite = "#" + toWrite + "#";

    Console.WriteLine(toWrite.Replace("\r", "\\r\r").Replace("\n", "\n\\n") + "\n\n");

If I ignore Acorn BBC and RISC OS (...and done), every \n or LF either comes after other NL bytes or by itself. Put in the text version of it afterwards, duh. Vice versa the \r.

So much nicer to have...

\nstring with some\r

... rather than trying to figure out if a cut caught the CR previous to that \n by printing int values or something similarly overcomplicated.

Labels: , , ,

posted by ruffin at 8/12/2016 01:05:00 PM

Support freedom
All posts can be accessed here:

Just the last year o' posts:

Powered by Blogger Curmudgeon Gamer badge