วันอังคารที่ 19 พฤษภาคม พ.ศ. 2558

การทำ Knowledge Management ไม่ใช่แค่มี Tools อย่างเดียวนะเธอ


...Tools ในการทำ Knowledge Management ในองค์กรนั้น เป็นเพียงตัวช่วยตัวนึงเท่านั้น ไม่ได้รับประกันว่าทำออกมาแล้วนั้นจะประสบความสำเร็จ
... ที่จะทำให้มันประสบความสำเร็จได้นั้น ต้องมีหลายๆองค์ประกอบ หลายๆรูปแบบ ซึ้งเราจะมาดูกันว่าเค้าใช้แนวคิดหรือวิธีการอะไรบ้างที่นิยมทำกัน ซึ้งบางอัน


ไม่จำเป็นต้องมีระบบอะไรก็ได้ก็สามารถเป็นองค์กรแห่งการเรียนรูปได้
เรามาดูกันดีกว่าว่ามีอะไรกันบ้าง

1. ชุมชนนักปฏิบัติ Community of practice : Co P เป็นการจัดกลุ่มคุณกิจที่ทำเรื่องเดียวกัน มารวมตัวกันด้วยเรื่องที่สนใจเรื่องเดียวกัน (Domain) มาพบปะกันสม่ำเสมอ (Community) และมาพัมนาวิธีการทำงานในเรื่องนั้นๆให้ดีขึ้น

2. การศึกษาดูงาน (Study tour) หรือ สุนทรียทัศนา เป็นการขอไปเรียนลัดจากประสบการณ์ของผู้อื่นโดยเข้าไปดูสถานที่จริง การปฏิบัติจริงๆของเขา หรืออาจใช้ในหน่วยงานตนเองโดยการให้เพื่อนที่ทำดีๆสาธิตหรือทำเป้นตัวอย่างให้เราดู ให้เราเรียนรู้ก็ได้

3.  การทบทวนหลังปฏิบัติการหรือการถอดบทเรียน : After action review (AAR) เมื่อทำงานเรื่องใดเรื่องหนึ่งเสร็จแล้ว ก็มีการมานั่งทบทวนร่วมกันผ่านทางการเขียนและการพูด ด้วยการตอบคำถามง่ายๆว่า วันนี้ที่ทำนี่เพื่ออะไรหรืออยากได้อะไร ทำแล้วได้ตามที่คาดหวังไว้ไหม ทำไมถึงได้มากกว่าหรือน้อยกว่า ได้อะไรดีๆเพิ่มขึ้นมาบ้างและถ้าจะทำแบบนี้อีกควรปรับปรุงอย่างไร ในระยะหลังมีคนคิดการทบทวนก่อนปฏิบัติ (Before action review : BAR)ขึ้นมาใช้และการทบทวนขณะปฏิบัติ (During action review : DAR)

4.  การเรียนรู้ร่วมกันหลังงานสำเร็จ : Retrospect เป็นกิจกรรมที่ทีมทำงานสำเร็จไปแล้วระยะหนึ่ง ก็นัดเจอกันเพื่อทบทวนย้อนหลังงานนั้นๆ เช่นทบทวนการดูแลผู้ป่วย การสัมนาผู้ป่วย เป็นต้น

5.  เรื่องเล่าเร้าพลัง : Springboard Storytelling เป็นการถอดความรู้ฝังลึกโดยการมอบหมายให้ผู้ที่มีผลงานดีหรือมีวิธีการทำงานที่ดี มาเล่าให้คนอื่นๆฟังว่าทำอย่างไร คนเล่าจะต้องเล่าให้สนุก น่าฟัง เร้าใจ เล่าให้เห็นการปฏิบัติ เห็นบุคคล ตัวละครในเหตุการณ์ ใช้ภาษาเชิงปฏิบัติจริง เล่าสิ่งที่ตนเองทำจริงๆกับมือ ไม่ปรุงแต่ง ใส่สีตีไข่ เล่าเหมือนเล่านิทานเด็กฟัง

6. การค้นหาสิ่งดีๆรอบๆตัว : Appreciative Inquiring หรือสุนทรียสาธก เป็นการมองเชิงบวก พยายามค้นหาสิ่งดีๆ ความสุข คำชื่นชม ความดีงามที่อยู่ในตัวคน ในองค์การ ในการทำงานหรือนวัตกรรมต่างๆเพื่อนำมาเผยแพร่ให้คนอื่นๆได้ทราบ

7.  เวทีเสวนา : Dialogue หรือสุนทรียสนทนา เป็นจัดกลุ่มพูดคุยกันเพื่อเอาสิ่งดีๆที่แต่ละคนมีอยู่ในตัวเองหรือในการปฏิบัติออกมา โดยไม่ขีดวงที่ชัดเจนมากเกินไป มีเพียงการกำหนดประเด็นกว้างๆในเรื่องที่จะสนทนากัน ไม่รู้คำตอบสุดท้ายว่าคืออะไร ไม่กำหนดเวลาสนทนาของแต่ละคน เปิดกว้างด้านเวลา สถานที่ บุคคลและเปิดกว้างทางใจของทุกคนที่เข้าร่วมกิจกรรมกัน บรรยากาศสบายๆ บรรยากาศเชิงบวก พูดเรื่องเก่า ท้าวความหลังที่ดีๆ พูดถึงสิ่งที่ทำจริงๆในอดีต ไม่ใช่ความคิดเห็นที่จะทำในอนาคต ลักษณะสำคัญของการเข้ากลุ่มสุนทรียสนทนาในการจัดการความรู้จึงมีลักษณะสำคัญ 4 ประการคือพูดอย่างจริงใจ ฟังอย่างตั้งใจ ถามอย่างซาบซึ้งใจและจดอย่างเข้าใจใส่ใจ

8. เพื่อนช่วยเพื่อน : Peer Assist  เชิญทีมอื่นมาแบ่งปันประสบการณ์ดีๆให้เรา มาแนะ มาสอน มาบอก มาเล่าให้เราได้ฟังเพื่อจะได้นำไปประยุกต์ใช้ในหน่วยงานเรา

9.  Action Learning การเรียนรู้โดยการปฏิบัติ เป็นการรวมกลุ่มกันของผู้ปฏิบัติเพื่อจะแก้ไขปัญหาใดปัญหาหนึ่ง โดยการวิเคราะห์สาเหตุ วิเคราะห์ทางเลือก เลือกทางเลือกที่เหมาะสมแล้วนำไปปฏิบัติ พร้อมทั้งติดตามประเมินผลเพื่อปรับให้ดีขึ้นเรื่อยๆ ในภาษานักคุณภาพเขาเรียกทำ CQI Story

10.  Benchmarking มาตรฐานเปรียบเทียบ เป็นการตกลงกันเองในกลุ่มผู้ปฏิบัติอาจเป้นระดับบุคคล งาน แผนก ฝ่าย กลุ่มงานหรือองค์การก็ได้ กำหนดประเด็นร่วมกันแล้วนำมาเปรียบเทียบกันเพื่อร่วมมือกันในการยกระดับงานให้ดีขึ้นเรื่อยๆ ไม่ใช่เปรียบเทียบเพื่อแข่งขันเอารางวัลกัน แต่เปรียบเทียบเพื่อเรียนรู้ร่วมกัน ในการเปรียบเทียบมาตรฐานปฏิบัติมี 2 แบบคือ Process Benchmarking และ Result Benchmarking เครื่องมือที่นำหลักการเปรียเบทียบมาตรฐานปฏิบัติมาใช้คือเครื่องมือชุดธารปัญญา

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

12.  Mentoring การเป็นพี่เลี้ยง เป็นการให้คนทำงานที่อยู่คนละฝ่ายหรือกลุ่มงานหรือแผนกหรือแผนกเดียวกันก็ได้ มาช่วยแนะนำวิธีการทำงาน ช่วยเหลือสนับสนุน คอยให้คำปรึกษาชี้แนะ มักใช้ในการเรียนรู้ในกลุ่มผู้บริหารหรือผู้ที่จะก้าวไปเป็นผู้บริหาร

13.  Portfolio แฟ้มงานเพื่อการพัฒนา เป็นการบันทึกผลงานดีๆ นวัตกรรมในการทำงาน คำชื่นชม ความภาคภูมิใจทั้งระดับบุคคล ระดับแผนกหรือระดับองค์การ เรียกอีกอย่างว่าบัญชีความสุข

14.  บทเรียนจากความผิดพลาด : Lesson Learned ผมมักเรียกกิจกรรมนี้ว่า ผิดเป็นครู ในทางการแพทย์มักจะมีการทำอยู่บ่อยๆเพื่อลดความผิดพลาดในการรักษาผู้ป่วย ที่เรียกว่า Dead case conference ในการทำกิจกรรมผิดเป็นครูนี้ ถ้าเริ่มทำKMใหม่ๆ ไม่แนะนำให้ใช้ เพราะคนยังไม่มีความสัมพันธ์กันดีพอ ยังไม่เปิดใจเข้าหากัน อาจเป็นบ่อเกิดของการโทษกันหรือทะเลาะกินใจกันได้ กิจกรรมผืดเป็นครูที่ดี ควรเป็นคนที่ทำผิดพลาดหรือทำงานไม่สำเร็จ เป็นผู้ที่นำเอาความผิดพลาดนั้นมาเล่าให้คนอื่นๆฟังอย่างเต็มใจ เล่าให้เห็นวิธีการ เหมือนทำเรื่องเล่าเร้าพลัง เล่าโดยไม่พยายามปกป้องตนเอง คนฟังก็ต้องฟังอย่างเข้าใจ เห้นใจ ไม่ตำหนิ ไม่ว่ากล่าวโทษ ไม่หาผู้กระทำผิด แต่เป็นการเรียนรู้จากเหตุการณ์เพื่อหาสาเหตุของความผิดพลาด จะได้วางระบบเพื่อป้องกันความผิดพลาดนั้นๆ ไม่ให้คนอื่นๆผิดพลาดซ้ำอีก ในการทำคุณภาพจะมีการทำการบริหารความเสี่ยง (Risk management : RM) ก็เป็นไปตามหลักการนี้ กิจกรรมผิดเป็นครูนี้ ดีมากสำหรับการเรียนรู้ของตนเอง

ขอบคุณแหล่งที่มา https://www.gotoknow.org/posts/119306

facebook api กับการแสดงผลรูปภาพจาก fanpage facebook ชื่อดัง

ก่อนอื่นเรามาหา facepage แนวรูปภาพที่เราชื่นชอบกันก่อนเลย และในที่นี้ขอเป็นเพจ

9GAG in Thai https://www.facebook.com/9gaginthai

จากนั้นนำชื่อของเพจที่อยู่บน Url นั่นก็คือ 9gaginthai มาใส่ใน api นี้

https://graph.facebook.com/9gaginthai/albums?fields=id%2Cname

ซึ้งจากที่เห็นในส่วนของ query ของ url ก็จะเห็นได้ว่า ผมต้องการ fields เพียงแค่ id และ ชื่อของอัลบั้มเท่านั้น ซึ้งถ้าไม่ระบุอะไร facebook ก็จะให้เรามาทั้งหมด ไม่ว่าจะเป็นการ like comment เป็นต้น ก้ไปศึกษารูปแบบข้อมูลเอานะครับ



จะเห็นผลลัพธ์ json ในรูปแบบดังนี้ จากนั้น เราจะนำ id ของ อัลบั้มรูปที่เนราต้องการมาใส่ไว้ใน api นี้ ดังนี้

โดยผมเลือก id ของ Timeline Photo มาใช้นั้นคือ 194110460693515
https://graph.facebook.com/194110460693515/photos?limit=30

โดยค่า limit สามารถเลือกได้ และจะกรองเอาเฉพาะฟิวที่เราต้องการก็ได้ แต่ผมจะเลือกมาทั้งหมดเลย

จากผลลัพธ์ ภายใต้ data [] จะมี array ของ object ของรูปอยู่ จามจำนวน limit ที่ได้ทำการร้องขอไป
- id คือ id ของโพส
- create_time โพส ณ เวลาใด
- from โพสโดยใคร
- image[] ภายในจะมีรูปสำหรับทำทัมเนลพร้อมทั้งมีขนาด width และ height ขนาดต่างๆให้เลือกอีกด้วย
- link คือ url ต้นฉบับของโพสนั้นๆ
- source คือ ต้นฉบับของรูป (ซึ้งตรงนี้ละที่ต้องการ อิอิ)
- comment และ like ตรงนี้ไปศึกษาเอานะครับ มีข้อมูลที่เป็นประโยชน์หลายอย่างมากๆ
- width และ height ของรูปต้นฉบับก็มีมาให้น๊ะจ๊ะ


เท่านี้ เราจะเอาข้อมูลไปทำอะไรต่อนั้นก็สุดแท้ แล้วแต่ พวกนายเลยว่าจะทำอะไรเด้อออออ

รีวิว App MacID ใช้เพื่อปลดล็อกเครื่อง Mac

เนื่องจากปัจจุบัน คอมพิวเตอร์ผมตั้งเอาไว้กับที่เป็นเวลานานๆ และเป็นที่ส่วนรวม และผมก็ไม่ได้อยู่หน้า Mac ของตัวองตลอดเวลา ซึ้งบางครั้งผมก็ลืมที่จะ logout สื่อสังคมออนไลน์ต่างๆของตนเอง
...ดังนั้นจึงจะมีไอ้คุณเพื่อนบางคน แอบดูหรือแอบไปรู้รหัส login เครื่อง Mac ของเรา เพราะการตั้งรหัสเครื่องนั้น คนส่วนใหญ่จะตั้งรหัสสั้นๆ เพื่อที่จะ login เข้าเครื่อง Mac ได้อย่างรวดเร็ว จึงเป็นเหตุให้ไอ้เพื่อนพวกนี้รู้รหัสเครื่องของเราได้ไม่ว่าจะแอพดูหรือเดา หรือบลาๆๆ ด้วยวิธีต่างๆ และจากนั้นมันเอาเอา User facebook หรืออย่างอื่นไปแกล้งเรา ด้วยการโพสข้อความในลักษณะที่ เราเบี่ยงเบนทางเพศ หรือการตั้งสถานะต่างๆที่ทำให้เราเกิดอาการอับอาย หรือผู้อื่นได้รับการเข้าใจผิดเกี่ยวกับเรา ... และสิ่งนี้คือเรื่อง 'ตลก' เฮฮาสำหรับทุกคน

... วันนี้ผมจึงจะมานำเสนอแอพที่จะช่วยปล็ดล๊อกเครื่อง Mac ให้เราได้อย่างรวดเร็ว และทำให้เราตั้งรหัสยาวๆได้ และจะไม่ต้องพิมพ์รหัสให้เพื่อนแอบดูด้วย

App Mac ID

- เครื่อง Mac ที่เข้าใช้ได้
  Macbook Air ปี 2011 หรือมากกว่า
  Macbook Pro ปี 2012 หรือมากกว่า
  iMac ปี 2012 หรือมากกว่า
  Mac Mini ปี 2011 หรือมากกว่า
  MacPro ปี 2013 หรือมากกว่า

- iPhone ที่เข้าใช้ได้
  iPhone4s
  iPhone5
  iPhone5c
  iPhone5s
  iPhone6
  iPhone6Plus
  iPad mini
  iPad mini 2
  iPad mini 3
  iPad 4 gen
  iPad Air
  iPad Air 2
  iPod touch 5 gen

ก่อนอื่นไปโหลดโปรแกรมของ Mac ใน website นี้ก่อนเลย http://macid.co/


ต่อมาไปโหลด ​App จากทาง iOS ด้วย

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


หน้าตา App  จากการใช้งานจริง




WebSockets กับเว็บแชทขั้นพื้นฐาน ตอนที่ 3

WebSockets กับเว็บแชทขั้นพื้นฐาน ตอนที่ 3



จากเดิมที่เรามารู้จักกับ concept ทั้งหมด รวมถึงการทำงานในทาง Server ไปแล้วนั้น เราจะมาดูวิธีการทำงานของทาง Client กันบ้าง

*** code ของ client ทั้งหมดอยู่ ณ บทความตอนที่ 2

ส่วนที่ 1 
         <div id='body'>
<textarea id='log' name='log' readonly='readonly'></textarea><br/>
<input type='text' id='message' name='message' />
</div>

คือส่วนของการแสดงผลหลัก

ส่วนที่ 2
                 $(document).ready(function() {
log('Connecting...');
Server = new FancyWebSocket('ws://127.0.0.1:9300');

$('#message').keypress(function(e) {
if ( e.keyCode == 13 && this.value ) {
log( 'You: ' + this.value );
send( this.value );

$(this).val('');
}
});

//Let the user know we're connected
Server.bind('open', function() {
log( "Connected." );
});

//OH NOES! Disconnection occurred.
Server.bind('close', function( data ) {
log( "Disconnected." );
});

//Log any messages sent from server
Server.bind('message', function( payload ) {
log( payload );
});

Server.connect();
});

Server = new FancyWebSocket('ws://127.0.0.1:9300');
// คือการสร้างตัวแปร Server เพื่อรองรับการ connect Web Socket ไปยัง ip 127.0.0.1 ที่ port 9300 ที่ได้ setting เอาไว้ที่ Code ทาง Server

// การ bind open เข้าไป เมื่อมีการสั่ง connect ก็จะทำงานตัวนี้
Server.bind('open', function() {
log( "Connected." );
});

// การ bind close เข้าไป พูดง่ายๆคือ เมื่อปิดหน้านี้ไป จะทำการ Disconnect
Server.bind('close', function( data ) {
log( "Disconnected." );
});

// การ bind message เข้าไป คือเมื่อมี Message จากผู้ใช้อื่นๆเข้ามา  ก็จะผ่านตัวนี้
Server.bind('message', function( payload ) {
log( payload );
});

// เชื่อมต่อ Web Socket
Server.connect();

// ฟังก์ชันสำหรับการส่งข้อความไปยัง web socket
// โดย send ค่าใน text ไปยัง Server
function send( text ) {
Server.send( 'message', text );
}

// คือ ฟังก์ชันสำหรับการเพิ่มผลลัพธ์ เพื่อแสดงผลในส่วนแสดงผลหลัก
function log( text ) {
$log = $('#log');
//Add text to log
$log.append(($log.val()?"\n":'')+text);
//Autoscroll
$log[0].scrollTop = $log[0].scrollHeight - $log[0].clientHeight;
}

วันพุธที่ 18 มีนาคม พ.ศ. 2558

WebSockets กับเว็บแชทขั้นพื้นฐาน ตอนที่ 2


Web Sockets กับการ Impliment เว็บแชทขั้นพื้นฐาน

ตอนที่ 1 : http://aobkung.blogspot.com/2015/03/websockets-1.html
ตอนที่ 3 : http://aobkung.blogspot.com/2015/05/websockets-3.html

ก่อนอื่นเราจะต้องบอกก่อนว่า จะทำการ implement ในฟั่ง Process ของ server โดยการใช้ Class ของคนที่เขียน WebSocket มาอยู่แล้ว ซึ้งเป็นภาษา PHP และทำออกมาได้ดีพอสมควร (ในแง่การใช้ มันง่ายดี)

สามารถเข้าไป Download ได้ที่
   
            https://github.com/ghedipunk/PHP-Websockets

โดยที่เราจะสนใจ file ที่ชื่อ   websockets.php และ users.php

และที่สำคัญจะต้องติดตั้ง PHP Command line มาด้วย ซึ้งผมใช้ Mac OS X ดังนั้นจึงทำการติดตั้งผ่านโปรแกรมที่ชื่อว่า MAMP ซึ้งจะมีเวอร์ชั่นฟรีให้โหลด (ค้นหาเอาเลยใน Google) เอาไปใช้ได้



         ขอบเขตของ web chat ที่เราจะเขียน


           - เป็นห้อง Chat รวม เมื่อเข้าไปแล้วทุกคนสามารถคุยกันได้ (ทุกคนเห็นข้อความที่เราพิมพ์ออกไป)
           - เป็นเมื่อมีคน connect เข้ามา หรือปิดการเชื่อมต่อ (ปิดโปรแกรม) ก็จะแจ้งเตือนให้กับผู้อื่นได้รับทราบด้วย
           - บอกหมายเลข ID ของแต่ละคนเพื่อแยกตัวตนซึ้ง Class WebSocketServer จะทำหน้าที่สร้างขึ้นมา

          ขั้นตอนที่ 1

          เริ่มจากการ Impliment ทางฟั่ง Server กันก่อนเลย (บางแหล่งเริ่มอธิบายจาก Client ก่อน แต่ผมเข้าใจมันมาจากทาง Server ก่อน ดังนั้นขอแบบนี้ละกันนะครับ ฮาๆ)
         เอาละ เริ่มจากเข้าไปดู code ที่ไฟล์ websockets.php กันก่อน ใน class จะเห็น code ดังนี้
// Called immediately when the data is recieved.
abstract protected function process($user,$message);
// Called after the handshake response is sent to the client.
abstract protected function connected($user);      
// Called after the connection is closed.
abstract protected function closed($user);           
จะมี abstract function อยู่ 3 function ให้เราเอาไป implement เอาเอง ซึ้งก็คือ 3 function หลักที่เป็นหัวใจของการทำ Web Socket ก็คือ connected closed และ Process(การ get และ send ข้อมูล) ดังนั้นเราจะสร้าง Class ของเราขึ้นมาเอาไว้ใช้งาน โดนสือทอด Class WebSocketServer ที่คุณ ghedipunk ได้เขียนและนำเอามาลงเอาไว้ใน Github นั้นเอง

สร้าง testWebSocketChat.php
<?php
require './websockets.php';
class testWebSocketChat extends WebSocketServer {

          protected function process ($user, $message) {
               
          }
          protected function connected ($user) {
 
          }
          protected function closed ($user) {
 
          }
}
$testWebSocketChat = new testWebSocketChat("127.0.0.1","9000");
try {
          $testWebSocketChat->run();
}
catch (Exception $e) {
          $testWebSocketChat->stdout($e->getMessage());
}

จะอธิบายทีละขั้น ดังนี้
     - require ไฟล์ของ Class WebSocketServer เข้ามา
     - สร้าง function ที่เป็น abstract ทั้งหมดเอาไว้ และจะอธิบายว่าแต่ละกันทำอะไรบ้างในขั้นตอนที่ 2
     - สร้าง Object ของ testWebSocketChat ขึ้นมา พร้อมระบุ ip ของ Server เราในที่นี้คือเครื่องของเราเองนั่นคือ 127.0.0.1 พร้อม Port ที่ต้องการจะใช้เชื่อมต่อ Socket กันซึ้งผมกำหนดไปเป็น 9000 (ตัวอย่างไฟล์การทำงานของต้นฉบับก็ใช้ port นี้เลยใช้ตามไม่มีเหตุผลอื่น ฮาๆๆๆ) ซึ้งการกำหนดนี้จะเข้าไปทำงานที่ __construct ในไฟล์ websockets.php ซึ้งมันทำงานยังไงก็ตามเข้าไปดูได้เลยจ้า
     - และใช้คำสั่ง run() เพื่อเริ่มกระบวนการทำงาน

          ขั้นตอนที่ 2

           เราจะ Implement function connected กันก่อนซึ้งจะเป็นไปตามนี้คือ
           - เมื่อมี user connect เข้ามานั้นจะทำการแจ้งเตือนให้กับทุกคนที่อยู่ในห้อง Chat (ยกเว้นตัวเราเอง)
           - function connect มีการ pass parameter ที่ชื่อ $user คือรายละเอียดของ user คนนั้นที่ connect เข้ามา
           - $this->users คือ ตัวแปรที่เก็บรายละเอียดของ User ทุกๆคน ที่ Connect เข้ามายัง Process Socket ของเรา ซึ้งจะเป็น Array
           - $this->send( <user> , <data> ) คือคำสั้งที่ใช้ส่งข้อมูลไปยัง user คนนั้นๆ ซึ้นมันทำงานยังไงนั้น ....... ยาวเลยบ่องตง ตามเข้าไปดูเองใน websockets.php เลยจ้า
ดังนั้นเราจะเขียนโปรแกรมอกมาได้ดังนี้

protected function connected ($user) {
    foreach ($this->users as $value) {
         if ($value != $user)
              $this->send($value , "id ".$user->id." (".date("Y-m-d H:i:s").") : Connected");
    }
}
 ภายในส่วนของ data จะส่งข้อควาที่เป็น id และ เวลา ไปด้วยตามขอบเขตที่เขียนเอาไว้ด้วย

           ขั้นตอนที่ 3

            Implement function closed ก็จะมีรายละเอียดเหมือนๆกับ connected นั่นละครับ เพียงแต่เปลี่ยนคำพูดนิดหน่อยเท่านั้นเอง

protected function closed ($user) {
    foreach ($this->users as $value) {
         if ($value != $user)
              $this->send($value , "id ".$user->id." (".date("Y-m-d H:i:s").") : Disconnect");
    }
}

           ขั้นตอนที่ 4

             Implement function process 
      - จะทีการ pass parameter เข้า user และ message ที่ถูกส่งมาจาก Client 
      - เพิ่ม id เข้าไปในข้อความ เพื่อระบุตัวตนได้ตามขอบเขต 
      - ส่งข้อความไปยังทุกคนยกเว้นตนเอง
protected function process ($user, $message) {
    $message = "id ".$user->id." : ".$message;
    foreach ($this->users as $key => $value) {
          if ($value != $user) {
               $this->send($value,$message);
          }
    }
}

             ขั้นตอนที่ 5

               จากที่ได้ Implement code ทั้งหมดไปแล้ว ซึ้งง่ายมากๆ ก็จะถึงตอนที่เราจะทำการรัน Daemon Process ของโปรแกรมที่เราเขียนกันแล้ว ซึ้งง่ายมากๆ โดยไปยัง path ที่เขียนไฟล์ testWebSocketChat.php และใช้คำสั่ง.....
php testWebSocketChat.php

          เท่านี้ก็เรียบร้อย รอให้บริการกับทาง Client ที่จะเข้ามายัง Process ได้เลย และสำหรับการ Implement ทางฟั่ง Server ก็มีเท่านี้ ส่วนทางด้าน Client นั้นจะขอยกเอาไปเล่ากันต่อบทความต่อไปนะครับ แต่จะทิ้ง code ทาง client เอาไว้ให้แล้วเอาไปดูกัน เพราะมันเข้าใจได้โดยที่ไม่ต้องอธิบาย แต่สำหรับคนที่ไม่เข้าใจก็รอในบทความต่อไปเลยครับ

ไฟล์ client.html

<!doctype html>
<html>
<head>
<meta charset='UTF-8' />
<title>WebSocket4Chat</title>

<style>
input, textarea {border:1px solid #CCC;margin:5px;padding:5px}

.main {max-width:800px;margin:auto}
#chatbox {width:100%;height:400px;font-size: 15px;}
#message {width:100%;line-height:30px;font-size: 15px;}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">

function getDate () {
var objToday = new Date(),
                weekday = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'),
                dayOfWeek = weekday[objToday.getDay()],
                domEnder = new Array( 'th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th' ),
                dayOfMonth = today + (objToday.getDate() < 10) ? '0' + objToday.getDate() + domEnder[objToday.getDate()] : objToday.getDate() + domEnder[parseFloat(("" + objToday.getDate()).substr(("" + objToday.getDate()).length - 1))],
                months = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'),
                curMonth = months[objToday.getMonth()],
                curYear = objToday.getFullYear(),
                curHour = objToday.getHours() > 12 ? objToday.getHours() - 12 : (objToday.getHours() < 10 ? "0" + objToday.getHours() : objToday.getHours()),
                curMinute = objToday.getMinutes() < 10 ? "0" + objToday.getMinutes() : objToday.getMinutes(),
                curSeconds = objToday.getSeconds() < 10 ? "0" + objToday.getSeconds() : objToday.getSeconds(),
                curMeridiem = objToday.getHours() > 12 ? "PM" : "AM";
var today = curHour + ":" + curMinute + ":" + curSeconds + curMeridiem + "," + dayOfMonth + " " + curMonth + ", " + curYear;

return today;
}
function writeChatbox( text ) {
$chatbox = $('#chatbox');
//Add text to chatbox
$chatbox.append(($chatbox.val()?"\n":'')+text);
//Autoscroll
$chatbox[0].scrollTop = $chatbox[0].scrollHeight - $chatbox[0].clientHeight;
}

function checkStatusConnectSocket(state) {
if (state == 1) {
return 'You : Connected ('+getDate()+')';
}
else if (state == 3) {
return 'You : Disconnected ('+getDate()+')';
}
else if (state == 0) {
return 'You : Init Socket ('+getDate()+')';
}
}


function init() {
var host = "ws://127.0.0.1:9000/"; // SET THIS TO YOUR SERVER
try {
socket = new WebSocket(host);

socket.onopen    = function(data) {
  writeChatbox (checkStatusConnectSocket(socket.readyState));
  };
socket.onmessage = function(data) {
// console.log(data);
   writeChatbox (data.data);
  };
socket.onclose   = function(data) {
   writeChatbox (checkStatusConnectSocket(socket.readyState));
  };
}
catch (ex) {
writeChatbox (ex);
}
}
function send(data) {

if(!data) {
alert("Message can not be empty");
return;
}

try {
socket.send(data);
} catch(ex) {
writeChatbox ('Can not send Data to server ('+ex+')');
}
}

$(document).ready(function() {

$('#message').keypress(function(e) {
if ( e.keyCode == 13 && this.value ) {
writeChatbox( 'You: ' + this.value );

send( this.value );

$(this).val('');
$(this).focus();
}
});

init();
});
</script>
</head>
<body>
<div class="main">
<textarea id='chatbox' name='chatbox' readonly='readonly'></textarea>
<input type='text' id='message' name='message' />
</div>
</body>
</html>

วันอังคารที่ 17 มีนาคม พ.ศ. 2558

WebSockets กับเว็บแชทขั้นพื้นฐาน ตอนที่ 1


WebSockets 

ตอนที่ 2 http://aobkung.blogspot.com/2015/03/websockets-2.html
ตอนที่ 3 http://aobkung.blogspot.com/2015/05/websockets-3.html

           ถ้าจะให้พูดง่ายๆ คำพูดไม่สวยหรูก็คือ เป็นสิ่งหนึ่งที่ทำให้ Client สามารถรับอะไรต่างๆนาๆที่ server อยากจะให้โดยที่ไม่ต้องส่ง requests ไปยัง server ว่ามีอะไรจะให้ไหม ถ้ามีส่งมาน๊ะ อะไรประมานนั้น จึงประหยัดทั้งเวลาที่ใช้รอในการ requests ลดการทำงานของ server ลง เพราะไม่ต้องรับ requests ถี่ๆ(บางคนใช้วิธีการตั้งเวลาเพื่อขอรีเควสเรื่อยๆอาจจะทุกๆ 2 วินาที) เป็นต้น 
            แต่ถ้าให้พูดถึงการทำโปรแกรมแชท , ทำ notification หรืออะไรก็แล้วแต่ที่เป็นไปในลักษณะ real time ก็มีวิธีที่จะนำไปใช้ได้อยู่คร่าวๆดังนี้

  1. Long Polling
  2. Server-Sent Event
  3. Websockets

            Ajax Long Polling

       


           
            client จะทำการส่ง requests ผ่าน http ไปยัง server จากนั้นเมื่อ server มี state ใหม่ๆหรือมี new information ที่จะต้องการส่งไปยัง Client ก็จะส่งข้อมูลมาให้ (โดยที่ไม่ต้องร้องขอข้อมูลไปบ่อยๆ แต่ร้องขอไปครั้งเดียว เมื่อมีอะไรเกิดขึ้นก็จะบอก) จึงต่างจาก Ajax Ploling ธรรมดา

            Server-Sent Event

           

                เมื่อ Client ส่ง request ไปยัง server ผ่าน HTTP ทาง sever จะสร้าง Process ขึ้นมาพร้อมกับการลืบค้น State ใหม่ๆกับ Database และส่งกลับมายัง Client รับ State ใหม่ๆไป ซึ้งจะเห็นได้จะเป็น Real-time traffic จาก server ไปสู่ client แต่วิธีการเช่นนี้จะมี Default delay อยู่ที่ 3 วินาที

                Websockets

             

               จะเป็นการที่ Client กับ Server เปิดการเชื่มต่อกัน ถ้าพูดให้เห็นภาพ เหมือนกับการที่เรา(Server)เอาเชือกมาผูกกับคนอื่นๆ(Client) และเชื่อมีแรงตึง ถ้าเชือกหย่อนเมื่อไหร่แปลว่าคนๆนั้นไม่ได้เชื่อมต่อ และการส่งของให้กันก็ร้อยผ่านเชือกไป เมื่อของไปกระทบตัวคนๆนั้นก็จะรู้ตัวและหยิบของไป ประมานนั้น ซึ้งไอ้เจ้า Web Sockets นี้จะสร้าง Process 1 Process ขึ้นมาด้วยการใช้คำสั่งของ Server เพื่อเป็น Process ที่ใช้ในการรองรับการเชื่มต่อ รอรับข้อมูล ส่งข้อมูล (Process เดียวบริการทุก Client) มันจึงเป็นเหตุผลให้มีสรรพคุณที่ได้โม้เอาไว้ในย่อหน้าแรก และนี่ละคือพระเอกของเรา



        Conclusion

..Long-pollingServer-Sent EventsWebSockets
Browser supportSupported by the most of currently used browsersSupported by Chrome 9+, Firefox 6+, Opera 11+, Safari 5+The latest hybi-10 protocol supported by Chrome 14, Firefox 7 betas, hybi-07 supported by Firefox 6
Server-loadingTakes little of CPU resources, but creates idle processes per user expending server memoryWorks in many ways as long-polling, unless SSE doesn’t need to close connection every time when response is sentThe best possible solution. Server has the only process serving any requests. No loops, memory/CPU expense per client, but per client action
Client-loadingDepends on implementation, though it always an asynchronous process.Natively implemented in the browser, takes minimum resourcesNatively implemented in the browser, takes minimum resources
TimelinessNear real-time, though black out period between sending response and making a new request adds some delayDefault delay 3 sec., but can be changedTrue real-time
Complexity of implementationVery easyEven easierRequires an EventMachine server and a custom port being open

จากตารางเปรียบเทียบจะเห็นได้ว่า WebSockets นั้น ด้าน server-loading นั้นเป็น The best possible solution เลยทีเดียวและ only process serving any requests ส่วนทางด้าน Timeliness นั้นก็คงพูดได้แค่ว่า True real-time ปัจจุบันเลยละจร้าาาาา

ข้อมูลอ้างอิง 



งั้นเรามาเริ่มการ Impliment กันเลยดีกว่า ซึ้งเราจะทำด้วย ภาษา php ในฟั่งของ Server (ที่ใช้ Run เพื่อรองรับการเชื่อมต่อ ) และ javascript ใช้สำหรับ Client เพื่อเชื่อมต่อ ส่งข้อมูล และรับข้อมูล
(ผู้อ่านท่านไหนไม่คล่องเรื่อง javascript ajax jquery ก็ศึกษาเพิ่มเติมตามเว็บทั่วๆไป เพราะจะอธิบายทุกบรรทัดคงไม่ไหว )
.
.
.
.
.
.
.
แต่สำหรับตอนที่ 1 ขอพักเอาไว้เท่านี้ก่อนครับ บทความต่อไปในตอนที่ 2 จะเป็นการ impliment ครับ


วันเสาร์ที่ 21 กุมภาพันธ์ พ.ศ. 2558

มารู้จัก Genetic Algorithm พื้นฐานกัน มันกว่าที่คิด


Genetic Algorithm 





           ขั้นตอนวิธีเชิงพันธุกรรม (Genetic Algorithm – GA) เป็นเทคนิคทางปัญญาประดิษฐ์ (AI : artificial intelligence) อย่างหนึ่งที่ใช้ในการค้นหา การเพิ่มประสิทธิภาพ และการเรียนรู้ (Search, Optimization, and Learning) ด้วยการเลียนแบบทฤษฎีการวิวัฒนาการทางธรรมชาติ โดยขั้นตอนวิธีเชิงพันธุกรรมมีจุดเด่นในด้านความทนทานต่อความผิดพลาดในการค้นหาคำตอบจากแหล่งข้อมูลที่มีความซับซ้อนและยากที่จะสร้างแบบจำลองด้วยสมการคณิตศาสตร์ เนื่องจากเป็นกระบวนการค้นหาที่ไม่มีความเฉพาะเจาะจงกับแบบจำลองหรือลักษณะเฉพาะของข้อมูลแบบใดแบบหนึ่ง ด้วยเหตุนี้ขั้นตอนวิธีเชิงพันธุกรรมจึงถูกนำมาประยุกต์ใช้ในการแก้ปัญหาได้หลากหลายรูปแบบ
     - ตั้งแต่การจัดตารางเวลา (Timetable Scheduling)
     - การออกแบบระบบควบคุมอัตโนมัติ (Control System Design)
     - การออกแบบเพื่อเพิ่มประสิทธิภาพของระบบท่อส่งก๊าซ (Gas Pipeline Optimization)
     - การพัฒนาระบบปัญญาประดิษฐ์ (AI : artificial intelligence) ที่สามารถเรียนรู้จากสภาพแวดล้อมได้ (Genetic Based Machine Learning)
     เป็นต้น
    โดยหลักการของขั้นตอนวิธีเชิงพันธุกรรม เป็นการเลียนแบบกระบวนการวิวัฒนาการตามธรรมชาติ เพื่อพัฒนาหรือทำการ
“วิวัฒนาการ” 
คำตอบที่ดีที่สุดในการแก้ปัญหา

ที่มา : https://kapitaennem0.wordpress.com/2013/07/17/genetic-algorithm/

(ผู้เขียนบล๊อกนี้อธิบายได้ดี ผมจึงนำมานำเสนอต่อ)

Genetic Algorithm มีอะไรบ้าง

สำหรับองค์ประกอบหลักๆ ของ Genetic Algorithm มีดังนี้

1. Chromosome Encoding
2. Initial Population
3. Fitness Function
4. Genetic Operator -> Selection, Crossover, Mutation
5. Replacement

1. Chromosome Encoding

เป็นขั้นตอนในการแปลงปัญหาให้เป็น Chromosome หรือพูดง่ายๆคือ รูปแบบหรือรูปร่างของข้อมูลของปัญหานั้นๆ
เช่น ปัญหา Binary Encoding จะมีลักษณะของ Chromosome เป็นดังนี้
1001 1011
นิยามให้มันมี 0 หรือ 1 และมียีนในแต่ละ  Chromosome ทั้งหมด 8 ตัว

2. Initial Population

คือการ สร้างประชากรขึ้นมาโดยการสุ่มสร้างหรือสุ่มเลือกขึ้นมา และการสร้างจำนวนประชากร(จำนวน Chromosome) จะเป็น Parameter ของ Algorithm
เช่น เราจะสร้างประชากรขึ้นมา 4 Chromosome โดยการสุ่มเลข 0 , 1 เข้าไปใน Chromosome
A: 0110 0100
B: 0010 1011
C: 1110 1101
D: 1101 1001

3. Fitness Function

คือสิ่งที่จะใช้ในการการประเมินค่าความเหมาะสม หรือ คะแนนของประชากรนั้นๆ เพื่อใช้ในการพิจารณาว่า โครโมโซมตัวนั้น เหมาะหรือไม่ที่จะนำมาใช้สืบทอดพันธุกรรมสำหรับสร้างโครโมโซมรุ่มใหม่หรือไม่ โดยสมการหรือวิธีการในการคิดค่า Fitness นั้นขึ้นอยู่กับปัญหานั้นๆ
เช่น ในปัญหา Binary Encoding เราจะให้ Chromosome ที่มีเลข 1 จะนับเป็น 1 คะแนน
A: 0110 0100 = 3
B: 0010 1011 = 4
C: 1110 1101 = 6
D: 1101 1001 = 5

4. Genetic Operator

จะให้พูดง่ายๆในขั้นตอนนี้คือ เป็นวิธีปรับเปลี่ยนองค์ประกอบของ Chromosome ซึ้งจะแบ่งออกเป็น 3 ส่วนได้แก่
       1 Selection
          เพื่อให้เกิดการอยู่รอดของสิ่งมีชีวิต จึงต้องทำการคัดเลือกประชากรบางส่วนเพื่อใช้ในการสืบทอดในรุ่นถัดไป ซึ้งในที่นี้คือการคัดเลือก Chromosome ที่จะใช้ในการทำขั้นตอน Genetic ในขั้นตอนถัดไป โดยวิธีการคัดเลือกนั้นก็มีมากมายหลายอย่าง เช่น
   - Roulette Wheel
   - Ranking
   - Tournament
   - Elitist
   - Steady State
   เป็นต้น
โดยปัญหา Binary Encoding นั้นเราจะใช้วิธีการคัดเลือกทั้งหมด (ง่ายดี) และสำหรับการ Crossover จะใช้ค่า Fitness ที่ดีที่สุดผสมกัน

        2 Crossover
           เป็นกระบวนการในการนำ 2 Chromosome มาผสมกันกันเพื่อให้ได้ Chromosome ใหม่ๆเกิดขึ้น
และสำหรับ ปัญหา Binary Encoding เราจะใช้วิธีที่ง่ายที่สุดคือ แบ่งครึ่ง Chromosome ระหว่าง 2 Chromosome และนำมาผสมกัน
C: 1110 1101 = 6
D: 1101 1001 = 5
B: 0010 1011 = 4
A: 0110 0100 = 3
ดังนั้น  C กับ D , A กับ B จะ Crossover กัน

C' : 1110 / 1001
D' : 1101 / 1101
B' : 0010 / 0100
A' : 0110 / 1011
       3 Mutation
          คือการทำการเปลี่ยนแปลงคุณลักษณะภายใน Chromosome ในบางตำแหน่งของรุ่นลูกเพื่อให้เกิดลักษณะใหม่ๆเกิดขึ้น เช่น จากตัวอย่าง ในตำแหน่งยีนที่ 7 สิ่งใดมีค่าเป็น 0 ให้เปลี่ยนเป็น 1 ทั้งหมด
C' : 1110 / 1011
D' : 1101 / 1111
B' : 0010 / 0110
A' : 0110 / 1011
5. Replacement
หรือการแทนที่ประชากรรุ่นเก่า ซึ้งวิธีการแทนที่ก็มีหลายหลายรูปแบบมากมาย ไม่ว่าจะเป็นการแทนที่ประชากรรุ่นเก่าทั้งหมด หรือการแทนที่ประชากรเฉพาะบางประชากรเท่านั้นโดยมีวิธีเลือกจากค่า Fitness หรือ ประชากรที่ถูกคัดเลือกจาก Selection แล้ว copy ประชากรที่ไม่ได้ถูกเลือก Selection มาเป็นรุ่นถัดไป บลาๆๆๆๆๆๆๆๆ มากมาย



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

ทั้งหมดนี้คือ Genetic Algorithm ขั้นพื้นฐานเท่านั้น ซึ้งเป็น Algorithm ที่ใช้ศิลปะในการทำอีกมากมาย ซึ้งมันทำให้ผมรู้สึกสนุกนั้นเอง ... ผิดพลาดประการก็ขออภัยมา ณ ที่นี้ด้วยครับ หรือมีอะไรเพิ่มเติมก็ comment มาด้านล่างได้เลยครับ