<?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>The journey with little green men &#187; Uncategorized</title>
	<atom:link href="http://bakhtiyor.com/category/uncategorized/feed/" rel="self" type="application/rss+xml" />
	<link>http://bakhtiyor.com</link>
	<description>Blog about mobile software development and the universe</description>
	<lastBuildDate>Sat, 12 Dec 2009 08:47:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>SQLite Full-Text Search</title>
		<link>http://bakhtiyor.com/2009/08/sqlite-full-text-search/</link>
		<comments>http://bakhtiyor.com/2009/08/sqlite-full-text-search/#comments</comments>
		<pubDate>Fri, 21 Aug 2009 19:53:40 +0000</pubDate>
		<dc:creator>bakhtiyor</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[full-text search]]></category>
		<category><![CDATA[sqlite]]></category>
		<guid isPermaLink="false">http://bakhtiyor.com/?p=397</guid>
		<description><![CDATA[SQLite contains full-text search module called FTS3, using this module you can easily add fast full text search to an Android application. First you need to create virtual table: CREATE VIRTUAL TABLE TableName USING FTS3(ColOne TEXT, ColTwo DATETIME) Your table must contains at least 1 TEXT field. The FTS3 virtual table acts like a regular [...]]]></description>
			<content:encoded><![CDATA[<p>SQLite contains full-text search module called FTS3, using this module you can easily add fast full text search to an Android application.<br />
First you need to create virtual table:</p>
<pre class="brush: sql">
CREATE VIRTUAL TABLE TableName
    USING FTS3(ColOne TEXT, ColTwo DATETIME)
</pre>
<p>Your table must contains at least 1 TEXT field.<br />
The FTS3 virtual table acts like a regular table, but you need to manually maintain the indexes to keep referential integrity — you should UPDATE the FTS3 table from time to time.<br />
The full-text query in SQLite looks like this:</p>
<pre class="brush: sql">
SELECT * FROM TableName WHERE ColOne MATCH &#039;search phrase&#039;
</pre>
<p>Make sure you use MATCH instead of equals or LIKE to scan a TEXT column in a virtual table.<br />
There is a sample application to demonstrate full-text search in action:<br />
<img src="http://bakhtiyor.com/wp-content/uploads/2009/09/fts3.jpg" alt="fts3" title="fts3" width="320" height="480" class="aligncenter size-full wp-image-423" /><br />
Download full-text search <a href="http://bakhtiyor.com/wp-content/uploads/2009/08/fts3.zip">sample application</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://bakhtiyor.com/2009/08/sqlite-full-text-search/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Delays in publication</title>
		<link>http://bakhtiyor.com/2009/06/delays-in-publication/</link>
		<comments>http://bakhtiyor.com/2009/06/delays-in-publication/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 07:19:47 +0000</pubDate>
		<dc:creator>bakhtiyor</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://bakhtiyor.com/?p=326</guid>
		<description><![CDATA[Sorry for delays in publication of “30 days” projects. I faced up with some technical troubles at my “home office”, hope they will be fixed soon. Thanks to all for cheering up and supporting.]]></description>
			<content:encoded><![CDATA[<p>Sorry for delays in publication of “30 days” projects. I faced up with some technical troubles at my “home office”, hope they will be fixed soon.</p>
<p>Thanks to all for cheering up and supporting.</p>
]]></content:encoded>
			<wfw:commentRss>http://bakhtiyor.com/2009/06/delays-in-publication/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android FancyGestureDetector</title>
		<link>http://bakhtiyor.com/2009/05/fancy-gesture-detector/</link>
		<comments>http://bakhtiyor.com/2009/05/fancy-gesture-detector/#comments</comments>
		<pubDate>Fri, 29 May 2009 09:17:57 +0000</pubDate>
		<dc:creator>bakhtiyor</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[gesture]]></category>
		<guid isPermaLink="false">http://bakhtiyor.com/?p=156</guid>
		<description><![CDATA[Android port of Fancy Gestures See also algorithm description and customization information. Download Android project and executable /* * Android FancyGestureDetector * Copyright (c) 2009 Bakhtiyor Khodjayev (http://bakhtiyor.com) * * Version: 0.1 * Url: http://bakhtiyor.com/2009/05/fancy-gesture-detector/ * * Original Javascript jQuery Version: Anant Garg (http://anantgarg.com/2009/05/21/jquery-fancy-gestures) * Original ActionScript Version: Didier Brun (http://www.bytearray.org/?p=91) (didier@bytearray.org) * * Licensed [...]]]></description>
			<content:encoded><![CDATA[<p>Android port of <a href="http://anantgarg.com/2009/05/21/jquery-fancy-gestures/">Fancy Gestures</a> </p>
<p><object width="445" height="364"><param name="movie" value="http://www.youtube.com/v/laCxG26EtYA&#038;hl=en&#038;fs=1&#038;border=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/laCxG26EtYA&#038;hl=en&#038;fs=1&#038;border=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="445" height="364"></embed></object></p>
<p>See also <a href="http://www.bytearray.org/?p=91">algorithm description</a> and <a href="http://anantgarg.com/2009/05/21/jquery-fancy-gestures/">customization information</a>. </p>
<p>Download Android <a href="http://bakhtiyor.com/wp-content/uploads/2009/05/fancy-gestures.zip">project</a> and <a href="http://bakhtiyor.com/wp-content/uploads/2009/05/fancy-gestures.apk">executable</a></p>
<pre class="brush: java">
/*
 * Android FancyGestureDetector
 * Copyright (c) 2009 Bakhtiyor Khodjayev (http://bakhtiyor.com)
 *
 * Version: 0.1
 * Url: http://bakhtiyor.com/2009/05/fancy-gesture-detector/
 *
 * Original Javascript jQuery Version: Anant Garg (http://anantgarg.com/2009/05/21/jquery-fancy-gestures)
 * Original ActionScript Version: Didier Brun (http://www.bytearray.org/?p=91) (didier@bytearray.org)
 *
 * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.bakhtiyor.android.gestures;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.view.MotionEvent;
public class FancyGestureDetector {
    public interface OnGestureListener {
        public void onGesture(String gesture);
    }
    private final static int HIGHEST_SCORE = 100000;
    private final static double SECTOR_RAD = Math.PI * 2 / 8;
    @SuppressWarnings(&quot;serial&quot;)
    private final static List&lt;Double&gt; ANGLES = new ArrayList&lt;Double&gt;() {
        {
            double step = Math.PI * 2 / 100;
            double sector;
            for (double i = -SECTOR_RAD / 2; i &lt;= Math.PI * 2 - SECTOR_RAD / 2; i += step) {
                sector = Math.floor((i + SECTOR_RAD / 2) / SECTOR_RAD);
                add(sector);
            }
        }
    };
    private final OnGestureListener onGestureListener;
    private final Map&lt;String, int[]&gt; gesturesMap = new HashMap&lt;String, int[]&gt;();
    private final List&lt;Double&gt; moves = new ArrayList&lt;Double&gt;();
    private double lastPositionX;
    private double lastPositionY;
    public FancyGestureDetector(OnGestureListener onGestureListener) {
        this.onGestureListener = onGestureListener;
    }
    public void addGesture(String name, int[] sequence) {
        gesturesMap.put(name, sequence);
    }
    public void addGestures(Map&lt;String, int[]&gt; gestures) {
        gesturesMap.putAll(gestures);
    }
    public int[] getGesture(String name) {
        return gesturesMap.get(name);
    }
    public Map&lt;String, int[]&gt; getGestures() {
        return Collections.&lt;String, int[]&gt; unmodifiableMap(gesturesMap);
    }
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            setLastPosition(event.getX(), event.getY());
            return true;
        case MotionEvent.ACTION_MOVE:
            addMove(event);
            return true;
        case MotionEvent.ACTION_UP:
            matchGesture();
            resetMoves();
            return true;
        }
        return false;
    }
    public void removeGesture(String name) {
        gesturesMap.remove(name);
    }
    private void addMove(MotionEvent event) {
        double difx = (event.getX() - lastPositionX);
        double dify = (event.getY() - lastPositionY);
        double sqDist = (difx * difx + dify * dify);
        double sqPrec = (8 * 8);
        if (sqDist &gt; sqPrec) {
            setLastPosition(event.getX(), event.getY());
            double angle = Math.atan2(dify, difx) + SECTOR_RAD / 2;
            if (angle &lt; 0) {
                angle += Math.PI * 2;
            }
            int index = (int) Math.floor(angle / (Math.PI * 2) * 100);
            moves.add(ANGLES.get(index));
        }
    }
    private double costLeven(int[] a, Double[] b) {
        if (a[0] == -1)
            return b.length == 0 ? 0 : HIGHEST_SCORE;
        double[][] d = new double[a.length + 1][b.length + 1];
        double[][] w = new double[a.length + 1][b.length + 1];
        int x, y;
        for (x = 1; x &lt;= a.length; x++) {
            for (y = 1; y &lt; b.length; y++) {
                d[x][y] = difAngle(a[x - 1], b[y - 1]);
            }
        }
        for (y = 1; y &lt;= b.length; y++) {
            w[0][y] = HIGHEST_SCORE;
        }
        for (x = 1; x &lt;= a.length; x++) {
            w[x][0] = HIGHEST_SCORE;
        }
        w[0][0] = 0;
        double cost, pa, pb, pc;
        for (x = 1; x &lt;= a.length; x++) {
            for (y = 1; y &lt; b.length; y++) {
                cost = d[x][y];
                pa = w[x - 1][y] + cost;
                pb = w[x][y - 1] + cost;
                pc = w[x - 1][y - 1] + cost;
                w[x][y] = Math.min(Math.min(pa, pb), pc);
            }
        }
        return w[x - 1][y - 1];
    }
    private double difAngle(int a, double b) {
        double dif = Math.abs(a - b);
        if (dif &gt; 8 / 2) {
            dif = 8 - dif;
        }
        return dif;
    }
    private void matchGesture() {
        double result = HIGHEST_SCORE;
        double res;
        String gesture = null;
        for (Map.Entry&lt;String, int[]&gt; entry : gesturesMap.entrySet()) {
            int[] matchMove = entry.getValue();
            res = costLeven(matchMove, moves.toArray(new Double[moves.size()]));
            if (res &lt; result &amp;&amp; res &lt; 30) {
                result = res;
                gesture = entry.getKey();
            }
        }
        if (gesture != null) {
            onGestureListener.onGesture(gesture);
        }
    }
    private void resetMoves() {
        moves.clear();
        setLastPosition(0, 0);
    }
    private void setLastPosition(float x, float y) {
        lastPositionX = x;
        lastPositionY = y;
    }
    @SuppressWarnings(&quot;serial&quot;)
    public final static Map&lt;String, int[]&gt; LETTER_GESTURES = Collections
            .&lt;String, int[]&gt; unmodifiableMap(new HashMap&lt;String, int[]&gt;() {
                {
                    put(&quot;A&quot;, new int[] { 5, 3 });
                    put(&quot;B&quot;, new int[] { 2, 6, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4 });
                    put(&quot;C&quot;, new int[] { 4, 3, 2, 1, 0 });
                    put(&quot;D&quot;, new int[] { 2, 6, 7, 0, 1, 2, 3, 4 });
                    put(&quot;E&quot;, new int[] { 4, 3, 2, 1, 0, 4, 3, 2, 1, 0 });
                    put(&quot;F&quot;, new int[] { 4, 2 });
                    put(&quot;G&quot;, new int[] { 4, 3, 2, 1, 0, 7, 6, 5, 0 });
                    put(&quot;H&quot;, new int[] { 2, 6, 7, 0, 1, 2 });
                    put(&quot;I&quot;, new int[] { 6 });
                    put(&quot;J&quot;, new int[] { 2, 3, 4 });
                    put(&quot;K&quot;, new int[] { 3, 4, 5, 6, 7, 0, 1 });
                    put(&quot;L&quot;, new int[] { 4, 6 });
                    put(&quot;M&quot;, new int[] { 6, 1, 7, 2 });
                    put(&quot;N&quot;, new int[] { 6, 1, 6 });
                    put(&quot;O&quot;, new int[] { 4, 3, 2, 1, 0, 7, 6, 5, 4 });
                    put(&quot;P&quot;, new int[] { 6, 7, 0, 1, 2, 3, 4, 5, 6 });
                    put(&quot;Q&quot;, new int[] { 4, 3, 2, 1, 0, 7, 6, 5, 4, 0 });
                    put(&quot;R&quot;, new int[] { 2, 6, 7, 0, 1, 2, 3, 4, 1 });
                    put(&quot;S&quot;, new int[] { 4, 3, 2, 1, 0, 1, 2, 3, 4 });
                    put(&quot;T&quot;, new int[] { 0, 2 });
                    put(&quot;U&quot;, new int[] { 2, 1, 0, 7, 6 });
                    put(&quot;V&quot;, new int[] { 3, 5 });
                    put(&quot;W&quot;, new int[] { 2, 7, 1, 6 });
                    put(&quot;X&quot;, new int[] { 1, 0, 7, 6, 5, 4, 3 });
                    put(&quot;Y&quot;, new int[] { 2, 1, 0, 7, 6, 2, 3, 4, 5, 6, 7 });
                    put(&quot;Z&quot;, new int[] { 0, 3, 0 });
                    put(&quot; &quot;, new int[] { 0 });
                    put(&quot;?&quot;, new int[] { 6, 7, 0, 1, 2, 3, 2 });
                }
            });
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://bakhtiyor.com/2009/05/fancy-gesture-detector/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
