Cookie Notice

As far as I know, and as far as I remember, nothing in this page does anything with Cookies.

2010/07/30

A Cute Bit Of Talking Code

As I've previously mentioned, I have problems talking to computers but have few problems having them talk to me. I have a crontab on my work machine that runs every 15 minutes to tell me the time of day. ( Yes, my computer will give me the time of day. )

I found out quickly that just piping date into Festival won't make you happy. I wrote this to force a pronunciation. It's simple Perl, and it doesn't deal with Festival directly. But it gives me the pronunciation I want.

If it's useful to you, use in good health.

#!/usr/bin/perl

# */15 8-17 * * 1-5 ~/bin/curr_time.pl | /usr/bin/festival --tts &> /dev/null

use 5.010 ;
use strict ;
use warnings ;
use Data::Dumper ;
use subs qw( hour minute ampm ) ;
my @time = localtime ;
my @output ;

my @hour =  qw{
    Twelve One Two Three Four Five Six Seven Eight Nine Ten Eleven Twelve
    } ;

push @output , hour(@time) ;
push @output , minute(@time) ;
push @output , ampm(@time) ;
say join ' ' , @output ;

# -- hour -------------------
sub hour {
    my @time = @_ ;
    my $hour ;
    if    ( $time[2] % 12 == 0 ) { $hour = 12 ; }
    elsif ( $time[2] > 12 )      { $hour = $time[2] - 12 ; }
    else                         { $hour = $time[2] ; }
    return $hour[ $hour ];
    }

# -- minute -----------------
sub minute {
    my @time = @_ ;
    my $minute = sprintf '%d' , $time[1] ;
    if    ( $time[1] < 10 ) { $minute = 'oh ' . $minute ; }
    if    ( $time[1] == 0 ) { $minute = '' ; }
    return $minute;
    }

# -- a.m. - p.m. ------------
sub ampm {
    my @time = @_ ;
    my $m ;
    if    ( $time[2] == 0  && $time[1] == 0 )  { $m = 'Midnight' ; }
    elsif ( $time[2] == 12  && $time[1] == 0 ) { $m = 'Noon' ; }
    elsif ( $time[2] <  12   )                 { $m = 'A M' ; }
    else                                       { $m = 'P M' ; }
    return $m;
    }

Check My Math

There's a function. getJSON. It could be easily presumed to just get (in the colloquial sense) a JSON object. It doesn't. It uses the HTTP GET method.

As it turns out, it is just a rebadge of the more generic GET.

$.getJSON( url , query_object , function( data ) { ... } ) ; 

Is equivalent to this.

$.get( url , query_object , function( data ) { ... } , 'json'  ) ; 

And, of course, this is generic. If you want to POST and get JSON back, you do this.

$.post( url , query_object , function( data ) { ... } , 'json'  ) ; 

But they will not not not not NOT do this.

$.postJSON( url , query_object , function( data ) { ... } ) ; 

Because that function name assumes you've put together a JSON object and are posting it, not downloading it with the POST method.

Assuming that I was just getting JSON and not GETting JSON, as jQuery seems to want me to assume, has caused me several days of problems. Am I right in thinking that their rational encourages people to have problems?

I'm So Stupid!



I have just moved my application from getJSON with me handling the data by creating the URL by myself to getJSON by creating an object for the function to handle. And did it work? No it didn't work. I spent much of yesterday trying to think myself around the problem. And this morning, I started again with the jQuery AJAX documentation.

"Load JSON-encoded data from the server using a GET HTTP request."

I'm using getJSON and wondering why I get the GET-related problem.

I chose the empty box! I'm so stupid!

I will now proceed to write postJSON. After, of course, I bash my head against the wall over and over again.

2010/07/29

Handwriting Recognition

Jeff Atwood went on about Speech Recognition and how, despite what Star Trek says, it's not likely to become a major mode of computer interface. Not that I've done much with speech recognition, but it sounds about right to me. Honestly, when I want to tell the computer something, I want to poke it with my mouse or trackball or type at it with a keyboard. (When I want it to tell me something, I am not against having it talk to me. I have written a script that makes a time string that's much more friendly to Festival. ("Eleven 55 A M")


Toward the end, Jeff goes on about handwriting recognition, starting with the Apple Newton.
I learned Palm's Graffiti handwriting recognition language and got fairly proficient with it. More than ten years later, you'd expect to see massively improved handwriting recognition of some sort in today's iPads and iPhones and iOthers, right? Well, maybe, if by "massively improved" you mean "nonexistent".
There is a point I think he fails to consider. Apple Newton's handwriting recognition was trying to recognize your handwriting. Graffiti was more about you learning to write the variant of the letter set that Graffiti could understand.

You could take notes on a Palm, if your concept of "taking notes" is "Get eggs on way home". But, if your idea of taking notes was "I'm taking a Senior-level networking course with Comer and don't want to use a paper notebook", you could not really do that on a Palm. The key is that it's faster and easier to type, especially if you can use a dictionary and do lookahead guessing of what you're trying to type. (Although my wife has problems with her Blackberry understanding what she means.) Typing won out in the marketplace of portable items because it's easier to do at speed than handwriting recognition.


But, considering the lineage of the iPhone, it makes me wonder. "Handwriting recognition. Is there an app for that?"

Solution to the Javascript Object problem

eval()

I should've seen it a while ago.

var jsonA = new Array() ;
var sample_array = [ "foo" , "bar" , "blee" ] ;
for ( var i = 100 ; i <= 290 ; i++ ) {
    for ( j in sample_array ) {
        var k = i * i * (j+1) ;
        k = '"' + k.toString() + '"' ;
        jsonA.push( sample_array[j] + i + " : " + k ) ;
        }
    }
    var json = jsonA.join(" , ") ;
    x = eval( "( { " + json + " } )" ) ;
That is, create an array. put each name:value pair into the array in the name colon value format. Join 'em with commas. Wrap with curly braces ("This is an Object, JS") and parens ("I'm JS. I'm a language. It's my job to have crazy syntax.") Run eval(). I don't show my JSON step, but it's basically taking the params and pushing them back. The interesting thing is, with the data I made up here, the top is between 570 and 585 elements. I don't know if that's an HTTP limitation, an eval() limitation or a jQuery limitation, but I know that once I hit that, the code flakes. Which is interesting.

2010/07/28

The Problem With Javascript Objects / Hashes

Javascript has Objects. This is a good thing, allowing you to do useful and good things.

var objFoo = {
    foo : "foobarblee" ,
    bar : "barbleequuz" ,
    blee : "bleequuzbaaz"
    }
for ( i in objFoo ) {
    var j = objFoo[i] ;
    alert( i + ":" + j ) ;
    }
    // Yes, this is a fairly annoying example.

I'm in a position where I had been sending stuff through AJAX by using GET. I blew out the top of what you can send by GET and now must learn to use POST.

GET is easy.

var query_string = new Array() ;
for ( i in objFoo ) {
    var j = objFoo[i] ;
    query_string.push( i + '=' + j ) ;
    }
var url = "http://foo.bar/?" + query_string.join('&') ;
// coded but not tested

That's fine, if you want to generate only the right side. For query strings, I can do this and it works.

var query_string = new Array() ;
for ( h = 0 ; h < 10 ; h++ ){
    for ( i in objFoo ) {
        var j = objFoo[i] ;
        query_string.push( i + h + '=' + j ) ;
        }
    }
var url = "http://foo.bar/?" + query_string.join('&') ;
// coded but not tested
And I do a LOT of this. Enough to get the rare 414 HTTP error code. But I cannot figure out how to do this for POST.
var x = { foo : "bar" , "blee" : "quuz" } ;
$.getJSON( url , x , function(response) {
    ....
    } ) ;
Notice that foo is just as acceptable for a value name as "blee". Quotes are optional, which means the name cannot be set via program by any means I can name. And I so far cannot fake it with Arrays being Associative/Hashes.
var x = new Array() ;
x["foo"] = "bar"; 
x["blee"] = "quuz" ;
$.getJSON( url , x , function(response) {
    ....
    // no love for this version
    } ) ;

There has to be a way around this. This is obvious enough that someone besides me hit it. Help me find the solution?

2010/07/23

Quick Code Post - gen_password.pl

It has been suggested to me that I've let it go far too long since I've updated this blog, so I'm writing an update. This one is on some code I've been floating around for a while.

Everyone has a password scheme. For some people, their scheme is to write it down on a post-it note and stick it to their monitor. For some people, their scheme is to have one in memory and us it for their bank, their email, their online stores, their social media sites, etc. And, for a lot of people, their password is a string that they'll remember, like the name of a loved one or pet, or the registry number of their favorite starship.

The last scheme is profoundly stupid, especially when you can easily pop out hundreds of really random passwords.

The first scheme is seriously unadvisable. You should never ever ever ever ever write down a password.

The middle one .... it has problems. But assuming that you're not writing 'em down and leaving 'em everywhere, and assuming that you're using passwords that meet a strong security definition (8 characters or more, uppercase and lowercase and digits, not real dictionary words), you have a set of passwords that do not fit easily into your head and thus fall out when you need them.

I'm still struggling with this. But I have developed a password generator, included here, that's configurable for password length, using upper-case letters and digits, and number of rows of passwords. My take is to make a long list of passwords, find one you can make a mental mnemonic for, start using that one until you have it in your head, and then delete the list. If you have a secure machine to hold these passwords, they're held securely. So it's not really writing them down.

If the technique works for you, great. If you think it's dumb, tell me in comments and I'll adjust to a better scheme.


#!/usr/bin/perl

# A big password list generator

use 5.010 ;
use strict ;
use warnings ;
use Getopt::Long ;

srand ;

my @uppercase = 'A' ... 'Z' ;
my @lowercase = 'a' ... 'z' ;
my @digits    = 0 .. 9 ;
my @chars ;

my $uppercase = 0 ;
my $lowercase = 1 ;
my $digits    = 0 ;
my $cols      = 8 ;

my $rows = 20 ;
my $chars_per_column = 78 ;

GetOptions(
    'uppercase'   => \$uppercase ,
    'digits'      => \$digits ,
    'cols=i'      => \$cols ,
    'rows=i'      => \$rows ,
    ) ;

if ( $lowercase ) { push @chars , @lowercase ; }
if ( $uppercase ) { push @chars , @uppercase ; }
if ( $digits    ) { push @chars , @digits ; }
my $chars = $#chars ;

for ( 1 .. $rows ) {
    my @x ;
    for ( 1 .. int $chars_per_column / ( $cols + 1 ) ) {
        my $password ;
        for ( 1 .. $cols ) {
            $password .= $chars[ int rand $chars ] ;
            }
        push @x , $password ;
        }
    say join ' ' , @x ;
    }

2010/07/21

Weird Problem on Ubuntu Lucid

I've lost my home directory.

Not anything in it, though. If I want to edit ~/test.pl, I can type vi ~/test.pl or even move to my home directory and type vi test.pl and it edits as it should. But if I type ls ~ , it hangs indefinitely. It comes back after a reboot, of course, but that can mess with my workflow.

2010/07/02

Two Heads are better than One

I spent a while looking at new AGP video cards yesterday. Or maybe I should write "new", as AGP is like the last dodo, walking and talking but doesn't know it's extinct yet.
I was doing so for this purpose: I could not get my current dual-head AGP card to work. I had cloned screens and when I tried to set it up for dual-head, both screens looked like this. -->

Which is pretty in a way, but not useful.

It seems that Linux, and specifically Ubuntu Lucid, has taken X out of Xorg and put it into the kernel for more speed. They call it KMS, and for your nominal case, it's a good thing. When working with cloned monitors, I was able to get the pretty Compiz stuff working, like transparent terms that show the term underneath. That's sexy right there. It just sucked for my Radeon video card.

And here I must confess a dumbass attack. Consider this sample code they suggest for turning off KMS.
echo options radeon modeset=0 < /etc/modprobe.d/radeon-kms.conf 
I tried that, and because I wasn't in root, it didn't work, so I used vi. And when I went back to check /etc/modprobe.d/radeon-kms.conf it read like this.
echo options radeon modeset=0 
Of course it was confused by the echo in there. But now it works fine. Yay me.