Sunday, December 31, 2017

=== update

I updated my old Triple Equals Overrated ramble with a long postscript... while I'm not suggesting changing === as default for my company, or even the received wisdom of "avoid type coercion for comparisons), the people who like double equals aren't JUST dunderheaded cavepeople...

Thursday, December 28, 2017

Monday, December 25, 2017

pretty print json from unix shell

I've been digging using little .json files on the filesystem as a kind of DIY NoSQL database, but they're not always pretty to look at. Was looking for a pretty printer for 'em, thought I might have to do something in node or python but "json_pp" is already there in my Mac Terminal. The only weird thing is it only seems to read from STDIN (not from a file) so you have to do
json_pp < SOMEFILE.json

Sunday, December 24, 2017

asssteroidsss and sound generation

I used to make small games fairly regularly, often for Glorious Trainwrecks. Sadly this might be my first (and last, I suppose!) game of the year...

Pippin Barr (who has a great blog) made a set of games called Sibilant Snakelikes, older games as seen through a classic Snake game lens (his take on Shadow of the Colossus is especially great)

Since I was in middle school, I've used the idea of "move something on screen with an x/y position by only adjusting an xspeed and yspeed variable and adding them to x and y position every clock tick" - it's a very easy to program way to get a pleasing sense of motion in a game world. (The pinnacle of exploiting this was probably my Atari 2600 mashup JoustPong)

Atari's Asteroids used a roughly similar physics, albeit with more sophisticated rotations, so I wanted to see what happens if I further shoehorned it into the quantized world of Snake -

You can see the game and fiddle with its code here. One thing it's doing is using the P5.js sound libraries to make the notes - I really like this approach, having all the graphics and the sounds embedded in one file as text is a great throwback to the old 8-bit type bit computer magazines, vs having external graphics and sound files. Unfortunately, the library isn't super clearly documented, and mixed up with the functions that rely on external mp3s or wavs... If my understanding firms up I'll try to write more on it. (I'm tempted to make my own mini-sequencer from it...)

learn css grid there

An online course on css grid.

Thursday, December 21, 2017

php - sending mail/email

I've found it tough to reliably send mail from PHP, and the command line in general.

It feels like gmail (my usual testing recipient) really hates old school ways of sending email via scripts - like to the extent stuff doesn't even wind up in the recipient's SPAM box, it just goes away.

I'll still look for a better solution but right now the most reliable thing I've found is


<?php
// Pear Mail Library                                                                                                                                                             
require_once "Mail.php";

$from = '<kirkjerk@gmail.com>';
$to = '<kirkjerk@gmail.com>';
$subject = 'Hi testing mail!';
$body = "Hi,\n\nHow are you, how are thigns going?";

$headers = array(
    'From' => $from,
    'To' => $to,
    'Subject' => $subject
);

$smtp = Mail::factory('smtp', array(
        'host' => 'ssl://smtp.gmail.com',
        'port' => '465',
        'auth' => true,
        'username' => 'kirkjerk@gmail.com',
        'password' => 'MYPASSWORD'
    ));

$mail = $smtp->send($to, $headers, $body);

if (PEAR::isError($mail)) {
    echo('<p>' . $mail->getMessage() . '</p>');
} else {
    echo('<p>Message successfully sent!</p>');
}

?>
As far as I can tell, much of the header stuff (like trying to munge the From) is ignored- plus you have to have your password in plain text in a script which stinks.  I'll try to update this entry if I refine this technique, like getting reply-tos working etc.

Wednesday, December 20, 2017

php - imagemagick for thumbnail gallery making

Just here for reference is a script I used to make a simplistic thumbnail gallery with links to fullsize, full of copy and paste bits from a few sources. You need a folder named thumb/ where it will dump the smaller versions. It uses Imagemagick thumbnailImage to set a maximum size of 300x300 but preserve the aspect ration and then dumps HTML I copy and paste into the index. This is for a gallery archive for my real-world Wall o' Peeps




<?
$skips = "";
$files = array_diff(scandir("."), array('..', '.'));
foreach($files as $i => $justname){

    $UPPERCASE = strtoupper($justname);

    $UPPERCASE = strtoupper($justname);
    if(endsWith($UPPERCASE,".JPG") || endsWith($UPPERCASE,".JPEG") ){

        $filename = $justname;
        $image = new Imagick($filename); 
        autorotate($image);
        $d = $image->getImageGeometry(); 
        $w = $d['width']; 

    
            $image->thumbnailImage(300,300,true);

            $image->writeImage("thumb/".$filename);
            $d2 = $image->getImageGeometry(); 
            $w2 = $d2['width']; 
            $h2 = $d2['height'];
            print htmlspecialchars("<a href=\"$justname\"><img width=\"$w2\" height=\"$h2\" src=\"thumb/".$justname."\"></a>\n\n");
            print "<br><br>\n";
       

    } else {
    $skips = $skips . "  skip $justname<br><br>";
    }
}
print "<br><br>$skips";

function autorotate(Imagick $image)
{
    switch ($image->getImageOrientation()) {
    case Imagick::ORIENTATION_TOPLEFT:
        break;
    case Imagick::ORIENTATION_TOPRIGHT:
        $image->flopImage();
        break;
    case Imagick::ORIENTATION_BOTTOMRIGHT:
        $image->rotateImage("#000", 180);
        break;
    case Imagick::ORIENTATION_BOTTOMLEFT:
        $image->flopImage();
        $image->rotateImage("#000", 180);
        break;
    case Imagick::ORIENTATION_LEFTTOP:
        $image->flopImage();
        $image->rotateImage("#000", -90);
        break;
    case Imagick::ORIENTATION_RIGHTTOP:
        $image->rotateImage("#000", 90);
        break;
    case Imagick::ORIENTATION_RIGHTBOTTOM:
        $image->flopImage();
        $image->rotateImage("#000", 90);
        break;
    case Imagick::ORIENTATION_LEFTBOTTOM:
        $image->rotateImage("#000", -90);
        break;
    default: // Invalid orientation
        break;
    }
    $image->setImageOrientation(Imagick::ORIENTATION_TOPLEFT);
    return $image;
}


function startsWith($haystack, $needle)
{
     $length = strlen($needle);
     return (substr($haystack, 0, $length) === $needle);
}

function endsWith($haystack, $needle)
{
    $length = strlen($needle);

    return $length === 0 || 
    (substr($haystack, -$length) === $needle);
}

?>

Wednesday, December 13, 2017

php - download in the browsers, not as a download

In making a band chart/pdf management system, I needed a method for streaming/download files.

PHP makes it pretty easy, but I had to bang around just a bit before I could figure out how to let it try and open stuff in a browser window (vs going to straight to the download folder)

The code ended up a s
if(securityCheck(getLoggedInUser(),$_BAND,false)){
if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: '.mime_content_type($file)); 
            #vs application/octet-stream or application/pdf
    header('Content-Disposition: inline; filename="'.basename($file).'"');
            #vs Content-Disposition: attachment
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    readfile($file);
} else {
print "NO LUCK $FILENAME";
}
   exit;
} else {
print "UNAUTHORIZED";
exit;
}

The bits that were different from the original example I copy and pasted are in bold.

Also, I learned the power of urldecode() :-D

the state of javascript

The State of Javascript 2017 - Angular 1's high "would NOT use again" value is still validating for my prejudices :-D

Tuesday, December 12, 2017

what'd i say? what'd i say? on facebook

I've posted alot about facebook here, including talking about the UI/UX details they get right (that post was from before they added various reaction types instead of the ubiquitous like ... also before the full depth of the echo chamber effect and manipulation by outside parties was known...)

One small thing I've noticed is how if I make a post and then go away from the site, there's a small window of time where if I bounce back to Facebook, my own post is the first thing I see. Whether that's because people like the reassurance of "yes I really just posted that and it went through" or are prone to make comments or edits, it's a terrific little UX detail.

Thursday, December 7, 2017

freemarker boolean weirdness

Freemarker Madness - my coworker helped me learn that
<#if ((allYearsForTrimName!false) && (!canShow("f:listings.seoLinksVariantContext")))>`
does about what you'd expect (in terms of not executing the block if that canShow routine returns true) but
<#if (allYearsForTrimName!false && (!canShow("f:listings.seoLinksVariantContext")))>
(without the safety paren around allYearsForTrimName) always evaluates as true and executes the block.

(I also got reminded myself that while ftl functions can't really print to the page, you can assign stuff to a global-ish variable and print it after ... really, log/printf based debugging will always be a crucical tool in testing your assumptions, even when in a system that has a rich step through debugger.)

So the coworker mentioned freemarket documentation warns about that precedence glitch... but man, that's an annoying one! You really don't want your language messing up boolean operations...


Wednesday, December 6, 2017

the joy of text and todo

In the late 90s there was an online comedy series called "Computer Stew" (Ahead of its time - way before people were putting series on Youtube, or even before there was Youtube)

My favorite episode was a rap tribute to Notepad.exe- but it's the line from the introduction with John Hargraves and Jay on Speakerphone that sticks with me:
"Well Jay, it's getting to be that time of year when everyone is giving out their awards for best software..."
"That's right! Best office suite, best paint program! Best online game!"
"And you know which program would win hands-down in my book..."
"Unfortunately I do sir."
"It's Notepad, that little text editor that comes with Window? I love that thing, man!"
"I know you do. I can't understand it. I think you're insane. Folks, John manages the entire show with little todo-lists inside of NOTEPAD!"
"I love Notepad! It's small, it never crashes... they never add any features to it... in fact I think I feel a song coming on..."

My current favorite equivalent of Notepad.exe is Simplenote - it is cloud based but beautifully minimalist, I run the native app on iOS and MacOS (and can get to a webpage with all my info when on someone else's computer.) I love how it makes the first line of text the defacto title (a trick PalmPilots used) and how it never tries to duplicate the font and color of stuff pasted into it (those are two things that its competitor Evernote gets wrong - plus Simplenote never begs me to upgrade.) Also I periodically get Simplenote to let me download a zipfile, my complete archive that I can backup safely, on my own terms.

There's one limitation though - Simplenote's collection is a list, usually ordered by "last modified" (Though it allows you to "pin" notes to the top - I reserve this for a single "scratch" note that I use to transfer text between my laptop and my phone, great when I want to be wordy in a chat program that I don't have for Mac) But going back to Computer Stew, the line about "little todo-lists", plural, suggests Hargrave may have used Notepad in that style where you have multiple windows of the program running, each always open to its todo list, each nestled on its own certain part of the screen, allowing "muscle memory" to kick and in help you keep track of which list is which.

(Of course now "markdown" brings new options for documents that make sense as text or run through to something with a richer layout palette)

That use of Notepad is a digital version of "Post-It notes stuck 'round the cubicle", and in fact Macs come with a "Stickies" app that has a more skeuomorphic view of the same thing. But virtual-stickies-on-PC-screen aren't portable, so these kind of Todo lists have always been secondary to what I keep in a dedicated checklist app - on PalmPilots back in the day, and now on iPhone for the past decade. Checklists are great (epecially since I can set up daily or weekly or monthly recurring reminders) but they are kind of flat, missing the "muscle memory" of a 2D space.

Padlet is a web-based system that lets you do something like the stickies but in a multiple-machine way, by treating the browser as the overall surface area. The program's focus is collaboration, however, so lacks Todo features such as dated and recurring Todos. And while that view is great on a big screen, it doesn't work as well condensed onto a handheld device.

Once upon a time I grabbed to domain name "todo2d.com" as a placeholder for an app that would combine Padlet's sense of a 2D space with fundamental Todo features. Never got around to it, especially since the audience for it is a bit niche. Currently I use Appigo Todo on my phone, which is pretty solid, but I'd love to find a Todo App that allowed multiple list but with an option of viewing all the contents of all lists at once. (For example, I'd love a separate list for stuff where I'm waiting for someone else, or that needs to be done at home or at a specific store...

gesture interfaces and the tao of programming

Rant at work: "@##!@# Somehow I used some magic gesture on my touchpad, and now Slack is zoomed in - but its not the normal zoom I can adjust with cmd-+ and cmd-- and cmd-0 ; instead it's just decided that slack should be in a magic window that I can pan back and forth with two finger swiping, but I have no idea of how to make everything fit" (restarting Slack seemed to fix it though it felt like I had to do so twice.)

Gestures where an errant side of a finger creates radical behaviors violates this part of Tao of Programming
A program should follow the "Law of Least Astonishment". What is this law? It is simply that the program should always respond to the user in the way that astonishes him least.
BTW, the Tao of Programming is brilliant - it's weirdly authentic, like I've seen other things that parody the form of the Tao Te Ching but they generally don't also say smart things about their subject matter....