RPS Arena
Arkadaşlarınla canlı oynadığın, eleme usulü bir taş-kağıt-makas turnuvası.
Arkadaşlarınla lobi koduyla ya da rastgele eşleşerek oynadığın, eleme usulü çevrim içi taş-kağıt-makas turnuvası. Lobiyi kuran kişi oda adını, puanı ve süreleri yönetiyor.

- Durum
- Yayında
- Kategori
- Oyun
- Güncelleme
- 27 Ağustos 2026
- Yığın
- ReactNode.jsSocket.io
- Bağlantılar
- Canlı site Kaynak kod
RPS Arena, taş-kağıt-makası gerçek zamanlı ve eleme usulü bir turnuvaya çeviriyor. Oyuncular bir lobi kodu etrafında toplanıyor ve canlı bir eleme tablosu üzerinden oynuyor. Kendin lobi kurabilir, kodla (/?code=ABC12) katılabilir ya da en fazla 8 kişilik açık lobilerden birine rastgele girebilirsin. Tablo 2 ile 64 arası oyuncuyu tek eleme usulünde eşliyor ve gerektiğinde BYE veriyor; BYE her zaman gerçek bir oyuncuya denk geliyor. Turnuvayı yayında göstermek isteyenler için oturum gerektirmeyen bir OBS overlay'i de var (/overlay/KOD, yeşil fon için ?chroma=1).
React arayüzü ve Node.js + Socket.IO sunucusu tek bir Docker container'ında çalışıyor. Turnuva durumu diske yazılıyor, bu yüzden sunucu yeniden başlasa da maç saatleri kaldığı yerden kuruluyor.
Turnuva nasıl ilerliyor
Lobiyi kurup kodu paylaşıyorsun, herkes Hazırım diyor. Yönetici Kurayı çek ile tabloyu oluşturuyor, gerekirse Kurayı boz ile geri alıyor. Turnuvayı başlat ilk turun bütün maçlarını aynı anda açıyor. Bir tur bitince sıradakini yönetici başlatıyor; otomatik geçiş açıksa tur kendiliğinden başlıyor. Final bitince şampiyon ilan ediliyor, Yeni turnuva da aynı kodla lobiyi yeniden açıyor. Yöneticinin önünde her an tek bir "Sıradaki adım" düğmesi oluyor ve bu düğme maçın oynandığı Arena sekmesinde de görünüyor.
Kuralları da ayarlayabilirsin: maçı kaç puana ilk ulaşanın kazanacağı (2-5), hamle süresi (5-20 saniye), geri sayım (0-5 saniye) ve tur geçişinin elle mi otomatik mi olacağı. Her raundun sonunda kısa bir ara veriliyor ve iki oyuncu da sonucu görüyor. Süre dolarsa hamleni sistem atıyor. Yönetici turnuvayı duraklatabiliyor, bir maçın kazananını elle atayabiliyor, maçı baştan başlatabiliyor ya da bir oyuncuyu çıkarabiliyor. Canlı tablo, aktivite akışı ve podyumun yanında, 1-2 saniyede hamle yapan test botları da eklenebiliyor.
Sekmeyi kapatsan bile geri gelip yeniden bağlanabiliyorsun. Yöneticinin bağlantısı düşerse 30 saniye sonra yetki başka birine geçiyor. Turnuvadan gerçekten çıkmak istersen Ayrıl düğmesi var.
Sunucuda mantık socket'ten ayrı
Depo, backend ve frontend workspace'lerinden oluşan bir npm monorepo'su. Sunucuda Socket.IO handler'larını ince tuttum; asıl iş tournament/ altındaki servislerde:
flow.service.tshamleleri, raunt saatini, faz geçişlerini ve yönetici komutlarını yürütüyor.match.service.tsmaç kurallarını yan etkisiz saf fonksiyonlar olarak tutuyor.presence.service.tsbağlantıları, yönetici devrini, yeniden başlatma sonrası kurtarmayı ve lobi temizliğini üstleniyor.timer.service.tssunucudaki bütün zamanlayıcıların tek kayıt defteri.
İstemci ile sunucu arasındaki mesaj biçimi tournament.types.ts içinde tanımlı. Ön yüz bu dosyayı import type ile kullanıyor; böylece iki taraf hep aynı sözleşmeye bağlı kalıyor.
Durum bellekte tutuluyor ve bir dosyaya da yazılıyor. Sunucu yeniden başladığında saatler bu dosyadan yeniden kuruluyor; SIGTERM geldiğinde de durum beklemeden diske yazılıyor. 3 saat boyunca içinde kimse olmayan lobiler siliniyor. Docker'da arka uç derlenmiş ön yüzü de sunuyor, bu yüzden tek bir container yetiyor. Arayüz ise design.md içinde kilitlediğim bir tasarım sistemine ve tokens.css içindeki token'lara dayanıyor.
Sunucu tarafında Node.js 22, TypeScript, Express 5, Socket.IO 4 ve Zod, istemci tarafında React 19, Vite 7 ve socket.io-client kullandım.