ITKMITL PHP Competition

สำหรับบล็อควันนี้ @Fantasier request มาครับว่าอยากให้ blog เกี่ยวกับการแข่ง PHP ในงาน openhouse ที่คณะ IT ลาดกระบัง

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

มาถึงโจทย์นะครับ โจทย์นี้จะประกาศเมื่อเริ่มแข่ง ผมเลยต้อง skim อ่านอย่างไวได้ความประมาณว่าแพนด้าอยากคุยกัน เลยให้ทำ Panda chat lnw โดยมีแชทรูทต่างๆ ให้เข้าไปแชทได้ จะต้องมีการแสดง user online มีระบบกรองคำหยาบและ emoticon

แข่งอันนี้ดีอย่างครับ เค้าจะมีภาพกราฟฟิคต่างๆ ให้เลย คือไม่ต้องไปนั่งทำเองเหมาะสำหรับคนทำกราฟฟิคไม่เก่งแบบผม ให้ใช้เวลาโฟกัสกับโค้ดได้เลย

สำหรับชั่วโมงแรกนะครับ ผมปั่น register ก่อนเป็นอย่างแรก​โดยออกแบบฐานข้อมูลตามโจทย์ให้มาเป๊ะ แล้วก็ form ตามโจทย์เลย แต่โค้ดสำหรับการสมัครนี่สิครับนั่งเขียนยาวมาก โดยทำ design ที่ว่าไปก่อนนี้ประมาณ 20 นาทีส่วนอีก 40 นาทีเป็นโค้ดสมัครครับ โดยจะต้องมี input validation แทบทุกช่อง และผมเองลืม print regular expression มา​​ ฉะนั้นเดาสดครับ ก็โชคดึว่ามันไม่ค่อยบั๊กเลยสามารถเสร็จได้ทัน ส่วนการ login นั้นแค่ดึงมาเช็คอยู่แล้วครับเขียนไม่นาน และการตรวจสอบ user ผมจะแยกเป็น function ไว้อยู่แล้ว ซึ่งจะเขียนเป็นลำดับแรกๆ (แนวนี้ผมได้ไอเดียจากฟังก์ชั่น is_user_logged_in ของ WordPress ครับ และ project Sora เองก็มีฟังค์ชั่นนี้)

ต่อมาครับเป็นรายการแชท ถึงตรงนี้ผมเองว่าน่าจะเริ่มออกแบบฐานข้อมูลได้แล้ว เลยทำทีเดียวให้เสร็จครับ บังเอิญว่าโจทย์ตรงกับแชทที่ผมเคยทำมาก่อน เลยออกแบบตามของ bd2.in.th อันเก่าไปเลย (อันเก่าผมเขียนด้วยอารมณ์โมโหครับ ทำเสร็จในวันเดียวได้ แต่เห็นโจทย์วันนี้ตอนแรกผมเองยังว่าไม่น่าจะเสร็จทัน AJAX) ก็จะมีตารางสำหรับเก็บห้องแชท เก็บข้อความในแชท เก็บ user online ครับ เสร็จแล้วการ list ก็ไม่ยากครับดึงมาใส่ตัวแปร แล้วผมจะแยกส่วนของ template (view) ไปอีกไฟล์เลย (คือแยก view-controller ชัดเจน ส่วนถ้าจะมี model ใน PHP layer คงไม่ทันครับ)

ถัดมาของห้องแชทครับ ตรงนี้ผมก็ทำ layout ให้เสร็จก่อน จากนั้นจึงเริ่มที๋โค้ด ผมตัดสินใจว่าจะไม่ gratefully degrade (project sora ถ้าปิด javascript จะเห็นข้อความเก่าแต่ทำอะไรไม่ได้ครับ) แต่จะดึงข้อความด้วย javascript 100% เลย (คือถ้าปิด javascript จะไม่เห็นข้อความ) จากนั้นก็เขียน chat server ขึ้นมาครับ โดยเป็นไฟล์ที่จะไปเรียกเอารายการแชทล่าสุดมาทำ JSON ให้แล้วส่งกลับ จากนั้น JavaScript จะหาว่า ID ล่าสุดที่เคยประมวลผลไปคือเลขอะไร แล้วก็จะไม่ประมวลผล ID ที่น้อยกว่าเลขนั้นทำให้ข้อความไม่ซ้ำถึง server จะส่งมาซ้ำ ต่อมาครับก็จะเป็นการส่ง ส่งไปแล้วจริงๆถ้าให้ไวมันจะต้องคืนข้อความมาให้เราประมวลผลใน client ได้ครับ แต่ด้วยความขี้เกียจผมเลยไม่คืนอะไรมา แล้วให้ client ดึงแชทใหม่อีกรอบไปเลย จบ

ถึงตรงนี้ได้ผมก็เหลือแต่ส่วนเดียวแล้วแหละครับ คือ user online ตรงนี้อัลกอรึธึมยาก ผมเชื่อว่ามีวิธีง่ายกว่านี้ (เพราะโจทย์กำหนด และแชทอื่นๆ เค้าทำได้) แต่ผมไม่รู้ครับ วิธีที่ผมใช้คือ client จะ poll server เป็นระยะ ตัว server จะเก็บเวลาที่ poll ไว้ แล้วคืนไปว่าใน 5 วิเนี่ยมีใครติดต่อมาบ้าง จากนั้น client จะเปรียบเทียบจากข้อมูลเก่ากับข้อมูลใหม่ว่ามีใครหายไปหรือเข้ามาบ้างครับแล้วก็จะทำการแสดงข้อความ (แชทของ bd2 อันเก่าใช้วิธีนี้ แต่จะวาด list ใหม่เลยไม่มีการถอด user ออกทีละคนได้ ส่วนแชทปัจจุบันวิธีเก็บ user online ซับซ้อนกว่านี้ครับเพราะใช้ websocket ไว้ถ้ามีโอกาสจะมาเล่า) แล้วก็สำหรับ user online ในหน้าแรกครับ บังเอิญนึกถึง GROUP BY ที่อยากเล่นอยู่ เลยลองเขียนไปดูว่า `SELECT room, COUNT(*) cnt FROM online WHERE room=1 AND time >= ‘time()-5’ GROUP BY room` แล้วมันก็ได้ผลครับ ทำให้มันดึงทีเดียวหลายห้องได้ใน query เดียว​ (bluewavechat ยังต้องนั่งดึงทีละเพลงเลยครับ)

ที่เหลือก็เก็บรายละเอียดครับ พวกกรองคำหยาบ และ emote และที่สำคัญมากคือเวลาอ่านแชทข้างบนอยู่มันจะไม่ autoscroll

สำหรับการ present นะครับ ผมพูดตาม slide ที่เตรียมไป กรรมการเองยังงงๆ กับเรื่อง salt ที่ผมเน้นย้ำด้วยแหละครับ (ผมรู้จัก salt จาก SMF น่ะครับ — กรรมการก็ถามเรื่องนี้) แล้วก็ที่โดนท้วงมาก็จะมี IE ที่ผมพลาดลืมเช็ค แล้วก็เรื่อง autoscroll บั๊กนิดหน่อยครับ นอกจากนี้ผมยังพูดเรื่อง WebSocket ที่เป็นชื่อทีมไปด้วยว่าถ้าได้ใช้แชทคงจะเจ๋งกว่านี้ (ถ้าทันเวลา) นะครับ เค้าก็เลยถามถึงเรื่องตรงนี้หน่อยซึ่งผมก็อธิบายแชทของ bd2.in.th ไปให้ฟัง

สำหรับผลการแข่งขัน ได้ที่ 1 ครับ ทุนการศึกษา 4,000 บาทและโควต้า งานนี้ต้องขอบคุณ bd2.in.th นี่แหละครับที่ทำให้ผมได้เขียนแชทสองตัวฝึกประสบการณ์

ปล. ผมว่าโจทย์มันเน้นที่ AJAX ไปนะครับ คือแชทที่เขียนไม่ใช้ AJAX นี่มันจะแบบว่าไม่เร้าใจเลยแล้ว present ไม่มัน มันมีอีกหลายๆ อย่างนะครับที่ไม่มี AJAX ก็ได้ บางอย่างใช้ AJAX แล้วมันจะเป็นส่วนเกินด้วยซ้ำ