//sinancanozer.dev
← işlere dön
API·2026·GELİŞTİRİLİYOR

MathBank API

5–8. sınıflar için LGS'ye hazırlanan öğrencilere yönelik, rekabetçi oyunlardan ilham alan rütbe tabanlı bir ilerleme sistemi üzerine kurulu oyunlaştırılmış matematik pratiği platformu.

Solo Geliştirici · Kişisel Proje · 2026
Matematik müfredatı gözden geçirmesi: Zeynep Kabaş Özer, matematik öğretmeni
  • Java 25
  • Spring Boot
  • PostgreSQL
  • JPA/Hibernate
  • JWT
  • React
  • TypeScript
MathBank API

Context#

Türkiye'de 5–8. sınıf öğrencileri için matematik pratiği, yirmi yıl öncesiyle aynı görünüyor: kalın test kitapları, tekrar eden alıştırmalar, geri bildirim döngüsü yok. İlk kırılan şey motivasyon oluyor — özellikle LGS'ye, yani ulusal lise yerleştirme sınavına giden o uzun süreçte.

MathBank kişisel bir gözlemden doğdu. Her hafta sonu saatlerce dereceli (ranked) oyunlarda kasan çocuklar, yirmi dakikalık matematik ödevine oturamıyor. Sorun matematik değil. Sorun, çerçeveleme.

Bu yüzden, matematik pratiğini League of Legends ya da Valorant gibi oyunların beceri gelişimine yaklaştığı şekilde ele alan bir platform yaptım: 25 kademeli dereceli bir ilerleme sistemi, sınava dayalı yükselme ve düşme, rütbenle birlikte ölçeklenen bir soru havuzu, ve kilometre taşları için rozetler. Her sınav, dereceli bir maç. Matematik gerçek — her soru 2025 Maarif müfredatına (5–6. sınıflar) ve MEB müfredatına (7–8. sınıflar) göre özenle hazırlanıyor, güvendiğim bir matematik öğretmeni tarafından gözden geçiriliyor. Değişen şey, ambalaj.

Challenge#

Üç şey zordu, ve farklı sebeplerle zordu.

İlki şemaydı. On üç entity — Grade, Subject, Subtopic, Question, User, RankExam, ExamAnswer, RankTier, Badge ve diğerleri — kendimi köşeye sıkıştırmadan birbiriyle ilişkilenmeliydi. Tek başına RankTier'in 25 sıralı değere sahip bir enum olmasına, getNextTier ve getPreviousTier yardımcılarına, ve soruları ait oldukları kademeyle ilişkilendirmenin temiz bir yoluna ihtiyacı vardı. Şemayı erken yanlış kurarsan, sonraki on sprint boyunca kan kaybedersin.

İkincisi sınav motoruydu. Her dereceli sınav 30 soru çekiyor — 10 kolay, 12 orta, 8 zor — öğrencinin sınıfına ve mevcut kademesine göre filtrelenmiş. Net puan tıpkı gerçek LGS'deki gibi hesaplanıyor: doğru sayısından yanlışların dörtte biri çıkarılıyor, boş bırakılanlar yanlış sayılıyor. Yükselme, düşme ve koruma-kalkanı mantığı tek bir yerde yaşıyor. Tüm bunların hile-dayanıklı olması gerekiyor: sınav ortasında doğru cevaba göz atmak yok, biri aktifken ikinci bir sınav başlatmak yok, id'yi tahmin ederek başkasının sınavına erişmek yok.

Üçüncüsü operasyonel disiplindi. Solo olmak, her kararın benim olması demek. Beni geçersiz kılacak bir mimar yok, aptalca hatayı yakalayacak bir gözden geçiren yok. O yüzden çözüm, konvansiyonlara sıkıca yaslanmak ve yapıyı framework'ün dayatmasına bırakmaktı.

Approach#

Spring Boot'u bilinçli seçtim. Java ve Spring eğitimi aldım, ve her gün başvurmasam da, proje sıkı yapı, öngörülebilir desenler ve uzun vadeli okunabilirlik gerektirdiğinde, en çok güvendiğim ekosistem bu. Görüşlü (opinionated) yerleşim — controller'lar, service'ler, repository'ler, DTO'lar — solo bir projenin kaosa sürüklenmesini engelliyor.

Önce şema geldi. Herhangi bir kod yazmadan önce 13 entity'nin tümünü, ilişkilerini ve RankTier enum'unu kâğıda çizdim. Bir BaseEntity sınıfı, createdAt ve updatedAt'i merkezileştirdi, böylece o boilerplate'i asla iki kez yazmadım. RankTier'e sadece değerler değil, gerçek metotlar eklendi — getOrder, getNextTier, getPreviousTier — böylece yükselme mantığı çağrı yerinde doğal okunuyor. Rütbeyi ayrı bir tablo yapmayı düşündüm; performans ve niyet açısından enum kazandı.

Sınav motoru zengin bir domain modeli kullanıyor. exam.finish(), exam.recordCorrectAnswer() ve exam.calculateNet() gibi metotlar entity'nin kendisinde yaşıyor. Controller'lar sınav durumuna uzanmıyor — entity'ye ne olduğunu söylüyor ve kararı ona bırakıyor. Bu "söyle, sorma" (tell, don't ask) deseni, motoru test etmesi, okuması ve genişletmesi daha kolay hale getirdi.

İki tuzak gerçek zaman kaybettirdi. Birincisi, JPA entity'lerini doğrudan controller'lardan döndürmek LazyInitializationException tetikliyordu — klasik Hibernate tuzağı. Çözüm: sıkı bir DTO katmanı, her yanıt biçimi kendine ait bir SubjectResponse, QuestionResponse ya da ExamResponse'a devredilmiş. İkincisi, Spring Security ve multipart/form-data, CSV içe aktarma endpoint'inde anlaşamadı; bunu çözmek, güvenlik filtre zincirinin dosya yüklemelerini nasıl ele aldığını yeniden düşünmek demekti.

Tech Stack#

Çekirdekte Java 25 üzerinde Spring Boot 4.0.3 var. JPA/Hibernate, PostgreSQL'e karşı kalıcılığı yönetiyor — işlemsel güvenliği ve içine büyüyecek kadar derin bir özellik seti için seçildi. JWT, ayrı access ve refresh token'larla kimlik doğrulamayı sağlıyor; BCrypt, 12 gücünde parolaları hash'liyor. Swagger, API dokümantasyonunu controller'lardan otomatik üretiyor.

API, yedi domain'e yayılmış 25 endpoint sunuyor: auth, questions, subjects, exams, leaderboard, user stats ve badges. Versiyonlama ilk günden /api/v1/ altında yaşıyor, böylece gelecekteki kırıcı değişiklikler mevcut istemcileri bozmuyor.

Frontend, TypeScript ve Vite ile React 19, Tailwind ile stillendi. Axios, token yenileme için interceptor'larla HTTP'yi yönetiyor. Frontend bu aşamada bilinçli olarak minimal — daha zor problem backend'di, ve API yüzeyi oturduktan sonra frontend onun üzerine kuruluyor.

Önbellek, hız sınırlama ve yük testi Sprint 8 için planlanıyor: leaderboard önbelleği için Upstash üzerinde Redis, kullanıcı başına hız limitleri için Bucket4j, yük testleri için k6. Dağıtım, Sprint 9'da backend için Railway'e ve frontend için Vercel'e taşınıyor.

Visuals#

// GALLERY · 05 ITEMS
[01/05]

25 kademeli rütbe sistemi: 5 rütbe × 5 kademe, bir Java enum'u olarak modellendi

Enum üzerindeki domain metotları: getNextTier, getPreviousTier, fromOrder

13 entity ve ilişkileri: Grade, Subject, Subtopic, Question, User, RankExam, ExamAnswer, RankTier, Badge ve daha fazlası

REST API yüzeyi: 7 domain'e yayılmış 25 endpoint, /api/v1/ altında versiyonlanmış

Sistem mimarisi: istemci, REST API, iş mantığı, kalıcılık ve altyapı katmanları

Outcome#

Şu anda geliştirme aşamasında. Backend kabaca %80 tamamlandı; 25 endpoint'in tümü uygulandı ve Postman üzerinden manuel olarak test edildi. On üç entity, yedi service, altı exception tipi, sekiz rozet stratejisi ve 25 kademeli bir rütbe sistemi yerel ortamda çalışıyor. Frontend %10'da — giriş ve kayıt ekranları — dashboard, sınav ekranı ve sonuç ekranı Sprint 5–6'da geliyor.

Soru havuzu, Bronze 1 kademesinde elle hazırlanmış 34 soruda duruyor. Hedef 5.000: dört sınıf, 25 kademe, kademe başına 50 soru. Bu hacmi üretmek mühendislikten çok bir içerik problemi, ve müfredat gözden geçirmesinin en çok önem taşıdığı alan da burası.

Şu ana kadarki toplam geliştirme süresi: beş yoğun günde yaklaşık 50 saat. Sprint 9, mathbank.com.tr adresinde halka açık dağıtımı yayınlıyor. Sprint 10, React Native mobil yapısını başlatıyor.

MathBank, bir portfolyo süsü değil, gerçek öğrencilere yönelik gerçek bir platform. Portfolyo çerçevesi bir yan etki: aynı proje, şema tasarımı, domain modelleme ve solo kısıtlar altında ürün çıkarma konusunda nasıl düşündüğümü de gösteriyor.