내 사이트에서 사용할 성과 시스템을 디자인하는 가장 좋은 방법을 생각하고 있습니다. 데이터베이스 구조는 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
기본적으로 사용자가 이미 해당 배지를 받았는지 확인 하는 확장 클래스에서 나옵니다 . 그렇지 않은 경우 배지 db 테이블을 업데이트합니다. 배지 클래스는 또한 사용자의 모든 배지를 검색하고 배열로 반환하는 등의 작업을 처리합니다 (예 : 사용자 프로필에 배지를 표시 할 수 있음).
이미 라이브 사이트에서 시스템이 처음 구현되는 경우는 어떻습니까?
각 배지에 추가 할 수있는 "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 클래스는 main badge 클래스를 확장하므로 논리 함수를 재사용 할 수 있습니다. try_award
이에 대한 특수 쿼리를 생성하는 이유는 이전 이벤트를 "시뮬레이션"할 수 있기 때문입니다. 즉, 모든 사용자 게시물을 $event->trigger()
살펴보고 특히 많은 배지에 대해 매우 느린 것처럼 이벤트 클래스를 트리거 할 수 있기 때문입니다. 따라서 대신 최적화 된 쿼리를 만듭니다.
어떤 사용자가 상을 받습니까? 이벤트를 기반으로 다른 사용자 에게 수여하는 모든 것
Badge
클래스 award
기능에 역할 user_id
- 그들은 항상 상을 받게됩니다. (이것은 마찬가지입니다 기본적으로 배지 즉에게 세션 사용자 ID 발생하는 경우 발생하는 사람에게 수여된다 default_event
크론 작업은 분명히 모든 사용자와 상 별도의 사용자 통해 루프하지만, 기능)
따라서 사용자가 코딩 항목을 제출하는 코딩 챌린지 웹 사이트에서 예를 들어 보겠습니다. 그런 다음 관리자는 항목을 판단하고 완료되면 모든 사람이 볼 수 있도록 챌린지 페이지에 결과를 게시합니다. 이 경우 POSTED_RESULTS 이벤트가 호출됩니다.
게시 된 모든 항목에 대해 사용자에게 배지를 부여하고 싶다면, 예를 들어 상위 5 위 안에 들었다면 크론 작업을 사용해야합니다. 결과가 게시되었습니다)
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 기능은 매개 변수가 제공되지 않은 경우에도 계속 작동합니다.