Add Scroogle to your search area in Firefox 2.0 Install the 'Scroogle Scraper' search plugin.

exit.jpgBecause tech companies seem to have a high rate of turnover, you’ll soon likely be in the position of leaving or interviewing an employee who is leaving. Either way, it’s important to find answers to some important questions such as:

  • If the CEO left unexpectedly today and you were put in charge, what are the first things you would change?
  • What could have changed six months ago that would have prevented you from looking for a new job?
  • If you weren’t looking, what factors tipped the scale when an opportunity came up?
  • Who do you think is next to resign and why?
  • If one person leaving the firm would cause you to think twice about leaving, who would that person be?
  • Why didn’t you leave us sooner than now?
  • How did your manager communicate your responsibilities? DO you think he or she was fair and reasonable?
  • Describe any areas of conflict that have affected either your performance or morale, or that you believe affected other employees

src: Inc. Magazine, April 2006

You all remember Josh Coates, CEO of Berkeley Data Systems/Mozy, right? Mozy is the company with the Windows program which allows you to backup your harddrive to their petabyte array all safe and securely. Truth be told, I could never get their app to work on my system, but that’s hardly significant. What is important is that EMC, the king of storage, just bought Mozy for a cozy 76 million dollars.

Mozy had raised only 1.9 million in capital, which makes their VC people (Wasatch Ventures) very, very happy.

You’ll also remember that Josh’s Mozy held the popular $20,000 dollar computer programming “death matches.”

Strong work, Josh!

* yes, I know that “mozying” is not a word; it’s “moseying”

  • Does the business idea lend itself to venture capital investment?

    1. is it the next big thing?

    2. can it produce 5x-20x return on an investment of 5 million in 3-5 years?
    3. does it have some sort of infringement protection (network effect, patent, big head start)?
  • Are there tiered service levels (e.g. free, basic, pro)?
  • How many paying subscribers at what monthly rate do you predict in 1,6,12,18 months? (how did you arrive at your prediction?)
  • Are there possibilities for affiliate relationships?
  • What variable and fixed costs will you incur?
  • How will you advertise and drive traffic to your site?
  • How will you handle customer support?
  • Is there any inventory to manage?
  • How much staff is required? Where will you find the best people?

Start with a SWOT analysis

Then, find answers to these questions:

  • Are there competitors?
  • Does the service satisfy an important need?
  • Is it a one time/infrequent purchase or would it be on a subscription model?
  • What is the estimated profit margin?
  • Does it depend on a lot of people resources to run it?
  • How easily would it scale?
  • How easy would it be for competitors to copy?
  • Does it lend itself to patent/copyright protection?
  • What is the market size?
  • Are there substitute services?
  • Does the service lend itself to the “network effect?”

Real Age calculators have become all the rage lately and so I decided to reverse engineer (and improve) a popular one (http://www.poodwaddle.com/realage.htm .) The poodwaddle calc is made in flash, but I made mine in php and javascript with an XML backend. Below is the code I used to read the Real Age XML into a PHP array. (oh, and you’ll also need the PHP XML parsing class from php.net.)

  1. <?
  2. if (!isset($_SESSION['questionArray'])) //cache
  3. {
  4. $lookupTable=array();
  5. foreach($xml->children[0]->children as $lookup)
  6. {
  7. if ($lookup->name=='row')
  8. $lookupTable[$lookup->attributes["input"]]=$lookup->attributes["output"];
  9. }
  10.  
  11. $questionArray=array();
  12. foreach($xml->children[1]->children as $questions)
  13. {
  14. $tempQuestion=new Question();
  15. $tempQuestion->title=$questions->children[0]->content;
  16. $tempQuestion->prompt=$questions->children[1]->content;
  17. $tempQuestion->genderSpecific=$questions->children[2]->content;
  18. $tempQuestion->controllable=$questions->children[4]->content;
  19. $tempQuestion->options=array();
  20. foreach($questions->children[3]->children as $option)
  21. {
  22. $optionPrompt=$option->attributes["prompt"];
  23. $RAEffect=$option->attributes["RA-effect"];
  24. $tempQuestion->options[$optionPrompt]=$RAEffect;
  25. }
  26. $questionArray[]=$tempQuestion;
  27. }
  28. $_SESSION['questionArray']=$questionArray;
  29. $_SESSION['lookupTable']=$lookupTable;
  30. }
  31. ?>

The actual Real Age code is pretty ugly, but I’ll post it as soon as I clean it up. Yes it works in IE and FF. Yes, the javascript slider code is slow (but it works!). It’s from the dojokit. It was the only vertical slidebar that allowed custom labels I could find.

healthitblogs_sml.jpgI recently stumbled upon Javascript/Canvas Graph library which allows you to create cool network graphs with nodes and interconnections. Now that I had a graphic library, I needed something with lots of connections to graph. That’s when I thought of mapping health IT blog sites. Now all I needed was a spider…

Spiders, robots, crawlers all work on the same principle: start with a seed url(s), request the urls and then parse out the resultant html for all link tags which are then pushed into the queue for crawling.

time for some code:

  1. <?
  2. $tldList=file("tlds.txt");
  3. $masterList=file("masterList.txt");
  4. $acceptableNodes=array();
  5. foreach($masterList as $node)
  6. {
  7. $node="http://".trim($node);
  8. $acceptableNodes[]=parse_url_domain ($node);
  9. }
  10. //print_r($acceptableNodes);
  11. $connections=array();
  12. $nodeCounter=array();
  13. foreach ($masterList as $webpage)
  14. {
  15. $url ="http://".trim($webpage);
  16. $strippedWebpage=parse_url_domain ($url);
  17. $input = file_get_contents($url); //or die("Could not access file: $url");
  18. if (!$input) continue;
  19. $regexp = "<a\s[^>]*href=(\"??)([^\" >]*?)\\1[^>]*>(.*)<\/a>";
  20. $URLs=array();
  21. if(preg_match_all("/$regexp/siU", $input, $matches, PREG_SET_ORDER))
  22. {
  23. foreach($matches as $match)
  24. {
  25. //echo($match[2]."\t");
  26. $currentURL=parse_url_domain ($match[2]);
  27. //echo($currentURL);
  28. //echo("\n");
  29. if ($currentURL!=$webpage && !in_array($currentURL,$URLs)&&check_domain($currentURL)&&check_tld($currentURL))
  30. {
  31. $URLs[]=$currentURL;
  32. if (in_array($currentURL,$acceptableNodes)&& ($strippedWebpage!=$currentURL))
  33. {
  34. $connections[]="$strippedWebpage -> $currentURL";
  35. $nodeCounter[$currentURL]++;
  36. }
  37. }
  38.  
  39. }
  40. }
  41. echo("$webpage : \n");
  42. print_r($URLs);
  43. }
  44. echo("connections: ");
  45. print_r($connections);
  46. echo("nodeCounter: ");
  47. print_r($nodeCounter);
  48. echo("javascript edges: ");
  49. $multiplier=3;
  50. foreach($connections as $connection)
  51. {
  52. list($from,$to)=explode(" -> ",$connection);
  53. $fromCtr=3*$nodeCounter[$from];
  54. $toCtr=3*$nodeCounter[$to];
  55. echo("g.addEdge($('".$from."'), $('".$to."'),".$fromCtr.",".$toCtr.");\n");
  56. }
  57. function parse_url_domain ($url)
  58. {
  59.  
  60. $raw_url= parse_url($url);
  61. if ($raw_url['host'] == '')
  62. {
  63. $raw_url['host'] = $raw_url['path'];
  64. }
  65. $domain_only[1] = $raw_url['host'];
  66. return strtolower($domain_only[1]);
  67. }
  68. function check_domain ($url)
  69. {
  70. if (!ereg("^.*\..*$", $url))
  71. {
  72. return false;
  73. }
  74. $local_array = explode(".", $url);
  75. for ($i = 0; $i < sizeof($local_array); $i++)
  76. {
  77. if (!ereg("^(([A-Za-z0-9!#$%&#038;'*+/=?^_`{|}~-][A-Za-z0-9!#$%&#038;'*+/=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$", $local_array[$i]))
  78. {
  79. return false;
  80. }
  81. }
  82. return true;
  83. }
  84. function check_tld($url)
  85. {
  86. global $tldList;
  87. $parts=explode(".",$url);
  88. $lastpart=trim($parts[count($parts)-1]);
  89. foreach($tldList as $item)
  90. {
  91. if (trim($item)==$lastpart)
  92. return true;
  93. }
  94. return false;
  95.  
  96. }
  97. ?>

and no, I’m not talking about the Utah Summer Games Arm Wrestling competition.

I’m talking about Python, the programming language. And to encourage adoption of that language some clever people created a little Python programming game (back in 2005.) You’re presented with a riddle of sorts and you’re supposed to code up a python script to solve it. Only, I don’t like people telling me what to do, so I intentionally did NOT code up python to solve them. I used PHP mostly. Here are my notes:

QUESTION 1: what’s 2^38?
ANSWER: I asked google: http://www.google.com/search?hl=en&q=2%5E38&btnG=Google+Search
and then I used the answer to get to the next step: 274877906944.html

QUESTION 2: given: K->M, O->Q, E->G, decode: g fmnc wms bgblr rpylqjyrc gr zw fylb. rfyrq ufyr amknsrcpq ypc dmp. bmgle gr gl zw fylb gq glcddgagclr ylb rfyr’q ufw rfgq rcvr gq qm jmle. sqgle qrpgle.kyicrpylq() gq pcamkkclbcb. lmu ynnjw ml rfc spj.
ANSWER: I used an online cryptogram solver (though i could have written a simple script to shift up two letters…)
“map” then, shifts to “ocr”, which leads to http://www.pythonchallenge.com/pc/def/ocr.html

QUESTION 3: Find rare characters in the mess below (mess omitted)
ANSWER: php:
$challenge=file_get_contents('phychall2.txt');
echo(ereg_replace("[^a-z]","",$challenge));

which produces: http://www.pythonchallenge.com/pc/def/equality.html

QUESTION 4: “One small letter, surrounded by EXACTLY three big bodyguards on each of its sides.”
ANSWER: I used textpad’s regex ([a-z][A-Z][A-Z][A-Z][a-z][A-Z][A-Z][A-Z][a-z]) and found “linkedlist”, which means: http://www.pythonchallenge.com/pc/def/linkedlist.html

QUESTION 5: “urllib may help. DON’T TRY ALL NOTHINGS, since it will never end. 400 times is more than enough”
ANSWER:
$linked="12345";
for($x=0;$x<400;$x++)
{
$page=file_get_contents("http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=$linked");
echo($page."\n");
$previouslinked=$linked;
$linked='';
list($blank,$linked)=@split('and the next nothing is ',$page);
$pos = strpos($page, "Divide");
if ($pos === false)
{
if ($linked=='') die();
}
else
{
$linked=$previouslinked/2;
echo("divide found!!");
}
echo($linked."\n");
}

which produces: http://www.pythonchallenge.com/pc/def/peak.html

QUESTION 6: peak hell
ANSWER:
arghh. have to use python…need to load the pickle dump:

import pickle
unpicklefile = open('banner.p', 'r')
unpickledlist = pickle.load(unpicklefile)
unpicklefile.close()
for item in unpickledlist:
print item

python unpickle.py > nextstep.txt

lines look like: [(’ ‘, 14), (’#', 5), (’ ‘, 70), (’#', 5), (’ ‘, 1)]

parse them with:

$problem=file("nextstep.txt");
$parseout=array('(',']',')','[',"'");
function printit($value,$times)
{
for($loop=0;$loop<$times;$loop++)
echo($value);
}
foreach($problem as $line)
{
$tuples=split('),',$line);
foreach($tuples as $tuple)
{
list($first,$second)=split(',',$tuple);
$first=trim(str_replace($parseout,'',$first));
if ($first=='') $first=' ';
$second=trim(str_replace($parseout,'',$second));
printit($first, $second);
}
echo("\n");
}

which produces a nifty ascii art version of: http://www.pythonchallenge.com/pc/def/channel.html

QUESTION 7: : now there are pairs (in http://www.pythonchallenge.com/pc/def/channel.zip)
ANSWER:

$linked="90052";
for($x=0;$x<909;$x++)
{
$bigArray[]=system("zipinfo -v channel.zip {$linked}.txt|tail -3|head -1",$retval);
$page=file_get_contents("{$linked}.txt");
$previouslinked=$linked;
$linked='';
list($blank,$linked)=@split('Next nothing is ',$page);
$pos = strpos($page, "Collect");
if ($pos === false);
else
{
$x=10000;
}
}
$counter=2;
foreach($bigArray as $dot)
{
if ($dot=='') $dot=' ';
echo($dot);
if ($counter++%65==1) echo("\n");
}

Which produces more ASCII art and leads to: http://www.pythonchallenge.com/pc/def/oxygen.html

QUESTION 8: the next level is [105, 110, 116, 101, 103, 114, 105, 116, 121]
ANSWER:

$im = imagecreatefrompng("oxygen.png");
for($x=3;$x<629;$x+=7)
{
$rgb = imagecolorat($im, $x, 46);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
echo(chr($r));
}

more code:

$thelist=array(105, 110, 116, 101, 103, 114, 105, 116, 121);
foreach($thelist as $entry)
{
echo(chr($entry));
}


http://www.pythonchallenge.com/pc/def/integrity.html

QUESTION 9:
un: ‘BZh91AY&SYA\xaf\x82\r\x00\x00\x01\x01\x80\x02\xc0\x02\x00 \x00!\x9ah3M\x07<]\xc9\x14\xe1BA\x06\xbe\x084'
pw: 'BZh91AY&SY\x94$|\x0e\x00\x00\x00\x81\x00\x03$ \x00!\x9ah3M\x13<]\xc9\x14\xe1BBP\x91\xf08'
ANSWER: missing link : bee
use commandline python, arghh…

s = "BZh91AY&SYA\xaf\x82\r\x00\x00\x01\x01\x80\x02\xc0\x02\x00 \x00!\x9ah3M\x07<]\xc9\x14\xe1BA\x06\xbe\x084"
import bz2
bz2.decompress(s)
'huge'
t = "BZh91AY&SY\x94$|\x0e\x00\x00\x00\x81\x00\x03$ \x00!\x9ah3M\x13<]\xc9\x14\xe1BBP\x91\xf08"
bz2.decompress(t)
'file'

QUESTION 10: first+second=?
ANSWER:
connect the dots

$image = imagecreatefromjpeg("good.jpg");
$col_poly = imagecolorallocate($image, 255, 0, 0);
$firstArray=array(146,399,163,...);
$secondArray=array(156,141,165,...);
imagepolygon($image, $firstArray,count($firstArray)/2, $col_poly);
imagepolygon($image,$secondArray,count($secondArray)/2,$colpoly);
header("Content-Type: image/jpeg");
imagejpeg($image);


http://www.pythonchallenge.com/pc/return/cow.html
http://www.pythonchallenge.com/pc/return/bull.html

QUESTION 10: a = [1, 11, 21, 1211, 111221, len(a[30]) = ?
ANSWER:
googled for code:

#!/usr/bin/perl
$str="1"; for (1 .. shift(@ARGV)) { print($str, ", "); @a = split(//, $str); $str=""; $nd=shift(@a); while (defined($nd)) { $d=$nd; $cnt=0; while (defined($nd) && ($nd eq $d)) { $cnt++; $nd = shift(@a); } $str .= $cnt.$d; } } print($str);

paste into textpad for character count
http://www.pythonchallenge.com/pc/return/5808.html

QUESTION 11: odd even
ANSWER:
PBM (Portable BitMap) file (PBM stores single bit pixel image as a series of ascii “0″ or “1″’s. The magic identifier for PBM is “P1″.)

32 0s and 1s (separated by spaces) on 20 rows makes 640
then switch to 1s and 0s and do this 240 times


print "P1\n", "640 480\n";
my $odd = ( "0 1 " x 16 . "\n" ) x 20;
my $even = ( "1 0 " x 16 . "\n" ) x 20;
for ( 1 .. 240 ) { print $odd, $even }

gimp:
load image
load mask.txt as a layer
select that layer
layer->color to alpha
white->alpha

produces: evil

Maybe you, too, are forced to use a web app that doesn’t support Firefox? At my work, we use Salesnet.com. Says salesnet.com’s login help screen “The application supports Internet Explorer 5.0, 5.5, 6.x, and 7.x. You cannot login with any other browser.”

That’s pretty inconvenient, particularly because it doesn’t even do a very good job in IE 7.0. It keeps complaining about the pop-up blocker being on, when the pop-up blocker is clearly off. Annoying.

Enough of this silliness! I installed the User Agent Switcher Firefox extension, restarted firefox, instructed the extension to identify my browser as IE 6.0 and HUZZAH! I could log into salesnet.com and do my work.

Nice job dumb Salesnet.com people.

As you probably know, Microsoft released its long awaited XP successor, Vista. Some have asked what I think of it. I’ve played around with Vista a bit at work and my firm recommendation is to NOT UPGRADE TO VISTA. There is no compelling advantage. Indeed, I’m aware of many negative effects of upgrading: programs not running, device drivers not working etc.

As well, Microsoft recently released Office 2007, which contains new versions of Excel and Word. Here’s the catch: the default file format .xlsx and .docx ARE NOT BACKWARD COMPATIBLE! That is the epitome of stupidity. Purely retarded. Why would they do that?!?!?

My next desktop operating system will surely not be Vista. It will be a version of Linux. Linux has not, in my opinion, been ready for the desktop for some time, but it’s becoming better and better all the time. Stay tuned!

In my last blog entry on GPS and Google Maps, I gave the PHP source to a file that queries the USB attached GPS device, parsed the XML and returns a JSON encoded array with values containing the latitude and longitude and timestamp and if the current position has moved significantly. Now we need a webpage to call that php code and display a google map:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script language="JavaScript" type="text/javascript" src="/js/prototype.js"></script>
<script>
function GetXmlHttpObject()
{
return Try.these(
function() {return new XMLHttpRequest()},
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
function() {return new ActiveXObject('Microsoft.XMLHTTP')}
) || false;
}
function queryGPSunit()
{
document.getElementById("status").innerHTML="querying GPS..."
var url="queryGPSunit.php"
xmlHttp=GetXmlHttpObject()
if (xmlHttp==null)
{
alert ("Browser does not support HTTP Request")
return
}
xmlHttp.onreadystatechange=GPSreturned
xmlHttp.open("GET",url,true)
xmlHttp.send(null)
}
var first=1;
var long=0;
var lat=0;
var timeStamp =0;
function GPSreturned()
{
if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
{
//alert(xmlHttp.responseText)
eval("var decoded_data = "+xmlHttp.responseText);
lat = decoded_data[0]
long = decoded_data[1]
timeStamp = decoded_data[2]
moved = decoded_data[3]

if (moved==1||first==1)
{
document.getElementById("currentGPS").innerHTML=lat+" "+long+" "+timeStamp
document.getElementById("status").innerHTML="moving"
first=0
load(lat,long)
}
else
{
document.getElementById("status").innerHTML="paused"
setTimeout('queryGPSunit()', 4000);
}
}
}
</script>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Maps JavaScript API Example</title>
<script src="http://maps.google.com/maps?file=api&v=2&key=[insert your key here]"
type="text/javascript"></script>
<script type="text/javascript">

//<![CDATA[

function load(lat,long) {
if (GBrowserIsCompatible()) {
var map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(lat,long), 16,G_HYBRID_MAP);
var point = new GLatLng(lat,long);
map.addOverlay(new GMarker(point));
setTimeout('queryGPSunit()', 4000);
}
}

//]]>
</script>
</head>
<body onload="queryGPSunit()" onunload="GUnload()">
<table><tr><td>
<div id="map" style="width: 700px; height: 500px"></div>
</td><td>
<b>GPS and timestamp: </b><div id="currentGPS"></div><br />
<b>Status:</b> <div id="status"></div>
</td>
</tr>
</table>
</body>
</html>

« Previous PageNext Page »

Send to a friend * Print this page * Join the club * Talk with my robot * Advertise here * Search this Site * Donate * Link to me


Web hosting by Utah Hub *  Powered by CreativeTap *  In association with Segomo
Unless otherwise noted, Copyright 2004-2006, Ryan Byrd. All Rights Reserved.
Ryan Byrd dot net -- probably the coolest site in Utah