Zastanawiam się nad najlepszym sposobem zaprojektowania systemu osiągnięć do wykorzystania w mojej witrynie. Strukturę bazy danych można znaleźć w Najlepszym sposobie, aby stwierdzić brakujące 3 lub więcej kolejnych rekordów, a ten wątek jest naprawdę rozszerzeniem umożliwiającym uzyskanie pomysłów od programistów.
Problem, który mam z wieloma rozmowami o odznakach / systemach osiągnięć na tej stronie jest po prostu taki - wszystko to mówi i nie ma kodu. Gdzie są rzeczywiste przykłady implementacji kodu?
Proponuję tutaj projekt, do którego, mam nadzieję, ludzie mogliby się przyczynić i mam nadzieję, że stworzy dobry projekt do kodowania rozszerzalnych systemów osiągnięć. Nie mówię, że to jest najlepsze, dalekie od tego, ale to możliwy blok startowy.
Prosimy o zgłaszanie swoich pomysłów.
mój pomysł na projekt systemu
Wygląda na to, że panuje powszechna zgoda co do stworzenia „systemu opartego na zdarzeniach” - za każdym razem, gdy występuje znane zdarzenie, takie jak tworzenie, usuwanie postów itp., Wywołuje klasę zdarzenia w ten sposób.
$event->trigger('POST_CREATED', array('id' => 8));
Następnie klasa zdarzenia sprawdza, jakie odznaki „nasłuchują” tego zdarzenia, a następnie przechodzi do tego requires
pliku i tworzy instancję tej klasy, na przykład:
require '/badges/' . $file;
$badge = new $class;
Następnie wywołuje domyślne zdarzenie, przekazując dane odebrane, gdy trigger
zostało wywołane;
$badge->default_event($data);
odznaki
To wtedy dzieje się prawdziwa magia. każda odznaka ma własne zapytanie / logikę w celu określenia, czy należy przyznać odznakę. Każda plakietka ma np. Następujący format:
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
function pochodzi z klasy rozszerzonej, Badge
która zasadniczo sprawdza, czy użytkownikowi przyznano już tę odznakę, a jeśli nie, zaktualizuje tabelę baz znaczników. Klasa badge zajmuje się również pobieraniem wszystkich identyfikatorów dla użytkownika i zwracaniem ich w tablicy itp. (Tak więc identyfikatory mogą być np. Wyświetlane w profilu użytkownika)
co się stanie, gdy system zostanie wdrożony po raz pierwszy w już działającej witrynie?
Istnieje również zapytanie o zadanie „cron”, które można dodać do każdej odznaki. Powodem tego jest to, że gdy system odznak jest po raz pierwszy wdrażany i uruchamiany, odznaki, które powinny już zostać zdobyte, nie zostały jeszcze przyznane, ponieważ jest to system oparty na wydarzeniach. Dlatego zadanie CRON jest uruchamiane na żądanie dla każdej odznaki, aby nagrodzić wszystko, co ma być. Na przykład zadanie CRON dla powyższego wyglądałoby następująco:
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);
}
}
}
Ponieważ powyższa klasa cron rozszerza główną klasę badge, może ponownie użyć funkcji logicznej try_award
Powodem, dla którego tworzę wyspecjalizowane zapytanie, jest to, że mogliśmy "zasymulować" poprzednie zdarzenia, tj. Przejrzeć każdy wpis użytkownika i wywołać klasę zdarzenia tak $event->trigger()
, jakby była bardzo powolna, szczególnie w przypadku wielu odznak. Dlatego zamiast tego tworzymy zoptymalizowane zapytanie.
jaki użytkownik otrzyma nagrodę? wszystko o nagradzaniu innych użytkowników na podstawie wydarzenia
Funkcja Badge
klasowa award
działa user_id
- zawsze otrzymają nagrodę. Domyślnie odznaka jest przyznawana osobie, która spowodowała wystąpienie zdarzenia, tj. Identyfikator użytkownika sesji (dotyczy to default_event
funkcji, chociaż zadanie CRON oczywiście przechodzi przez wszystkich użytkowników i nagradza oddzielnych użytkowników)
Weźmy więc przykład, w przypadku wyzwania z kodowaniem, użytkownicy witryny przesyłają swój kod. Administrator następnie ocenia zgłoszenia i po zakończeniu publikuje wyniki na stronie wyzwania, aby wszyscy mogli je zobaczyć. W takim przypadku wywoływane jest zdarzenie POSTED_RESULTS.
Jeśli chcesz przyznać odznaki użytkownikom za wszystkie opublikowane wpisy, powiedzmy, że jeśli znaleźli się w pierwszej piątce, powinieneś użyć zadania cron (chociaż pamiętaj, że zaktualizuje się to dla wszystkich użytkowników, a nie tylko dla tego wyzwania wyniki zostały opublikowane dla)
Jeśli chcesz wybrać bardziej konkretny obszar do aktualizacji za pomocą zadania cron, zobaczmy, czy istnieje sposób na dodanie parametrów filtrowania do obiektu zadania cron i uzyskanie funkcji cron_job, aby z nich korzystać. Na przykład:
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);
}
}
Funkcja cron będzie nadal działać, nawet jeśli parametr nie zostanie podany.