Saturday, November 15, 2014

PHP Alphanumeric Encoder/Decoder

The following two functions are an alphanumeric encoder and decoder respectively.  The intent of the first function is to take a base 10 number and encode it using some character set.  It is hardcoded to use a charset of “1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ”.  Because there are 36 characters in this character set, the encoder effectively becomes a base 10 to base 36 encoder by default.  But you can either alter the default encoding string or pass in the alphabet you want to use as a second argument and encode the base 10 number to any base you desire.  The second function reverses the process.

I have tested both functions quite extensively, and they both appear to work flawlessly.

  /**
    * Encode a base 10 number into some alternate base
    *
    * @param int $num
    * @param string $alphabet
    * @return string $alphaNum
    */
   public static function alphaEncode($num, $alphabet=null) {
      $result = '';
      if (!$alphabet) {
         $alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
      }
      $alphabet = str_split($alphabet);
      if ($num == 0) {
         return $alphabet[0];
      }
      $base = count($alphabet);
      while ($num > 0) {
         $remainder = $num % $base;
         $num = floor($num / $base);
         $alphaNum = $alphabet[$remainder] . $alphaNum;
      }
      return $alphaNum;
   }
   
   /**
    * Decode an encoded number back into base 10
    *
    * @param string $alphaNum
    * @param string $alphabet
    * @return int $num
    */
   public static function alphadDecode($alphaNum, $alphabet=null) {
      $result = '';
      if (!$alphabet) {
         $alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
      }
      $alphabet = str_split($alphabet);
      $base = count($alphabet);
      $num = 0;
      $idx = 0;
      $charCount = strlen($alphaNum);
      $charArray = str_split($alphaNum);
      foreach ($charArray as $char) {
         $power = ($charCount - ($idx + 1));
         $charIndex = array_search($char, $alphabet);
         $num += $charIndex * pow($base, $power);
         $idx++;
      }
      return $num;

   }

Wednesday, August 20, 2014

Disable Toyota Prius Backup Alarm Using Techstream

I recently bought my daughter a 2010 Toyota Prius.  I noticed the backup alarm when we were test driving it, and it doesn’t grow on you over time.  So I decided to try and disable it. 

I had a Toyota Techstream compatible module (an overseas knockoff) leftover from a problem with my wife’s Lexus.  The same module works on all Toyotas.  So I was able to use it on the Prius as well. 

You can find one by Googling “toyota mini vci amazon”.  You will get a bunch of hits.  One of them is here: http://www.amazon.com/Newest-V8-00-034-Techstream-Diagnostic-Software/dp/B00C9B32J4.

Make sure it comes with the software, or you can locate a copy somewhere.  I got a copy of the software with mine, and I downloaded a newer one as well.  I assume the “V8.00.034” in the above product refers to the software version as the cable doesn't have versions like that, and so I assume the software is included.

Anyway, assuming you now have a usb driven mini-VCI on hand because you ordered it from somewhere, plug it in to the port under the driver’s side dashboard and fire up the Techstream software on your PC.

If you need help setting up the software and connecting it, there are a lot of other sources such as this one: http://www.obdinnovations.com/mini-vci-for-toyota-software-installation-guide/

There’s some screenshots below, but to make a long story short, the sequence of commands you need to run is:

Combination Meter/Select Utility & then Select Customize/Select Warning/Select Reverse Buzzer/Change it from “Continual” to “Single” and then press the right arrow at the bottom.  Continuous beeping should now be off.

First, go to system select: Combination Meter as shown below.


Click the green arrow at the bottom right.  Now select Utility from the left hand menu of the resulting page and hit the bottom right green arrow again (sorry no screenshot of that).  Now select the Customize option and hit the lower right green arrow again.




Select the backup buzzer option on this page and change it from continual to single.




Now press the Green Arrow bottom right, and you are done.  Test your backup buzzer.  It should now be a single beep.   There are some other settings available on this menu such as the seatbelt buzzers, but I'd prefer my daughter use the seat belts, so I did not mess with them.








Tuesday, May 6, 2014

Javascript Text Filter

This Javascript function is designed to filter the options shown in a multi-select field based on a value entered in an input field.   This is a screen capture of the resulting HTML:



So we have the following multi-select options:
---------------------------------------------------------
blackhat seo
seo
seo consulting
seo rules

If we type “seo” into the input field, we only want to display:
----------------------------------------------------------------------------------
seo
seo consulting
seo rules

because those are the only entries beginning with “seo”.  As the user deletes characters, we want the entries to be restored as appropriate, and we want a button to reset the filter (equivalent to deleting all the characters in the search field).

I wrote this function for siteolytics.com.  It is used to filter trackable keywords, but of course it can be used to filter down any sort of selectable list (and could easily be modified to work with any other type of list as well).  

Specifically, it is used on the following Siteolytics page:

But you need to create an account and enter a site you want to track before you can reach it.  Of course if you are actually interested in tracking SEO on your site, then it's well worth the effort as Siteolytics has a lot of nifty tracking features for all things SEO related.  But otherwise, you can get the idea from the attached screenshot.

It should be noted that Siteolytics runs on cakePHP.  So I used the forms helper when creating the actual HTML ( hence the odd naming convention).

There are four HTML elements involved:
  1. A text box to enter the search phrase
  2. A reset button to clear the search phrase
  3. A multi-select form to display the result
  4. A hidden master list of items we use to restore the multi-select box
The html for the search text is:
-----------------------------------------------------------------
<input name="data[Search][keywordFilter]" value="" onkeyup="filterElements()" size="25" type="text" id="SearchKeywordFilter">

The html for the reset button is:
--------------------------------------------------------------------
<input type="button" id="btnClearFilter" onclick="clearFilter()" value="Clear Filter">

The multi-select field where we display the result:
---------------------------------------------------------------------------------
<select name="data[Search][trackedKeywords][]" size="5" multiple="multiple" style="width:100%;" id="SearchTrackedKeywords">
<option value="0">blackhat seo</option>
<option value="1">seo</option>
<option value="2">seo consulting</option>
<option value="3">seo rules</option>
</select>

The master list of items we use to restore filtered items:
------------------------------------------------------------------
<select name="data[Search][masterKeywords]" size="1" style="display:none" id="SearchMasterKeywords">
<option value="0">blackhat seo</option>
<option value="1">seo</option>
<option value="2">seo consulting</option>
<option value="3">seo rules</option>
</select>


The required Javascript functions are only two.  One, filterElements, both deletes and restores items in response to the text input in the search field, and other function, clearFilter, resets the filter and restores all the items.

We are detecting the “onkeyup” event on the search box which fires the “filterElements” Javascript function:
-----------------------------------------------------
function  filterElements () {
   var index;
   var filterBox = document.getElementById('SearchKeywordFilter');
   var filterVal = filterBox.value;
   var keywordList = document.getElementById('SearchTrackedKeywords');
   var keywordListCount = keywordList.options.length;
   var masterList = document.getElementById('SearchMasterKeywords');
   var masterListCount = masterList.options.length;
   var counter = 0;
   for (index=0; index < masterListCount; index++) {
       var text = masterList.options[index].text.toLowerCase();
       if (text.indexOf(filterVal) == 0) {  // == 0 means we found that string
          if (counter >= keywordListCount) {
             var option = document.createElement("option");
             keywordList.add(option);
          }
          keywordList.options[counter].text = masterList.options[index].text;
          counter++;
       }
   }
   for (index=counter; index < keywordListCount; index++) {  // null out any remaining
                                  // select options beyond the end of our current list
       keywordList.options[counter] = null;
   }
}

We have a function that resets the options list by copying the master list back into the working selection list:
-------------------------------------------
function  clearFilter () {
   var index;
   var filterBox = document.getElementById('SearchKeywordFilter');
   var keywordList = document.getElementById('SearchTrackedKeywords');
   var keywordListCount = keywordList.options.length;
   var masterList = document.getElementById('SearchMasterKeywords');
   var masterListCount = masterList.options.length;
   filterBox.value = '';
   for (index=keywordListCount; index < masterListCount; index++) { // add back the options
                                                       // we've nulled out with the filter
      var option = document.createElement("option");
      keywordList.add(option);
   }
   for (index=0; index < masterListCount; index++) {
      keywordList.options[index].text = masterList.options[index].text; // set the text of 
               // the existing options and any newly created ones to match the master list
   }

}