मैं अपनी साइट पर उपयोग के लिए एक उपलब्धियों प्रणाली को डिजाइन करने का सबसे अच्छा तरीका सोच रहा हूं। डेटाबेस संरचना को 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
जो मूल रूप से यह देखने के लिए जांचता है कि क्या उपयोगकर्ता को पहले से ही उस बैज से सम्मानित किया गया है, यदि नहीं, तो बैजबीबी तालिका को अपडेट करेगा। बैज क्लास एक उपयोगकर्ता के लिए सभी बैज को पुनः प्राप्त करने और इसे एक सरणी में वापस करने आदि का ख्याल रखता है, आदि (ताकि बैज को उपयोगकर्ता प्रोफ़ाइल पर प्रदर्शित किया जा सके)
क्या होगा जब सिस्टम पहले से ही पहले से ही लाइव साइट पर लागू हो?
एक "क्रोन" नौकरी क्वेरी भी है जिसे प्रत्येक बैज में जोड़ा जा सकता है। इसका कारण यह है क्योंकि जब बैज सिस्टम बहुत पहले लागू किया जाता है और initilaised होता है, तो पहले से अर्जित किए जाने वाले बैज को अभी तक सम्मानित नहीं किया जाना चाहिए क्योंकि यह एक इवेंट आधारित सिस्टम है। इसलिए प्रत्येक बैज की मांग पर एक 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);
}
}
}
जैसा कि उपरोक्त क्रोन वर्ग मुख्य बैज क्लास का विस्तार करता है, यह तर्क फ़ंक्शन का फिर से उपयोग कर सकता है try_award
इसका कारण यह है कि मैं इसके लिए एक विशेष क्वेरी बनाता हूं, हालांकि हम पिछली घटनाओं को "अनुकरण" कर सकते हैं, अर्थात प्रत्येक उपयोगकर्ता पोस्ट के माध्यम से जा सकते हैं और घटना वर्ग को ट्रिगर कर सकते हैं जैसे $event->trigger()
यह बहुत धीमा होगा, विशेष रूप से कई बैज के लिए। इसलिए हम इसके बजाय एक अनुकूलित क्वेरी बनाते हैं।
उपयोगकर्ता को क्या पुरस्कार मिलता है ईवेंट के आधार पर अन्य उपयोगकर्ताओं को पुरस्कृत करने के बारे में
Badge
वर्ग award
समारोह पर काम करता है user_id
- वे हमेशा पुरस्कार दिया जाएगा। डिफ़ॉल्ट रूप से बैज उस व्यक्ति को प्रदान किया जाता है जिसने इस घटना को घटित किया है अर्थात सत्र उपयोगकर्ता आईडी (यह default_event
फ़ंक्शन के लिए सही है , हालांकि CRON जॉब स्पष्ट रूप से सभी उपयोगकर्ताओं और पुरस्कारों को अलग करता है)
तो चलो एक उदाहरण लेते हैं, एक कोडिंग चुनौती वेबसाइट पर उपयोगकर्ता अपनी कोडिंग प्रविष्टि प्रस्तुत करते हैं। व्यवस्थापक तब प्रविष्टियों का न्याय करता है और जब पूरा हो जाता है, तो सभी को देखने के लिए चुनौती पृष्ठ पर परिणाम पोस्ट करता है। जब ऐसा होता है, तो एक POSTED_RESULTS ईवेंट कहलाता है।
यदि आप पोस्ट की गई सभी प्रविष्टियों के लिए उपयोगकर्ताओं के लिए बैज प्रदान करना चाहते हैं, तो वे कहते हैं, यदि उन्हें शीर्ष 5 में स्थान दिया गया है, तो आपको क्रॉन जॉब का उपयोग करना चाहिए (हालांकि यह ध्यान में रखते हुए यह सभी उपयोगकर्ताओं के लिए अपडेट होगा, न कि केवल उस चुनौती के लिए परिणाम के लिए पोस्ट किया गया)
यदि आप क्रोन जॉब के साथ अपडेट करने के लिए अधिक विशिष्ट क्षेत्र को लक्षित करना चाहते हैं, तो आइए देखें कि क्या क्रोन जॉब ऑब्जेक्ट में फ़िल्टरिंग मापदंडों को जोड़ने का एक तरीका है, और उनका उपयोग करने के लिए 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);
}
}
यदि पैरामीटर की आपूर्ति नहीं की जाती है, तब भी क्रॉन फ़ंक्शन काम करेगा।