programing

실적 시스템을 코드화하는 최선의 방법

kingscode 2022. 10. 1. 21:16
반응형

실적 시스템을 코드화하는 최선의 방법

사이트에서 사용하는 성과 시스템을 설계할 수 있는 최선의 방법을 생각하고 있습니다.데이터베이스 구조는 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을 할 수 .try_award

하는 이유는 수 예를 "시뮬레이션 수 .$event->trigger()특히 많은 배지의 경우 매우 느릴 것입니다.대신 최적화된 쿼리를 만듭니다.

어떤 사용자가 상을 받을까요?이벤트에 따라 다른 사용자에게 부여하기 위한 모든 것

Badge ★★★awarduser_id을 사용하다으로는 이 를 발생시킨 ID는 " 사용자 ID"에 해당됩니다).default_event 작업이 모든 합니다).

예를 들어 코딩 챌린지 웹사이트에서 사용자가 코딩 엔트리를 제출합니다.그런 다음 관리자가 엔트리를 판단하고 완료되면 결과를 챌린지 페이지에 게시하여 모든 사용자가 볼 수 있도록 합니다.이 경우 POST_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 함수는 계속 작동합니다.

저는 문서 지향 데이터베이스라고 불리는 보상 시스템을 구현한 적이 있습니다(이것은 플레이어에게 진흙탕이었습니다).PHP 및 MySQL로 변환된 구현의 주요 특징:

  • 배지에 대한 모든 세부 정보가 사용자 데이터에 저장됩니다.MySQL을 사용하는 경우 성능 향상을 위해 이 데이터를 데이터베이스의 사용자당 하나의 레코드에 저장해야 합니다.

  • 담당자가 작업을 수행할 때마다 코드는 지정된 플래그('POST_MESSAGE')로 배지 코드를 트리거합니다.

  • 1개의 이벤트에 의해서, 예를 들면 투고수등의 카운터가 트리거 되는 일이 있습니다.increase_count('POST_MESSAGE').여기서 POST_MESSAGE 카운트가 300보다 크면 배지를 보상해야 한다는 체크("300_POST")를 받을 수 있습니다.

  • 플래그 방식에서는 보상 배지에 코드를 붙입니다.예를 들어 플래그 300_POST가 전송되면 배지 reward_badge("300_POST")를 호출해야 합니다.

  • flag 메서드에서는 사용자의 이전 플래그도 존재해야 합니다.따라서 사용자가 FIRST_COMMENT, FIRST_POST, FIRST_READ를 가지고 있는 경우 배지를 부여("NEW USER")하고 100_COMMENT, 100_POST, 300_RE를 얻을 수 있습니다.AD 배지를 부여할 수 있습니다("ExperiENCED_USER")

  • 이 모든 깃발과 배지는 어떻게든 저장해야 합니다.플래그를 비트로 생각할 수 있는 방법을 사용합니다.이것을 정말로 효율적으로 보존하는 경우는, 비트로 간주해 이하의 코드를 사용합니다(복잡하지 않은 경우는, 「0000000011000」이라고 하는 베어 스트링을 사용할 수도 있습니다).

$achievments = 0;
$bits = sprintf("%032b", $achievements);

/* Set bit 10 */
$bits[10] = 1;

$achievements = bindec($bits);

print "Bits: $bits\n";
print "Achievements: $achievements\n";

/* Reload */

$bits = sprintf("%032b", $achievments);

/* Set bit 5 */
$bits[5] = 1;

$achievements = bindec($bits);

print "Bits: $bits\n";
print "Achievements: $achievements\n";
  • 사용자를 위해 문서를 저장하는 좋은 방법은 json을 사용하여 사용자 데이터를 단일 텍스트 열에 저장하는 것입니다.json_encode 및 json_decode를 사용하여 데이터를 저장/검색합니다.

  • 다른 사용자가 조작한 일부 사용자 데이터에 대한 작업을 추적하려면 항목에 데이터 구조를 추가하고 해당 항목의 카운터도 사용하십시오.예를 들어 읽기 횟수입니다.배지의 부여에는 위에서 설명한 것과 동일한 기술을 사용합니다.그러나 업데이트는 당연히 소유 사용자의 게시물에 들어가야 합니다.(예를 들어 기사에서는 배지를 1000번 읽습니다).

UserInfuser는 배지/포인트 서비스를 구현하는 오픈소스 게임화 플랫폼입니다.API는 http://code.google.com/p/userinfuser/wiki/API_Documentation 에서 확인하실 수 있습니다.

저는 그것을 구현하고 기능 수를 최소화하려고 노력했습니다.php 클라이언트의 API는 다음과 같습니다.

class UserInfuser($account, $api_key)
{
    public function get_user_data($user_id);
    public function update_user($user_id);
    public function award_badge($badge_id, $user_id);
    public function remove_badge($badge_id, $user_id);
    public function award_points($user_id, $points_awarded);
    public function award_badge_points($badge_id, $user_id, $points_awarded, $points_required);
    public function get_widget($user_id, $widget_type);
}

결과적으로 위젯을 사용하여 데이터를 의미 있는 방식으로 표시할 수 있습니다.이러한 위젯에는 트로피 케이스, 리더보드, 마일스톤, 실시간 알림, 순위 및 포인트가 포함됩니다.

API의 실장은 http://code.google.com/p/userinfuser/source/browse/trunk/serverside/api/api.py 에서 확인할 수 있습니다.

성과는 부담이 될 수 있으며, 만약 당신이 좋은 형태를 갖추지 않았다면 나중에 그것들을 추가해야 한다면 더욱 그렇다.Event학급.

이것은 성취를 실현하는 나의 기법과 연결된다.

' 그 에 '카테고리'라는kills게임의 카테고리는 첫 번째 킬, 10번째 킬, 1000,000킬 등에 대해 1로 상을 받을 수 있다.

그리고 좋은 어플리케이션의 척추, 이벤트를 다루는 클래스.다시 킬 게임을 상상하면 플레이어가 무언가를 죽이면 일이 벌어진다.기록 있으며, .Events관련된 다른 장소에 정보를 보낼 수 있는 클래스입니다.

방법으로 의 예를 들 수 있습니다.Achievements수업하고 그 선수가 한 명이어야 한다는 걸 확인하세요.

「 」의 Achievements클래스는 단순하며, 플레이어가 다음 목표를 달성하기 위해 필요한 만큼의 킬을 가지고 있는지 확인하기 위해 데이터베이스를 체크하는 것입니다.

Redis를 사용하여 사용자의 성과를 BitField에 저장하고 싶지만 MySQL에서도 동일한 기술을 사용할 수 있습니다.,를 ▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▼int 다음에 또 한 번.and이미 획득했는지 확인하기 위해 당신이 그 성과로 정의한 비트를 포함한 int를 확인합니다. 한 합니다.int컬럼을 지정합니다.

이것의 단점은 그것들을 잘 정리해야 하고, 2^14에 대응하는 것을 나중에 기억할 수 있도록 코드에 코멘트를 해야 한다는 것입니다.가 표에 되어 있는 , 2.여기서 2^pk는 2^pk로 하면 됩니다.pk는 성과표의 주요 키입니다. 는 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

if(((2**$pk) & ($usersAchInt)) > 0){
  // fire off the giveAchievement() event 
} 

이렇게 하면 나중에 성과를 추가할 수 있으며, 이는 잘 들어맞을 것입니다. 단지 이미 수여된 성과 중 가장 중요한 키를 절대 바꾸지 마십시오.

언급URL : https://stackoverflow.com/questions/4192653/best-way-to-code-achievements-system

반응형