Tuesday, October 18, 2011

complaining to eharmony

honestly, i don't have a big beef with eharmony.com.

i didn't really care where they advertised... until today.

eharmony has been supporting rush limbaugh's program, and even that didn't tick me off... until today.

rush limbaugh recently went on air supporting the Lords Resistance Army (LRA), an armed gang that routinely kidnaps children and forces them into prostitution and into being child soldiers.

and eharmony wants to advertise on this guy's show? what!?

again, i have no beef with eharmony. they probably weren't thinking about how extreme limbaugh can be and were only thinking of his marketing demographic.

that's fine.

but do you really want your brand associated with a guy who's advocating for rapists & kidnappers?

anyway... i gave them a call and sent them an email, if you feel the same way i do, maybe you can do the same.

please keep it professional, though. the eharmony guys need to know that limbaugh is the uncivilized one, not the people disappointed with his behavior.

feel free to use this as a template if you want to drop them a line @ publicrelations@eharmony.com or give them a call @ +1 626 795 4814.

-cheers!

dear sirs,

i recently learned your firm is advertising on the rush limbaugh show.

normally i would support your effort to communicate your message as broadly as possible.

but mr. limbaugh's recently comments in support of the lords resistance army (LRA) are incompatible with civil society. while i do support mr. limbaugh's right to make whatever comments he chooses, i am disappointed he has used it to support an organization that kidnaps children forcing them to become child soldiers or prostitutes.

by advertising on mr. limbaugh's show, you are associating your brand with an individual who appears to be advocating for the elimination of basic civil behavior.

i urge you to reconsider your affiliation with mr. limbaugh. however, until you cease advertising on his program, i am boycotting your service and asking my network of friends and co-workers to do the same.

-sincerely,
-meadhbh hamrick
--
meadhbh hamrick * it's pronounced "maeve"
@OhMeadhbh * http://meadhbh.org/ * OhMeadhbh@gmail.com

Saturday, October 15, 2011

Two Thousand Words that Belongs to Workers, Farmers, Officials, Scientists, Artists, and Everybody

Cribbed From: http://library.thinkquest.org/C001155/documents/doc26.htm (duplicated here because the original page had what appeared to be delphi related errors and a background making it virtually unreadable.)

Our Source:
Navratil, Jaromir. "The Prague Spring 1968". Hungary: Central European Press, 1998, pp. 177-181
Original Source: “Dva Tisice Slov”, Literarny Listy (Prague), 27 June 1968 pp.1
Translated by: Mark Kramer, Joy Moss and Ruth Tosek

Comment: The 2000 words manifesto was a document written by Ludvik Vaculik. It was furthermore signed by a numerous of other famous Czechoslovak people as writers, intellectuals and scholars. It quickly became the symbol of the Prague Spring-movement.

The first threat to our national life was from the war. Then came other evil days and events that endangered the nation's spiritual well being and character. Most of the nation welcomed the socialist program with high hopes. But it fell into the hands of the wrong people. It would not have mattered so much that they lacked adequate experience in affairs of state, factual knowledge, or philosophical education, if only they had enough common prudence and decency to listen to the opinion of others and agree to being gradually replaced by more able people.

After enjoying great popular confidence immediately after the war, the communist party by degrees bartered this confidence away for office, until it had all the offices and nothing else. We feel we must say this, it is familiar to those of us who are communists and who are as disappointed as the rest at the way things turned out. The leaders' mistaken policies transformed a political party and an alliance based on ideas into an organization for exerting power, one that proved highly attractive to power-hungry individuals eager to wield authority, to cowards who took the safe and easy route, and to people with bad conscience. The influx of members such as these affected the character and behavior of the party, whose internal arrangements made it impossible, short of scandalous incidents, for honest members to gain influence and adapt it continuously to modern conditions. Many communists fought against this decline, but they did not manage to prevent what ensured.

Conditions inside the communist party served as both a pattern for and a cause of the identical conditions in the state. The party's association with the state deprived it of the asset of separation from executive power. No one criticized the activities of the state and of economic organs. Parliament forgot how to hold proper debates, the government forgot how to govern properly, and managers forgot how to manage properly. Elections lost their significance, and the law carried no weight. We could not trust our representatives on any committee or, if we could, there was no point in asking them for anything because they were powerless. Worse still, we could scarcely trust one another. Personal and collective honor decayed. Honesty was a useless virtue, assessment by merit unheard of. Most people accordingly lost interest in public affairs, worrying only about themselves and about money, a further blot on the system being the impossibility today of relying even on the value of money. Personal relations were ruined, there was no more joy in work, and the nation, in short, entered a period that endangered its spiritual well being and its character.

We all bear responsibility for the present state of affairs. But those among us who are communists bear more than others, and those who acted as components or instruments of unchecked power bear the greatest responsibility of all. The power they wielded was that of a self-willed group spreading out through the party apparatus into every district and community. It was this apparatus that decided what might and might not be done: It ran the cooperative farms for the cooperative farmers, the factories for the workers, and the National Committees for the public. No organizations, not even communist ones, were really controlled by their own members. The chief sin and deception of these rulers was to have explained their own whims as the "will of the workers". Were we to accept this pretense, we would have to blame the workers today for the decline of our economy, for crimes committed against the innocent, and for the introduction of censorship to prevent anyone writing about these things. The workers would be to blame for misconceived investments, for losses suffered in foreign trade, and for the housing shortage. Obviously no sensible person will hold the working class responsible for such things. We all know, and every worker knows especially, that they had virtually no say in deciding anything. Working-class functionaries were given their voting instructions by somebody else. While many workers imagined that they were the rulers, it was a specially trained stratum of party and state officials who actually ruled in their name. In effect it was these people who stepped into the shoes of the deposed ruling class and themselves came to constitute the new authority. Let us say in fairness that some of them long ago realized the evil trick history had played. We can recognize such individuals today by the way they are redressing old wrongs, rectifying mistakes, handing back powers of decision-making to rank-and-file party members and members of the public, and establishing limits on the authority and size of the bureaucracy. They share our opposition to the retrograde views held by certain party members. But a large proportion of officials have been resistance to change and are still influential. They still wield the instruments of power, especially at district and community level, where they can employ them in secret and without fear of prosecution.

Since the beginning of this year we have been experiencing a regenerative process of democratization. It started inside the communist party, that much we must admit, even those communists among us who no longer had hopes that anything good could emerge from that quarter know this. It must also be added, of course, that the process could have started nowhere else. For after twenty years the communists were the only ones able to conduct some sort of political activity. It was only the opposition inside the communist party that had the privilege to voice antagonistic views. The effort and initiative now displayed by democratically minded communists are only then a partial repayment of the debt owed by the entire party to the non-communists whom it had kept down in an unequal position. Accordingly, thanks are due to the communist party, though perhaps it should be granted that the party is making an honest effort at the eleventh hour to save its own honor and the nation's. The regenerative process has introduced nothing particularly new into our lives. It revives ideas and topics, many of which are older than the errors of our socialism, while others, having emerged from below the surface of visible history, should long ago have found expression but were instead repressed. Let us not foster the illusion that it is the power of truth which now makes such ideas victorious. Their victory has been due rather to the weakness of the old leaders, evidently already debilitated by twenty years of unchallenged rule. All the defects hidden in the foundations and ideology of the system have clearly reached their peak. So let us not overestimate the effects of the writers' and students' criticisms. The source of social change is the economy. A true word makes its mark only when it is spoken under conditions that have been properly prepared---conditions that, in our context, unfortunately include the impoverishment of our whole society and the complete collapse of the old system of government, which had enabled certain types of politicians to get rich, calmly and quietly, at our expense. Truth, then, is not prevailing. Truth is merely what remains when everything else has been frittered away. So there is no reason for national jubilation, simply for fresh hope.

In this moment of hope, albeit hope still threatened, we appeal to you. It took several months before many of us believed it was safe to speak up; many of us still do not think it is safe. But speak up we did exposing ourselves to the extent that we have no choice but to complete our plan to humanize the regime. If we did not, the old forces would exact cruel revenge. We appeal above all to those who so far have waited on the sidelines. The time now approaching will decide events for years to come.

The summer holidays are approaching, a time when we are inclined to let everything slip. But we can safely say that our dear adversaries will not give themselves a summer break; they will rally everyone who is under any obligation to them and are taking steps, even now, to secure themselves a quiet Christmas! Let us watch carefully how things develop, let us try to understand them and have our answers ready. Let us forget the impossible demand that someone from on high should always provide us with a single explanation and a single, simple moral imperative. Everyone will have to draw their own conclusions. Common, agreed conclusions can only be reached in discussion that requires freedom of speech-the only democratic achievement to our credit this year.

But in the days to come we must gird ourselves with our own initiative and make our own decisions. To begin with we will oppose the view, sometimes voiced, that a democratic revival can be achieved without the communists, or even in opposition to them. This would be unjust, and foolish too. The communists already have their organizations in place, and in these we must support the progressive wing. They have their experienced officials, and they still have in their hands, after all, the crucial levers and buttons. On the other hand they have presented an Action Program to the public. This program will begin to even out the most glaring inequalities, and no one else has a program in such specific detail. We must demand that they produce local Action Programs in public in every district and community. Then the issue will suddenly revolve around very ordinary and long awaited acts of justice. The Czechoslovak Communist Party is preparing for its congress, where it will elect its new Central Committee. Let us demand that it be a better committee than the present one. Today the communist party says it is going to rest its position of leadership on the confidence of the public, and not on force. Let us believe them, but only as long as we can believe in the people they are now sending as delegates to the party's district and regional conferences.

People have recently been worded that the democratization process has come to a halt. This feeling is partly a sign of fatigue after the excitement of events, but partly it reflects the truth. The season of astonishing revelations, of dismissals from high office, and of heady speeches couched in language of unaccustomed daring-all this is over. But the struggle between opposing forces has merely become somewhat less open, the fight continues over the content and formulation of the laws and over the scope of practical measures. Besides, we must give the new people time to work: the new ministers, prosecutors, chairmen and secretaries. They are entitled to time in which to prove themselves fit or unfit. This is all that can be expected at present of the central political bodies, though they have made a remarkably good showing so far in spite of themselves.

The everyday quality of our future democracy depends on what happens in the factories, and on what happens to the factories. Despite all our discussions, it is the economic managers who have us in their grasp. Good managers must be sought out and promoted. True, we are all badly paid in comparison with people in the developed countries, some of us worse than others. We can ask for more money, and more money can indeed be printed, but only if it is devalued in the process. Let us rather ask the directors and the chairmen of boards to tell us what they want to produce and at what cost, the customers they want to sell it to and at what price, the profit that will be made, and of that, how much will be reinvested in modernizing production and how much will be left over for distribution. Under dreary looking headlines, a bard battle is being covered in the press-the battle of democracy versus soft jobs. The workers, as entrepreneurs, can intervene in this battle by electing the right people to management and workers' councils. And as employees they can help themselves best by electing, as their trade union representatives, natural leaders and able, honorable individuals without regard to party affiliation.

Although at present one cannot expect more of the central political bodies, it is vital to achieve more at district and community level. Let us demand the departure of people who abused their power, damaged public property, and acted dishonorably or brutally. Ways must be found to compel them to resign. To mention a few: public criticism, resolutions, demonstrations, demonstrative work brigades, collections to buy presents for them on their retirement, strikes, and picketing at their front doors. But we should reject any illegal, indecent, or boorish methods, which they would exploit to bring influence to bear on Alexander Dubcek. Our aversion to the writing of rude letters must be expressed so completely that the only explanation for any such missives in the future would be that their recipients had ordered them themselves. Let us revive the activity of the National Front. Let us demand public sessions of the national committees. For questions that no one else will look into, let us set up our own civic committees and commissions. There is nothing difficult about it; a few people gather together, elect a chairman, keep proper records, publish their findings, demand solutions, and refuse to be shouted down. Let us convert the district and local newspapers, which have mostly degenerated to the lever of official mouthpieces, into a platform for all the forward-looking elements in politics; let us demand that editorial boards be formed of National Front representatives, or else let us start new papers. Let us form committees for the defense of free speech. At our meetings, let us have our own staffs for ensuring order. If we hear strange reports, let us seek confirmation, let us send delegations to the proper authorities and publicize their answers, perhaps putting them up on front gates. Let us give support to the police when they are prosecuting genuine wrongdoers, for it is not our aim to create anarchy or a state of general uncertainty. Let us eschew quarrels between neighbors, and let us avoid drunkenness on political occasions. Let us expose informers.

The summer traffic throughout the republic will enhance interest in the settlement of constitutional relations between Czechs and Slovaks. Let us consider federalization as a method of solving the question of nationalities, but let us regard it as only one of several important measures designed to democratize the system. In itself this particular measure will not necessarily give even the Slovaks a better life. Merely having separate governments in the Czech Lands and in Slovakia does not solve the problem of government. Rule by a state and party bureaucracy could still go on; indeed, in Slovakia it might even be strengthened by the claim that it had "won more freedom."

There has been great alarm recently over the possibility that foreign forces will intervene in our development. Whatever superior forces may face us, all we can do is stick to our own positions, behave decently, and initiate nothing ourselves. We can show our government that we will stand by it, with weapons if need be, if it will do what we give it a mandate to do. And we can assure our allies that we will observe our treaties of alliance, friendship, and trade. Irritable reproaches and ill-argued suspicions on our part can only make things harder for our government, and bring no benefit to ourselves. In any case, the only way we can achieve equality is to improve our domestic situation and carry the process of renewal far enough to some day elect statesman with sufficient courage, honor, and political acumen to create such equality and keep it that way. But this is a problem that faces all governments of small countries everywhere.

This spring a great opportunity was given to us once again, as it was after the end of the war. Again we have the chance to take into our own hands our common cause, which for working purposes we call socialism, and give it a form more appropriate to our once-good reputation and to the fairly good opinion we used to have of ourselves. The spring is over and will never return. By winter we will know all.

So ends our statement addressed to workers, farmers, officials, artists, scholars, scientists, technicians, and everybody. It was written at the behest of scholars and scientists.

Wednesday, August 10, 2011

This Side Up? When Mobile Web Pages Rotate

So I spent a little time this last week working on my "mini mobile CV." It's targeted at mobile devices and was intended originally to demonstrate that I knew how to properly select easy to read fonts and high contrast color schemes for constrained hardware. But as I got into it and saw my device automatically rotate from landscape to portrait mode, I got curious. "What is the best way to detect an orientation change on a mobile device?"

Being familiar with "dark ages" web programming, I originally assumed the solution would involve a fair amount of hackery, reading the heights and widths of transparent divs and so forth. But fortunately, it's not hard at all. Despite recent W3C efforts to define a standard DeviceOrientation Event Specification, it seems many Android devices in the field are copying Apple's Mobile Safari behavior.

You probably want to start by figuring out if the device rendering the page will be generating orientation change events. Do this with the following code snippet:

var supportsOrientation = ( "onorientationchange" in window );

This line checks to see if the 'onorientationchange' property is set in the window object. If it is, then your browser should generate orientationchange events. Next, we want to add an event listener, like so:

if( supportsOrientation ) {
window.addEventListener( "orientationchange", function () { console.log('w00t'); }, false );
}

Of course, printing out a debugging message to the console every time there's an orientation change is vaguely useless, so we may want to consider something beefier. When the orientationEvent fires, you'll want to read window.orientation to find out how many degrees the device has been rotated. But be careful, on some devices, you'll get a shower of these events even though you've only rotated your device once. It's good practice to remember the last orientation value and only "do something" when the orientation actually changes.

var previousOrientation;

function checkOrientation () {
if( previousOrientation !== window.orientation ) {
previousOrientation = window.orientation;
// do interesting things here
}
}

So, putting it all together and adding a bit of callback convenience, you get something like this:

function Rotor ( callback ) {
this.callback = callback;
if( "onorientationchange" in window ) {
this.previous = window.orientation;
callback( this.previous, null );
window.addEventListener( "orientationchange", this, false );
}
}

Rotor.prototype.handleEvent = function ( e ) {
var current = window.orientation;
if( current !== this.previous ) {
this.callback( current, e );
}
this.previous = current;
};

To use it, just instantiate a new Rotor, giving it a callback that knows what to do when the device is rotated.

var roton = new Rotor( function( rotation, event ) { alert( 'current rotation: ' + rotation ); } );

Cheers!

Wednesday, July 20, 2011

strange programmer habits : number and string mutation

Some of my favorite programming languages allow you to be "fast and loose" with data types. JavaScript and PHP, for instance, will convert variables between number and string types as needed. Some consider this behavior to be "sub-optimal," while others don't. But understanding how your programming language converts literals or variables between types is important, no matter what language you're using.

Consider the following C program:
#include <stdio.h>
int main( int argc, char *argv[] ) {
  char *start = "1234";
  int a = 2;
  printf( "%s\n", (start + a ) );
}
When you compile and run this program, it prints out the string "34" and then exits. Now look at this JavaScript function:
function foo() {
  var start = "1234";
  var a = 2;
  console.log( start + a );
}
It should print out the string "12342". Understanding why C does one thing and JavaScript does another is important. C aficionados can probably quickly point out that the printf() function was taking a pointer to an array of characters as it's input. Adding the integer 2 to the pointer caused it to point 2 bytes ahead. When interpreted as a string, "(start + a)" is simply a two byte string with the value "34".

JavaScript, on the other hand, converts the number 2 into the string '2' and appends it to the string.

Doing the same thing in PHP yields even different results. Executing the following PHP fragment will cause the system to print the string "1236":
$start = "1234";
$a = 2;
echo ( $start + $a )
PHP peeks inside the variable $start, sees that it looks like a number and then converts it to an integer and performs the addition.

JavaScript provides a functions to convert numbers to strings and vice versa. The "String( val )" function attempts to convert the argument 'val' to a string while the "Number( val )" function attempts to convert 'val' to a number. People went to the trouble of specifying these functions and documenting them, so you might as well use them.

Some people, their minds perhaps addled by exposure to early versions of PHP have been seen to do things like this in javascript:
var a = 12;
console.log( "" + a );
or
var b = '34';
console.log( 1 * b );
Adding an empty string to a number in JavaScript will (should) cause the interpreter to convert the value of a into a string. Multiplying the string b by one should do the opposite (convert the string into a number.)

Some people believe this type of conversion is faster, others think it's just plain ugly. It is certainly the case that "standard" functions exist to do the same thing, and might convey the programmer's intent more clearly.

It's up to you, of course, which technique you use to coerce a value to a particular type, but if you inherit code with superfluous additions and multiplication, this might be what's going on.

Wednesday, July 13, 2011

strange programmer habits : avoiding goto's by using do..while's

In the early days of computer software, programmers were using languages like assembly, fortran, cobol and lisp to produce reasonably small programs to compute trajectories, maintain inventory databases or accounting systems and whatnot. Computing systems weren't big enough to allow programmers to make the massive software systems like modern operating systems, web browsers or computer games.

This is probably why it took a couple decades for people to understand how bad "spaghetti code" was; it's easy to dismiss spaghetti being a problem when your complete software system is one or two pages long. But when a printout of your system requires you to chop down a medium sized forest, concepts like "structured programming" and "design patterns" really start to become important.

One of the popular issues around the programmer's water-cooler in the 1980's was whether or not people who use goto's should have their fingers chopped off. Edsger Djikstra penned the canonical software engineering jeremiad about this subject entitled “go-to statement considered harmful” [PDF]. You can probably guess his opinion from the paper's title.

So in the 80's and 90's, software engineers were taught that goto's led to un-maintainable software, headaches and all manner of social ills ranging from global warming to bad movies to disco. "Use a goto," they would say, "and it's like asking the local DJ to play Disco Duck on the radio." Structured programming, good software engineering technique and eschewing goto's would lead to a new era of increasingly good Cure albums, Alien sequels that didn't suck and fewer evenings in the office at midnight debugging the crap code you wrote last year.

But, like the one true ring, the expressive power of the goto is difficult to resist. Many software wizards, on their way to a life of perdition (i.e. - writing video games) countered that the goto could be used on occasion, if done correctly. Consider the following routine; it tries to open a file and read a few bytes. If there are errors along the way, it uses a goto to branch to clean-up routine before exiting:
int doSomething( char *filename ) { int err = 0; FILE *file = (FILE *) NULL; char buffer[ 80 ]; size_t bytesRead = 0; if( NULL == filename ) { err = -1; goto exuent_omnis; } if( (FILE *)NULL == ( file = fopen( filename, “r” ) ) ) { err = errno; goto exuent_omnis; } bytesRead = fread( buffer, 80, 1, file ); if( ferror( file ) ) { err = -2; goto exuent_omnis; } /* more code here */ exuent_omnis: if( (FILE *) NULL != file ) { fclose( file ); } return( err ); }
"What could be wrong with this?" the pro-goto lobby would ask. IMHO, this example is pretty readable, and the goto DOES actually increase readability. Especially if you consider that nested if's are frequently offered as the alternative:
int doSomething( char *filename ) { int err = 0; FILE *file = (FILE *) NULL; char buffer[ 80 ]; size_t bytesRead = 0; if( NULL != filename ) { if( (FILE *)NULL != ( file = fopen( filename, “r” ) ) ) { bytesRead = fread( buffer, 80, 1, file ); if( ! ferror( file ) ) { /* more code here */ } else { err = -2; break; } fclose( file ): } else { err = errno; } } else { err = -1; } return( err ); }
People who propose extensive use of nested if's should have their thumbs broken. This example isn't that bad, but when nested ifs start spanning pages, they can get a bit difficult to read. The alternative to using gotos in this example would be to use a do...while() loop whose repeat condition has been explicitly set to zero (or false for C++ users.):
int doSomething( char *filename ) { int err = 0; char buffer[ 80 ]; size_t bytesRead = 0; do { if( NULL == filename ) { err = -1; break; } if( (FILE *)NULL == ( file = fopen( filename, “r” ) ) ) { err = errno; break; } bytesRead = fread( buffer, 80, 1, file ); if( ferror( file ) ) { err = -2; break; } /* more code here */ } while( 0 ); if( (FILE *) NULL != file ) { fclose( file ); } return( err ); }
Developers who like this kind of code will tell you it captures the succinct directness of a goto without actually having a goto. Because we break out of the loop, there's only one place control can go: to the statement after the while( 0 ); And we avoid nested if's. I've encountered at least one developer who believes this technique is harmful; it uses the do...while language feature for something it was not intended for, and as such, could be confusing to younger programmers.

Whether you make Djikstra cry by using a goto, produce deep levels of indents or use a do...while(0) that's confusing to in-expert programmers; it's entirely up to you. But hopefully this article will have made you aware of the different techniques you'll encounter in the wild.

-Cheers!

Wednesday, July 6, 2011

strange programmer habits : commas at the beginning of lines

So, consider this C program:
#include <stdio.h> char *verbs[] = { "quit" , "score" , "inventory" , "go" , "get" , NULL }; int main() { int i; for( i = 0; verbs[ i ] != NULL; i++ ) { printf( "verb %02d: %s\n", i, verbs[ i ] ); } }
or it's javascript equivalent::
var verbs = [ "quit" , "score" , "inventory" , "go" , "get" ]; for( var i = 0, il = verbs.length; i < il; i++ ) { console.log( "verb " + i + ": " + verbs[ i ] ) }
Both these programs declare an array of strings and then print them out. But contrary to popular convention, the commas separating individual elements of the verbs array come not at the end of the line, but at the beginning.

The compiler (or interpreter) couldn't care less about this stylistic convention, of course. All it cares about is if there are commas between array elements. The comma-first style is there to make it easier for you to add, delete or move single lines in the array. By putting the comma at the beginning of the line, you move the elements in the array around without having to manually add (or remove) a trailing comma at the end of the array.

This strange habit doesn't effect the output your compiler produces and it's main benefit is to save a couple milliseconds when cutting and pasting entries in an array. But a small number of programmers (myself included) have gotten used to seeing arrays that look like this, so don't be surprised if you see this style from time to time.

Wednesday, June 29, 2011

strange programmer habits : literal comes first in a comparison

Consider this JavaScript code:
function foo( aString ) { if( ‘:error’ == aString ) { handleError(); } }
Why put the variable reference after the string literal? So you don't accidentally turn the comparison into an assignment. Look at this code:
function foo( aString ) { if( aString = ‘:error’ ) { handleError(); } }
Do you see the error? The programmer has accidentally dropped one of the equal signs in the comparison operator. If this code was being edited at 4AM the day before a big demo, believe me, it would be hard to spot.
But if put the literal was first and then forgot the extra equals sign, we would get an error. Go ahead and try it. Open up the javascript debugger in your browser and copy this code fragment into it:
( function ( aString ) { if( ‘:error’ = aString ) { console.log( ‘looks like we were passed an error token.’ ); } } ) ( ‘blarg’ );
You should get a syntax error, which should clue you off that you forgot an equals sign. This is a programmer habit seen in most "curley brace" languages (C, C++, Java, Python, etc.) JavaScript programmers may also want to consider using the "strict equal" comparison operator (i.e. the triple equals.) Refer to Mozilla's excellent Javascript Docs for more info.

Tuesday, June 21, 2011

chromium os on a dell mini 9? i like it

so for the last week i've been playing with chromium os. it's the linux-based web-focused operating system from google everyone's been yammering about for the past week. samsung and acer just released a couple "chromebooks," and it seems like the tech press is falling over itself to pan the devices. but i recently took the plunge and installed chromium on my dell vostro a90 (aka mini 9) and here are my impressions.

i like it. (with some caveats)

let me start by saying i'm a bit of a google fangrrl; not a complete fangrrl, but a fangrrl nonetheless. i started taking google services seriously several years ago when i subscribed to gmail. i love it: all my mail is available from any PC i happen to be sitting in front of. i was also an early adopter of writely (later google docs.) i love it for exactly the same reason: my documents automatically follow me around from machine to machine.

so i'm not a google fangrrl in the same way that people can be apple fans. design is important to me, but i'm more interested in the program's interface and capabilities. sure, cool looking hardware is nice, but it's the UX that counts. google's UI for gmail, gdocs, &c aren't "beautiful" in the way that apple interfaces are beautiful; but they're more than good enough. i am also not so much of a google fan that i use google buzz or wave or orkut.

i've been burned by syncing too many times in the past to trust anyone to get it right. i like the google services because they give me document and service mobility without having to think about it. that is my primary consideration.

yes, i occasionally happen to have my netbook powered on when there's no network coverage. and that sucks. for me, the benefits of service mobility outweigh the drawbacks of not being able to get to my docs when the network evaporates.

so i'm sure you've heard of gmail and google docs and picasa. i use them. they're great. however, there are a couple other services you might not have heard about. (and it's okay, these are all pretty much services for software developers.)

one service i kind of had to start using is Cloud9. it's a javascript editor and development environment right in your web browser. it's not perfect, but with the recent git and mercurial integration, Cloud9 is the node.js developer's equivalent of an unstoppable force whose kung fu will defeat the forces of evil. okay. maybe it only seems that way 'cause i'm a fan of storing your stuff in the cloud. but check it out. when my free trial expires, i'm totally giving them the small amount of money they're asking for. your mileage may vary.

in the future, i hope the Cloud9 team convert my money into a group editing / etherpad-esque feature.

so that's basically been my week. i installed chromium on my dell (thanks to the work by Doug Anson of Dell's CTO's Office.) i continued using google services i have been using, and started using (and was impressed by) Cloud9.

and i think the future is going to be even brighter. google docs currently have the problem that they don't make use of HTML5's local storage and web application APIs to provide a compelling "offline experience." (gmail currently has an "offline mode.") but CNET (and others) are reporting that we'll start seeing offline editing features this summer. if/when this happens, one of the largest complaints people have about chromebooks will disappear.

so... chromium on the dell mini-9 is a great alternative to paying $500 for a new laptop; especially if, like me, you happen to have a mini-9 hanging around the house. installing the OS was pretty straight-forward; use the link to Doug Anson's build above; hexxeh flow had some problems loading on my mini-9. but even Doug's work has a few warts:
  1. there's no audio - this is a known problem. Doug says it'll likely get fixed in a future release.
  2. there's no (easy) java - the most recent dell build of chromium doesn't ship with java, and the stock java installer for linux barfs (i'm guessing because of unfulfilled dynamic libraries.) i didn't spend a lot of time on getting it to work, and have seen java work on other chromium builds, so i know it can be done. it's just not easy.
  3. wifi's turned off out of the box - like many linux devices that use broadcom wifi chipsets, you have to download the proprietary drivers using a wired ethernet connection before you can experience wireless bliss. but it's pretty straight-forward to add the drivers. the release notes intimate the dell guys are working with the broadcom lawyers to figure out a way to include the drivers in the stock build, so maybe this problem will go away.
  4. WebGL? if it's enabled in the may 13th build, i've yet to see it work.
so, chromium os on a dell mini 9: i like it. it's not without it's warts, but it's a better alternative than plunking down $500 on a new laptop.

Monday, June 6, 2011

a few new node modules

people who know me know that i love node.js, the javascript network application framework. most of the projects i've prototyped in the last couple of years have been done with javascript in a browser and node.js on the server. i don't know why it took me so long to think about this, but i'm finally releasing some of the tools i developed. (okay, technically, i re-implemented them to avoid some project specific kruft.)

but anyway, in the last couple of weeks i released two node packages: node-props and node-mug.

node-props.js

node-props is a package that lets developers read properties from one or more URIs specified on the command line. so, basically, you can do this:
node application.js --config file:///etc/host_props.json --config https://example.org/app_props.js
i found the ability to grab properties from multiple locations is good for "cloud-like" applications. i use it to separate "host config" parameters (e.g. - addresses & ports to listen on) from "application config" parameters (like db addresses, etc.)

separating the two classes of config info provides a bit of flexibility if you're deploying an array of servers. by placing application config information on a central server, you only need to change a single file to change your app's behavior.

the package has been published to the npm registry and the source is available at https://github.com/OhMeadhbh/node-props

node-mug.js

the node-mug package exports an interface developers can use to generate RFC 4122 compliant Version 4 (random) UUIDs. unlike some other UUID generators for node, node-mug collects entropy from the /dev/urandom file present on most modern *nix systems. paranoid app developers can configure the system to read entropy from /dev/random.

interested users can install node-mug via npm or retrieving the source from the git repository at https://github.com/OhMeadhbh/node-mug

happy coding!

Tuesday, May 31, 2011

fun with node.js - building a node development appliance for virtual box

so... people who know me know i've been raving about this thing called node.js for the last several years. if you haven't heard about it, click over to the wikipedia's entry on node and take a minute to read it, i'll wait.

the simplest description of node would be to call it a "javascript web server." this is a decent description when talking to non-tech folks, though us technorati know it's really an "ecmascript application server framework."

turns out node can do some amazingly cool stuff. what most people have heard about is it's pretty good at handling high load situations. slightly less well known are the benefits of using the same code to render HTML in the server as is used to render HTML in AJAXy client apps running in a browser.

ultimately though, it's just a lot of fun to program apps with node.

so... to help spread the node.js gospel, i put together a virtual box appliance you can use to try it out without the fuss of having to download and compile the core packages yourself. i also added mongodb (and the node driver) to the image so you can play with persistence.

anyway... you can find more detailed info over at the node appliance page on my site. it's not a small download, but the time you lose in the download is more than made up for by the time you save by not having to configure it yourself.

you can find more information about node at the official node website (complete with docs!) and tim caswell's "how to node" site. you can keep up with the node community by following the #nodejs hashtag on twitter, visiting nodejs.se or dropping in on the #nodejs IRC channel.

happy coding!

Sunday, May 29, 2011

on accessing services from within second life

so a few moments ago, @ZauberExonar asked on twitter if anyone was aware of a JSON parser in the Linden Scripting Language (LSL). people unfamiliar with LSL or Second Life(tm) may want to skip this blog posting. in typical "software architect" fashion, i'm answering his question with several paragraphs of "why JSON and LSL don't mix" (and what you can do about it.)

a very brief intro to JSON

JSON, as we all know, is a transfer syntax that encodes messages in a way that looks remarkably like a JavaScript / ECMAScript object declaration. So... if you execute this JavaScript:

var foo = {   success: false,   error: "insufficient cheese error: recommend rebooting universe" };
console.log( JSON.stringify( foo ) );

you would get a JSON blob that looks something like this:

{"success":false,"error":"insufficient cheese error: recommend rebooting universe"}
so far, so good, right? you start with a JavaScript object and you convert it into a string that represents the object using a familiar syntax. it's now ready to send over the network. the receiver can execute this code to deserialize the string version of the message into a real live object:

var bar = JSON.parse( "{\"success\":false,\"error\":\"insufficient cheese error: recommend rebooting universe\"}" );

and now the receiver has an object it can manipulate.

the cool thing about JSON as a transfer syntax is messages are serialized using encoding rules that are way easy to process in JavaScript (the programming language of the web.) so it's easy to understand why web-devs love the heck out of JSON.

XML, in comparison, is seemingly bloated. XML allows you to define your own tags, each with semantics specific to the message. this can be a good thing in some situations, but you have to add the smarts to your JavaScript application to grab specific bits of data out of the XML and construct objects to contain the data.

enter the virtual world

but if we want to consume a JSON service in the virtual world, things get a little complicated. in Second Life, the programming language of choice is LSL (Linden Scripting Language.) a lot of people love to hate on LSL. i'm not going to do that here. but i will say this: parsing JSON or XML in LSL is a pain in the ass.

perhaps the most irritating aspect of LSL in this regard is it's lack of associative arrays. whether you call them maps, dictionaries, objects or associative arrays, they all let you use a string as a key into a collection of items.

because there's no associative array in LSL, you can't pull off the JavaScript trick of creating a new object that's essentially identical to the JSON. no, you have to map the contents of the JSON string into a list (which is like an array) or global variables.

JSON lovers aren't alone... XML partisans have discovered they're in the same boat: you have to parse the message and reason about the semantics of each field while constructing a list or setting global variables.

easy parsing?

and another aspect of JSON and XML parsing in LSL that's sub-optimal: you have to write LSL to look at each character in the message string.

okay, this is not precisely true. if your message does not include escaped quotes or curly braces, you can use llParseString2List() to build a list that's MUCH easier to parse. the down side of this approach is it's not entirely easy to handle curly braces inside strings and honestly, the code to implement it frequently looks bizarre.

so what i've started to do is to use a LSL-friendly format i'm calling the "DSD Text Transfer Syntax." experienced readers will recognize DSD as the abstract type system i routinely threatened the VWRAP group with. DSD text looks like this:

:v:1
appkey:u:77c3dd7c-4639-4681-aa52-a7dd35e96fd8
:{:
success:0:
error:s:insufficient%20cheese%20error%3A%20reboot%20universe
errno:i:23
desc:l:http%3A//example.com/error_descriptions/cheese.html
:}:

messages are a collection of individual lines (separated by either a CR or a CRLF.) each line contains three fields separated by colon characters. the first field is a "name" field; the second is a "type tag" while the third is the data in question. note that not all lines have a name, and not all lines have a data field. also note that colon characters are verboten in the data field, so we encode strings and URIs that may contain them.

people familiar with the LLSD binary encoding will likely recognize the tag characters, they're directly ripped off from that spec. (i also added a version tag so parsers will be able to know when they receive a message they may have problems interpreting.)

so the way you parse this in LSL is to split a message into lines like so:

// assume the string 'message' contains the complete message text
list lines = llParseString2List( message, ["\n", "\r", "\n\r"], [] );
integer lineCount = llGetListLength( lines );
integer i;
for( i = 0; i < lineCount; i++ ) {
string currentLine = llList2String( lines, i );
list fields = llParseString2List( currentLine, [":"], [] );
string name = llList2String( fields, 0 );
string key = llList2String( fields, 1 );
string data = llList2String( fields, 2 );

// now process the name-key-data triple
}

what you do when you process the name, key and data values depends on your app. i find i'm frequently either stuffing them into global variables or constructing new lists with the values. to parse the message above, we do something like this:

// parse location info message. generates a list with the following members:
// 0 - integer - success (1 for success, 0 for failure)
// 1 - integer - errno (0 for success)
// 2 - string - error description ("" if call was successful )
// 3 - string - URL for more information ("" if call was successful)
// 4 - string - region name
// 5 - float - x location in region
// 6 - float - y location in region
// 7 - string - comment text

list parseLocationInfoMessage( message ) {
integer success = TRUE;
integer errno = 0;
string error = "";
string desc = "";

integer in_map = FALSE;
integer version;

string region = "";
float x = 0.0;
float y = 0.0;
string comment = "";

list lines = llParseString2List( message, ["\n", "\r", "\n\r"], [] );
integer lineCount = llGetListLength( lines );
integer i;

for( i = 0; i < lineCount; i++ ) {
string currentLine = llList2String( lines, i );
list fields = llParseString2List( currentLine, [":"], [] );
string name = llList2String( fields, 0 );
string key = llList2String( fields, 1 );
string data = llList2String( fields, 2 );

// now process the name-key-data triple

if( 'v' == key ) {
version = (integer) data;
if( 1 != version ) {
success = FALSE;
errno = -1;
error = "invalid message version";
break;
}
} else if( '{' == key ) {
in_map = TRUE;
} else if( '}' == key ) {
in_map = FALSE;
} else {
if( FALSE == in_map ) {
success = FALSE;
errno = -2;
error = "parsing error";
break;
}

if( 'success' == name ) {
if( '1' == key ) {
success = TRUE;
} else {
success = FALSE;
}
} else if( 'errno' == name ) {
errno = (integer) data;
} else if( 'error' == name ) {
error = llUnescapeURL( data );
} else if( 'desc' == name ) {
desc = llUnescapeURL( data );
} else if( 'region' == name ) {
region = llUnescapeURL( data );
} else if( 'x' == name ) {
x = (integer) data;
} else if( 'y' == name ) {
y = (integer) data;
} else if( 'comment' == name ) {
comment = llUnescapeURL( data );
}
}
}

return( [ success, errno, error, desc, region, x, y, comment ] );
}

some might argue this is no less complex than XML or JSON parsing in LSL, but for my money, it seems a little more straight-forward.

making services give you DSD Text

ideally you're in a position to control both the server and the client. if you are, then your server code gets to decide what type of encoding you send back to the client. slatebureau.com uses the same API endpoints for requests, irrespective of where they come from. to determine what encoding to use, it looks for the Accept:, Content-Type: and S-SecondLife-Shard: headers in the request and uses this algorithm.

  1. if an Accept: header is present, and you can generate the mime type the client is requesting, use it. if you can't generate the encoding requested, send a 406 status code.

    in other words, if you ask for a 'application/json' or 'application/dsd+json', i'm going to give you JSON. if you ask for 'text/plain' or 'application/dsd+text', i'm going to give you the text format described here.

  2. if there's no Accept: header but there is a Content-Type: header present in the request, send the response in the format of the content type. if you can't generate that encoding, don't freak out, continue to step 3.

    so if there was a Content-Type: header in the request and there wasn't an Accept: header, i'm going to try to encode the response using the same type. if your request included a json blob with an 'application/json' Content-Type, i'll try to generate that as a response.

  3. send a DSD-Text formatted response.

so... anyway... i wrote a few DSD parsers in PHP and JavaScript. i'll try to dig them out and post them to github. -cheers!

Sunday, March 20, 2011

the return of hbmobile.org

so i'm in the process of turning the hbmobile.org web site back on, and i'm going back to spending my spare time making gadgets. there's a big long story behind this, so let's take it piece by piece.

i work for klout.com right now, but for a big chunk of my career, i worked for companies in the mobile value chain. most of the time i worked there, i wondered "why do mobile phones suck so hard?"

we all have some pretty great phones available to us at the moment, so it's easy to forget: before the iPhone and Android OS, being a developer on a mobile device was expensive, difficult and frustrating. expensive 'cause you frequently had to pay tens of thousands of dollars for development systems before you could even begin to start developing a mobile app. difficult 'cause you had to learn an entirely new operating system and dev platform and frustrating 'cause the mobile OS vendor, handset manufacturer or carrier would frequently hobble your app beyond recognition.

back before Android and iPhone, a bunch of us hobbled together our own DIY phones without these problems. Surj Patel and Deva Seetharam put together a "TuxPhone" back in 2005-2006. I spent some time putting bits of hardware and software together in 2006, while Craig Hughes and Gordon Kruberg of gumstix.com did some heavy lifting, building a GumStix daughterboard populated with a mobile phone chipset.

we also had this group called "the homebrew mobile phone club." modeled on the earlier "homebrew computer club," the idea was to provide support and encouragement for people building their own devices.

in 2008, the group fell apart. partially 'cause i had to concentrate on getting divorced. but also 'cause we were getting more or less what we wanted from the mobile industry. the iPhone and Android used familiar operating systems and well known development tools; you didn't have to pay google or apple insane amounts of cash for dev systems and you more or less had access to all of the phone's hardware.

for the most part we declared victory and moved on with our lives.

we did do a lot of very cool stuff. Adrian Cockroft used the "myPhone" project as an excuse to learn how to develop enclosures for mobile devices. i wrote a hack of a lot of control software for GSM modems. and Craig & Gordon did an insanely good job of developing open hardware that could send and receive phone calls and text messages. James Young saved our old wiki at the hbmobile.org backup; go check it out, there's a lot of cool stuff there.

sure... it's not that big of a deal when you compare it to what HTC and LG do, but remember, we were a bunch of individuals with soldering irons, extra cash and a few extra hours per week. we proved you didn't HAVE to be a multi-billion dollar company to build a mobile phone.

that the myPhone was more expensive than a subsidized iPhone, and had fewer apps than Symbian was not the point. the point was, we were able to build it on our own. we also shared as much as we could, using open source and creative common licenses for most system components. (read my blurb for O'Reilly called "the complete open phone" for the rationale behind this decision.)

so... we did a lot of cool stuff and moved on with our lives.

but now i'm reactivating the hbmobile.org domain to work on a new project.

AT&T has announced they're going to buy T-Mobile. This is a bad deal for everyone (except AT&T share-holders.) Om Malik has a great blog post on why it's a bad deal here: "In AT&T and T-Mobile Merger, Everybody Loses."

for the last year i've been worried by moves from the carriers: price increases, charging for tethering, wireless bandwidth caps, etc. and now we're falling towards monopoly in the GSM world.

i'm going to spend my spare time for the next couple months trying to solve the "quality communications services over unlicensed spectrum" problem. i'm not trying to dislodge AT&T or Apple or Microsoft. i'm not trying to build mobile phones that will be the next big thing at SxSW. i want to build some prototypes of systems that sidestep licensed spectrum and the problems of carving it up and giving it to monopolies.

if you're interested, take a look at the new hbmobile.org site. subscribe to my blog feed and consider listening to my rants on twitter.

if it makes sense, i'll also be hosting meetings in san francisco (and in second life.) stay tuned!

Saturday, March 12, 2011

radiation monitoring station

so sparkfun.com has this geiger counter device i've been eyeing for a year or two. (actually, i think this is an updated version of the one i was lusting over.) and now that we've apparently had an explosion at Fukushima 1, i believe we'll see an increase in environmental radiation. fwiw, someone posted a video of the explosion, if you haven't seen it already.

my college friend wilbur related to me that during the chernobyl meltdown in the 80's, his high school science teacher tracked the rise and decay of environmental radiation. that always seemed like a fun project to me. sort of like a weather station, but in touch with current events.

anyway, so i'm going to order one of these things tomorrow night. if we can get 10 people in the bay area, we could even do a group buy (ping me on twitter at @OhMeadhbh.) but i think tomorrow i'll be setting up a website to track decay events and map them on a google map.

cheers!

Tuesday, March 8, 2011

driving in dallas

my mom just forwarded this one to me as part of an explanation for why the rest of the family is frightened by her driving... her excuse: "i learned to drive in dallas." i tried figuring out who wrote this, but no luck. if it's yours, please ping me so i can give proper attribution.

First you must learn to pronounce the city name. It is DAL-LUS, or DAA-LIS depending on if you live inside or outside LBJ Freeway.

Next, if your Mapsco is more than a few weeks old, throw it out and buy a new one. If in Denton County and your Mapsco is one-day-old, then it is already obsolete. Forget the traffic rules you learned elsewhere. (Frisco has screwed everything up.)

Dallas has its own version of traffic rules... "Hold on and pray."
There is no such thing as a dangerous high-speed chase in Dallas . We all drive like that.

All directions start with, "Get on Beltline," which has no beginning and no end. (It REALLY DOESN'T!!!)

The morning rush hour is from 6 to 10. The evening rush hour is from 3 to 7. Friday's rush hour starts Thursday morning.

If you actually stop at a yellow light, you will be rear-ended, cussed out and possibly shot. When you are the first one on the starting line, count to five when the light turns green before going to avoid crashing with all the drivers running the red light in cross-traffic.

Construction on Central Expressway is a way of life and a permanent form of entertainment. We had sooo much fun with that, we have added George Bush Freeway and the High Five to the mix.

All unexplained sights are explained by the phrase, "Oh, we're in Fort Worth !"

If someone actually has his or her turn signal on, it is probably a factory defect. Car horns are actually "Road Rage" indicators - and remember, it's legal to be armed in Texas ..

All old ladies with blue hair in a Mercedes have the right of way. Period. And remember, it's legal to be armed in Texas ..

Inwood Road, Plano Road, NW Highway, East Grand, Garland Road, Marsh Lane, Josey Lane, 15th Street, Preston Road all mysteriously change names as you cross intersections (these are only a FEW examples). The perfect example is what is MOSTLY known as Plano Road . On the south end, it is known as Lake Highlands Drive, cross Northwest Highway and it becomes Plano Road, go about 8 miles and it is briefly Greenville Ave, Ave K, and Highway 5. It ends in Sherman ...

The North Dallas Tollway is our daily version of NASCAR. The minimum acceptable speed on the Dallas North Toll Road is 85 mph. Anything less is considered downright sissy. It also ends in Sherman .

If asking directions in Irving or SE Dallas , you must have knowledge of Spanish. If in central Richardson or on Harry Hines, Mandarin Chinese will be your best bet. If you stop to ask directions on Gaston or Live Oak, you better be armed... and remember, it's legal to be armed in Texas

The wrought iron on windows near Oak Cliff and Fair Park is not ornamental!!

A trip across town east to west will take a minimum of four hours, although many north/south freeways have unposted minimum speeds of 75.

It is possible to be driving WEST in the NORTH-bound lane of EAST NORTHWEST Highway . Don't let this confuse you.

LBJ is called "The Death Trap" for two reasons: "death" and "trap."

If it's 100 degrees, Thanksgiving must be next weekend. If it's 10 degrees and sleeting/snowing, the Fort Worth Stock Show is going on. If it has rained 6 inches in the last hour, the Byron Nelson Golf Classic is in the second round (if it's Spring) - and it is the Texas State Fair if it's Fall.

If you go to the Fair, pay the $8.00 to park INSIDE Fair Park . Parking elsewhere could cost up to $2500 for damages, towing fees, parking tickets, and possibly a gunshot wound. If some guy with a flag tries to get you to park in his yard, run over him.

Any amusement parks, stadiums, arenas, racetracks, airports, etc., are conveniently located as far away from EVERYTHING as possible so as to allow for ample parking on grassy areas.

Final Warning: Don't Mess With Texas Drivers ... remember, it's legal to Be armed in Texas

Monday, February 21, 2011

on the benefit of open mobile devices

in which the lack of an open hardware ecosystem for hobbyists and experimenters is described and bemoaned; radical ideas espous'd; and a solution to the world's mobile woes is consider'd.

in a different life i was the co-instigator for the Homebrew Mobile Phone Club. it was great fun, and i got to work with some insanely brilliant people, notably Adrian Cocroft and Craig Hughes (formerly of GumStix.) our objective was to support people who were building their own mobile phones, the same way the famous Homebrew Computer Club had supported early innovators in what grew into the PC industry.

we were active for about 2 years between 2006 and 2008, and were, in fact, able to make a home-brew system that could place and receive phone calls and text messages. at least 90% of the credit should go to Craig Hughes and Gordon Kruberg at gumstix. while i was busy getting divorced, Craig, Gordon and Adrian were doing real work.

after demoing our hardware at the Maker Faire 2007, we more or less moved on to other interesting projects. mostly 'cause the iPhone, Android G1 and FIC / OpenMoko Neo 1973 seemed to be doing a MUCH better job at opening up the potential for mobile applications.

i think a lot of us felt we had accomplished our task. we demonstrated what could be done with off the shelf hardware and software and (i hope) we tweaked the "big guys" into realizing there was a huge ecosystem in end-user selectable apps for mobile devices. remember, this was before the iPhone or Droid; the most successful application phone s'til then were the Palm Treo and various WinCE devices. realistically, we were a small amount of gasoline on an already growing fire.

but after a couple years, i'm still mildly disappointed. sure, we have some GREAT application platforms: iPhone, WP7, Android. heck, even BlackBerry looks good.

there's enough competition between the major mobile OSes that we're bound to get an increasing number of cool software features. but mobile hardware is still dominated by a small handful of companies: Apple, HTC, LG and (for the moment) Nokia.

this is an understandable situation. most people buying mobile phones use it to talk and text. whomever can deliver that simple feature set the cheapest will win large markets. an increasing number of people are experimenting with smartphones (iPhone, Droid, etc.) but it's still reasonably small compared to the number of people who just want to gab and text. and sure, as full feature smart phones get cheaper and cheaper, you'll see a lot more people adopting them.

but this isn't the market i'm talking about.

i'm talking about people who want to try out new things with mobile devices. like integrating RFID / near field communication with mobile devices. or adding a DECT radio module to a phone. or experimenting with eInk displays. or stuffing a mobile phone into a small wearable pin shaped like a star-fleet insignia.

and then i read this article: "Meshnets, Freedom Phones and the People's Internet." if you wanted, you could interpret the article as "yet another utopian pipe-dream by a young anarchosyndicalist," and maybe you would be right. but i think there are some pretty important social and business ramifications in this article.

i think what i realized after reading chris' article is that gilmore's quote about the internet applies to mobile phone companies as well. the internet does interpret censorship as damage and does route around it. we learned this in egypt. so my corollary to gilmore's quote would be something like this: "local economies interpret market domination by remote actors as damage and innovate around them."

"local" in this sense can be either geographically local or "local" to a vertical market or local to a concept.

throughout the middle-east right now, we see grass roots movements resisting and toppling repressive and allegedly corrupt regimes. the mubarak government did a reasonably bad job of cutting off the country from the outside completely, but they did cause some turmoil amongst opposition organizers "on the ground."

in about a year, we are told, we'll see a multi-party democracy holding elections. informed opinion is there'll be no one group holding majority power. in this environment, i believe it will be politically difficult for the emergent government to maintain a regulatory regime restrictive enough to include an "internet off switch." my suspicion is the fear of other political actors in the new egypt will trump fears of a second grass roots movement that can take down the new government.

i'm enough of a techno-anarcho-syndicalist to think that's a good thing.

but i wonder, is there an equivalent situation in the mobile marketplace? will the desire to shake off the yoke of Apple's oppressive app review regime lead to an iPhone uprising? will the info-proletariat revolt if/when Google eventually starts being evil and tracking mobile devices to deliver you targeted ads?

okay... maybe i'm overstating it a bit.

but right now we have a mobile infrastructure that's top-down. you want 4G? great. you have to wait for verizon to think your market is important enough. you want to add an RFID reader to mobile device. it sure as hell won't EVER happen on a Verizon phone, so you'll have to wait for T-Mobile to notice your market, add some limited support, then realize there's not enough cash there and abandon you.

for the past year i've been toying with the idea of trying to setup a company to provide LTE or WiMAX support in the San Lorenzo Valley. There's waaay too little ROI to justify this as a commercial entity, but there are enough geeks in the valley that a co-op might be doable. The cost of the equipment is falling rapidly, thanks to Huawei kicking the collective asses of the entrenched players (Ericsson, Nokia-Siemens, etc.)

i think i could convince a few peeps to sign up for VoIP over LTE if there were an off the shelf handset that would support it. but none of the majors will make such a handset if there's a market of less than a million phones.

and this gets me back to thinking about mobile handsets. wouldn't it be fun if there was a "handset kit" you could buy for a couple hundred bucks. think if it like LEGO for mobile phones. you want GSM? fine, you add the GSM brick. you want an OLED display? fine, you add the OLED brick. you can sort of already do this if you're handy with a soldering iron. (just go to sparkfun.com and search for cellular devices.)

but wouldn't it be fun if we had something "for the rest of us," who wanted to mix and match features of our mobile devices, but didn't want to design a new PCB every other week?

if we had something like that, we could experiment with all sorts of crazy "last mile" wireless concepts up here in my valley. protesters in repressive regimes could easily change from a centrally managed SMS/GSM system to... heck... use your imagination here... twitter over wi-fi to iridium uplinks to the interwebs.

the point here is, in terms of technology, protesters in egypt have the same interest in affordable tech experiments as 4G customers in the mountains. the centralized "powers that be" will not offer what we need either for economic or political reasons. maybe it's time to think about a "post-carrier" world?

why? 'cause every time Verizon and T-Mobile tell me they can't do something, it makes me start looking for a way to route around them.

Wednesday, February 2, 2011

experiments with social media

so i've been curious about second life people's twitter behavior and thought it might be fun to do a few experiments. no no, not talking about evil torturous experiments on defenseless digital animals. and i'm not scraping my social network, getting ready to sell them out to advertisers. i'm just genuinely curious about people's behavior with respect to tweeting and re-tweeting.

the following tests won't be held up by the APA as exemplars of rigorous experimental design. but i hope they'll satisfy some curiosity. also, i should point out that i'm not hiding my intentions by claiming some great reward or a chance to win a bazillion dollars that aren't there. no. i'm offering a few, inexpensive rewards. i'm also paying things in Linden Dollars (L$'s.) this is the game script for second life; it's a lot easier to pay people directly in-world than to mail out checks or deal with PayPal.

experiment 1 : re-tweet this please

my first experiment was this simple tweet:
social experiment. what happens when i ask people to retweet retweet requests in the guise of a social experiment? - please RT!
so i'm basically just asking people to please re-tweet a message. i'm offering no incentives to do so, only the pure joy of participating in my personal experiment. after about eight hours, only two people had re-tweeted this message.

experiment 2 : minor financial reward for re-tweeting

the second experiment was this tweet:
okay. social media experiment 2 : i'll give 50 lindens (each) to the first 10 people who retweet this message.
so i'm changing things up here and providing an incentive. if you re-tweet that message, i'll give you L$ 50. before you get too excited, you should probably note that 50 lindens equates to something around 20 US cents (or US$ 0.20 .) so it's not a really big reward.

i doubt this will be a great shock, but more people re-tweeted this message; after about 4 hours, about 5 people re-tweeted the message. so, it turns out that, at least in my social network, more people will re-tweet a message if there's a personal reward.

another interesting factoid: there was at least one person who re-tweeted this message who i can't see. i believe this means they're protecting their tweets and i'm not following them. people who want to try to get more "twitter buzz" by offering a reward should probably remind folk that if you can't see them, you can't reward them.

experiment 3 : rewarding someone else (a non-profit)

here's my third tweet:
social experiment: if 10 people retweet this message in the next 4 hours, i'll donate L$500 to Bridges for Women, http://sl8.us/gAPHcs4_E
in this case, i'm telling people they'll get no direct reward, but their actions can help out a non-profit. what i didn't really tell people is i planned to donate L$ 500 to Bridges for Women's Second Life presence whether i got the requisite re-tweets or not; it seems like we would be teasing them if we didn't. Also, L$ 500 is about US $2.00, so it's not like we're talking about a huge pile of cash. Still, L$ 500 could be useful if they wanted to spruce up their second life presence a bit with a few inexpensive knick-knacks.

this tweet proved way more popular than the previous two. it took about 2 hours for me to get 10 re-tweets. it's possible, however, this may be because there are just a lot more of my twitter peeps looking at twitter in the early afternoon (pacific time) than in the morning. or it's just that people are more motivated by altruism. or maybe small linden rewards just don't register with people.

experiment 4 : follow me and re-tweet and i'll give you some lindens

with my fourth tweet, i'm getting back to appealing to people's self interest:
social experiment : L$50 to the next 10 new followers who retweet this message. (follow me, then tweet your #secondlife avatar name)
but we're not talking about a lot of cash; remember, L$50 is about US$ 0.20 (20 cents.) also note that i'm telling people to publicly associate their second life and twitter identities. some people may not want to do that. sounds pretty straight-forward, right? yes and no. remember, this is for NEW followers. existing followers, in the immortal words of willy-wonka, "get nothing."

this experiment was crafted in part to avoid the problem with experiment 2 where you couldn't see (or reward) people who were protecting their tweets. you can setup twitter to send you an email message when someone starts following you (in fact, i think that's the default behavior) so you'll always be able to see new followers.

after about an hour, i had 7 re-tweets (though one was from someone whom i think already followed me.) i'm confident it won't take too long to get the last couple new followers.

experiment 5 : lindens for current followers who recruit new followers

the next tweet tries to overcome this last impediment:
social experiment : L$50 for the first 10 existing followers who convince new people to follow me. get new followers to tweet your name.
like previous tweets, we're not talking about a lot of cash. L$50 is about 20 cents. but i was curious if it would affect the outcome.

i actually want to publish this post before people on the east coast start going to sleep, and i just posted this tweet. i'm going to come back with results later with results.

observations

i should probably lead off by reminding people they can observe some of the results themselves. i don't protect my tweets, so you can click on these links to see the individual tweets. if you're using "new twitter," you should see a list of people who have re-tweeted the tweet in question.
the second observation i made is that i'm capable of producing some really gawd-aweful social experiments. if i tried submitting these experiments and "results" to a peer-reviewed journal, i'm pretty sure they would be rejected. if i tried to submit them as part of a class in social experimental design, i would be happy to get a D.

"real" experiments start with hypotheses; i didn't do this. they then describe what the testing methodology is going to be; i kinda-sorta did this, but in a haphazard way. and they usually describe how the hypothesis will be confirmed or refuted BEFORE conducting the experiment. i totally didn't do this.

so... observation 2: i'm not really doing a good job at being a social scientist here. but honestly, it's okay. these are anecdotal observations and i never claimed to be a trained social scientist. i know little of how sociological / anthropological experiments are constructed; just enough to be confident i'm doing it wrong here.

the third observation: i think twitter is caching the HTML of individual tweet pages. i noticed that if i used the twitter web page to see who's been re-tweeting things, it seemed to change considerably less often than if i used the API.

more important observations

maybe more important are the following observations:
  1. it seems more of my followers are active in the afternoon. yes. this is a completely unscientific statement. i'm conflating time with message content. had i repeated the same message in the morning and afternoon, we could have an "apples to apples" comparison.
  2. my followers seem to be somewhat altruistic. pat yourselves on the back, twitter followers, you seem to be eager to give away my hard-earned lindens to charities. seriously though, it took only a couple minutes to get 5 people re-tweet the message in experiment 3 and we finished the challenge with a couple hours to spare.
  3. larger sums seem more interesting to people than small sums. when i offered L$50 rewards, uptake was a little slow. slower than when i offered to donate L$500 to a charity. so maybe larger sums motivate people more than smaller sums.
  4. different experiments didn't seem to affect each other. after tweeting the L$500 challenge in experiment 3, i waited to see if there would be more interest in experiment 2. i was thinking we might see a couple people looking at the "big tweet" and then notice the others. but no dice.
  5. some of my followers think i'm a rube. perhaps they're not aware of just how high-brow embedding roald dahl references in pseudo-scientific observations is. but at least one follower indicated i was behaving like a dork for running these experiments.
  6. way more of my followers use the #NewTwitter re-tweet feature than copy and paste messages into new tweets. this shouldn't be a shocker, it's a lot easier on the twitter web page to hit the "re-tweet" link than it is to copy or paste. however, other twitter clients make "re-tweeting with comments" much easier. still, it looks like most people chose the easy "single click re-tweeting" route.
applying these observations

let me start this section by saying you're crazy to use these results as justification for any particular action. it would be nice to say "aha! evidence PROVES larger sums lead to more followers in twitter!" but i just don't see that being an interesting or particular defensible statement based on this data. that being said, the anecdotal data collected might be used to inform a more rigorous set of experiments.

but the data, anecdotal such that it is, might suggest a few "truths."
  1. your network may respond better at specific times of the day. i'm going to speculate that for most people, the majority of their human followers are in the same time zone as themselves. tweeting at 3AM is simply going to reach fewer people since fewer people are awake. it might be a cool idea for someone to come up with a tool to see when their twitter followers are most active. actually, i think most twitter analytics packages do this already.
  2. if you're going to give money away, people respond better to larger sums. i speculate this is because "more is always better" when it comes to cash. a more interesting way to spin this is that maybe some people just filter out low value commercial tweets. for instance, if someone told me "i'll give you a US$1 gift certificate for amazon" and i happened to be in the middle of an involved task, i may simply choose to ignore it. but if they said, "retweet this within 5 minutes for a US$500 amazon gift certificate," i would probably drop what i was doing and start retweeting. so i'm hypothesizing the existence of a "value point" for each person. rewards below that point are not worth the effort. i would be very interested to see someone come up with a "real" experiment for how to determine where this value point is for users.
  3. multiple promotions may have a synergistic effect, but i didn't see that here. i'm going to speculate there are a few people out there who even though they're not interested in a particular promotion, after seeing a it, they'll click on a "more info" or "other promotions" button or look at someone's twitter profile. they may find a promotion or tweet that's more in line with their needs or has a better value proposition for them. i guess what i'm saying is, i hypothesize promotions like the experimental tweets i used here get certain people's attention. while you have their attention, it's easy to convince a few of them to look at other promotions. but i think you have a limited window of opportunity when you have their attention. i spread these tweets out over the course of a full day and had pretty poor luck getting cross-pollenization.
so that's it: my deep thoughts about promotions and twitter. please ping me if you wind up doing "real" research in this field, i'd love to hear about it.

update 1

here's a quick update on the last experiment. so far NO ONE has retweeted the last tweet. this could be due to fatigue (seriously, how long can i keep asking my twitter followers to retweet things.) or it could be because it involves recruiting people to do things. the first four experiments required people simply to press a button. but the last experiment required people to go out, find someone to recruit, and get them to do something.

so maybe we can add one more important observation:
  1. you get more responses when tasks are easier to perform. the rewards i'm offering are on the order of L$50 or US$0.20 (not accounting for exchange fees.) maybe it's unreasonable to assume people will (as @shava23 says) "risk reputation for 20 cents." or maybe my followers aren't the recruiting type. or maybe you're not properly motivating existing followers by saying you'll reward new followers. discuss.