Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Skor tabloları ve turnuvalar

Bu sayfa oyuncuların puanla yarıştığı skor tablolarını (leaderboard) ve eleme usulü turnuvaları anlatır. Puanı güvenilir sunucudan yazıp oyun içinde sıralamayı göstermek istiyorsanız okuyun.

Ne işe yarar

Rekabet modülü (competition) iki şey sağlar:

  • Skor tablosu: Oyuncu başına en iyi puanı tutan, sezonlara bölünebilen sıralama.
  • Turnuva: Oyuncu ya da klan katılımcılarıyla tek eleme, çift eleme ya da lig usulü bracket; final ödülü ile.

Puan yazma ve tablo yönetimi sunucu anahtarıyla yapılır. Oyun istemcisi tabloyu oyuncu oturumuyla okur ve sunucu anahtarı gerekmez.

Modül kapalıysa uçlar 404 ve {"code":"module_disabled","module":"competition"} döner. Modülü Oyun ayarları › Modüller sayfasından açın.

Panelde nerede

Ne yapacaksınızPanel sayfası
Tablo tanımlamak, sezon, birim ve görünürlük ayarlamakLeaderboard
Bir tablonun en yüksek kayıtlarını ve sezon geçmişini görmekLeaderboard ayrıntısı
Turnuva için ödül para birimiPara birimleri

Turnuvalar için panel ekranı yoktur; yalnız REST ile yönetilir.

Veri modeli (düz dille)

  • Tablo tanımı: key, name, metric_expr, order (asc: küçük puan iyi, desc: büyük puan iyi), season, tie_policy, player_visible, unit ve unit_suffix. Tanım sürümlüdür.
  • Sezon (season): none (hiç sıfırlanmaz), daily, weekly, monthly (UTC takvimine hizalı: gün 00:00 UTC’de, hafta Pazartesi 00:00 UTC’de, ay ayın birinde döner) ya da custom (custom_period_ms uzunluğunda dönem). Sezon kapanınca sıralaması değişmez bir kayda alınır.
  • Puan: Tam sayı (i64). Bir oyuncunun sezondaki en iyi puanı sayılır (desc’te en yüksek, asc’te en düşük). Daha kötü bir puan göndermek sıralamayı değiştirmez.
  • Eşitlik (tie_policy): Şimdilik tek seçenek score_achieved_player_id: önce puan, sonra o puana ilk ulaşan, sonra oyuncu kimliği.
  • Sıra (rank): 1’den başlar.
  • Birim (unit): points, money (en küçük para birimi) ya da duration_ms; unit_suffix 1–8 karakterlik ektir ($, ms …). Birim yalnız gösterim içindir.
  • player_visible: true ise oyuncu oturumu tabloyu okuyabilir; varsayılan false.
  • metric_expr: Kayıt anında derlenen CEL ifadesi (zorunlu, boş olamaz). Eklentilerin kendiliğinden kurduğu tablolar event.score kullanır; REST ile kurarken de aynı ifadeyi yazın.

Oyunun yaptığı çağrılar

Yöntem ve yolKimlikNe yapar
POST /v1/leaderboardssunucu anahtarıTablo tanımı oluşturur
GET /v1/leaderboards, GET /v1/leaderboards/{key}sunucu anahtarıTanımları listeler / okur
POST /v1/leaderboards/{key}/scoressunucu anahtarıOyuncu puanı yazar (Idempotency-Key zorunlu, 202)
GET /v1/leaderboards/{key}/entries?limit=&cursor=sunucu anahtarıİlk sıralar (sayfalı)
GET /v1/leaderboards/{key}/around-me?player_id=&radius=sunucu anahtarıOyuncunun çevresindeki sıralar
GET /v1/player/leaderboards/{key}?limit=oyuncu oturumuTablonun ilk sayfası ve oyuncunun kendi satırı
POST /v1/tournamentssunucu anahtarıTurnuva oluşturur
GET /v1/tournaments/{id}sunucu anahtarıTurnuva durumunu okur
POST /v1/tournaments/{id}/participantssunucu anahtarıKatılımcı kaydeder (Idempotency-Key)
POST /v1/tournaments/{id}/startsunucu anahtarıBracket üretip başlatır
POST /v1/tournaments/{id}/matches/{match_id}/resultsunucu anahtarıMaç sonucu bildirir ya da itirazı çözer (Idempotency-Key)

Sunucu uçları Authorization: Bearer crx_live_<önek>_<gizli> ister; istemci anahtarı ve oyuncu oturumu reddedilir. Oyuncu ucu çerez ya da oturum belirteci ve x-crx-env: <ortam uuid> ile çalışır; geliştirici anahtarı kabul edilmez.

Not

TypeScript SDK’sında oyuncu okuması için player.leaderboard(key, { limit }) vardır; sunucu uçları (puan yazma, tanım, turnuva) için tipli istemci yoktur ve ham REST ile çağrılır. Bkz. TypeScript SDK.

Tablo tanımı

POST /v1/leaderboards
Authorization: Bearer crx_live_<önek>_<gizli>
Content-Type: application/json

{
  "key": "daily-earnings", "name": "Günlük kazanç",
  "metric_expr": "event.score", "order": "desc",
  "season": "daily", "tie_policy": "score_achieved_player_id",
  "player_visible": true, "unit": "money", "unit_suffix": "$"
}

201 döner ve { id, key, name, metric_expr, order, season, custom_period_ms, tie_policy, season_key } gelir. season: "custom" için custom_period_ms pozitif olmalıdır.

Puan yazmak

POST /v1/leaderboards/daily-earnings/scores
Authorization: Bearer crx_live_<önek>_<gizli>
Idempotency-Key: score-oyuncu-1234-2026-11-03
Content-Type: application/json

{ "player_id": "0192f0f2-5b1a-7c3e-9d11-4a5b6c7d8e9f", "score": 4200 }
{ "entry": { "rank": 7, "player_id": "0192f0f2-…", "score": 4200, "achieved_at_ms": 1790000000000 }, "replayed": false }

Yanıt 202’dir: puan kalıcı olarak kabul edilmiştir; sıralama projeksiyonu kısa bir gecikmeyle güncellenir, bu yüzden hemen ardından okunan tablo birkaç saniye geride kalabilir. Idempotency-Key zorunludur: aynı anahtar ve aynı gövde aynı sonucu replayed: true ile döndürür.

Tabloyu oyuncu oturumuyla okumak

GET /v1/player/leaderboards/daily-earnings?limit=10
x-crx-env: 0192f000-0000-7000-8000-00000000e001
{
  "leaderboard": { "key": "daily-earnings", "name": "Günlük kazanç", "order": "desc", "season": "daily", "seasonKey": "2026-11-03", "seasonEndsAtMs": 1790121600000, "unit": "money", "unitSuffix": "$" },
  "entries": [ { "rank": "1", "playerId": "…", "displayName": "Ayşe", "score": "9800", "achievedAtMs": 1790000000000 } ],
  "me": { "rank": "7", "playerId": "…", "displayName": "Siz", "score": "4200", "achievedAtMs": 1790000000000 }
}
  • Yalnız player_visible tablolar okunur; aksi 404. Modül kapalıysa da 404.
  • limit 1–50 (varsayılan 20).
  • rank ve score JSON’da ondalık metindir (kayıpsız i64); SDK bunları bigint yapar. Alan adları bu uçta camelCase’tir.
  • Yasaklı ve silinmiş oyuncular süzülür ve sıra sayfa içinde yoğun numaralanır; me, görünür oyuncular arasındaki sıranızdır. Bu sezonda puanı yoksa me null’dır.
  • Birinci sayfa kısa süre (en çok birkaç saniye) önbelleğe alınır.

Turnuvalar

POST /v1/tournaments
Authorization: Bearer crx_live_<önek>_<gizli>
Content-Type: application/json

{
  "name": "Kış Kupası", "format": "single_elimination", "participant_type": "player",
  "capacity": 16,
  "registration_opens_at_ms": 1790000000000, "registration_closes_at_ms": 1790086400000,
  "seeding_source": "registration_order",
  "prize_table": { "currency_key": "gold", "amount": 5000 }
}
  • format: single_elimination, double_elimination, round_robin. participant_type: player ya da clan.
  • capacity 2–1024; kayıt kapanışı açılıştan sonra olmalı; name 1–200 karakter.
  • seeding_source: registration_order (kayıt sırası; leaderboard_id verilmez) ya da leaderboard (yalnız oyuncu turnuvasında; leaderboard_id zorunlu).
  • prize_table: currency_key (boşluksuz, en çok 200 karakter) ve pozitif amount içeren nesne.
  • Akış: oluştur → participants ile kaydet ({ "participant_id" }) → start ile bracket’i üret → her maç için result bildir (reporter_id, reported_side: home away admin, outcome: home_win away_win draw, score). admin tarafı itirazı çözmek içindir.
  • Yanıtlar turnuvanın güncel görünümünü ({ "tournament": { … } }) taşır.

Sürümleme ve tekrar güvenliği

  • Puan yazma, katılımcı kaydı ve maç sonucu Idempotency-Key ister (aynı anahtar + aynı gövde: tekrar çalışmaz; farklı gövde: 422).
  • Tablo tanımı sürümlüdür; liste ve sıralama okumaları sürüm başlığı istemez.
  • Genel kurallar: Idempotency ve eşzamanlılık.

Olaylar

Puan kabulü score_submitted, sezon geçişi season_closed/season_opened olaylarını üretir; bunlar görev hedeflerinde ve kural otomasyonunda kullanılabilir. Webhook filtresi olarak seçilebilen türler arasında skor tablosu ya da turnuva olayı yoktur; filtresiz kayıtlı uç noktalar bütün olayları alır ve bunlara skor olayları da dahildir, ancak zarf biçimi belgelenmiş bir sözleşme değildir. Final ödülü için Ödüller sayfasındaki ödül verme akışını kullanın.

Sınırlar

  • Oyuncu okumasında limit 1–50; sunucu entries uçlarında sayfalama imleçlidir.
  • Turnuva capacity 2–1024.
  • season: custom için pozitif custom_period_ms gerekir.

Sık görülen hatalar

BelirtiNedenÇözüm
404 (oyuncu okuması)Tablo player_visible değil, yok ya da modül kapalıTanımı kontrol edin
403İstemci anahtarı ya da oyuncu oturumuyla sunucu ucuSunucu anahtarını sunucudan kullanın
400 (Idempotency-Key)Puan yazarken başlık yokAnahtar gönderin
Puan yazıldı ama sıralama değişmediOyuncunun sezondaki en iyi puanı daha iyiYalnız daha iyi puan sıralamayı değiştirir
Puan yazıldı ama tablo hemen güncellenmediProjeksiyon gecikmesiBirkaç saniye bekleyip okuyun
400 (turnuva)capacity, kayıt penceresi, prize_table ya da seed kuralı hatalıGövdeyi düzeltin

Çalışan örnek: puan yaz, tabloyu oku

/** Skor tablosu: sunucu puan yazar (ham REST), oyun istemcisi tabloyu oyuncu oturumuyla okur. */
import type { PlayerClient } from "@ferdiunal/open-play-ts";

/** Sunucu: `POST /v1/leaderboards/{key}/scores`. Sunucu anahtarı gerekir; Idempotency-Key zorunludur. */
export async function submitScore(baseUrl: string, serverApiKey: string, board: string, playerId: string, score: number, requestKey: string): Promise<number> {
  const response = await fetch(`${baseUrl}/v1/leaderboards/${encodeURIComponent(board)}/scores`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${serverApiKey}`,
      "Content-Type": "application/json",
      "Idempotency-Key": requestKey,
    },
    body: JSON.stringify({ player_id: playerId, score }),
  });
  if (response.status !== 202) throw new Error(`Puan yazılamadı: HTTP ${response.status} ${await response.text()}`);
  const body = (await response.json()) as { entry: { rank: number }; replayed: boolean };
  return body.entry.rank;
}

/** Oyun istemcisi: tablonun ilk sayfası ve oyuncunun kendi satırı (`player_visible` tablolar). */
export async function showBoard(player: PlayerClient, board: string): Promise<void> {
  const view = await player.leaderboard(board, { limit: 10 });
  for (const row of view.entries) console.log(`${row.rank}. ${row.displayName} — ${row.score}`);
  if (view.me !== null) console.log(`Siz: ${view.me.rank}. sıra, ${view.me.score} puan`);
}

İlgili sayfalar