ฉันกำลังคิดหาวิธีที่ดีที่สุดในการออกแบบระบบรางวัลพิเศษสำหรับใช้บนไซต์ของฉัน โครงสร้างฐานข้อมูลสามารถพบได้ในวิธีที่ดีที่สุดในการบอกระเบียนติดต่อกัน 3 รายการขึ้นไปที่ขาดหายไปและเธรดนี้เป็นส่วนเสริมในการรับแนวคิดจากนักพัฒนา
ปัญหาที่ฉันมีจากการพูดคุยมากมายเกี่ยวกับระบบตรา / รางวัลพิเศษบนเว็บไซต์นี้มีเพียงแค่นั้น - ทั้งหมดนี้เป็นการพูดคุยและไม่มีรหัส ตัวอย่างการติดตั้งโค้ดจริงอยู่ที่ไหน
ฉันเสนอการออกแบบที่ฉันหวังว่าผู้คนจะมีส่วนร่วมและหวังว่าจะสร้างการออกแบบที่ดีสำหรับการเข้ารหัสระบบความสำเร็จที่ขยายได้ ฉันไม่ได้บอกว่านี่เป็นสิ่งที่ดีที่สุดไกลจากมัน แต่มันเป็นช่วงเริ่มต้นที่เป็นไปได้
โปรดอย่าลังเลที่จะให้ความคิดของคุณ
แนวคิดการออกแบบระบบของฉัน
ดูเหมือนว่าฉันทามติทั่วไปคือการสร้าง "ระบบตามเหตุการณ์" - เมื่อใดก็ตามที่เหตุการณ์ที่ทราบเกิดขึ้นเช่นมีการสร้างโพสต์ลบ ฯลฯ จะเรียกคลาสเหตุการณ์เช่นนั้น ..
$event->trigger('POST_CREATED', array('id' => 8));
จากนั้นคลาสกิจกรรมจะค้นหาว่าป้ายใด "กำลังฟัง" สำหรับกิจกรรมนี้จากนั้นจึงเป็นrequires
ไฟล์นั้นและสร้างอินสแตนซ์ของคลาสนั้นดังนี้:
require '/badges/' . $file;
$badge = new $class;
จากนั้นจะเรียกเหตุการณ์เริ่มต้นที่ส่งผ่านข้อมูลที่ได้รับเมื่อtrigger
ถูกเรียก
$badge->default_event($data);
ป้าย
นี่คือที่ที่เวทมนตร์ที่แท้จริงเกิดขึ้น ป้ายแต่ละป้ายมีคำถาม / ตรรกะของตัวเองเพื่อพิจารณาว่าควรได้รับป้ายหรือไม่ แต่ละป้ายกำหนดไว้ในรูปแบบเช่นนี้:
class Badge_Name extends Badge
{
const _BADGE_500 = 'POST_500';
const _BADGE_300 = 'POST_300';
const _BADGE_100 = 'POST_100';
function get_user_post_count()
{
$escaped_user_id = mysql_real_escape_string($this->user_id);
$r = mysql_query("SELECT COUNT(*) FROM posts
WHERE userid='$escaped_user_id'");
if ($row = mysql_fetch_row($r))
{
return $row[0];
}
return 0;
}
function default_event($data)
{
$post_count = $this->get_user_post_count();
$this->try_award($post_count);
}
function try_award($post_count)
{
if ($post_count > 500)
{
$this->award(self::_BADGE_500);
}
else if ($post_count > 300)
{
$this->award(self::_BADGE_300);
}
else if ($post_count > 100)
{
$this->award(self::_BADGE_100);
}
}
}
award
ฟังก์ชันมาจากคลาสเพิ่มเติมBadge
ซึ่งโดยทั่วไปจะตรวจสอบเพื่อดูว่าผู้ใช้ได้รับตรานั้นแล้วหรือไม่หากไม่ได้รับการอัปเดตตารางฐานข้อมูลตรา คลาสตรายังดูแลการเรียกคืนตราทั้งหมดสำหรับผู้ใช้และส่งคืนในอาร์เรย์ ฯลฯ (ดังนั้นตราสามารถแสดงบนโปรไฟล์ผู้ใช้)
แล้วระบบจะถูกนำไปใช้งานครั้งแรกในเว็บไซต์ที่ใช้งานอยู่แล้วล่ะ?
นอกจากนี้ยังมีข้อความค้นหางาน "cron" ที่สามารถเพิ่มลงในแต่ละป้าย สาเหตุที่เป็นเช่นนี้เนื่องจากเมื่อระบบตราสัญลักษณ์ถูกนำมาใช้และเริ่มต้นเป็นครั้งแรกป้ายที่ควรได้รับแล้วยังไม่ได้รับรางวัลเนื่องจากเป็นระบบตามเหตุการณ์ ดังนั้นงาน CRON จึงถูกเรียกใช้ตามความต้องการสำหรับแต่ละป้ายเพื่อให้รางวัลสิ่งที่จำเป็นต้องมี ตัวอย่างเช่นงาน CRON สำหรับข้างต้นจะมีลักษณะดังนี้:
class Badge_Name_Cron extends Badge_Name
{
function cron_job()
{
$r = mysql_query('SELECT COUNT(*) as post_count, user_id FROM posts');
while ($obj = mysql_fetch_object($r))
{
$this->user_id = $obj->user_id; //make sure we're operating on the right user
$this->try_award($obj->post_count);
}
}
}
เนื่องจากคลาส cron ด้านบนขยายคลาสตราหลักจึงสามารถใช้ฟังก์ชันลอจิกซ้ำได้ try_award
เหตุผลที่ฉันสร้างคำค้นหาพิเศษสำหรับสิ่งนี้คือแม้ว่าเราจะ "จำลอง" เหตุการณ์ก่อนหน้านี้ได้กล่าวคืออ่านโพสต์ของผู้ใช้ทุกคนและเรียกใช้คลาสเหตุการณ์เหมือน$event->trigger()
ว่ามันจะช้ามาก ดังนั้นเราจึงสร้างแบบสอบถามที่ปรับให้เหมาะสมแทน
ผู้ใช้รายใดได้รับรางวัล ทั้งหมดเกี่ยวกับการให้รางวัลผู้ใช้รายอื่นตามเหตุการณ์
Badge
ระดับaward
ฟังก์ชั่นทำหน้าที่เกี่ยวกับuser_id
- พวกเขามักจะได้รับรางวัล โดยค่าเริ่มต้นป้ายจะมอบให้กับผู้ที่ทำให้เหตุการณ์เกิดขึ้นเช่นรหัสผู้ใช้เซสชัน (ซึ่งเป็นจริงสำหรับdefault_event
ฟังก์ชันแม้ว่างาน CRON จะวนซ้ำผู้ใช้ทั้งหมดและให้รางวัลผู้ใช้ที่แยกจากกัน)
ลองมาดูตัวอย่างเกี่ยวกับความท้าทายในการเข้ารหัสผู้ใช้เว็บไซต์ส่งรายการการเข้ารหัสของตน จากนั้นผู้ดูแลระบบจะตัดสินผลงานและเมื่อทำเสร็จแล้วให้โพสต์ผลการแข่งขันในหน้าท้าทายเพื่อให้ทุกคนได้เห็น เมื่อเกิดเหตุการณ์นี้จะมีการเรียกเหตุการณ์ POSTED_RESULTS
หากคุณต้องการมอบป้ายสำหรับผู้ใช้สำหรับรายการทั้งหมดที่โพสต์สมมติว่าหากพวกเขาได้รับการจัดอันดับให้อยู่ใน 5 อันดับแรกคุณควรใช้งาน cron (แม้ว่าจะไม่คำนึงถึงสิ่งนี้จะอัปเดตสำหรับผู้ใช้ทุกคนไม่ใช่เฉพาะสำหรับความท้าทายนั้น ผลลัพธ์ถูกโพสต์สำหรับ)
หากคุณต้องการกำหนดเป้าหมายพื้นที่ที่เจาะจงมากขึ้นเพื่ออัปเดตด้วยงาน cron ลองดูว่ามีวิธีเพิ่มพารามิเตอร์การกรองลงในอ็อบเจ็กต์งาน cron หรือไม่และรับฟังก์ชัน cron_job เพื่อใช้งาน ตัวอย่างเช่น:
class Badge_Top5 extends Badge
{
const _BADGE_NAME = 'top5';
function try_award($position)
{
if ($position <= 5)
{
$this->award(self::_BADGE_NAME);
}
}
}
class Badge_Top5_Cron extends Badge_Top5
{
function cron_job($challenge_id = 0)
{
$where = '';
if ($challenge_id)
{
$escaped_challenge_id = mysql_real_escape_string($challenge_id);
$where = "WHERE challenge_id = '$escaped_challenge_id'";
}
$r = mysql_query("SELECT position, user_id
FROM challenge_entries
$where");
while ($obj = mysql_fetch_object($r))
{
$this->user_id = $obj->user_id; //award the correct user!
$this->try_award($obj->position);
}
}
ฟังก์ชัน cron จะยังคงทำงานแม้ว่าจะไม่ได้ระบุพารามิเตอร์ก็ตาม