Update (December 2020)

I am trying to solve a two-body problem in the American West. Here's my CV. Also check out:

source view: experience.php


<?php



  require './classes/DB.php';
  require './classes/Research.php';





  // NOTE 2020-08-19: Formula is only inserted if LaTeX compiles (this is not true for blog posts, but is from the LaTeX page).
  //                  Due to filename reorg, everything has been de-loaded, but the OG files remain available.
  //                  This is maybe cheating, but not a huge amount.
  $formula_query = DB::getDB()->query( 'SELECT COUNT(*) FROM tblBlogFormulas' ); // WHERE isLoaded = 1' );
  $formula_row   = $formula_query->fetch_row();
  $formula_query->close();



  class Course
  {
    private $course_title;
    private $description;
    private $eval_mean;
    private $eval_median;
    private $has_notes;
    
    
    
    function __construct ( $course_title, $description, $eval_mean, $eval_median, $has_notes )
    {
      $this->course_title = $course_title;
      $this->description  = $description;
      $this->eval_mean    = $eval_mean;
      $this->eval_median  = $eval_median;
      $this->has_notes    = $has_notes;

      if ( is_array( $this->description ) )
      {
        $this->description = $this->description[ rand( 1, count( $this->description ) ) - 1 ];
      }
    }
    
    
    
    function toHTML ( $i )
    {
      $c = $i % 2 ? 'eee' : 'fff';

      $s = <<<EOH
<tr><td><strong>{$this->course_title}</strong>
EOH;

      if ( strlen( $this->eval_mean ) > 0 )
      {
        if ( strlen( $this->description ) > 0 )
        {
          $s .= <<<EOH
  <span style="display:block;font-size:9pt;margin-bottom:1ex;">Mean {$this->eval_mean}; median {$this->eval_median}
EOH;
        }
        else
        {
          $s .= <<<EOH
  <span style="display:block;font-size:9pt;">Mean {$this->eval_mean}; median {$this->eval_median}
EOH;
        }

        if ( $this->has_notes )
        {
          $s .= ' | <a href="/economics-notes">class notes</a>';
        }
        
        $s .= '</span>';
      }
      else if ( $this->has_notes )
      {
        $s .= '<span style="display:block;font-size:9pt;margin-bottom:1ex;"><a href="?economics-notes">class notes</a></span>';
      }

      $s .= <<<EOH
<p style="display:none;">{$this->description}</p></td><td class="more">
EOH;

      if ( strlen( $this->description ) > 0 )
      {
        $s .= <<<EOH
<a href="#" onclick="return showIt( this );">details</a>
EOH;
      }
      
      $s .= '</td></tr>';

      return $s;
    }
  }
  
  
  
  class Hobby
  {
    private $description;
    private $name;
    private $type;
    private $url;
    
    
    
    function __construct ( $name, $type, $url, $description )
    {
      $this->description = $description;
      $this->name        = $name;
      $this->type        = $type;
      $this->url         = $url;
    }
    
    
    
    function toHTML ( $i )
    {
      $s = '<tr><td>';

      $type_letter = strtoupper( substr( $this->type, 0, 1 ) );
      $type_color  = $this->type == 'Android' ? '229966' : ( $this->type == 'HTML' ? '536895' : '990000' );
      
      $s .= <<<EOH
<span style="color:#{$type_color};cursor:default;font-weight:400;margin-right:1ex;" title="{$this->type}">{$type_letter}</span> 
EOH;
      
      if ( $this->url != null )
      {
        $s .= <<<EOH
<a class="heavy" href="{$this->url}" target="_blank">{$this->name}</a>
EOH;
      }
      else
      {
        $s .= <<<EOH
<strong>{$this->name}</strong>
EOH;
      }
      
      $s .= <<<EOH
<p style="display:none;">{$this->description}</p></td><td class="more"><a href="#" onclick="return showIt( this );">details</a></td></tr>
EOH;

      return $s;
    }
  }
  
  
  
  class Job
  {
    private $description;
    private $job_title;
    private $location;
    private $years;
    
    
    
    function __construct ( $job_title, $location, $years, $description )
    {
      $this->description = $description;
      $this->job_title   = $job_title;
      $this->location    = $location;
      $this->years       = $years;
    }
    
    
    
    function toHTML ( $i )
    {
      $c = $i % 2 ? 'eee' : 'fff';
      $d = $i == 0 ? 'block' : 'none';
      $m = $i == 0 ? '' : 'margin:2ex -1ex -1ex -1ex;';
      
      $s = <<<EOH
<tr><td><span style="display:block;font-weight:400;">{$this->job_title}</span><span style="display:block;">{$this->location}, <em>{$this->years}</em></span><p style="display:none;">{$this->description}</p></td><td class="more"><a href="#" onclick="return showIt( this );">details</a></td></tr>
EOH;
      return $s;
    }
  }



  require './classes/Page.php';
  $page = new Page();



  $page->addHeader( <<<EOH
<style type="text/css">
  table
  {
    margin-bottom: 0px;
    margin-left:   15px;
    width:         550px;
  }
  
  td
  {
    padding-top: 0.8em;
  }
  
  td.more
  {
    padding-left:   1ex;
    position:       relative;
    width:          6ex;
    text-align:     center;
    vertical-align: top;
  }
  
  td > p
  {
    margin-bottom: 0ex;
  }

  @media screen and (max-width: 600px)
  {
    table
    {
      width: initial;
    }
  }
</style>
EOH
);
  
$page->addHeader( <<<EOS
<style type="text/css">
  ul.static-list li
  {
    margin-bottom: 2ex;
    text-align:    left;
  }

  ul.static-list > li > span.abstract-link
  {
    float:       right;
    line-break:  pre;
    position:    relative;
    right:       0px;
    margin-left: 3ex;
  }

  ul.static-list > li > span.abstract-link > span::after
  {
    content: " | ";
  }

  ul.static-list > li > span.abstract-link > span:last-child::after
  {
    content: "";
  }

  ul.static-list > li > div.abstract-text
  {
    text-align: justify;
  }

  ul.static-list > li > span.no-divider > span::after
  {
    content: "";
  }

  ul.static-list > li textarea.bibtex
  {
    background-color: #f2f2f2;
    border:           1px solid #999;
    box-shadow:       none;
    color:            #666;
    display:          none;
    font-family:      monospace;
    font-size:        8pt;
    margin:           1ex 0ex;
    outline:          none;
    resize:           none;
    width:            100%;
  }

  .coauthors
  {
    display:    block;
    font-style: italic;
  }

  .journal
  {
    display: block;
  }

  .paper-title
  {
    text-align: left;
  }

  @media screen and (max-width: 600px)
  {
    ul.static-list
    {
      margin-right: 3ex;
    }
  }
</style>
EOS
);


  
  $jobs = array(
    new Job( 'Manager, Data Analysis', 'Homestead Technologies', '2006-2009', 'Attempted to secure position programming; hired instead for mathematical aptitude. Analyzed company performance and provided decision support to executives. Designed sales compensation scheme which (may have) more-than-doubled revenue. Emphasized data accessibility and provided secure web interface to reports, individualized by employee. Earned own department and two employees. Modeled price sensitivity and vocally stood against price increases which later cost significant fraction of revenue. Learned that corporate buyout is financially nice but depression-inducing; came in third for quarter-mile time. Pioneered both <em>March Is Moustache Month</em> and <em>Now Grill It Out</em>.' ),
    new Job( 'Research Assistant', 'Stanford Medical School', '2006-2007', 'Assisted in statistical programming and user interface design for software-based cancer detection. Determined that system was excellent at detecting citrus fruit.' ),
    new Job( 'Web Designer', 'Stanford OFTS', '2005-2006', 'Innovated and maintained the website of the Office of Freshmen and Transfer Students, and related properties. Migrated static site to /cgi-bin so that student content could be delivered dynamically and responsively. Improved GPA and discovered the benefits of a cushy job.' ),
    new Job( 'Research Assistant', 'Stanford Department of Economics', '2004-2007', 'Coded and scraped address information for research into spatial monopolies in the asphalt market. Later, scraped data for use in contract research on antitrust and patent-gathering in the pharmaceutical industry.' ),
    new Job( 'Orientation Coordinator', 'Stanford New Student Orientation', '2004-2005', 'Co-led event planning and chaired website design. Won national award for <em>Outstanding Orientation Website</em>; the Internet Archive does not record this. Successfully delivered 1600 new students to their dorms and classes with a minimum volume of tears from parents.' ),
    new Job( 'Grader', 'Stanford Department of Mathematics', '2004-2006', 'Graded peers\' problem sets under the guise of alleviating graduate student stress. Came to understand the delicate balance of errors-in-grading and time-of-grading; derived optimal strategy.' ),
    new Job( 'Undergraduate Tutor', 'Stanford University Mathematics Organization', '2003-2006', 'Tutored undergraduate math courses, particularly calculus (of one and many variables), linear algebra, and differential equations. Developed useful teaching skills such as using a calculator and writing upside-down, and pointing left when I said "right." Learned persistence in attempting to explain concepts.' ),
    new Job( 'Reunion Homecoming Team Leader', 'Stanford Alumni Association', '2003-2007', 'Coordinated on-campus transportation and signage for Stanford reunions. Camped out in the golf cart parking lot to run dispatch for 70 hours over four days. Discovered that golf carts can climb stairs; hospitalized due to being run over by same. Learned intricacies of worker\'s compensation.' ),
    new Job( 'IT Support', 'Iron Age', '2003', 'Offered dial-in and dial-out support of the company network, setting up VPN connections remotely in twelve states and Puerto Rico. Learned to never say "click" when "left-click" is meant. Failed to receive a paycheck and similarly failed to receive appreciation for Windows networking.' ),
    new Job( 'Residence Associate', 'Columbia University', '2003', 'Jointly RA\'d a hall of rising high school seniors during a summer program at Columbia University. Hosted social events and trips around New York to keep students engaged. Encouraged teens to practice safe sex.' ),
    new Job( 'Mail Clerk', 'Ikon', '2002-2003', 'Moved boxes for coworker. Innovated mail delivery by encouraging that the radio be tuned to top-40 rather than country (the hourly <em>Ten Rounds with Jose Cuervo</em> was hitting morale). Learned to effectively sort large stacks of documents, a skill regularly applied while TAing. Wore protective anthrax clothing to thwart terrorists. Garnered respect by eating a Triple Baconator in less than one minute.' ),
    new Job( 'Courier', 'Jet Messenger Service', '2002', 'Pedaled a bicycle around downtown Pittsburgh to deliver what I was asked. Competitive advantage since the only other courier company in town had just been shut down for insane workers\' comp costs. Learned to work with ex-convicts. Due to the cost of Biggie-Sizing lunches (to maximize caloric intake) and the theft of a bicycle lock, made zero money. In light of this fact, tendered immediate resignation.' ),
    new Job( 'Rep I', 'Best Buy', '2001-2002', 'Wore camouflage to keep customers from knowing that I was an employee while stocking shelves. Learned how to properly throw a television, stereo system, or vacuum cleaner and then rebox it. Promoted to cashier because of my winning personality and ability to bullshit people into buying things they didn\'t need. Received death threats and was mentioned in a letter to the editor; quit to attend prom. Shortly after my resignation store management was terminated for presiding over the "highest-theft" store in the nation.' )
  );



  $programming = array(
    new Research( 'Fractal generator', '/v2/fractal/?canvas', 'HTML5 implementation of the <a href="/">splash page</a> fractals, built to test real-time image generation prior to site upgrade. 2D rendering in WebGL is still an emerging feature, with especial pitfalls if the underlying optimization problems are not known in advance; there\'s a <tt>&lt;canvas&gt;</tt> backup for browsers that don\'t make the grade.' ),
    new Research( 'Javascript Logo', '/v2/logo/', 'A partial (yet fairly robust) implementation of the Microworlds dialect of Logo through Javascript and canvas. Documentation is as-yet nonexistent, but there are several examples to demonstrate basic features; the header graphics on this website are generated through the interpreter, so viewing source is another excellent tool. Currently there is no turtle icon moving around, since <a href="http://inkscape.org/" target="_blank">Inkscape</a> runs like molasses on my machine.' ),
    new Research( 'LaTeX to png', '/latex.php', 'Generates png graphics from LaTeX math markup; although there are many similar services out there at present, back in 2008 this was pretty much the option. As of <em>right now</em>, I am hosting ' . $formula_row[0] . ' mathematical formulas available to the world, which proves that someone out there finds this useful.' ),
    new Research( 'ROFLBOT', '/roshambo-markov-chains-and-a-teaspoon-of-lulz/', 'A locally-successful rock-paper-scissors runner-up, coming in second place in the first-and-last annual Homestead Rock-Paper-Scissors championship (where the only rule was to not implement <a href="http://ofb.net/~egnor/iocaine.html" target="_blank">Iocaine Powder</a>). The primary challenge of this was not so much implementing a complex decision rule as it was implementing it in LOLCODE; I am proud of its performance given the constraints.' ),
    new Research( 'YALI', '/yali-yet-another-lolcode-interpreter/', 'A Perl interpreter for <a href="http://lolcode.com/" target="_blank">LOLCODE</a>; now <a href="http://portsmon.freebsd.org/portoverview.py?category=textproc&portname=yali" target="_blank">ships with FreeBSD</a>. While cat macros have come and gone &mdash; and good riddance &mdash; this experiment in language design and implementation has proved fairly instructive downstream.' )
  );



  $hobbies = array(
    new Hobby( 'A is for Acid Monkey', 'HTML', 'http://aisforacidmonkey.com', 'An unforgettable photograph deserves a safe place in the pantheon of Internet lore. Since <a href="https://www.google.com/search?gcx=c&sourceid=chrome&client=ubuntu&channel=cs&ie=UTF-8&q=lnkd" target="_blank">LNKD</a> creams me in the search results for my own name, it\'s good to know that a search for "monkey on acid" will lead the world unknowingly my way, without fail.' ),
    new Hobby( 'burratr', 'HTML', 'http://burratr.com', 'Have you ever been driving around town, gotten hungry, and thought, "Hey! I could use a burrito. But where should I go? Yelp won\'t work, since it\'s not burrito-specific. What\'s a guy to do?" Well search no more. This site is effectively deprecated, but provides everlasting documentation of a few holes-in-the-wall in the Menlo Park area (circa 2008).' ),
//    new Hobby( 'Cloudyvolve', 'Android', 'https://play.google.com/store/apps/details?id=org.eightbeers.android.cloudyvolve', 'A three-dimensional evolving cloud field which rotates with your phone; I find it calming. Since it would make for a stupid game, it\'s a wallpaper; move around enough and you\'ll see every face. There was nothing similar on the Android market so I wrote it myself.' ),
//    new Hobby( 'Cordless Phone', 'Android', 'https://play.google.com/store/apps/details?id=org.eightbeers.android.oldskooldialpad', 'Remember when your phone would play a dial tone when you picked it up off the cradle? When seven digits would connect you to your best friend on his tenth birthday? When you had to start over after you hit the wrong digit? With all these features and more, Cordless Phone takes your Android phone back to the last millennium.' ),
//    new Hobby( 'cumbiesbeta.org', 'HTML', 'http://cumbiesbeta.org', 'A proposal for my extended family\'s website, superseded by political constraints. This version shipped with a Java-compiled app to upload photos and comments directly, to avoid server timeouts from standard HTML form uploading.' ),
    new Hobby( 'eightbeers.org', 'HTML', 'http://eightbeers.org', 'Old content from my halcyon days needed a server to give it new life, so it resides here. As of yet, nothing is "live" enough to make it to the homepage (due to the incompetent programming of youth), but someday Choose My Underwear will reappear. Get excited.' ),
    new Hobby( 'GemIdent', 'Binary', 'http://gemident.com', 'I was asked by a friend to join a grant for development of a piece of software to identify cancer from stained biopsy slides. The software works quite well, although I\'m unclear on how many (if any) lives were saved.' ),
//    new Hobby( 'Meacon', 'Android', 'http://play.google.com/store/apps/details?id=org.eightbeers.android.meacon', 'Meacon is the self-location tracking app that everyone writes when they write a self-location tracking app &mdash; for all the people who have used their cell phones to record their own tracklogs, none had released a general app to the market. Meacon submits the device\'s location to a user-specified URL on an interval, has a location-free debug file for ease of use, and avoids recording location data internally so that data is owned by the user and no one else.' ),
//    new Hobby( 'NextBeer', 'HTML', 'http://next.eightbeers.org', 'Need a fresh local brew in a hurry? In or around Denver, San Francisco, or Seattle? Want to be sure that you don\'t go to some chumpy place without a dartboard? NextBeer was built to help solve important questions like these, with an eye toward helping beer tourists crawl by the seat of their pants. Incidentally, also a fun data mining project. <span style="font-style:italic;">Data updated and new cities added by request, so don\'t hesitate to <a href="/about.php">get in touch</a>.</span>' ),
    new Hobby( 'opensourcebar.org', 'HTML', 'http://opensourcebar.org', 'During the senior year of my undergraduate education, my roommates and I decided that the one thing we needed most was a homemade bar. Nine months, a few dozen kegs and a handful of grade points later we were moving out, but were not interested in losing our dear asset. We staged a second-price auction, and were to be rewarded with a cool $500 before Housing issued and ultimatum that the bar must be disposed of post haste.' ),
//    new Hobby( 'Reaction', 'Android', 'https://play.google.com/store/apps/details?id=org.eightbeers.android.reaction', 'A poll-notification app for linking your Android device to a server. Obtains a list of items requiring response from the server, lets you know, then lets you take the appropriate action. Originally formulated for moderating blog comments, it is capable of operating in far broader capacities; I still use it just for spam-checking.' ),
//    new Hobby( 'Reverse Ringtone', 'Android', 'https://play.google.com/store/apps/details?id=org.eightbeers.reverseringtone', '"Irritating." "Stupid." "Hilarious." An Android app which overrides your native ringtone, playing the DTMF tones for the incoming number when the call arrives. Since this concept is difficult to get across in words, I highly recommend downloading and giving it a shot. If you don\'t want to wait for an incoming call, there\'s always <a href="http://www.bevoz.com/Find-My-Phone" target="_blank">this</a>.' ),
//    new Hobby( 'routeslipper.org', 'HTML', 'http://routeslipper.org', 'At a point in time, <a href="http://klimb.org/" target="_blank">Klimb</a> was <em>the</em> way to figure out information about appropriate cycling routes in the Bay Area (other than dropping by the local shops). Since I moved around frequently, I saw the need for something of the same style, but more dynamic; enter routeslipper. Today, there are a billion bike-route sites out there, and it seems a new one comes to the fore every few months. routeslipper was the first, if the least-loved.' ),
    new Hobby( 'ShabKyle.com', 'HTML', 'http://shabkyle.com', 'Originally a website for wedding details, now the official site of my newly-founded nuclear family. A <a href="http://www.shabkyle.com/dev/photos/" target="_blank">wedding photo search engine</a> is up for interested parties.' ),
//    new Hobby( 'UCLA Bicycle Parking', 'Android', 'https://market.android.com/details?id=org.eightbeers.android.uclabp', '<span style="font-style:italic;">Now defunct.</span> Of limited interest to most but extreme interest to some, UCLA maintained a set of bicycle lockers which operate by phone. Trouble is, while they looked free and clear many were secretly locked with no hope of parking a bicycle. This Android app provided information on which parking structures had available lockers and which did not.' ),
//    new Hobby( 'Un-chained', 'HTML', 'http://shabkyle.com/yunc/', 'A local search engine built on the <a href="http://yelp.com" target=""_blank">Yelp</a> API, using crowdsourced information to attempt to filter out different levels of chain (or to include only the same). If you\'ve ever found yourself in a new locale and looking for local color on Yelp, you have surely seen listing after listing of chain restaurants. While there are times when all you want is a reliable hamburger and a chain will serve you well, there are others when this information is essentially spam. Un-chained solves this problem.' ),
    new Hobby( 'Where is Kyle?', 'HTML', 'http://whereiskyle.net?', 'Sometimes you just need to know where I am, <em>right now</em>. Problem solved.' )
    // new Hobby( 'Where is Kyle?', 'Android', 'https://play.google.com/store/apps/details?id=org.eightbeers.android.whereiskyle', 'All the information of <a href="http://whereiskyle.net?" target="_blank">Where is Kyle?</a>, all the convenience of an app. Includes the option to receive notifications when I am within 25m of your current location, which is surprisingly nontrivial mathematically (details forthcoming). Sure would be useful if you wanted to throw me a surprise party, right?' )
  );


  
  $page->printPageHeader();


  
?>
<h3>professional</h3>
<p>
  I've been steadily &mdash; if not gainfully &mdash; employed since high school, and have acquired a number of unanticipated skills along the way. With luck my future employment won't center on my ability to fix a printer, sort mail, set up a corporate VPN, sell a product warranty, navigate a city, be a chauffeur, or monitor the comings-and-goings of seventeen-year-olds, but in <span style="font-style:italic;">this economy</span> one can never be too sure. This list exists in full form chiefly to keep me from forgetting.
</p>
<!--<ul class="static-list">-->
<table cellpadding="0" cellspacing="0">
<?php

  for ( $i = 0; $i < count( $jobs ); ++$i )
  {
    print $jobs[$i]->toHTML( $i );
  }

?>
</table>
</ul>
<h3>programming</h3>
<p>
  Coding helps me explore unusual, aesthetic questions. While it might be a stretch to classify the following as research proper, each represents something deeper than just-a-website. All can be played with to satisfy your own curiosity, although some need to be downloaded first.
</p>
<ul class="static-list">
<?php

  for ( $i = 0; $i < count( $programming ); ++$i )
  {
    print $programming[$i]->toHTML( $i + count( $economics ), '', false );
  }
  
?>
</ul>
<h3>side-show</h3>
<p>
  I relax by riding my bike, building things, brewing beer, and writing code. Outside of a few forum posts and a handful of pictures there's not much evidence of the first three, but last has the satisfying property of self-exposition. I haven't received any queries about acquisition, but only time will tell; in the meantime, I'm happy enough to have made some piece of the world a little more entropic.
</p>
<p style="font-style:italic;">
  All Android projects have been removed, as it became impossible for me to keep up with the rapidly-shifting requirements of the Android marketplace. Partially because of Google's constant need to deprecate platform APIs and increase marketing presence, and partially because I misplaced the packaging keys.
</p>
<!--<ul class="static-list">-->
<table cellpadding="0" cellspacing="0">
<?php

  for ( $i = 0; $i < count( $hobbies ); ++$i )
  {
    print $hobbies[$i]->toHTML( $i );
  }
  
?>
</table>
<!--</ul>-->
<script type="text/javascript">
  //<!--[CDATA[
    function showIt ( e )
    {
      var td = e.parentNode.parentNode.childNodes[0];
      
      for ( var ie = 0; ie < td.childNodes.length; ++ie )
      {
        var cn = td.childNodes[ie];
        
        if ( cn.tagName && cn.tagName.toUpperCase() == 'P' )
        {
          if ( cn.style.display == 'none' )
          {
            cn.style.display = 'block';
            e.innerHTML      = 'less';
            
            clear( e.parentNode );
          }
          else
          {
            cn.style.display = 'none';
            e.innerHTML      = 'more';
          }
          
          break;
        }
      }
      
      return false;
    }
    
    
    
    function clear ( e )
    {
      while ( e.childNodes.length )
      {
        e.removeChild( e.childNodes[0] );
      }
    }
  //]]-->
</script>
<?php
  
  

  $page->printPageFooter();
  
  
  
?>