วันเสาร์, สิงหาคม 30, 2551

หนึ่งเสียงของผม

สถานการณ์ตอนนี้ประชาชนแต่ละคนควรแสดงจุดยืนของตนเอง เพื่อให้ผู้นำอย่าง นายก, กำนัล, หัวหน้าห้อง หรือ สส. ที่ได้รับเลือกจากกระบวนการประชาธิปไตย ได้ทราบว่าคนที่เลือกท่านมาเป็นตัวแทนเขาคิดอะไรกันอยู่ ผมคิดแบบนี้ครับ

5 ข้อหลัก


  1. ผมเชื่อว่าประชาธิปไตยเป็นระบบที่เหมาะสมกับช่วงเวลานี้ ดูจากแนวโน้มจะเห็นระบบที่ดีกว่าจ่อคิวอยู่แต่โลกยังไม่พร้อม 
  2. ผมต้องการให้ทุกคนใช้กติกาของประชาธิปไตย ถ้ามีคนโกงก็ฟ้องกรรมการ ถึงแม้กรรมการเล่นโกงด้วยเราก็ไม่ควรเอาไม้ไล่ตีกรรมการ หรือเล่นโกงแบบเดียวกับอีกฝ่าย แต่ควรใช้กระบวนการที่ระบอบประชาธิปไตยวางไว้ให้ในการต่อสู้ ถ้าสังเกตุการ์ตูนญี่ปุ่นเวลาตัวร้ายโกง พระเอกจะต้องใช้กติกาของเกมนั้นเอาชนะตัวโกงให้ได้ แล้วจะได้ใจของผู้ชม และใจของคู่แข่งไปครอง ผมว่าเราปลูกฝังแบบนั้นก็ดีเหมือนกันนะครับ 
  3. เราต้องอยู่กับระบอบทุนนิยมให้ได้ ไม่ใช่วิ่งหนีหรือลากคนอื่นหนีไปด้วย แต่ต้องหาทางรับมือ อย่ากลัวความจริง
  4. หากต้องการสร้างตัวอย่างให้ลูก ต้องเริ่มจากตนเองก่อน ได้ยินคนบอกว่า "ถ้านายกโกง แล้วต่อไปเราจะสอนลูกให้ดีได้อย่างไร" ผมคิดว่าเราต้องเริ่มจากการไม่ยัดเงินฝากลูกเข้าเรียน ไม่ซื้อของขวัญให้เจ้านานเพื่อหวังการขึ้นเงินเดือน หรือเอาขนมล่อให้ลูกนั่งนิ่งๆ เพราะเป็นการโกงเหมือนกัน แถมยังเป็น node ที่อยู่ใกล้ตัวลูกมากกว่านายก หลายเท่านัก ในกรณีที่ทำไม่ได้ก็ควรเข้าใจว่าสังคมมันไม่สมบูรณืได้ ควรหาทางอยู่ในสังคมมากกว่า (ไม้ได้หมายความว่าให้โกงนะครับ ดูได้จากข้อ 2,3) 
  5. การรถไฟควรแปรรูปครับ ตอนนี้แม้แต่การคุมพนักงานยังทำไม่ได้เลย ส่วนจะแปรรูปแล้วรัฐถือหุ้น 100% หรือเปล่าค่อยว่ากันอีกที

5 ข้อย่อย

  1.  การไฟฟ้าไม่ต้องแปรรูปก็ได้ วันก่อนไปทำเรื่องที่การไฟฟ้า ประทับใจมากครับ รวดเร็วและยิ้มแย้มตลอด แปรรูปไปกลัวเสียของ 
  2. ระบบการศึกษาต้องปรับปรุงขนานใหญ่ เริ่มจากการไม่ปล่อยคนไม่มีความสามารถออกมา ตอนนี้ราชภัฏหลายที่เป็นตัวอย่างที่ดีว่าคนเริ่มไม่อยากเรียน เพราะขึ้นชื่อว่าจบมาก็ทำงานไม่ได้ เอกชนไม่ยอมรับ ผมเชื่อว่าสิ่งมีชีวิตสามารถปรับตัวได้มันไม่ยอมตายแน่นอน ยกเว้นพวกกบในหม้อที่ค่อยๆเร่งไฟให้ร้อนทีละนิด กว่ามันจะรู้ตัวก็ไม่มีแรงโดดจากหม้อซะแล้ว อยาทำแบบนั้นในสถานศึกษาเลยครับ 
  3. นายกห้ามลาออกเพราะการกดดัน เหมือนในหนังที่ประธานาธิบดีสหรัฐอเมริกาต้องไม่ยอมผู้ก่อการร้าย ไม่อย่างนั้นจะเป็นแบบอย่างให้ประชาชนเดือนร้อนได้ในอนาคต 
  4. เปิดเผยข้อมูล หลายหน่วยงานใช้เงินภาษีในการค้นคว้าวิจัย แต่กลับไม่ยอมปล่อยข้อมูลให้ผู้เสียภาษี แต่เก็บไว้ทำรายได้เข้าตัวเอง เช่น กรมแผนที่ทหารไม่ยอมปล่อยข้อมูลแผนที่ กรมอุตุนิยมไม่ยอมปล่อยข้อมูลลมฟ้าอากาศที่เก็บได้จากทั่วประเทศ ศูนย์ข้อมูลนายก เป็นต้น (สำหรับศูนย์ข้อมู,นายก ไม่รู้ว่าทักสินไปแล้วมีคนทำต่อหรือเปล่า) 
  5. อินเตอร์เน็ตเสรี ควรพัฒนาเครื่องมือที่ดีพอ เพื่อให้พ่อแม่ผู้ปกครอง หรือร้าน internet นำมาใช้กรองเนื้อหาที่ไม่เหมาะสมกับเยาวชน ไม่ควรมาดักที่ ISP ฝากเสียงของผมในการพิจารณาด้วยครับ ไม่อยากเป็นผู้ดูอย่างเดียว 


ปล. สำหรับเรื่อง software ผมก็ไม่อยากเป็นผู้ใช้อย่างเดียวเหมือนกัน จะทำเท่าที่ทำได้นะครับ เช่นเข้าไปร่วมบ่นใน http://getsatisfaction.com เป็นต้น

วันพฤหัสบดี, สิงหาคม 28, 2551

ruby XML

วันก่อนเขียน SAX Parser ด้วย Ruby สำหรับ

Leximac

ผมสร้าง class ขึ้นมา 3 ไฟล์ ไฟล์แรกเป็นการสั้งให้ Sax ทำการอ่านไฟล์ และเป็นตัวบอกว่าอ่านแล้วให้ไปเรียก method ใน Object ไหน

#sax_parser.rb 
require 'rubygems' 
require 'xml/libxml' 
require 'handler'  

class SaxParser   

def initialize(xml)
  @parser = XML::SaxParser.new    
  @parser.string = xml    
  @parser.callbacks = Handler.new   
end

def parse     
  @parser.parse    
  @parser.callbacks.elements   
end 

end 

ไฟล์ Sax Parser จะอ่าน xml ทีละ element แล้วมาเรียก method ใน Handler ตาม XML ที่อ่านได้ สามตัว

* start element
* character
* end element

character มันทำตัวสมชื่อทีเดียวครับ อ่านมาทีละตัวอักษรจริงๆ ต้องเอามาต่อๆ กันเอาเอง

# handler.rb 

require 'word'  

class Handler   
attr_accessor :elements, :current_element    

def initialize     
  @elements = []     
  @@word = Word.new   
end    

def on_start_element(element, attributes)     
  @current_element = element     
  if element == 'Doc'       
    @@word = Word.new     
  end     
  if element =='dictionary'       
    print xml_header     
  end 
end    

def on_characters(characters = '')     
  case @current_element      
  when "id"       
    @@word.unique_id << characters      
  when "ecat"       
    @@word.english_category << characters      
  when "esearch"       
    @@word.english_search << characters      
  when "eentry"       
    @@word.english_entry << characters      
  when "tentry"       
    @@word.thai_entry << characters      
  when "esyn"       
    @@word.english_sync << characters      
  when "ethai"       
    @@word.english_thai << characters     
  end   
end    

def on_end_element(element)     
  @current_element = nil     
  if element == "Doc"       
    print @@word.to_xml       
    @@word = nil     
  end     
  if element == "dictionary"       
    print xml_button     
  end   
end    

def method_missing(method_name, *attributes, &block)   
end    

def xml_header       
  # string for xml header   
end     

def xml_buttom      
  # string for xml buttom   
end 

end 

ผมแยก Object Word ออกมาจากตัว handler เพราะอยากได้ลูกน้องในการเขียนโปรแกรม อยากฝึกให้ Word มันเก่งที่สุดในเรื่องของมัน handler จะได้คิดน้อยลง ต่อไปน่าจะเก่งขนาดคิดถึงความสัมพันธ์ของ word หรือเก่งถึงขั้น insert ข้อมูลลง database ได้เลยทีเดียว


class Word    
  attr_accessor :english_search, :english_entry, :thai_entry, :english_category,
                :english_sync, :english_thai, :unique_id    

def initialize     
  @english_search = []     
  @english_entry = []     
  @thai_entry = []     
  @english_category = []     
  @english_sync = []     
  @english_thai = []     
  @unique_id = []     
  Array   
end    

def to_xml     
  id = english_search.to_s.gsub(' ','_')     
  xml = "<d:entry d:title="\"#{english_search}\"" 
  id="\"#{id}_#{unique_id}\"">\n"     
  xml += "  <d:index d:value="\"#{english_entry}\"/">\n"     
  xml += "  <span class="entry">#{english_entry}\n"     
  xml += "  <span class="category">(#{english_category})\n"     
  xml += "  <div class="\"thai_entry\"">#{thai_entry}</div>\n" 

  unless thai_entry.empty?     
    xml += "  <div class="\"english_thai\""><span class="label">
              คำเหมือน :</span><span class="words"> 
              #{english_thai}</span></div>\n" 
  unless english_thai.empty?     
    xml += "  <div class="\"english_sync\"">
              <span class="label">คำเหมือน :</span><span class="words">           
              #{english_sync}</span></div>\n" 
  unless english_sync.empty?     
    xml += "\n"   
end 
end 


ไฟล์สุดท้ายไม่ค่อยเกี่ยวเท่าไหรครับ เอาไว้เรียกใช้สามไฟล์ข้างบน

require 'sax_parser'  
xml = open(ARGV[0], 'r').collect { |l| l }.join puts SaxParser.new(xml).parse 

ใน blog ตัวอย่าง Sax Parser บอกว่า libxml เร็วกว่า EXML ที่เป็น default ของ Ruby ซะอีก หลังจากที่ได้ลองกับ XML ของ Lexitron จัดว่าประทับใจทีเดียวครับ

ที่มา -- lucaguidi.com

วันจันทร์, สิงหาคม 25, 2551

เอา ScreenSave มาเป็น background

จริงๆ คงมีน้อยคนที่อยากเอา ScreenSaver มาแทน background image นอกจากจะเอาไว้อวดเพื่อน เพราะถ้าเอามาใช้จริงคงลายตาน่าดู แถมเปลือง CPU ด้วย



สำหรับคนที่อยากลอง ให้เปิด terminal ขึ้นมาแล้วพิมพ์

/System/Library/Frameworks/ScreenSaver.framework/Resources/ScreenSaverEngine.app/Contents/MacOS/ScreenSaverEngine -background

เป็นอันเสร็จพิธี ถ้าอยากเอา background เก่ากลับมาก็ให้กด ctrl+c ที่ terminal ตัว ScreenSaver ก็จะหายไป

 ที่มา - tuaw

วันอาทิตย์, สิงหาคม 24, 2551

เขียน Helper ช่วยในการสร้าง form

วิธีการใส่ label ให้ text_field สามารถทำได้ดังนี้ครับ สร้างไฟล์ form_tag_helper.rb ใส่ไว้ที่ app/helpers module FormTagHelper def label_text_field(object, method, options = {}) options[:temp_label] = method if method begin_html, end_html = wrapping_html(options) begin_html + text_field(object, method, options) + end_html end private def wrapping_html(options) label = options[:label] ? options.delete(:label) :options[:temp_label].to_s.titlecase options.delete(:temp_label) generated_html = "" generated_html << "
" generated_html << "" generated_end_html = "" generated_end_html << "
" return generated_html, generated_end_html end end
จากนั้นใส่ include ApplicationHelper ไว้ใน application.rb ด้วยครับ เวลาเอาไปใช้เราแค่ใส่สั้นๆ ใน view แบบนี้ครับ <% label_text_field :quotation, :cname, :label => "creater name" %> ถ้ามีให้ใส่หลาย field จะยิ่งคุ้มมากๆ และในกรณีที่เราตั้งชื่อ field ดีๆ เราสามารถเขียนแค่ <% label_text_field :quotation, :creater_name %> เป็นการลด code เพิ่มความเข้าใจ และลดความเสี่ยงที่จะเกิด bug ไปในตัว ฟังก์ชัน wrapping_html สร้างไว้เพราะในการใช้งานจริงเราไม่ได้มี label_text_field แค่อันเดียว เราอาจจะต้องมี label_text_area label_live_search label_text_field_require ด้วย เวลาแก้ไขจะได้แก้ที่เดียว สำหรับสร้างฟอร์มแบบนี้ใน rails 2.0 ( f.label_text_field ) ลองดูที่ [customize text_field](http://apirak.com/?q=node/4) นะครับ

หมดสมัยของการย่อชื่อตัวแปร

เมื่อกี้พยายามแกะ xml ของ Lexitron เพื่อนำมาสร้าง HTML ให้กับโปรแกรม Dictinary.app แล้วพบตัวย่อหลายตัว อ่านแล้วงงๆ เช่น

<xml>
  <doc>
    <esearch>able-bodied   
    <eentry>able-bodied</eentry>   
    <tentry>แข็งแรง</tentry>   
    <ecat>ADJ</ecat>   
    <esyn>healthy; fit</esyn>   
    <id>76</id>
</doc>
</xml>

พยายามแกะ แล้วได้ความว่า

ตัวย่อตัวเต็มคำแปร
esearchenglish searchตัวอักษรที่ใช้อ้างอิงตอนค้นหา
eentryenglish entryคำนี้ในภาษาอังกฤษ
tentrythai entryคำนี้ในภาษาไทย
ecatenglish categoryประเภทของคำ
esynenglish synchronizeคำเหมือนในภาษาอังกฤษ
ethaienglish thaiคำเหมือนในภาษาไทย

ปัญหาคือผมไม่รู้ว่าตัวเองเดาถูกหรือเปล่า ผมเข้าใจว่าคนออกแบบน่าจะคิดถึงเรื่องการเก็บข้อมูลถ้ามีซ้ำกันมากๆ จะทำให้ขนาดของไฟล์ใหญ่ จึงย่อคำให้เล็กลง แต่ยังไม่อยากย่อให้เหลือแค่ตัวอักษรเดียวเพราะอยากให้อ่านเข้าใจด้วย แต่สวนตัวผมคิดว่าถ้าจะย่อควรจะย่อให้เหลือตัวอักษรเดียวไปเลยครับ

ถ้ากลัวอ่านไม่เขาใจ ให้ใส่ comment ที่หัวของ xml แทน หรือทางที่ดีกว่านี้คือใส่ตัวเต็มแล้ว compress file เอา อาจจะใช้ gzip ซึ่งทำให้ไฟล์มีขนาดเล็กลง และถ้า gzip มันฉลาดพอ มันน่าจะรวบคำพวกนี้ให้เหลือแค่ไม่กี่ bit ให้เราด้วยเลย จากนั้นก็ยกเป็นหน้าที่ของโปรแกรมอ่าน xml ที่จะต้องแตก zip ออกมาก่อนหรือแปลงไฟล์ไฟล์เป็นรูปแบบที่ต้องการก่อนนำไปใช้จริง

อีกตัวอย่างหนึ่งในเรื่องการตั้งชื่อ field ใน table เป็นตัวย่อ เช่น appdate, cname, no เป็นต้น ผมเข้าใจว่าการย่อชื่อ field มีประโยชน์ตอนที่เราเขียน SQL จะได้เขียนสั้นๆ ยิ่งต้องเขียน SQL ยาวๆ และ มากมายใน code การย่อตัวแปลยิ่งดูมีเหตุมีผลมากขึ้น

แต่ในปัจจุบันเรามี ORM เข้ามาแทนที่การเขียน SQL ดังนั้นการย่อชื่อใน table นอกจากจะไม่จำเป็นแล้ว ยั่งทำให้สับสนอีกด้วย ขอยกตัวอย่างของ Active Record การ query ข้อมูลจาก database เช่น การค้นหา quotation ที่สร้างโดยนาย A แบบที่สร้างชื่อ field แบบย่อ

quotations = Quotation.find_all_by_cname(A)

หรือ

quotations = Quotation.find_all_by_creatname(A) 

เทียบกับ การใช้ชื่อ field แบบเต็ม

quotations = Quotation.find_all_by_creater_name(A) 

แบบที่หลังจะอ่านรู้เรื่องมากขึ้นเรื่อยๆ ผมคิดว่าเรายอมตั้งขื่อ field ให้อ่านรู้เรื่องไปเลยดีกว่า หรืออาจถึงขนาดตั้งชื่อ field ใน table ให้เป็นคำเดียวกับที่จะเขียนใน label เลยจะดีที่สุด

เวลาที่เราเขียน application เราจะให้ application ของเราตั้งชื่อตัวแปลตามชื่อ field จากฐานข้อมูล ลดความซ้ำซ้อนของโปรแกรมไปได้มากทีเดียว การย่อชื่อยังพบได้อีกหลายจุดในโปรแกรมของเรา หลายครั้งมันดูดีเพราะต้องนำไปใช้หลายที่ แต่ถ้าเป็นไปได้ให้ใช้ตัวเต็มๆ เพื่ออ่านรู้เรื่องสำคัญกว่าครับ

การตัดสินใจว่าจะย่อหรือไม่น่าจะมาจากคำถามว่า เวลาคนอื่นมาอ่าน code ของเราจะเข้าใจหรือเปล่า ย่อตรงจุดนี้แล้วต้องไปเป็นการเพิ่ม code ที่อื่นหรือไม่ เช่นกรณีของ label เป็นต้น ถ้าคิดแล้วว่าไม่เข้าใจและเป็นการเพิ่ม code ก็อย่าย่อเลยครับ

วันศุกร์, สิงหาคม 22, 2551

เขียน Ruby Helper แบบ Block

หลังจาก extend ตัว form_for มาได้ซักพัก ตอนนี้เจอโจทย์ว่าต้องสร้าง helper ที่มีตัวเปิดหัวปิดท้ายประมาณว่า

<div class="label">....</div>

ส่วนที่อยู่ตรงกลางเราให้คนใช้ ใส่กันเอง ประมาณนี้
< label_wrapping do %> .... <% end %> 

ถ้าเรามี code ที่ต้องเขียนแบบนี้ซ้ำๆ โดยเฉพาะพวกหน้า form การเขียนย่อได้แบบนี้จะช่วยลด code ได้มาก และช่วยให้การแก้ไขในภายหลังทำได้จากจุดเดียวด้วย วิธีการคือสร้าง Helper ประมาณนี้ครับ

def label_wrapping(options, &block)     
  begin_html = %{<div class="label">}
  end_html = %{</div>}
  content = capture(&block)     
  concat(begin_html, block.binding)     
  concat(content, block.binding)     
  concat(end_html,block.binding)   
end   


สิ่งที่ return ออกมาคือ HTML ที่ถูก code ของเราครอบไว้แล้ว

วันพุธ, สิงหาคม 20, 2551

โปรแกรม Leximac เพื่อ OS X Leopard

โปรแกรม Leximac version ค. ทำเป็น plugin กับโปรแกรม Dictionary.app ของ Leopard ไปเลยครับ



การใช้งานให้ download ไฟล์ข้อมูลมา unzip (มี copy ไว้สองที่)


จากนั้น copy ไปไว้ที่ ~/Library/Dictionaries หรือไม่ก็ /Library/Dictionaries ก็ได้ ถ้าเอาไว้ที่ home ของเราจะต้องสร้าง folder Dictionaries เอง ถ้าเอาไว้ตรงกลางก็ไม่ต้องสร้างครับ เมื่อวางเสร็จแล้วให้ restart Dictionary.app เป็นอันเสร็จพิธี

การใช้งานให้เปิดโปรแกรม /Application/Dictionary.app แล้ว search ตามปกติเราจะห็นคำแปลภาษาไทยอยู่ด้านล่าง ถ้าต้องการให้ขึ้นเฉพาะของ leximac ให้เลือก tab leximac ได้เลยครับ

วันอังคาร, สิงหาคม 19, 2551

Dictionary Thai-English on Leopard

สองสามวันนี้ลองเอาข้อมูล Dictionary ของ lexitron มาทำเป็น plugin dictionary ของ Leopard


ตอนนี้ยังมีปัญหาอยู่หลายจุด เรียงตามลำดับความเลวร้าย ได้ดังนี้

  • อักษร "ก" หายไป ไม่รู้หายไปตอนไหน ต้องลองศึกษา utf-8 อีกทีว่าจะต้องแปลง ก.ไก่ ยังไง 
  • มีแต่ dictionaty english -> thai เพราะยังไม่ได้แปลง thai -> english รอแก้ปัญหาแรกได้ก่อน 
  • ตัว HTML ไม่สวย เพราะออกแบบ css แบบคร่าวๆ เท่านั้น 
  • ยังไม่ได้ทำปกหน้า ปกหลัง 
  • อยากทดลองแยกออกมาเป็น applicaiton สำเร็จรูปอีกตัว 
  • อยากให้ dictionary ของเราใส่รูปได้ด้วย 

สุดท้ายอาจจะต้องทำ พจนานุกรมเสรี ให้ทุกคนเข้ามาแก้ไขได้เอง เหมือน wikitinary (ไม่รู้ว่า จริงๆ เราดูด xml ออกมาจาก wiki ได้หรือเปล่า) ใครสนใจเอาไปทดลองใช้ชั่วคราว สามารถ download ได้ที่นี้ครับ

Leximac_dictionary_0_2.zip

 หลังจาก unzip แล้วให้เอาไปไว้ที่

  • ~/Library/Dictionaries/ หรือ  /Library/Dictionaries/
แล้ว restart โปรแกรม Dictionary.app จะเห็น tab Leximac ขึ้นมา ทดลอง search ดูจะเห็นคำแปลภาษาไทยออกมาครับ รบกวนผู้รู้ด้าน xml+utf-8 ฝาก comment ไว้ด้วยนะครับ ตอนนี้ยังไม่รู้จะทำยังไงให้ ก.ไก่ กลับมา

เพิมเติม (2010 snow leopard) 

ต้องเข้า preference แล้ว check ที่ Leximac


วันเสาร์, สิงหาคม 16, 2551

วาดครัวด้วย SketchUp

พักงาน dictionary มาวาดครัว ได้ออกมาประมาณนี้ครับ





อันนี้ครัวฝรั่ง ส่วนครัวไทยอยู่นอกบ้านครับ