<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>whats the plot &#187; code</title>
	<atom:link href="http://whatstheplot.com/blog/category/code/feed/" rel="self" type="application/rss+xml" />
	<link>http://whatstheplot.com/blog</link>
	<description>a plotting plotter plotted a plot at whatstheplot.com</description>
	<lastBuildDate>Fri, 26 Feb 2010 07:25:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0-alpha</generator>
		<item>
		<title>google buzz &#8211; friend or follow</title>
		<link>http://whatstheplot.com/blog/2010/02/10/google-buzz-friend-or-follow/</link>
		<comments>http://whatstheplot.com/blog/2010/02/10/google-buzz-friend-or-follow/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 01:21:03 +0000</pubDate>
		<dc:creator>ahmedre</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[buzz]]></category>
		<category><![CDATA[google]]></category>

		<guid isPermaLink="false">http://whatstheplot.com/blog/?p=452</guid>
		<description><![CDATA[i like the site for twitter, &#8216;friendorfollow,&#8217; which tells me who i am following and isn&#8217;t following me back, who are following me and i am not following back, and so on.  given that i got access to google buzz today, i decided to write a little script to help me determine the breakdown [...]]]></description>
			<content:encoded><![CDATA[<p>i like the site for twitter, &#8216;friendorfollow,&#8217; which tells me who i am following and isn&#8217;t following me back, who are following me and i am not following back, and so on.  given that i got access to google buzz today, i decided to write a little script to help me determine the breakdown of my friends (specifically, who i am following and isn&#8217;t following me back, since the rest of the information is easy to read off of the website anyway).</p>
<p>this script will tell you who your friends are (lol, i wish), who your fans are, and who you are following but isn&#8217;t following you back.  unfortunately, there&#8217;s a manual step involved (getting the server response with your friends and followers).  there&#8217;s really no point in trying to automate this right now, because soon enough, i expect that one of the google apis will expose this functionality.</p>
<p>download it from github <a href="http://gist.github.com/301093">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://whatstheplot.com/blog/2010/02/10/google-buzz-friend-or-follow/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>salam, android!</title>
		<link>http://whatstheplot.com/blog/2010/01/22/salam-android/</link>
		<comments>http://whatstheplot.com/blog/2010/01/22/salam-android/#comments</comments>
		<pubDate>Fri, 22 Jan 2010 11:01:23 +0000</pubDate>
		<dc:creator>ahmedre</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[islam]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[quran]]></category>
		<category><![CDATA[screenshots]]></category>

		<guid isPermaLink="false">http://whatstheplot.com/blog/?p=439</guid>
		<description><![CDATA[after the nexus one came out, i became a little more interested in android.  while i had written a simple &#8217;salam world&#8217; app some time ago, i figure it would be nice to delve a little deeper and try to write something remotely useful.
so without further adieu, introducing a (very simple) quran for android:

source [...]]]></description>
			<content:encoded><![CDATA[<p>after the nexus one came out, i became a little more interested in android.  while i had written a simple &#8217;salam world&#8217; app some time ago, i figure it would be nice to delve a little deeper and try to write something remotely useful.</p>
<p>so without further adieu, introducing a (very simple) quran for android:</p>
<p><img alt="" src="http://whatstheplot.com/images/android_quranview-01.21.2010.png" title="android quran screenshot" class="aligncenter" width="247" height="407" /></p>
<p>source code on <a href="http://github.com/ahmedre/quran_android">github</a></p>
<p>for the most part, android is fairly fun and easy to develop for.  however, one of the most frustrating parts is the extremely limited memory for apps.  since apps can&#8217;t be on the sd card (due to some security issues), you are limited to the very small amount of memory on the device.  consequently, in order to display the images for the quran in this app, i have to require the user to download the images to their sd card (or do it for them over the web).</p>
<p><b>note</b> &#8211; try it at your own risk, i only tested it on the emulator&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://whatstheplot.com/blog/2010/01/22/salam-android/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>quran jetpack script</title>
		<link>http://whatstheplot.com/blog/2009/11/16/quran-jetpack-script/</link>
		<comments>http://whatstheplot.com/blog/2009/11/16/quran-jetpack-script/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 08:21:13 +0000</pubDate>
		<dc:creator>ahmedre</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[islam]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[jetpack]]></category>
		<category><![CDATA[quran]]></category>

		<guid isPermaLink="false">http://whatstheplot.com/blog/?p=401</guid>
		<description><![CDATA[so i had a little bit of time before i depart on my journey for hajj, so i wanted to play around with the firefox jetpack extension a little bit.  so without further adieu, this post is here to introduce a simple quran plugin for jetpack  
what is it
this is a quran script [...]]]></description>
			<content:encoded><![CDATA[<p>so i had a little bit of time before i depart on my journey for hajj, so i wanted to play around with the firefox jetpack extension a little bit.  so without further adieu, this post is here to introduce a simple quran plugin for jetpack <img src='http://whatstheplot.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><b>what is it</b><br />
this is a quran script for <a href="https://jetpack.mozillalabs.com">jetpack</a>, a plugin for firefox which allows customizing the browser just through javascript.</p>
<p>when you are typing in a textarea (in wordpress, gmail, google talk, etc), if you highlight any text in the format of sura:ayah (ex 1:1) and right click on it, you will be given a menu that allows you to replace that with the actual verse (in arabic, transliteration, or translation).</p>
<p>this is very nifty for taking notes, chatting, sending emails, etc.</p>
<p><b>how does it look like?</b><br />
here is a screenshot:<br />
<img src="http://whatstheplot.com/misc/quran.jetpack/screenshot.jpg" alt="quran jetpack script screenshot" /></p>
<p><b>known issues</b><br />
- sometimes, the server appears to take long to reply so it doesn&#8217;t return and you are forced to try again.<br />
- the plugin doesn&#8217;t work on google docs and other sites that overwrite right click functionality.<br />
- the plugin also doesn&#8217;t seem to be working on gmail when rich formatting is on.</p>
<p><b>how to install it</b><br />
- install <a href="https://jetpack.mozillalabs.com">jetpack</a> for firefox.<br />
- go to <a href="/misc/quran.jetpack/">this page</a>.  on the top right corner of the webpage, you will find a button that says, &#8220;Install&#8230;&#8221;.  click it.<br />
- scroll to the very bottom, click the &#8220;auto-update this feature&#8221; checkbox, and then click on &#8220;i know what i am doing, install it!&#8221;</p>
<p><b>source code</b><br />
the source is also available as on github in <a href="http://gist.github.com/235821">this gist</a>.</p>
<p><b>changelog</b><br />
<i>november 16th, 2009</i><br />
- fixed a bug in which the appended (sura:ayah) to the text was put at the end of the textarea rather than right after the ayah.<br />
- added a little favicon for the menu.</p>
<p><img src="http://whatstheplot.com/misc/quran.jetpack/screenshot_1.jpg" alt="quran jetpack script screenshot" /></p>
]]></content:encoded>
			<wfw:commentRss>http://whatstheplot.com/blog/2009/11/16/quran-jetpack-script/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>subqueries make life easy</title>
		<link>http://whatstheplot.com/blog/2009/09/13/subqueries-make-life-easy/</link>
		<comments>http://whatstheplot.com/blog/2009/09/13/subqueries-make-life-easy/#comments</comments>
		<pubDate>Sun, 13 Sep 2009 23:35:50 +0000</pubDate>
		<dc:creator>ahmedre</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://whatstheplot.com/blog/?p=358</guid>
		<description><![CDATA[often times while working with databases, you find the need to do some simple tasks (adding a column and populating it with a value from another table, etc).  rather than write a script to do this, use mysql&#8217;s native subquery (and temporary table) functionality &#8211; it makes life much easier.
consider the case where you [...]]]></description>
			<content:encoded><![CDATA[<p>often times while working with databases, you find the need to do some simple tasks (adding a column and populating it with a value from another table, etc).  rather than write a script to do this, use mysql&#8217;s native subquery (and temporary table) functionality &#8211; it makes life much easier.</p>
<p>consider the case where you have two tables:</p>
<pre class="brush: plain;">
mysql&gt; describe colors;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  |     | NULL    |       |
| color | varchar(10) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
</pre>
<p>and</p>
<pre class="brush: plain;">
mysql&gt; describe color_mapping;
+------------+---------+------+-----+---------+-------+
| Field      | Type    | Null | Key | Default | Extra |
+------------+---------+------+-----+---------+-------+
| picture_id | int(11) | YES  |     | NULL    |       |
| color_id   | int(11) | YES  |     | NULL    |       |
+------------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)
</pre>
<p>let&#8217;s say you want to update the colors table to add a frequency column such that you know how often a given color is used.  it turns out this is really easy using mysql:</p>
<pre class="brush: sql;">
alter table colors add frequency int;
update colors set frequency = (select count(*) from color_mapping \
   where color_mapping.color_id = colors.id);
</pre>
<p>and that&#8217;s it.  also useful are temporary tables:</p>
<pre class="brush: sql;">
create temporary table color_frequencies select color_id, count(*) as cnt \
   from color_mapping group by color_id;
</pre>
<p>if you then attempt to <code>desc color_frequencies</code>, you&#8217;ll see a table with two columns &#8211; a <code>color_id</code> and a <code>cnt</code> column.</p>
<p>hopefully this will save some people some efforts writing scripts next time some simple database updates are needed <img src='http://whatstheplot.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://whatstheplot.com/blog/2009/09/13/subqueries-make-life-easy/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>quran plugin updated for ubiquity 0.5</title>
		<link>http://whatstheplot.com/blog/2009/08/10/quran-plugin-updated-for-ubiquity-0-5/</link>
		<comments>http://whatstheplot.com/blog/2009/08/10/quran-plugin-updated-for-ubiquity-0-5/#comments</comments>
		<pubDate>Mon, 10 Aug 2009 08:55:08 +0000</pubDate>
		<dc:creator>ahmedre</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[islam]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[quran]]></category>
		<category><![CDATA[ubiquity]]></category>

		<guid isPermaLink="false">http://whatstheplot.com/blog/?p=350</guid>
		<description><![CDATA[i&#8217;ve done a quick port of the quran ubiquity plugin to work under the new version of ubiquity (0.5).  as you may know, ubiquity 0.5 and beyond use a new parser (parser 2) that isn&#8217;t compatible with the old parser (parser 1 for 0.1.x versions of ubiquity).
you can get it here.  make sure [...]]]></description>
			<content:encoded><![CDATA[<p>i&#8217;ve done a quick port of the quran ubiquity plugin to work under the new version of ubiquity (0.5).  as you may know, ubiquity 0.5 and beyond use a new parser (parser 2) that isn&#8217;t compatible with the old parser (parser 1 for 0.1.x versions of ubiquity).</p>
<p>you can get it <a href="http://gist.github.com/165091">here</a>.  make sure to select &#8220;automatically update this feed&#8221; so that you get any updates i may get around to making. </p>
<p>this version is pretty much identical to the older one, except that now, you can use &#8220;get-ayah,&#8221; &#8220;get ayah,&#8221; or &#8220;ayah&#8221; to get an ayah, and &#8220;search-quran&#8221; or &#8220;search quran&#8221; to do a search.  i hope to support some of the new stuff from the pre-alpha version of the quran api soon insha&#8217;Allah (other translations, etc).</p>
]]></content:encoded>
			<wfw:commentRss>http://whatstheplot.com/blog/2009/08/10/quran-plugin-updated-for-ubiquity-0-5/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>introducing waqt.org</title>
		<link>http://whatstheplot.com/blog/2009/07/10/introducing-waqt-org/</link>
		<comments>http://whatstheplot.com/blog/2009/07/10/introducing-waqt-org/#comments</comments>
		<pubDate>Fri, 10 Jul 2009 10:01:06 +0000</pubDate>
		<dc:creator>ahmedre</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[islam]]></category>
		<category><![CDATA[prayertimes]]></category>

		<guid isPermaLink="false">http://whatstheplot.com/blog/?p=337</guid>
		<description><![CDATA[today, i took the arabeyes php extension of itl, the yahoo geocoding api, and the geonames api and put together waqt.org.
it&#8217;s a fairly minimalistic prayertimes site.  the code is available on github.  note that the calculation method is currently hardcoded to use the isna method, but this is fairly easy to change.
]]></description>
			<content:encoded><![CDATA[<p>today, i took the arabeyes <a href="http://svn.arabeyes.org/viewvc/projects/itl/ports/php/">php extension of itl</a>, the <a href="http://developer.yahoo.com/maps/rest/V1/geocode.html">yahoo geocoding api</a>, and the <a href="http://www.geonames.org/">geonames api</a> and put together <a href="http://waqt.org">waqt.org</a>.</p>
<p>it&#8217;s a fairly minimalistic prayertimes site.  the code is available on <a href="http://github.com/ahmedre/waqt.org">github</a>.  note that the calculation method is currently hardcoded to use the isna method, but this is fairly easy to change.</p>
]]></content:encoded>
			<wfw:commentRss>http://whatstheplot.com/blog/2009/07/10/introducing-waqt-org/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>quran ubiquity plugin</title>
		<link>http://whatstheplot.com/blog/2009/05/19/quran-ubiquity-plugin/</link>
		<comments>http://whatstheplot.com/blog/2009/05/19/quran-ubiquity-plugin/#comments</comments>
		<pubDate>Tue, 19 May 2009 08:29:12 +0000</pubDate>
		<dc:creator>ahmedre</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[islam]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[quran]]></category>
		<category><![CDATA[ubiquity]]></category>

		<guid isPermaLink="false">http://whatstheplot.com/blog/?p=324</guid>
		<description><![CDATA[updated and released the first version of the quran ubiquity plugin!  you can go here to install it.
essentially, it contains two commands -
1.  search-quran &#8211; takes a parameter of what to search for and will show the results that match that particular query.  hitting enter will bring up the search results page.
2. [...]]]></description>
			<content:encoded><![CDATA[<p>updated and released the first version of the quran ubiquity plugin!  you can go <a href="http://gist.github.com/113971">here</a> to install it.</p>
<p>essentially, it contains two commands -<br />
1.  <strong>search-quran</strong> &#8211; takes a parameter of what to search for and will show the results that match that particular query.  hitting enter will bring up the search results page.<br />
2.  <strong>get-ayah</strong> &#8211; takes a parameter of which ayah (ex 2:2) and an optional parameter of the language/translation you want the ayah in (in english &#8211; muhsin khan, for example &#8211; note that ubiquity will provide suggestions for these).  hitting enter will insert the text into the selection space.</p>
<p>this is uber-useful for muslims imho :p  perhaps i will try to provide a screencast later on that shows how to use this for those who are still afraid to try it <img src='http://whatstheplot.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>*update*</strong> &#8211; rather than make my own screencast, i&#8217;ve decided to record a set of audio instructions on how to use it.</p>
<p>by the way &#8211; if you haven&#8217;t used ubiquity before, i highly recommend that you watch <a href="http://vimeo.com/1561578">this video</a> first.  it explains what ubiquity is and gives you an idea of what it is useful for.  to put it quite simply, ubiquity is amazing.  it&#8217;s an indispensable tool for your firefox.  watch the video <img src='http://whatstheplot.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>and here is the audio tutorial on the quran plugin for ubiquity.</p>
<p>enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://whatstheplot.com/blog/2009/05/19/quran-ubiquity-plugin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://whatstheplot.com/misc/ubiquity_quran-05.19.2009.mp3" length="1235405" type="audio/mpeg" />
		</item>
		<item>
		<title>migrating jaiku to identi.ca or twitter</title>
		<link>http://whatstheplot.com/blog/2009/04/13/migrating-jaiku-to-identica-or-twitter/</link>
		<comments>http://whatstheplot.com/blog/2009/04/13/migrating-jaiku-to-identica-or-twitter/#comments</comments>
		<pubDate>Mon, 13 Apr 2009 08:33:28 +0000</pubDate>
		<dc:creator>ahmedre</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://whatstheplot.com/blog/?p=291</guid>
		<description><![CDATA[i recently decided to move my tech tips microblog to identi.ca (the original copy was on jaiku), as i felt it was a little more befitting, actively developed, etc (although jaiku is now open source).
anyway&#8230; so i wanted to migrate my posts over &#8211; so i wrote a php script to do it (it assumes [...]]]></description>
			<content:encoded><![CDATA[<p>i recently decided to move my <a href="http://identi.ca/aretips">tech tips microblog</a> to <a href="http://identi.ca">identi.ca</a> (the original copy was on <a href="http://ahmedre.jaiku.com">jaiku</a>), as i felt it was a little more befitting, actively developed, etc (although jaiku is now open source).</p>
<p>anyway&#8230; so i wanted to migrate my posts over &#8211; so i wrote a php script to do it (it assumes your jaiku is public and reads it without hassling with oauth).</p>
<pre class="brush: php;">
&lt;?php
$sleepTime = 5;
$jaikuSource = &quot;http://username.jaiku.com/json&quot;;

$mode = 'identi.ca';
$baseStatusUrl = 'http://identi.ca/api/statuses/update.json';

// thanks, php-twitter
if ($mode == 'twitter'){
   $baseStatusUrl = 'http://twitter.com/statuses/update.json';
   $headers = array('Expect:', 'X-Twitter-Client: ',
      'X-Twitter-Client-Version: ','X-Twitter-Client-URL: ');
}

$ctr = 0;
$entries = array();

print &quot;destination account username: &quot;;
$username = trim(fgets(STDIN));
print &quot;password: &quot;;
system('stty -echo');
$password = trim(fgets(STDIN));
system('stty echo');
print &quot;\n&quot;;

$done = false;
$params = '';
while (true){
   $count = 0;
   $posts = fetchUrl($jaikuSource . $params);
   $json = json_decode($posts, true);
   $stream = $json['stream'];
   $lastEntry = null;
   foreach ($stream as $entry){
      if (isset($entry['comment_id'])) continue;
      $lastEntry = $entry;
      $count++;
      $entries[$ctr++] = $entry['title'];
   }
   if ($count == 0) break;
   $lastPostTime = $lastEntry['created_at'];
   $ts = split('-', $lastPostTime);
   $hd = split('T', $ts[2]);
   $min = split('Z', $ts[4]);
   $gmtime = gmmktime($hd[1], $ts[3], $min[0], $ts[1], $hd[0], $ts[0]) - 1;
   $params = &quot;?offset=$gmtime&quot;;
}

for ($i = $ctr-1; $i&gt;=0; $i--){
   $params = array('status' =&gt; $entries[$i]);
   if ($i != ($ctr-1)){
      print &quot;sleeping $sleepTime seconds\n&quot;;
      sleep($sleepTime);
   }
   twitterApiCall($baseStatusUrl, $params);
   print &quot;updated status to: &quot; . $entries[$i] . &quot;\n&quot;;
}

function fetchUrl($url){
   $ch = curl_init($url);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
   $resp = curl_exec($ch);
   curl_close($ch);
   return $resp;
}

function twitterApiCall($url, $args = null){
   global $username, $password, $headers;

   // thanks, php-twitter
   $ch = curl_init($url);
   if (!is_null($args)){
      curl_setopt($ch, CURLOPT_POST, true);
      curl_setopt($ch, CURLOPT_POSTFIELDS, $args);
   }
   if ((!empty($username)) &amp;&amp; (!empty($password)))
      curl_setopt($ch, CURLOPT_USERPWD, $username . ':' . $password);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
   if (!empty($headers))
      curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
   $resp = curl_exec($ch);
   $info = curl_getinfo($ch);
   curl_close($ch);
   if ($info['http_code']!=200)
      print &quot;error - got an http code of: &quot; . $info['http_code'] . &quot;\n&quot;;
}
</pre>
<p>make sure you edit <code>$baseStatusUrl</code> and <code>$mode</code> as necessary.  enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://whatstheplot.com/blog/2009/04/13/migrating-jaiku-to-identica-or-twitter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ubiquity rocks!</title>
		<link>http://whatstheplot.com/blog/2009/02/18/ubiquity-rocks/</link>
		<comments>http://whatstheplot.com/blog/2009/02/18/ubiquity-rocks/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 10:23:05 +0000</pubDate>
		<dc:creator>ahmedre</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[islam]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[quran]]></category>
		<category><![CDATA[screenshots]]></category>
		<category><![CDATA[ubiquity]]></category>

		<guid isPermaLink="false">http://whatstheplot.com/blog/?p=257</guid>
		<description><![CDATA[today, i felt like playing some more with ubiquity, which i had installed for a while now but had not played around with sufficiently.  i decided to try to write a simple plugin that will search the quran for a particular set of words.  to do this, i felt obliged to expose an [...]]]></description>
			<content:encoded><![CDATA[<p>today, i felt like playing some more with <a href="http://labs.mozilla.com/projects/ubiquity/">ubiquity</a>, which i had installed for a while now but had not played around with sufficiently.  i decided to try to write a simple plugin that will search the quran for a particular set of words.  to do this, i felt obliged to expose an api for the alpha version of <a href="http://quranicrealm.com">quranicrealm</a> first, which was good because i needed to do it eventually anyway.</p>
<p>and here&#8217;s the mandatory screenshot:<br />
<img alt="ubiquity - quran search preview" src="/images/ubi.sq_pre.02.18.2009.png" title="ubiquity - quran search preview" /></p>
<p>it still needs a lot of work&#8230;  things i still want to do if i get around to it:</p>
<ul>
<li>add a favicon (for the site and for the plugin)</li>
<li>more options (ex, &#8220;search english,&#8221; or &#8220;search transliteration,&#8221; etc)</li>
<li>replace the current text with a link (or translation).  this would be useful in im conversations or while writing blog posts.</li>
<li>a &#8220;get-ayah&#8221; command (to say, &#8220;get ayah 1 of sura fatiha in arabic,&#8221; for example).</li>
</ul>
<p>anyway, i&#8217;ll post up the code when i&#8217;ve added some improvements insha&#8217;Allah.  if you want it before then, post a comment.</p>
]]></content:encoded>
			<wfw:commentRss>http://whatstheplot.com/blog/2009/02/18/ubiquity-rocks/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>faster and better text search</title>
		<link>http://whatstheplot.com/blog/2009/01/25/faster-and-better-text-search/</link>
		<comments>http://whatstheplot.com/blog/2009/01/25/faster-and-better-text-search/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 01:54:04 +0000</pubDate>
		<dc:creator>ahmedre</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[lucene]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[sphinx]]></category>

		<guid isPermaLink="false">http://whatstheplot.com/blog/?p=232</guid>
		<description><![CDATA[important update (august 5th, 2009) &#8211; so i realized that some of the results here (specifically, the java lucene ones) were incorrect.  the reason is because as is mentioned on the lucene wiki, the first search has to initialize the caches.  as thus, the results aren&#8217;t accurate.  this seems to be very [...]]]></description>
			<content:encoded><![CDATA[<p><strong>important update (august 5th, 2009)</strong> &#8211; <em>so i realized that some of the results here (specifically, the java lucene ones) were incorrect.  the reason is because as is mentioned on the lucene wiki, the first search has to initialize the caches.  as thus, the results aren&#8217;t accurate.  this seems to be very true.  for example, if i run a test query, discard the results, and then run the real query, results for the three classes of queries are now 17, 8, and 4 ms respectively, which is very comparable (if not sometimes better) than that of sphinx.  i will probably need to re-run this benchmark to do a better job of giving the backend systems a level playing field to test on.</em></p>
<p><strong>update (jan 26th, 2009)</strong> &#8211; <em>as mentioned in the comments, the mysql results aren&#8217;t very accurate either because i was probably not properly searching against the index.</em></p>
<p>i have a set of ~6000 quotes (verses, if you will), along with a multiple set of translations for each of those verses.  before, i was searching across these verses using mysql.  while this seemed to work, it was very limiting, and i began looking into alternatives.</p>
<p>so i did a little bit of research and tried out <a href="http://lucene.apache.org/java/docs/">lucene</a> and <a href="http://www.sphinxsearch.com/">sphinx</a>.  for lucene, i specifically used the <a href="http://framework.zend.com/manual/en/zend.search.lucene.html">zend version</a> (i&#8217;ll discuss standard <a href="http://lucene.apache.org/">lucene</a> (java) towards the end of this post.)</p>
<p>i&#8217;ll show the results first, and then explain them after.</p>
<p><img src="http://chart.apis.google.com/chart?chs=350x100&#038;cht=bhs&#038;chd=t:8.030,7.542,8.324|8.304,7.898,11.131|106.254,106.561,108.747|285.759,116.222,224.381&#038;chds=0,400&#038;chco=ff0000,C6D9FD,4D89F9,123456&#038;chxt=y&#038;chxl=0:|query3|query2|query1&#038;chdl=sphinx|sphinx alt|mysql|lucene"/></p>
<p>the graph above shows a quick overview of the tests run.  a set of 3 different queries were run against 4 different backends.  the numbers were generated using apache bench (ab) using 100 requests with a concurrency of 1.</p>
<p><strong>backends</strong>:<br />
<em>lucene</em>:  this was the first implementation.  in it, each verse was a &#8220;document.&#8221;  each translation was a property of the document.  the total number of documents was thus equivalent to the number of verses. </p>
<p><em>sphinx</em>:  this was the second sphinx implementation (see sphinx alt below for the first implementation).  this implementation was just done to make the data model similar to that of lucene, which is exactly what it is.  although this ended up being the fastest (by &lt; 5ms in the tests run), i prefer the sphinx alt implementation because it&#8217;s closest to that of the database schema.</p>
<p><em>sphinx alt</em>: although it is named &#8220;sphinx alt&#8221; in the graph above, this is really the initial sphinx implementation.  in this model, a translation of one verse was a document.  consequently, the total number of documents was (number of translations) * (number of verses).  i sort of like this one most (even though it&#8217;s not the fastest) because it is the closest to the current database schema.</p>
<p><em>mysql</em>:  this is sort of the baseline, and, to be honest, it&#8217;s not fair either.  the query used here is something in the nature of getting the row where the text is like &#8216;%word1%word2%&#8217;;  the number of results returned by this are far fewer (and less valuable) than those returned by either lucene or sphinx.  one would need to do &#8220;where text like &#8216;%word1%word2%&#8217; or text like &#8216;%word2%word1%&#8217;&#8221; to get a more accurate estimate, but for baseline purposes, i simply ran the first query.  note that the query cache size is 0 (ie query cache is on but effectively off for this set of tests).  note that the text field has a fulltext index on it.</p>
<p><strong>results</strong>:<br />
sphinx wins hands down.  however, although it seems that lucene comes in last, this is not really accurate because of the type of mysql query being used.  from my limited tests (using a more complicated sql query), lucene and mysql have comparable performance, but lucene of course has the added benefit of more advanced query options, etc.</p>
<p>sphinx times were 8.030 ms, 7.542 ms, 8.324 ms, sphinx alt times were 8.304 ms, 7.898 ms, 11.131 ms, lucene times were 285.759 ms, 116.222 ms, 224.381 ms, and mysql times were 106.254 ms, 106.561 ms, 108.747 ms for queries 1, 2, and 3, respectively.  query 1 contained three words (+term1 +term2 +term3), query 2 contained one word (+term4), and query 3 contained two words (+term5 +term6).</p>
<p><strong>additional details</strong>:<br />
plain vanilla java lucene is usually faster than zend&#8217;s lucene implementation.  the largest difference can be noted in indexing times (a few seconds for java versus 15+ minutes in php).  if i had to index frequently, i&#8217;d use java lucene or sphinx because they are <em>insanely</em> faster.</p>
<p>for example, the first query takes 179.84 ms on average in java (over 100 queries) versus about 272.61 ms on average for php.  the second query takes 173.22 ms on average in java versus about 103.30 ms in php. the third query takes 178.98 ms on average in java versus about 214.78 ms in php.</p>
<p>php only won at the second query, which also happens to be the simplest query.  two things to note &#8211; first, the times here don&#8217;t include the jvm or php interpreter start times.  these are times reported by taking the time before and after the search call and displaying them.  second, unlike the first test, this was all run from the command line and not directly via web (didn&#8217;t want to bother setting up tomcat or solr, etc).</p>
<p>just for fun, i implemented the &#8220;sphinx alt&#8221; data scheme in java lucene as well and re-ran the 3 tests 100 times each.  the results were 178.54 ms, 160.20 ms, and 172.72 ms &#8211; very much comparable to the results with the alternate schema.</p>
<p><strong>the summary of this very long post in 2 words</strong>:  sphinx rocks.</p>
]]></content:encoded>
			<wfw:commentRss>http://whatstheplot.com/blog/2009/01/25/faster-and-better-text-search/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
