เทอมนี้ผมได้รับมอบหมายให้สอนวิชา Introduction to Computers and Programming ซึ่งเป็นวิชาพื้นฐานสำหรับนักศึกษาชั้นปีที่ 1 ทุกโปรแกรม มีนักศึกษาลงทะเบียนจำนวนมาก อย่างเทอมนี้ก็มีเกือบ 300 คน เนื้อหาหลักก็คือสอนการเขียนโปรแกรมภาษา C กับอัลกอริทึมพื้นฐาน (อย่างเช่น searching และ sorting) แต่การเขียนโปรแกรมเป็นทักษะที่ต้องฝึกฝนบ่อยๆ จึงทำเข้าใจและทำได้ วิชาก็เลยมีทั้งบรรยาย ปฏิบัติการ และการบ้าน (ปีนี้ดีหน่อยที่สามารถหาคนมาช่วยตรวจการบ้านได้)
เมื่อมีการบ้านให้คะแนนแล้ว ผมก็อยากจะให้ทำการบ้านกันจริงๆ (อย่างน้อยก็ควรจะได้สัมผัสและฝึกฝนด้วยตนเอง) เลยจะต้องหาทางตรวจว่าลอกการบ้านกันบ้างหรือเปล่า แต่การบ้านแรกคำถามจะค่อนข้างง่ายมาก ไม่สามารถพลิกแพลงหรือเขียนโปรแกรมแบบที่แตกต่างกันมากนัก (ส่วนใหญ่จะฝึกการเขียน expression ตามสูตรที่กำหนดให้) ก็เลยตรวจการลอกข้อสอบแบบง่ายๆ ก่อน (การบ้านครั้งต่อไปค่อยขยับขยายความซับซ้อนในการตรวจจับให้เพิ่มขึ้น) คือ ตรวจแค่ว่าส่งไฟล์เดียวกันมาหรือเปล่า ในที่นี้แปลว่าเอาไฟล์มาจากเพื่อนแล้วก็ upload ส่งมาให้เลยโดยไม่แตะต้องใดๆ ทั้งสิ้น
เมื่อจะตรวจแบบพื้นๆ ผมก็แค่ใช้ hash function มาสร้าง message digest จากไฟล์ที่นักศึกษาส่งมา ถ้าไฟล์ไหนมี message digest เหมือนกัน ก็แปลว่าลอกกันมาทั้งไฟล์ จะไปได้หักคะแนนถูก การหาค่า message digest ของไฟล์การบ้านทั้งหมด ก็ใช้คำสั่ง find ของ unix
$ cd assignment1
$ find . -name "*" -not -type d -exec shasum '{}' \; | sort > digest_list.txt
คำสั่ง find ใช้หาชื่อไฟล์ตามเงื่อนไขที่กำหนด ในที่นี้คือเอาทุกไฟล์ ยกเว้นไดเรคทอรี เมื่อได้ไฟล์แล้ว เราก็สามารถสั่งให้รันโปรแกรม shasum โดย ‘{}’ จะถูกแทนด้วยชื่อไฟล์ที่ค้นเจอแต่ละไฟล์ จากนั้นก็เอาไปเรียงลำดับเพื่อให้ไฟล์ที่มี digest เหมือนกันอยู่ติดกัน เก็บลงไฟล์ digest_list.txt ที่เหลือก็แค่เขียนโปรแกรมจับกลุ่มว่าไฟล์ที่เหมือนกันมีใครบ้าง จัดเป็นกลุ่มก็เรียบร้อย
Tags: plagiarism, programming, unix
ผมรู้สึกว่าการกรอกคะแนนนักศึกษาเป็นเรื่องยุ่งยาก โดยเฉพาะคะแนนการบ้านกับควิซ ที่เก็บมาแบบไม่ได้เรียงตามลำดับรหัสนักศึกษา ไม่รู้ว่าอาจารย์คนอื่นเขาทำกันยังไง (โดยเฉพาะวิชาที่สอนกัน 200-300 คน) เดิมผมมักจะเอากระดาษมาเรียงตามรหัสนักศึกษา แล้วค่อยไล่กรอกลง spreadsheet แต่มันก็ยุ่งยาก ขี้เกียจอีก
ความขี้เกียจนี้ส่งผลให้ผมไม่ค่อยได้คืนควิชหรือการบ้านกลับให้นักศึกษา แล้วก็จะมาหัวหมุนเอาตอนปลายเทอม เพราะต้องกรอกทุกอย่างให้เสร็จก่อนจะตัดเกรด
วันก่อนก็เลยเขียนโปรแกรมเล็กๆ เอาไว้กรอกคะแนนควิซโดยเฉพาะ ฟีเจอร์หลักๆ ที่ต้องการก็คือ อยากใส่แค่รหัสนักศึกษาบางส่วน (3-4 ตัวก็พอ) ถ้าไม่ซ้ำก็กรอกคะแนนไปได้เลย ถ้าซ้ำก็แสดงตัวเลือกให้หน่อย แล้วค่อยกรอกคะแนน ตอนแรกก็อยากจะทำเป็น GUI สวยงาม มี textbox ให้กรอกรหัส แล้วจะแสดงตัวเลือกเหมือนพวก autocomplete อะไรทำนองนั้น แต่ก็ดูยุ่งยาก ขี้เกียจอีก (จะเห็นว่าขี้เกียจกันทุกขั้นตอน) แต่สุดท้ายเลยได้โปรแกรม python แบบ command-line มาอันหนึ่ง รับข้อมูลเป็น text file มีแต่รหัสนักศึกษา ใช้ regular expression สำหรับเทียบรหัสกรอกเข้ามา แล้วก็ให้เลือกได้ ถ้ามีรหัสตรงหลายอัน จากนั้นก็กรอกคะแนนลงไปได้ เรียบร้อย ใช้ได้ดี ตามข้างล่างนี้ (แต่ไม่รับประกันความผิดพลาดถ้าจะเอาไปใช้ เพราะขี้เกียจเช็ค input error บางกรณีอีก) โปรดลองใช้กันได้ตามอัตภาพ ![]()
(more…)
Tags: input, python, score, teaching. programming
หลังจากงานราษฎร์ งานหลวง และโรคภัยไข้เจ็บรุมเร้า วันนี้มาเพิ่มคำศัพท์ภาษาญี่ปุ่นเกี่ยวกับคอมพิวเตอร์ ต่ออีกหน่อยดีกว่า วันนี้ว่าด้วยฮาร์ดแวร์ทั้งหลาย และศัพท์เกี่ยวข้องที่ @wittawatj แนะนำไว้
Tags: คอมพิวเตอร์, ภาษาญี่ปุ่น, japanese
ด้วยความที่อยากให้นักศึกษามีส่วนร่วมในการเรียนมากขึ้น เทอมนี้เลยพยายามเรียกนักศึกษาให้ช่วยตอบคำถาม หรือออกมาทำอะไรเล่นหน้าห้อง อย่างน้อยจะได้หลับกันน้อยลง หรือพยายามทำแบบฝึกหัดที่ให้ในห้องเรียนบ้าง แต่จะให้เลือกชื่อก็จำชื่อนักศึกษาทั้งหมดไม่ได้ แถมอาจจะเรียกบางคนซ้ำ หรือไม่ได้เรียกบางคนเลย เมื่อวานพอมีเวลาว่างอยู่บ้าง เลยนั่งเขียนโปรแกรม Java เล็กๆ ขึ้นมาหนึ่งตัว เอาไว้สำหรับสุ่มชื่อนักศึกษาในชั้นเรียน ตอนแรกก็กะจะทำเป็นโปรแกรมง่ายๆ คือแค่เปิดไฟล์อ่านชื่อนักศึกษามา แล้วก็แค่สุ่ม แต่ถ้าทำอย่างนั้นก็มีโอกาสที่บางคนจะโดนซ้ำ หรือสุ่มไม่ทั่วถึง
เพื่อเผื่อแผ่ให้ทุกคนถูกเรียกกันอย่างทั่วถึง เลยปรับการสุ่มนิดหน่อย โดยเก็บจำนวนครั้งที่นักศึกษาแต่ละคนถูกเรียกไว้ ถ้าโดนเรียกแล้วหนึ่งครั้ง ก็จะกำหนดโอกาสที่จะถูกสุ่มขึ้นมาอีกให้เป็น 1/2 ของเพื่อนที่ยังไม่เคยโดนเรียก ถ้าโดนสองครั้งก็จะลดไปอีกให้เหลือ 1/4 ของเพื่อนๆ คือให้เป็น 1/(2^n) เมื่อ n เป็นจำนวนครั้งที่ถูกเรียก เสร็จแล้วก็มานึกอีกว่าบางคนอาจจะโดนเรียกแล้วไม่อยู่ อย่ากระนั้นเลยจะต้องเก็บข้อมูลไว้หน่อยว่าคนนี้โดดเรียน เลยทำปุ่มให้กดได้ด้วยว่าโดดไปแล้วกี่ครั้ง (ไม่รู้เก็บไว้ทำไมเหมือนกัน)
สุดท้ายได้โปรแกรมออกมาหน้าตาแบบนี้
ถ้าใครสนใจลองโหลดไปเล่นได้ที่นี่ วิธีใช้ก็คือเตรียม text file ใส่ชื่อนักศึกษาบรรทัดละคน เขียน ID ก่อน แล้วค่อยตามด้วยชื่อ คั่นด้วย TAB อาจจะใส่จำนวนครั้งที่เรียกนักศึกษาไปแล้วด้วยก็ได้ คั่นด้วย TAB เหมือนกัน
ส่วนโค้ด ถ้าใครอยากได้ก็ขอมาล่ะกันครับ มันค่อนข้างเละเทะ ไม่อยากเผย อายครับ
ถ้ามีเวลาบ้าอีก ก็อาจจะเพิ่มฟีเจอร์อื่นๆ ไปด้วย
Tags: programming, teaching
เวลาผมให้นักศึกษาทำการบ้านเขียนโปรแกรม ผมมักจะให้ส่งการบ้านทางเมล เพราะคิดว่าสะดวกที่จะตรวจทางเมลมากกว่า จะทดสอบด้วยการรันโปรแกรมที่ส่งมาก็ได้ รวมทั้งยังสามารถใช้เครื่องมือต่างๆ ในการตรวจจับความคล้ายของโปรแกรมในกรณีที่ลอกกันมาได้อีกด้วย แต่ประสบการณ์ที่ผ่านมา จะพบปัญหาต่างๆ ที่ทำให้ผมไม่อยากตรวจการบ้าน ก็คือ เมลที่แต่ละคนส่งมา จะมีรูปแบบหลากหลาย ไม่ค่อยตรงกับที่กำหนดให้ เช่น ไม่ตั้งชื่อไฟล์ตามที่กำหนด บางคนก็ใช้โปรแกรมบีบอัดแบบแปลกๆ มาให้ บางทีบอกให้ส่งเป็น plain text ก็จะมีคนเขียนใน MS Word แล้วเปลี่ยน extension เป็น .txt จนอ่านไม่ออก หรือกำหนดให้ส่งเป็น .jar แต่ไม่รู้ยังไงใช้ WinRAR ทำเป็น .rar แล้วเปลี่ยน extension เป็น .jar เฉยเลย สุดท้ายผมจะต้องมานั่งไล่เช็คไล่เก็บไฟล์ทีละฉบับ บางคนยังส่งมาหลายที แถมยังมีการใช้แอดเดรสเดียวกัน ส่งการบ้านหลายชุดแทนเพื่อนอีก ทำให้สับสนได้ง่ายมาก และเนื่องจากผมจะต้องสอนนักศึกษาไม่น้อยกว่า 70-80 คน จึงเสียเวลาไปกับเรื่องนี้เยอะมาก จนพาลไม่ค่อยจะอยากตรวจสักเท่าไหร่
เมื่อวานเลยนั่งคิดว่าจะทำยังไงกับการบ้านในเทอมที่จะถึงนี้ดี จะทำเป็นเว็บให้อัพโหลดไฟล์ ก็ขี้เกียจเขียนเว็บ สุดท้ายจึงตัดสินใจจะใช้เมลเหมือนเดิม แล้วไปเขียนสคริปต์ด้วย fetchmail กับ procmail หรือไม่ก็ maildrop เพื่อคัดแยกเมลที่ส่งมา ไปไว้ในไดเรคทอรีที่กำหนด แยก attachment ออกจากเมล โดยอาจจะใช้ Perl หรือไม่ก็โปรแกรม ripMime พร้อมทั้งตอบเมลกลับแบบอัตโนมัติว่าได้รับการบ้านแล้ว (ในกรณีที่ส่งมาถูกตามที่กำหนด) สุดท้ายหวังว่าจะช่วยให้จัดการกับการบ้านทางเมลได้สบายขึ้น แต่วิธีการทั้งหมดก็จะยังไม่สามารถจัดการกับกรณีที่ส่งไฟล์มาผิดประเภทได้ แต่ไม่เป็นไรเพราะมีคนแนะนำวิธีจัดการมาให้แล้ว ก็คือไม่ต้องตรวจให้ 0 ไปเลย คนแนะนำรับรองว่าแค่ทำเพียงครั้งเดียวก็จะส่งถูกต้องทุกคน จริงๆ แล้วยังไม่ได้เขียนสคริปต์ทั้งหมดหรอก แต่จะเอามาเล่าเรื่อยๆ วันนี้เล่าถึง fetchmail ก่อนล่ะกัน
โปรแกรม fetchmail เป็นโปรแกรมสำหรับดึงเมลจากเซิร์ฟเวอร์ (จะเป็นแบบ POP3 หรือ IMAP ก็ได้) มาไว้ที่เครื่องของเรา การทำงานของมัน ก็จะคล้ายๆ โปรแกรมอ่านเมลทั่วไป เพียงแต่ว่าเป็นแบบ command line ที่ให้โหลดเป็นครั้งๆ ไป และอาจจะกำหนดให้ทำงานเป็น daemon คอยเช็คและโหลดอยู่ตลอดเวลาได้ด้วย การใช้งานก็ง่ายมาก แค่กำหนดข้อมูลเซิร์ฟเวอร์ที่จะไปโหลดไว้ในไฟล์ .fetchmailrc เช่น
set daemon 300 poll mail.mydomain.com protocol pop3 user "myname" password "mypassword" mimedecode mda "/usr/bin/maildrop" no keep fetchall
จะเป็นกำหนดให้อ่านเมลทั้งหมดจากเซิร์ฟเวอร์ด้วยโปรโตคอล pop3 ตามที่กำหนด จากนั้นส่งเมลที่ได้ทีละฉบับไปยังโปรแกรม maildrop ซึ่งเราจะสามารถกำหนด regular expression สำหรับคัดแยกเมลได้ ทีนี้จะเขียนวิธีการคัดแยกทำยังไงเอาไว้ต่อคราวหน้าล่ะกัน
Tags: assignment, fetchmail, linux, teaching, unix