วันศุกร์ที่ 27 ธันวาคม พ.ศ. 2556

start end format display number


abstract class StartEnd{
    protected $m = array();
    public function push($data){
        if (count($this->m)==0){
           $this->m[1] = $this->m[0] = $data;
        }else{
           $this->m[1] = $data;
        }
    }
    public function __toString(){
        if (count($this->m)==0){
            return '';
        }elseif ($this->m[0] == $this->m[1]){
            return (string)$this->m[0];
        }else{
            return $this->m[0].'-'.$this->m[1];
        }
    }
    public static function getFormat(array $a){
        $groups = array();
        $prev = -1;
        static::sort($a);
        foreach($a as $i){
              if ($prev !== static::getPrev($i)){
                     $se = new static();
                     $groups[] = $se;
              }
              $se->push($prev = $i);
        }
        return implode(',',$groups);
    }
    abstract public static function sort(&$a);
    abstract public static function getPrev($i);
}
class StartEndNumber extends StartEnd{
    public static function sort(&$a){
        sort($a,SORT_NUMERIC);
    }
    public static function getPrev($i){
        return $i-1;
    }
}
class StartEndDay extends StartEnd{
    protected static $enum = array('MON','TUE','WED','THU','FRI','SAT','SUN');
    public static function daySort($val1,$val2){
        return array_search($val1,static::$enum)-array_search($val2,static::$enum);
    }
    public static function sort(&$a){
        usort($a,'StartEndDay::daySort');
    }
    public static function getPrev($i){
        $position = array_search($i,self::$enum);
        if ($position === false){
                return false;
        }else{
                return self::$enum[$position-1];
        }
    }
}


$a = array(1,4,3,2,5,9,10,12);
echo StartEndNumber::getFormat($a),' '; //1-5,9-10,12

$a = array('TUE','MON','WED','FRI','SAT');
echo StartEndDay::getFormat($a); //MON-WED,FRI-SAT

วันอาทิตย์ที่ 15 ธันวาคม พ.ศ. 2556

calculate age from javascript

function get_age(ymd) {  
    var x = ymd.split('-');
    var y = x[0];
    var m = x[1];
    var d = x[2];
    var today = new Date();
    var test = m = (today.getMonth()+1 - m);
    if (test < 0) {
        y++;
    } else if (m == 0 && today.getDate() - d < 0) {
        y++;
    }
    var test2 = today.getFullYear() - y;
    if (test2 < 0)
        test2 = 0;
    return test2;
}


alert(get_age('1980-01-01'));

วันเสาร์ที่ 7 ธันวาคม พ.ศ. 2556

mod_rewrite test tool

http://htaccess.madewithlove.be/

เครื่องมือทดสอบ mod_rewrite โดยไม่ต้องไปแก้ .htaccess บ่อยๆ ทดสอบออนไลน์ได้เลยครับ

วันจันทร์ที่ 2 ธันวาคม พ.ศ. 2556

Zend certified engineer PHP 5.3


My Zend Certified Engineer Directory Page


ในที่สุดก็สอบผ่านเสียทีครับ กับการเตรียมสอบมาอย่างยาวนาน ใช้เวลาเตรียมตัวสอบมาเรื่อยๆ อาศัยช่วงว่างจากงานพิเศษบ้าง ช่วงดึกของวันจันทร์ถึงศุกร์ เป็นเวลา 3 เดือนเต็มๆ หลักก็มีอ่าน ebook ของ PHP-5-3-Study-Guide-v1 ของ Zend.com, Tutorial ตามเว็บไซต์ต่างๆ ที่คนที่สอบผ่านแล้วแนะนำ และอ่าน PHP Manual เนื้อหาหลักๆ ทั้งหมด

ในระหว่างการอ่านพบว่าตัวเองไม่ถนัดเขียนปากกาจดบันทึกซะแล้ว สมัยก่อนจดแล้วลบแล้วบางทีกลับมาดูอีกทีอ่านไม่ออก ผมเลยต้องหาตัวช่วยมาใช้เป็นโปรแกรมสร้าง Mind Map ตัวหนึ่งชื่อว่า FreeMind โปรแกรมตัวนี้จะสร้างข้อมูลเหมือน Tree/Directory สามารถจัดกลุ่มเพิ่มลบแก้ไขข้อมูลได้สะดวกมาก http://freemind.sourceforge.net

ในช่วงวันก่อนวันสอบก็ยังไม่แน่ใจในระดับความยากของข้อสอบ เพราะจากที่ทำตัวอย่างข้อสอบที่ผ่านๆ มาอยู่ในระดับยากมาก (ข้อสอบตัวอย่างมักจะถาม parameter ตัวที่ 3-4 ของ function ต่างๆ แบบสุ่มชื่อ function หรือถามผลลัพธ์ของการของโปรแกรมที่มีตัวแปร 3-5 ตัวแปร) วันเสาร์อาทิตย์ก่อนสอบก็ไม่สบายเสียอีกเวลาอ่านทบทวนที่จดไว้ใน Mind Map ได้ไม่มาก จะสอบผ่านไม่ผ่านไม่รู้แต่เสียดายที่เตรียมมาเยอะมาก ถ้าอ่านไม่จบแล้วสอบตกคงเสียใจมาก ถ้าอ่านจบที่เตรียมแล้วไม่ผ่านก็จะได้ทำใจว่าทำดีที่สุดแล้ว วันจันทร์ตอนเช้าเลยต้องตั้งตาอ่านให้ครบตั้งแต่ช่วงตี 2 ถึง 7 โมงกว่า อ่านจบค่อยสบายใจหน่อย :D

วันที่สอบก็หวั่นๆ อยู่หน่อย เพราะเป็นช่วงที่เกิดการชุมนุมและมีการประกาศหยุดงานในหลายๆ แห่ง ไม่รู้ว่าศูนย์สอบจะเปิดให้ผมเข้าไปสอบหรือเปล่า ผมสอบที่ศูนย์ CTT Center เลือกสอบที่นี่เนื่องจากตั้งใจจะสอบช่วงธันวาคมแต่ศูนย์สอบหลายแห่งไม่เปิดช่วงธันวาคมแต่ที่นี่เปิดอยู่เกือบทั้งเดือน การเดินทางก็สะดวกโดยลงที่สถานีไฟฟ้าใต้ดินเพชรบุรี เดินต่อไปอีก 300 เมตรก็ถึงครับ ก่อนสอบก็ต้องเก็บของในล็อคเกอร์ก่อน เพราะเค้าจะไม่อนุญาตให้เอาของส่วนตัวกระเป๋า โทรศัพท์มือถือ ฯลฯ เข้าสอบครับ

การสอบจะเป็นการสอบในระบบ online ก็จะมีเจ้าหน้าที่มาเซ็ตระบบให้เรียบร้อย โดยเริ่มต้นเค้าจะให้กระดาษทดมา ปรากฎว่าปากกาเขียนไม่ติด ผมเลยตะโกนขอปากกาใหม่ ตอนหลังสอบเจ้าหน้าที่คงงง ว่าเขียนทดอะไรหว่า ด้วยลายมือที่อ่านยากและที่ทดเขียนไว้ว่า 1+1 (จะเขียนทำไมเนี่ย 555)

ข้อสอบไม่สามารถเปิดเผยได้เพราะเป็นกฎของ Zend ครับ แต่หลักๆ แล้วไม่ยากอย่างที่คิด ระบบข้อสอบเค้าเป็นระบบที่ดีมาก คือทำแล้วสามารถตั้ง flag เพื่อให้กับมาตรวจทานเปลี่ยนแปลงข้อสอบได้สะดวกรวดเร็ว เนื่องจากทำข้อสอบเสร็จค่อนข้างเร็ว ผมจึงมีเวลาตรวจทานซ้ำได้พอสมควร หลักสำคัญก็คือควรจะอ่านข้อสอบให้ละเอียด บางคำตอบเหมือนจะถูกแต่ถ้าอ่านคำถามให้ดีและเช็คคำตอบอื่นจะพบว่าคำตอบที่ถูกต้องจะเป็นอีกข้อหนึ่ง ดังนั้นควรทำเสร็จให้เร็วจะได้กลับมา review ข้อสอบต่างๆ ที่ยังไม่มั่นใจ 100% อีกครั้ง ก่อนกดปุ่มยุติการสอบครับ

ถ้าเป็นการสอบผมจะใช้เวลาคุ้มตลอด  มีเวลาเหลือผมก็ review รอบสองจนครบ 90 นาที พอครบ 90 นาทีปุ๊บ ระบบแจ้งผลให้ทราบในทันที  Congratulation!!  สอบผ่านแล้ว เย้ๆๆ


ปล. ในการสอบครั้งนี้ผมไม่ได้เสียค่าใช้จ่ายในการเข้าสอบเอง ต้องขอขอบคุณพี่วี (webofficedesign.com) ที่สนับสนุนและเคี่ยวเข็ญทำให้ได้ไปสอบในครั้งนี้ด้วยครับ :)

วันศุกร์ที่ 15 พฤศจิกายน พ.ศ. 2556

php function return refernce

function return reference ก็คือ function ที่จะคืนค่าเป็น reference ของตัวแปรนั่นเองครับ

<?php
function &f(&$a,&$b,$status){
    if ($status == 1)
         return $a;
    else
         return $b;
}

$a=100;
$b=200;
$v1 = &f($a,$b,1); //reference $a
$v2 = &f($a,$b,0); //reference $b

$v1 = 11111;
$v2 = 22222;
var_dump($a); //เปลี่ยนตาม $v1
var_dump($b); //เปลี่ยนตาม $v2




วันพุธที่ 30 ตุลาคม พ.ศ. 2556

fairly_rand function

faily_rand function เป็น random function รูปแบบหนึ่ง ที่จะสุ่มตัวเลขขึ้นมาแบบไม่ซ้ำครับ

function fairly_rand($start,$end,$return=1){
//function นี้ $start และ $end ควรจะห่างกันมากๆ
$a = array();
$distance = ($end-$start)/$return;
$a[]=$start;
for($i=$start+$distance;$i<$end-($distance/2);$i+=$distance){
      $a[]=($a[]=floor($i))+1;
}
$a[]=$end;
$results = array();
for($i=0;$i<$return*2;$i+=2){
      $results[] = rand($a[$i],$a[$i+1]);
}
return $results;
}

$numbers = fairly_rand(1,500,5);
var_dump($numbers);

วันเสาร์ที่ 26 ตุลาคม พ.ศ. 2556

การเรียงลำดับภาษาไทยใน php / sorting thai characters


ในการเรียงลำดับโดย php ถ้าใช้ฟังค์ชั่น sort ธรรมดา จะเรียงทีละ byte หรือเรียงโดยให้ความสำคัญกับสระเท่าพยัญชนะจะทำให้เกิดการเรียงลำดับภาษาไทยที่ผิดพลาดดังนนี้ครับ

การบ้าน,ข้าว,เคย,โค,ไก่,ไข่

(ทำให้คำที่ขึ้นต้นด้วยสระเดียวกันเช่น ไ (สระไอไม้มาลัย) อยู่ติดกัน)
ใน php เราจะใช้การตั้งค่า locale และใช้ usort (User sort) ช่วยให้จัดเรียงลำดับภาษาไทยได้ถูกต้อง ดังนี้ครับ..

function sortthaitis620(&$a){
    setlocale(LC_COLLATE, 'thai');
    usort ($a, 'strcoll');
}
function sortthai(&$a){//สำหรับ utf8
    foreach($a as &$i){
      $i = iconv('UTF-8','TIS-620',$i);
    }
    setlocale(LC_COLLATE, 'thai');
    usort ($a, 'strcoll');
    foreach($a as &$i){
      $i = iconv('TIS-620','UTF-8',$i);
    }
}
$a = array('โค','เคย','ไก่','การบ้าน','ข้าว','ไข่');
sortthai($a);
echo implode(',',$a);

sortthaitis620 เป็น function สำหรับ เรียงลำดับข้อความภาษาไทยในตัวอักษรที่เข้ารหัสแบบ tis620 หรือ windows874

sortthai เป็น function สำหรับ เรียงลำดับข้อความภาษาไทยในตัวอักษรที่เข้ารหัสแบบ utf8 ครับ

แต่ถ้าต้องการเรียงลำดับข้อมูลในตารางของฐานข้อมูล mysql ที่ encoding เป็น utf8 ให้ select ดังนี้ครับ
SELECT * FROM tb ORDER BY CONVERT (column_name USING tis620);

วันอังคารที่ 8 ตุลาคม พ.ศ. 2556

วันจันทร์ที่ 23 กันยายน พ.ศ. 2556

Testing Corona SDK Native TextField on Windows

Native TextField is not supported in Corona Simulator
But we can use App Player Like BlueStack for testing.


local inputWeight = native.newTextField(10,10,50,10)
inputWeight:setReturnKey("done")
inputWeight:addEventListener("userInput", function( event )
if event.phase == "submitted" then
                                storyboard.WeightSubmit()       ---- THE MOST PROBLEMATIC
native.setKeyboardFocus(nil)
elseif event.phase == "ended" then
native.setKeyboardFocus(nil)
        end
end)


The code pattern of  native-textfield section is very easy. That is not a problem.

The real problem is the submit function.
You should test storyboard.WeightSubmit() in the Corona Simulator
until you sure everything is work. Because the simulator will tell you every time the error occur.
If you skip this step and go to test on Bluestack or on The real device, Debuging will be very complex and difficult. That's all. :)

วันศุกร์ที่ 14 มิถุนายน พ.ศ. 2556

การค้นหาแบบช่วงวันที่

สมมติว่า $date_start_search และ $date_end_search เป็นข้อมูลจากช่องกรอกข้อมูลวันที่
ในรูปแบบ yyyy-mm-dd ตัวอย่างเช่น 2013-01-01

กรณี 1
ช่วงวันที่ค้นหา(ทั้งหมด) อยู่ข้างในระหว่างช่วงวันที่ในฐานข้อมูล
.............|---------------|.................ช่วงวันที่ค้นหา
........||==============||.............ช่วงวันที่ในฐานข้อมูล
.............(---------------).................ช่วงข้อมูลที่ได้รับจากฐานข้อมูล
อยู่ในรูปของ sql query:
SELECT * FROM date_test WHERE
'$date_start_search' >= date_start AND '$date_end_search' <= date_end

กรณี 2
ช่วงช่วงวันที่ในฐานข้อมูล(บางส่วน) อยู่ข้างในช่วงวันที่ค้นหา
....|---------------|
.........||============||
.........(-----------)
หรือ
..........................|---------------|
.........||============||
........................(--------)
อยู่ในรูปของ sql query:
SELECT * FROM date_test WHERE date_start BETWEEN '$date_start_search' AND '$date_end_search'
SELECT * FROM date_test WHERE date_end BETWEEN '$date_start_search' AND '$date_end_search'
ตามลำดับ

กรณี 3
ช่วงวันที่ในฐานข้อมูล(ทั้งหมด) อยู่ข้างในระหว่างช่วงวันที่ที่ค้นหา
.....|------------------------------|
.........||============||
.........(-------------------)
อยู่ในรูปของ sql query:
SELECT * FROM date_test WHERE
date_start >= '$date_start_search' AND date_end <= '$date_end_search'


- เพียงแค่ query ของกรณีที่ 2 ก็ครอบคลุมกรณีที่ 3 แล้ว
- ส่วนกรณีที่ 2 ยังไม่ครอบคลุมกรณีที่ 1 เนื่องจากในกรณีที่ 1
ทั้ง date_start และ date_end ไม่ได้อยู่ข้างใน $date_start_search, $date_end_search
ทำให้ query ของกรณีที่ 2 ไม่สามารถค้นพบหากเกิดกรณีที่ 1 ขึ้น

ดังนั้น query ที่สมบูรณ์จะอยู่ในรูปแบบ

SELECT * FROM date_test WHERE
( '$date_start_search' >= date_start AND '$date_end_search' <= date_end )
OR ( date_start BETWEEN '$date_start_search' AND '$date_end_search' )
OR ( date_end BETWEEN '$date_start_search' AND '$date_end_search' )

ก็จะเป็นคำสั่งค้นหาข้อมูลในฐานข้อมูลที่อยู่ในช่วงวันที่ๆ ต้องการครับ :)

วันเสาร์ที่ 2 มีนาคม พ.ศ. 2556

XML Printer Class

<?php

$printer = new XMLPrinter('$data',array('path','value'));
$printer->write('111222222');

class XMLPrinter{
    public $columns = array();
    public $onlyFirstElement = false;
    public $rootName = '$root';
    public function __construct($rootName='$root',$columns=array('type','path','value'),$onlyFirstElement=false){
        $this->rootName = $rootName;
        $this->columns = $columns;
        $this->onlyFirstElement = $onlyFirstElement;
    }
    public function write($data){
        if (!$data instanceof SimpleXMLElement)
            $data = simplexml_load_string($data);
        $this->writeHeader();
        $this->_write($data,$this->rootName,0);
        $this->writeFooter();
    }
    public function _write(SimpleXMLElement $data,$name){
        $children = array();
        foreach($data as $item)
            $children[] = $item->getName();
        $children = array_unique($children);
        foreach($children as $child){
            $item = $data->$child;
            $isArray = isset($item[1]);
            $i = -1;
            while(isset($item[++$i])){
                $arrayPat = $isArray ? "[$i]" : '';
                $elementPat = $name.'->'.$item[$i]->getName().$arrayPat;
                if (count($item[$i]->attributes())>0)
                    foreach($item[$i]->attributes() as $attr=>$value)
                        $this->writeRow('attribute', $elementPat."['$attr']", $value);
                if (count($item[$i]->children())>0)
                    $this->_write($item[$i]->children(),$elementPat);
                else
                    $this->writeRow('element', $elementPat, $item[$i]);
                if ($this->onlyFirstElement)
                    break;
            }
        }
    }
    public function writeHeader(){
        echo '<style>';
        echo "nobr{max-width:600px;overflow:hidden;display:block;}";
        echo '</style>';
        echo '<table border="0" cellspacing="0"><tr>';
        foreach($this->columns as $column)
            echo '<th>'.$column.'</th>';
        echo '</tr>';
    }
    public function writeRow($type,$path,$value){
        if (strlen(trim($value)) > 0){
            echo '<tr>';
                foreach($this->columns as $column)
                    echo '<td><nobr>'.htmlspecialchars($$column).'</nobr></td>';
                //echo '<td><nobr>echo \'&lt;br&gt;'.str_replace("'",'\\\'',htmlspecialchars($$column)).'=\','.htmlspecialchars($$column).';</nobr></td>';
            echo '</tr>';
        }
    }
    public function writeFooter(){
        echo "</table>";
    }
}

วันอาทิตย์ที่ 17 กุมภาพันธ์ พ.ศ. 2556

Javascript to javascript bookmark code

ใส่โค้ด javascript ไว้ที่กล่องแรก กดปุ่ม encode จะได้โค้ด javascript url ที่เอาไปแทนที่ใน favorite/bookmark url แล้ว การกดปุ่ม favorite/bookmark จะกลายเป็นการ เรียกคำสั่ง javascript ได้ในทันทีครับ