Dalış Kayıt Defteri (Dive Logbook) — Araştırma & Tasarım Dokümanı
Hedef: Dünyadaki en gelişmiş dalış kayıt defteri sistemini tasarlamak.
Tarih: 2026-02-18
1. Mevcut Platformlar ve Analizi
A. Sertifika Kuruluşu Uygulamaları
| Platform | Artıları | Eksileri |
|---|
| PADI App | eCard yönetimi, QR ile eğitim dalışı doğrulama, en büyük kullanıcı tabanı | Dalış bilgisayarı import yok, basit log alanları, analiz yok |
| MySSI | 65K+ dalış noktası DB, QR ile buddy paylaşımı, ekipman yönetimi (seri no, fatura, bakım), ScubaPro LogTRAK entegrasyonu | Bazı loglar ana ekranda görünüp logbook'ta görünmüyor |
B. Dalış Bilgisayarı Üretici Uygulamaları
| Platform | Artıları | Eksileri |
|---|
| Garmin Dive | Otomatik GPS giriş/çıkış, kalp atışı + kalori, 4K+ dalış noktası | Kapalı ekosistem, 3. parti import yok |
| Shearwater Cloud | 10 saniyelik profil adımlama, en detaylı teknik dalış verisi, UDDF export | Fotoğraf/harita yok, manuel dalış eklenemez |
| Suunto App | BLE + USB senkron, etkinlik zaman çizelgesi, DM5 import | Basit veri, etkileşimsiz profil grafiği |
| ScubaPro LogTRAK | O2 toksisitesi, kalp atışı, kalori, en temiz UI | Paylaşım yok, fotoğraf yok, buddy/ekipman alanı yok |
| Oceanic+ | Apple Watch'u dalış bilgisayarına dönüştürür, canlı çevre verileri | Abonelik modeli, sadece Apple, sadece rekreasyonel |
C. Bağımsız / Evrensel Platformlar
| Platform | Artıları | Eksileri |
|---|
| Subsurface | En geniş bilgisayar desteği (libdivecomputer), çoklu bilgisayar birleştirme, açık kaynak, ücretsiz bulut | Eski UI, zayıf GPS/harita, mobilde UDDF import yok |
| DiveMate | USB + IR + BLE doğrudan telefonda, 170+ model, 65K+ dalış noktası, offline haritalar | Premium özellikler ücretli |
| Diviac | Tıkla-doğrula log onaylama, deniz canlıları DB, 200K+ dalgıç, 10K+ merkez | PADI satın aldı, geliştirici ilgisi azaldı |
| Diving Log 6.0 | 10 gaz CCR/trimix, en iyi masaüstü GPS/harita | Sadece Windows masaüstü, ücretli |
| Currents | En modern UI, lifetime fiyatlama, hibrit offline/online | Sadece iOS, küçük kullanıcı tabanı |
| Diveboard | Vatandaş bilimi (GBIF/OBIS biyoçeşitlilik veritabanlarına katkı) | Küçük kullanıcı tabanı, az özellik |
| Octologs | Başarım/rozet gamifikasyonu, uygulama içi mesajlaşma | Yeni, küçük topluluk |
| Seabook | AI fotoğraf bazlı tür tanımlama, 1700+ tür | Dalış logu zayıf, deniz canlısı odaklı |
| Wikibubbles | Gerçek zamanlı okyanus verileri, geçmişe dönük hava durumu otomatik doldurma | Çok yeni, küçük kullanıcı tabanı |
| Buddy App | Sosyal dalış ağı, eğitmen doğrulama, rezervasyon sistemi, dalış dükkanı dizini | Nispeten yeni, sınırlı özellikler |
D. Platform Karşılaştırma Matrisi
| Özellik | Subsurface | Diving Log | Garmin | MacDive | Diviac | MySSI | DiveMate |
|---|
| Ücretsiz | ✅ | ❌ | ✅* | ❌ | ✅/💰 | ✅ | ✅ |
| Açık Kaynak | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Teknik Dalış | ✅✅✅ | ✅✅✅ | ✅ | ✅✅ | ✅ | ✅ | ✅ |
| CCR/Rebreather | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Trimix | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
| Dalış Planlama | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Sosyal Özellik | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
| Deniz Yaşamı DB | ❌ | ❌ | ❌ | ❌ | ✅✅✅ | ✅✅ | ❌ |
| Harita/GPS | ✅ | ✅ | ✅✅ | ✅ | ✅ | ✅✅ | ✅✅ |
| Bulut Sync | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Bilgisayar Desteği | 50+ | 300+ | Garmin | 150+ | 100+ | Sınırlı | 170+ |
| Mobil Uygulama | ✅ | ✅ | ✅ | iOS | ✅ | ✅ | ✅ |
E. Kapanan Platformlar — Ders Çıkarılacak
Deepblu (Kapandı — Aralık 2023)
- En sosyal dalış platformuydu
- Kapanma nedeni: Kullanıcılar abonelik ödemeye isteksiz, sunucu maliyetleri arttı
- Ders: Bulut bağımlı platformlar sürdürülebilir gelir modeli olmadan çöker. Export yapamayan kullanıcılar verilerini kaybetti.
2. Piyasada Eksik Olan Özellikler (Fırsat Alanları)
- Eski UI'lar — Subsurface, Diviac, divelogs.de hepsi eski görünümlü. Modern, güzel arayüz rekabet avantajı.
- Vendor Lock-in — Garmin sadece Garmin, Suunto sadece Suunto import eder. Bilgisayar değiştiren kullanıcılar geçmişini kaybeder.
- Tek birleşik platform yok — Dalgıçlar sertifika için PADI, bilgisayar logu için Garmin, analiz için Subsurface, fotoğraf için Instagram kullanıyor.
- Zayıf offline — Teknede/uzak adada internet yok. Deepblu'nun kapanması riski kanıtladı.
- Abonelik yorgunluğu — Dalgıçlar defter için tekrarlayan ödeme istemiyor.
- Entegre dalış planlama + loglama yok — Keşif → planlama → loglama → analiz → paylaşım tek akışta değil.
- Eğitmen/Merkez panosu yok — B2B+B2C model: merkez öğrencileri yönetir, dalgıç logbook'unu yönetir, kesişirler.
- Akıllı çevre verisi otomatik doldurma yok — Konum + tarih → hava, gelgit, su sıcaklığı, ay evresi otomatik gelsin.
- AI deniz canlısı tanıma logbook'a entegre değil — Seabook ayrı uygulama, logbook'a gömülü değil.
- Çoklu kuruluş sertifika takibi yok — PADI, SSI, CMAS, TSSF hepsi ayrı. Tek yerde birleştiren yok.
- Doğrulanabilir dijital dalış kimliği yok — Dalış merkezlerinin kabul edeceği, değiştirilemez dijital dalgıç pasaportu.
- Rebreather/teknik dalış mobilde zayıf — Sadece masaüstü uygulamalar CCR/trimix destekliyor.
- Dalış sonrası değerlendirme araçları yok — Yapılandırılmış debrief kontrol listesi, beceri değerlendirmesi, eğitmen geri bildirimi.
- Bölgesel içerik yok — Yerel düzenlemeler, izin gereksinimleri, deniz parkı ücretleri, mevsimsel koşullar.
3. TurkeyScuba Dive Logbook — Özellik Listesi
3.1 Temel Dalış Kayıt Alanları
Dalış Kimliği
- Dalış numarası (otomatik artan)
- Tarih ve saat (giriş/çıkış)
- Dalış süresi (toplam, dip süresi ayrı)
- Yüzey aralığı (bir önceki dalıştan)
- Dalış tipi: rekreasyonel, teknik, serbest dalış (freediving), ticari, bilimsel, askeri, eğitim
- Dalış stili: tekne, kıyı, akıntı, gece, buz, mağara, batık, duvar, muck, derin, yükseklik
- Dalış amacı: eğlence, eğitim, fotoğrafçılık, araştırma, kurtarma, bakım
- Nefes alma modu: açık devre (OC), CCR, pSCR, serbest dalış
- Trip/seyahat gruplaması — çoklu dalışı bir gezi altında toplama
Konum
- Ülke, bölge, dalış noktası adı
- GPS koordinatları (giriş/çıkış ayrı ayrı)
- Dalış noktası ilişkilendirme (platformdaki dive_sites tablosuyla FK)
- Haritada görsel işaretleme
Derinlik & Profil
- Maksimum derinlik (m)
- Ortalama derinlik (m)
- Planlanan derinlik (m)
- Derinlik profili (zaman serisi — bilgisayardan import)
- Yükseklik düzeltmesi (rakım dalışı için)
Gaz & Hava Tüketimi
- Tüp tipi (çelik/alüminyum) ve hacmi (L)
- Gaz karışımı (hava/nitrox/trimix) — O2%, He%
- Başlangıç basıncı (bar)
- Bitiş basıncı (bar)
- SAC rate (hesaplanır)
- RMV (hesaplanır)
- Toplam tüketim (L)
- Çoklu tüp desteği (teknik dalış — dalış başına 10+ gaz)
- Gaz değişim noktaları ve zamanları
- Stage/bailout tüpleri
- Gaz kullanım tipi: dip, deco, seyahat, bailout, diluent
CCR/Rebreather Özel Verileri
- Setpoint değerleri ve değişim zamanları
- ppO2 değerleri (3 sensörden)
- Diluent gaz bilgisi
- Bailout gaz bilgisi
- Diluent → Bailout geçişi
- Scrubber kullanım süresi / kapasitesi
- Loop hacmi
Dekompresyon
- Dekompresyon algoritması (Bühlmann ZH-L16C, VPM-B, RGBM)
- Gradient faktörleri (GF Low / GF High)
- NDL (no-deco limit) — dalış boyunca
- Güvenlik durağı (derinlik/süre, uyum kaydı)
- Deco durakları (derinlik/süre)
- Tavan (ceiling) profili
- CNS% (Merkezi Sinir Sistemi oksijen toksisitesi)
- OTU (Oxygen Toxicity Units)
- Doku doygunluk verileri
- Kullanılan tablo/algoritma
Sıcaklık & Koşullar
- Hava sıcaklığı
- Yüzey su sıcaklığı
- Dip su sıcaklığı
- Termoklin derinliği
- Görüş mesafesi (m)
- Akıntı (yok/hafif/orta/güçlü)
- Dalga yüksekliği
- Rüzgar hızı/yönü
- Gelgit durumu
- Hava durumu
- Ay evresi (otomatik)
- Su tipi: tatlı su, tuzlu su, acımsı (brackish)
- Barometre basıncı
- UV indeksi
- Otomatik çevre verisi doldurma — konum + tarih → API'den hava, gelgit, su sıcaklığı çekilir
Güvenlik Kaydı
- Güvenlik durağı uyumu (evet/hayır)
- Hızlı çıkış (evet/hayır)
- Deko ihlali (evet/hayır)
- Aşım süresi (varsa)
- Olay/kaza raporu
- Buddy sistemi uyumu
- Dalış öncesi kontrol listesi (pre-dive checklist)
- Dalış planı vs gerçekleşen karşılaştırma
Fizyolojik Veriler
- Kümülatif CNS%
- Kümülatif OTU
- Tekrarlayan dalışlarda azot yüklenmesi
- Uçuşa/yüksekliğe çıkma için bekleme süresi
- Kalp atışı (bilgisayar destekliyorsa)
3.2 Ekipman Yönetimi
- BCD: marka, model, beden, entegre ağırlık cepleri
- Regülatör: marka, model, son bakım tarihi, sonraki bakım tarihi
- Dalış bilgisayarı: marka, model, firmware sürümü, pil durumu
- Dalış elbisesi: tip (wetsuit/drysuit/skin), kalınlık, başlık, eldiven, bot
- Ağırlık: toplam ağırlık, tip (kemer/entegre/ayak bileği), denge kontrolü
- Kamera: kamera tipi, housing, flaş, lens
- Diğer: fener, SMB, reel, bıçak, pusula, yazı tahtası
- Seri numarası takibi (her ekipman parçası)
- Fatura/makbuz ekleme (satın alma kanıtı)
- Bakım hatırlatıcıları (regülatör servisi, vb.)
- Dalış sayacı (her ekipman kaç dalışta kullanıldı)
- Ekipman kitleri (sık kullanılan set'leri kaydetme)
3.3 Buddy & Sosyal
Buddy Sistemi
- Buddy adı, sertifika seviyesi, iletişim bilgisi
- Eğitmen/divemaster adı, sertifika numarası, kuruluş
- Dijital imza/QR doğrulama (buddy veya eğitmen onayı — yeşil tik)
- Dalış merkezi adı, konum, derecelendirme
- Dalış grubundaki diğer kişiler
- Profil bazlı buddy listesi (sık dalış yapılan kişiler)
- Dalış daveti (buddy'yi dalışa davet etme)
- Buddy değerlendirmesi
- Birlikte yapılan dalış geçmişi
Topluluk Özellikleri
- Takip sistemi (follow/following)
- Dalış beğenme (like)
- Dalış yorumları (iç içe — nested comments)
- Feed/akış (takip edilen kişilerin dalışları)
- Mesajlaşma
- Grup/kulüp oluşturma
- Etkinlik planlama
- Dalış hikayesi paylaşımı (storytelling — blog benzeri)
- 3 seviye gizlilik: public / friends / private
3.4 Deniz Canlıları
- Tür adı (yaygın/bilimsel)
- Fotoğraf
- Miktar/boyut tahmini
- Davranış notu
- AI fotoğraf bazlı tür tanımlama (fotoğraf yükle → otomatik tür önerisi)
- Tür veritabanı (binlerce tür profili, fotoğraf, habitat bilgisi)
- Mercan sağlığı, yosun seviyesi, su berraklığı
- Nadir gözlemler işareti
- Kişisel "görülen türler" listesi (life list)
- Biyoçeşitlilik katkısı (anonim veri bilimsel veritabanlarına gönderilebilir — GBIF/OBIS)
Çevre Koruma Raporu
- Resif sağlığı değerlendirmesi (1-5)
- Mercan ağartması gözlemi (yok/hafif/orta/şiddetli)
- Deniz çöpü raporu (plastik, ağ, cam, vb.)
- Toplanan çöp miktarı
- İstilacı tür bildirimi
- Çevre koruma etkinliği katılımı
- Karbon ayak izi hesaplama (seyahat dahil)
- Reef Check / Project AWARE entegrasyonu
3.5 Medya
- Fotoğraf ekleme (dalış profili zaman çizelgesine bağlı, GPS etiketli)
- Video ekleme (kısa klipler)
- 360 derece fotoğraf desteği
- Fotoğraf etiketleme (tür, ekipman, buddy)
- Fotoğraf sıkıştırma ve optimize depolama
- Galeri görünümü
- Filigran ekleme (opsiyonel)
- Sosyal medya paylaşımı
- Serbest metin notları + özel notlar (sadece kullanıcı görebilir)
- Kişisel derecelendirme (1-5 yıldız) + zorluk derecelendirmesi (1-5)
- Cloudflare R2 depolama (mevcut altyapıyla uyumlu)
3.6 Sertifika Takibi (Çoklu Kuruluş)
- PADI, SSI, CMAS/TSSF, NAUI, BSAC, GUE, TDI/SDI ve diğerleri
- Sertifika adı, seviyesi, numarası, tarih
- eCard/belge fotoğrafı yükleme
- Sigorta bilgisi (DAN, vb.)
- İlk yardım/CPR sertifikaları
- TSSF Yetki Belgesi doğrulama (Türkiye'ye özel)
3.7 İstatistik & Analiz
- Toplam dalış sayısı, toplam süre, toplam dip zamanı
- Maks/ort/min derinlik istatistikleri
- SAC rate trendi (30 gün, 6 ay, ömür boyu)
- Hava tüketimi pattern görselleştirmesi
- En çok dalınan noktalar
- Aylık/yıllık dalış sıklığı grafikleri
- Sıcaklık ve görüş trendleri
- Ülke/bölge bazlı dalış haritası (heatmap)
- Buddy bazlı istatistikler
- Ekipman kullanım istatistikleri
- Dalış tipi dağılımı (pasta grafik)
- Kümülatif doku yüklemesi takibi (çoklu dalış günlerinde)
3.8 Gamifikasyon & Başarımlar
- Rozet sistemi:
- İlk dalış, 10/25/50/100/250/500/1000. dalış
- İlk gece dalışı, ilk batık dalışı, ilk akıntı dalışı
- Derinlik kilometre taşları (20m, 30m, 40m)
- Coğrafi başarımlar (5/10/20 farklı ülke)
- Tür başarımları (50/100/200 farklı tür gözlemi)
- Sezonluk başarımlar (her mevsimde dalış)
- Topluluk başarımları (10 buddy dalışı, 5 deniz temizliği)
- Seviye sistemi (SSI tarzı: OW → AOW → Rescue → Master → vb.)
- Liderlik tablosu (isteğe bağlı, anonim veya açık)
3.9 Güvenlik & Acil Durum
- Acil durum iletişim kişileri
- Kan grubu
- Tıbbi durumlar (alerji, ilaç, kronik hastalık)
- Sigorta bilgisi ve poliçe numarası
- En yakın basınç odası bulucu (harita üzerinde)
- DAN acil protokolleri (hızlı erişim)
- Tıbbi bilgi paylaşımı (dalış merkezine QR ile)
3.10 Dalış Bilgisayarı Entegrasyonu
- UDDF import/export (evrensel standart)
- Garmin FIT import
- Suunto SML/SDE import
- Shearwater XML import
- Subsurface XML import
- CSV import (genel)
- divelogs.de DLD import
- libdivecomputer entegrasyonu (gelecekte — 140+ model)
- Manuel giriş (bilgisayar olmadan)
- Çoklu bilgisayar birleştirme (aynı dalışta 2 bilgisayar verisi)
3.11 Dalış Planlama (Logbook Entegre)
- Dalış öncesi plan oluşturma
- Mevcut hava hesaplama aracı entegrasyonu (DECO 2000)
- Dekompresyon planlama (Bühlmann ZH-L16C + GF, VPM-B)
- Çoklu seviye dalış planlama
- Tekrarlayan dalış planlama (yüzey aralığı hesabı)
- Gaz tüketimi hesaplama
- Minimum gaz hesaplama (Rule of Thirds, Rock Bottom)
- Bailout gaz planlama (CCR)
- Runtime tablosu oluşturma
- Dalış planı yazdırma
- Rakımda dalış düzeltmesi
- EAD (Equivalent Air Depth) hesaplama
- MOD (Maximum Operating Depth) hesaplama
- END (Equivalent Narcotic Depth) hesaplama
- Best Mix hesaplama
- Plan şablonları (kaydet ve tekrar kullan)
- Dalış noktası koşulları kontrolü (gerçek zamanlı çevre verileri)
- Paketleme kontrol listesi
- Plan → Log dönüşümü (planlanan dalışı otomatik log taslağına çevir)
3.12 Offline-First Mimari
- Tüm loglama offline çalışır
- Fotoğraf/video offline kaydedilir, internet gelince senkronize olur
- Çakışma çözümü (aynı log iki cihazda düzenlenirse)
- PWA desteği (mobilde uygulama gibi çalışır)
- Local-first veritabanı (IndexedDB veya SQLite WASM)
3.13 Eğitmen / Dalış Merkezi Paneli (B2B)
- Öğrenci dalış loglarını görüntüleme ve onaylama
- Eğitim dalışı değerlendirme formu
- Beceri kontrol listesi (her eğitim dalışı için)
- Dalış sonrası debrief şablonu
- Sertifika ilerlemesi takibi
- Ekipman kiralama takibi
- Grup dalış yönetimi
3.14 Bölgesel İçerik (Türkiye Özel)
- TSSF düzenlemeleri ve gereksinimleri
- Deniz parkı izin/ücret bilgileri
- Mevsimsel koşullar takvimi
- Yasak bölgeler haritası
- Türkiye dalış noktaları veritabanı (mevcut)
3.15 Bildirim & Hatırlatma Sistemi
- Ekipman bakım hatırlatması (regülatör servisi, tüp testi, pil değişimi)
- Sertifika süresi dolmak üzere uyarısı (CPR, ilk yardım)
- Tıbbi muayene hatırlatması
- Buddy isteği bildirimi
- Dalış doğrulama bildirimi (buddy onayladı)
- Dalış beğeni/yorum bildirimi
- Takip bildirimi
- Başarım açıldı bildirimi
- Sigorta süresi dolmak üzere uyarısı
3.16 AI & Akıllı Özellikler
- AI destekli deniz türü teşhisi (fotoğraf ile)
- Akıllı dalış önerisi (hava/gelgit/görüş/deneyim seviyesine göre)
- SAC rate tahmin modeli (geçmiş verilere göre)
- Anomali tespiti ve güvenlik uyarıları (hızlı çıkış, deko ihlali)
- Otomatik dalış tipi sınıflama
- Doğal dil ile dalış notu oluşturma
- 3D dalış profili görselleştirme (GPS + derinlik verisiyle)
3.17 Teknik Özellikler
- Metrik/imperial birim değişimi
- Karanlık mod (dark mode)
- Çoklu dil desteği (en az 10 dil)
- GDPR uyumlu — veri yedekleme, geri yükleme, hesap silme, veri taşıma hakkı
- End-to-end şifreleme (tıbbi veriler için)
- 2FA (iki faktörlü doğrulama — mevcut)
- Rol bazlı erişim (dalgıç, eğitmen, merkez yöneticisi, admin)
- Import duplikasyon önleme (dosya hash kontrolü)
3.18 Veri Taşınabilirliği & Format Desteği
| Format | Tip | Yön |
|---|
| UDDF | XML — Evrensel standart | Import + Export |
| Garmin FIT | Binary — Garmin cihazlar | Import |
| Suunto SML | XML — Suunto cihazlar | Import |
| Shearwater XML | XML — Shearwater cihazlar | Import |
| Subsurface XML | XML — Subsurface | Import + Export |
| CSV | Düz metin — Genel | Import + Export |
| divelogs.de DLD | ZIP+XML | Import |
| DAN DL7 | DAN araştırma formatı | Import |
| Mares MDB | Mares cihazlar | Import |
| JSON | TurkeyScuba native | Export |
| PDF | Baskı/paylaşım | Export |
| HTML | Web paylaşımı | Export |
| Excel | Tablo analiz | Export |
| Google Earth KML/KMZ | Harita | Export |
| GPX | GPS izleri | Export |
4. Veritabanı Şeması (Supabase PostgreSQL)
4.1 Ana Tablolar
-- =============================================
-- DALIŞLAR (Ana tablo)
-- =============================================
CREATE TABLE dive_logs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
dive_number INTEGER, -- kullanıcı bazlı sıra numarası
trip_id UUID REFERENCES trips(id) ON DELETE SET NULL,
-- Tarih & Süre
dive_date DATE NOT NULL,
time_in TIMESTAMPTZ,
time_out TIMESTAMPTZ,
duration_min NUMERIC(6,1),
bottom_time_min NUMERIC(6,1), -- dip süresi (toplam süreden ayrı)
surface_interval_min INTEGER, -- bir önceki dalıştan
-- Konum
dive_site_id UUID REFERENCES dive_sites(id),
custom_site_name TEXT, -- DB'de olmayan nokta için
entry_point GEOGRAPHY(POINT, 4326), -- PostGIS giriş koordinatı
exit_point GEOGRAPHY(POINT, 4326), -- PostGIS çıkış koordinatı
country_code CHAR(2),
region TEXT,
-- Derinlik
max_depth_m NUMERIC(5,1),
avg_depth_m NUMERIC(5,1),
planned_depth_m NUMERIC(5,1),
altitude_m INTEGER DEFAULT 0, -- yükseklik dalışı için
-- Gaz (birincil tüp — çoklu tüp için dive_log_tanks)
tank_type TEXT, -- 'steel', 'aluminum'
tank_volume_l NUMERIC(4,1),
gas_mix TEXT DEFAULT 'air', -- 'air', 'ean32', 'ean36', 'trimix'
o2_percent NUMERIC(4,1) DEFAULT 21,
he_percent NUMERIC(4,1) DEFAULT 0,
start_pressure_bar INTEGER,
end_pressure_bar INTEGER,
sac_rate NUMERIC(5,1), -- hesaplanan SAC
rmv NUMERIC(5,1), -- hesaplanan RMV
-- Nefes alma modu & dalış amacı
breathing_mode TEXT DEFAULT 'open_circuit', -- 'open_circuit', 'ccr', 'pscr', 'freediving'
dive_purpose TEXT, -- 'fun', 'training', 'photography', 'research', 'rescue', 'maintenance'
dive_style TEXT, -- 'boat', 'shore', 'drift', 'night', 'ice', 'cave', 'wreck', 'wall', 'muck', 'deep', 'altitude'
water_type TEXT, -- 'salt', 'fresh', 'brackish'
-- Dekompresyon
deco_algorithm TEXT, -- 'buhlmann_zhl16c', 'vpm_b', 'rgbm'
gf_low INTEGER, -- gradient factor low (0-100)
gf_high INTEGER, -- gradient factor high (0-100)
ndl_min INTEGER,
safety_stop_depth_m NUMERIC(3,1),
safety_stop_min NUMERIC(3,1),
safety_stop_performed BOOLEAN DEFAULT TRUE,
deco_stops_performed BOOLEAN DEFAULT FALSE,
total_deco_min INTEGER,
cns_percent NUMERIC(5,2),
otu NUMERIC(7,2),
deco_table TEXT, -- 'deco2000', 'padi_rdp', vb.
-- Koşullar
air_temp_c NUMERIC(4,1),
surface_water_temp_c NUMERIC(4,1),
bottom_water_temp_c NUMERIC(4,1),
thermocline_depth_m NUMERIC(4,1),
visibility_m NUMERIC(4,1),
current TEXT, -- 'none', 'mild', 'moderate', 'strong'
surge TEXT, -- 'none', 'mild', 'moderate', 'strong'
wave_height_m NUMERIC(3,1),
wind_speed_kmh NUMERIC(4,1),
wind_direction TEXT,
weather TEXT, -- 'sunny', 'cloudy', 'rainy', 'overcast'
tide TEXT, -- 'high', 'low', 'incoming', 'outgoing', 'slack'
moon_phase TEXT, -- otomatik hesaplanır
barometer_hpa NUMERIC(6,1),
uv_index SMALLINT,
-- Dalış tipi & aktivite
dive_type TEXT[] DEFAULT '{}', -- ['recreational', 'night', 'drift', 'wreck', 'cave', 'ice', 'training']
activity TEXT[] DEFAULT '{}', -- ['photography', 'videography', 'research', 'cleanup', 'instruction']
entry_method TEXT, -- 'shore', 'boat', 'zodiac'
entry_technique TEXT, -- 'giant_stride', 'back_roll', 'seated'
-- Elbise & Ağırlık
suit_type TEXT, -- 'wetsuit', 'drysuit', 'skin', 'none'
suit_thickness_mm NUMERIC(3,1),
hood BOOLEAN DEFAULT FALSE,
gloves BOOLEAN DEFAULT FALSE,
boots BOOLEAN DEFAULT FALSE,
weight_total_kg NUMERIC(4,1),
weight_type TEXT, -- 'belt', 'integrated', 'ankle', 'mixed'
buoyancy_check BOOLEAN,
-- Buddy & Merkez
buddy_id UUID REFERENCES profiles(id),
buddy_name TEXT, -- platformda olmayan buddy için
instructor_id UUID REFERENCES profiles(id),
instructor_name TEXT,
dive_center_id UUID REFERENCES dive_schools(id),
custom_dive_center_name TEXT, -- platformda olmayan merkez için
-- Güvenlik
had_safety_issue BOOLEAN DEFAULT FALSE,
safety_issue_description TEXT,
rapid_ascent BOOLEAN DEFAULT FALSE,
missed_deco BOOLEAN DEFAULT FALSE,
-- Değerlendirme
rating SMALLINT CHECK (rating BETWEEN 1 AND 5),
difficulty_rating SMALLINT CHECK (difficulty_rating BETWEEN 1 AND 5),
notes TEXT,
private_notes TEXT, -- sadece kullanıcının görebileceği notlar
-- Doğrulama
verified_by UUID REFERENCES profiles(id), -- buddy/eğitmen onayı
verified_at TIMESTAMPTZ,
verification_method TEXT, -- 'qr', 'digital_signature', 'manual'
-- Bilgisayar import
computer_brand TEXT,
computer_model TEXT,
import_format TEXT, -- 'uddf', 'fit', 'sml', 'shearwater_xml', 'manual'
original_file_hash TEXT, -- kaynak dosya hash (duplikasyon önleme)
raw_import_data JSONB, -- orijinal import verisi (yedek)
-- Çevre verisi otomatik doldurma
env_data_auto_filled BOOLEAN DEFAULT FALSE,
env_data_source TEXT, -- 'openmeteo', 'stormglass', vb.
-- Gizlilik (3 seviye: public / friends / private)
visibility TEXT NOT NULL DEFAULT 'public'
CHECK (visibility IN ('public', 'friends', 'private')),
-- public → herkes görür
-- friends → sadece takipçiler (user_follows) görür
-- private → sadece sahibi görür
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now(),
deleted_at TIMESTAMPTZ -- soft delete
);
-- İndeksler
CREATE INDEX idx_dive_logs_user_id ON dive_logs(user_id);
CREATE INDEX idx_dive_logs_dive_date ON dive_logs(dive_date DESC);
CREATE INDEX idx_dive_logs_dive_site_id ON dive_logs(dive_site_id);
CREATE INDEX idx_dive_logs_entry_point ON dive_logs USING GIST(entry_point);
CREATE INDEX idx_dive_logs_deleted_at ON dive_logs(deleted_at) WHERE deleted_at IS NULL;
CREATE INDEX idx_dive_logs_visibility ON dive_logs(visibility);
-- =============================================
-- DECO DURAKLARI (dalış başına çoklu durak)
-- =============================================
CREATE TABLE dive_log_deco_stops (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
dive_log_id UUID NOT NULL REFERENCES dive_logs(id) ON DELETE CASCADE,
depth_m NUMERIC(4,1) NOT NULL,
duration_min NUMERIC(5,1) NOT NULL,
sort_order SMALLINT DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_deco_stops_dive_log ON dive_log_deco_stops(dive_log_id);
-- =============================================
-- ÇOKLU TÜP (teknik dalışlar için)
-- =============================================
CREATE TABLE dive_log_tanks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
dive_log_id UUID NOT NULL REFERENCES dive_logs(id) ON DELETE CASCADE,
tank_number SMALLINT NOT NULL DEFAULT 1,
tank_type TEXT, -- 'steel', 'aluminum'
tank_volume_l NUMERIC(4,1),
gas_mix TEXT DEFAULT 'air',
o2_percent NUMERIC(4,1) DEFAULT 21,
he_percent NUMERIC(4,1) DEFAULT 0,
start_pressure_bar INTEGER,
end_pressure_bar INTEGER,
switch_depth_m NUMERIC(4,1), -- gaz geçiş derinliği
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_tanks_dive_log ON dive_log_tanks(dive_log_id);
-- =============================================
-- EKİPMAN
-- =============================================
CREATE TABLE equipment (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
category TEXT NOT NULL, -- 'bcd', 'regulator', 'computer', 'suit', 'mask', 'fins', 'camera', 'light', 'smb', 'other'
brand TEXT,
model TEXT,
serial_number TEXT,
purchase_date DATE,
purchase_price NUMERIC(10,2),
currency CHAR(3) DEFAULT 'TRY',
notes TEXT,
image_url TEXT, -- R2'de fotoğraf
invoice_url TEXT, -- R2'de fatura
is_active BOOLEAN DEFAULT TRUE,
total_dives INTEGER DEFAULT 0, -- otomatik güncellenen sayaç
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now(),
deleted_at TIMESTAMPTZ
);
CREATE INDEX idx_equipment_user_id ON equipment(user_id);
-- =============================================
-- EKİPMAN BAKIM GEÇMİŞİ
-- =============================================
CREATE TABLE equipment_maintenance (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
equipment_id UUID NOT NULL REFERENCES equipment(id) ON DELETE CASCADE,
maintenance_type TEXT NOT NULL, -- 'service', 'repair', 'inspection', 'battery_change'
description TEXT,
performed_at DATE NOT NULL,
performed_by TEXT, -- servis merkezi adı
cost NUMERIC(10,2),
currency CHAR(3) DEFAULT 'TRY',
next_maintenance_date DATE, -- hatırlatıcı
next_maintenance_dives INTEGER, -- X dalış sonra bakım
receipt_url TEXT, -- R2'de makbuz
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_maintenance_equipment ON equipment_maintenance(equipment_id);
-- =============================================
-- DALIŞ-EKİPMAN İLİŞKİSİ
-- =============================================
CREATE TABLE dive_log_equipment (
dive_log_id UUID NOT NULL REFERENCES dive_logs(id) ON DELETE CASCADE,
equipment_id UUID NOT NULL REFERENCES equipment(id) ON DELETE CASCADE,
PRIMARY KEY (dive_log_id, equipment_id)
);
-- =============================================
-- EKİPMAN KİTLERİ (sık kullanılan setler)
-- =============================================
CREATE TABLE equipment_kits (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
name TEXT NOT NULL, -- 'Yaz seti', 'Teknik dalış seti'
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE equipment_kit_items (
kit_id UUID NOT NULL REFERENCES equipment_kits(id) ON DELETE CASCADE,
equipment_id UUID NOT NULL REFERENCES equipment(id) ON DELETE CASCADE,
PRIMARY KEY (kit_id, equipment_id)
);
-- =============================================
-- DENİZ CANLILARI GÖZLEMLERİ
-- =============================================
CREATE TABLE dive_log_species (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
dive_log_id UUID NOT NULL REFERENCES dive_logs(id) ON DELETE CASCADE,
species_id UUID REFERENCES marine_species(id), -- varsa DB'deki tür
custom_species_name TEXT, -- DB'de yoksa
quantity TEXT, -- 'single', 'few', 'school', 'many'
size_estimate TEXT, -- 'small', 'medium', 'large'
behavior_notes TEXT,
photo_url TEXT,
ai_identified BOOLEAN DEFAULT FALSE, -- AI ile tanımlandı mı
ai_confidence NUMERIC(3,2), -- 0.00-1.00 güven skoru
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_species_dive_log ON dive_log_species(dive_log_id);
-- =============================================
-- DENİZ TÜRLERİ REFERANS TABLOSU
-- =============================================
CREATE TABLE marine_species (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
common_name_tr TEXT,
common_name_en TEXT,
scientific_name TEXT NOT NULL,
family TEXT,
category TEXT, -- 'fish', 'invertebrate', 'mammal', 'reptile', 'coral', 'plant'
habitat TEXT[], -- ['reef', 'pelagic', 'sand', 'cave', 'wreck']
depth_range_min_m INTEGER,
depth_range_max_m INTEGER,
conservation_status TEXT, -- IUCN: 'LC', 'NT', 'VU', 'EN', 'CR'
image_url TEXT,
description_tr TEXT,
description_en TEXT,
regions TEXT[], -- ['mediterranean', 'red_sea', 'caribbean', 'indo_pacific']
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_marine_species_name ON marine_species(scientific_name);
-- =============================================
-- SERTİFİKALAR
-- =============================================
CREATE TABLE certifications (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
agency TEXT NOT NULL, -- 'PADI', 'SSI', 'CMAS', 'TSSF', 'NAUI', 'BSAC', 'GUE', 'TDI', 'SDI'
certification_name TEXT NOT NULL, -- 'Open Water Diver', 'Advanced', vb.
certification_level TEXT, -- '1_star', '2_star', '3_star' (CMAS) veya 'ow', 'aow', 'rescue', 'dm', 'instructor'
certification_number TEXT,
issue_date DATE,
expiry_date DATE, -- varsa (CPR/First Aid gibi)
instructor_name TEXT,
instructor_number TEXT,
dive_center TEXT,
card_front_url TEXT, -- R2'de eCard fotoğrafı
card_back_url TEXT,
is_verified BOOLEAN DEFAULT FALSE,
verified_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_certifications_user_id ON certifications(user_id);
-- =============================================
-- MEDYA (fotoğraf/video)
-- =============================================
CREATE TABLE dive_log_media (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
dive_log_id UUID NOT NULL REFERENCES dive_logs(id) ON DELETE CASCADE,
media_type TEXT NOT NULL, -- 'photo', 'video'
url TEXT NOT NULL, -- R2 URL
thumbnail_url TEXT,
caption TEXT,
taken_at TIMESTAMPTZ, -- fotoğrafın çekildiği an
depth_m NUMERIC(5,1), -- fotoğrafın çekildiği derinlik
location GEOGRAPHY(POINT, 4326), -- fotoğrafın GPS koordinatı
file_size_bytes BIGINT,
width INTEGER,
height INTEGER,
sort_order SMALLINT DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_media_dive_log ON dive_log_media(dive_log_id);
-- =============================================
-- BAŞARIMLAR / ROZETLER
-- =============================================
CREATE TABLE achievements (
id TEXT PRIMARY KEY, -- 'first_dive', 'dive_100', 'night_owl', 'globe_trotter_10'
name_key TEXT NOT NULL, -- i18n çeviri anahtarı
description_key TEXT NOT NULL,
icon TEXT NOT NULL, -- ikon adı veya URL
category TEXT NOT NULL, -- 'milestone', 'depth', 'geography', 'species', 'community', 'seasonal'
threshold INTEGER, -- eşik değeri (100. dalış için 100)
sort_order SMALLINT DEFAULT 0
);
CREATE TABLE user_achievements (
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
achievement_id TEXT NOT NULL REFERENCES achievements(id),
unlocked_at TIMESTAMPTZ DEFAULT now(),
dive_log_id UUID REFERENCES dive_logs(id), -- rozeti tetikleyen dalış
PRIMARY KEY (user_id, achievement_id)
);
CREATE INDEX idx_user_achievements_user ON user_achievements(user_id);
-- =============================================
-- ACİL DURUM & TIBBİ BİLGİ
-- =============================================
CREATE TABLE emergency_info (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE UNIQUE,
blood_type TEXT, -- 'A+', 'A-', 'B+', 'B-', 'AB+', 'AB-', 'O+', 'O-'
allergies TEXT[],
medications TEXT[],
medical_conditions TEXT[],
insurance_provider TEXT,
insurance_policy_number TEXT,
insurance_expiry DATE,
emergency_contact_1_name TEXT,
emergency_contact_1_phone TEXT,
emergency_contact_1_relation TEXT,
emergency_contact_2_name TEXT,
emergency_contact_2_phone TEXT,
emergency_contact_2_relation TEXT,
physician_name TEXT,
physician_phone TEXT,
notes TEXT,
share_with_dive_center BOOLEAN DEFAULT FALSE, -- QR ile merkeze paylaşım
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
-- =============================================
-- BASINÇ ODALARI (hiperbarik merkezler)
-- =============================================
CREATE TABLE hyperbaric_chambers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
location GEOGRAPHY(POINT, 4326) NOT NULL,
address TEXT,
city TEXT,
country_code CHAR(2),
phone TEXT,
phone_emergency TEXT,
is_24h BOOLEAN DEFAULT FALSE,
notes TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_chambers_location ON hyperbaric_chambers USING GIST(location);
-- =============================================
-- DALIŞA DAVET / BUDDY İSTEKLERİ
-- =============================================
CREATE TABLE dive_invitations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
inviter_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
invitee_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
dive_date DATE NOT NULL,
dive_site_id UUID REFERENCES dive_sites(id),
message TEXT,
status TEXT DEFAULT 'pending', -- 'pending', 'accepted', 'declined'
created_at TIMESTAMPTZ DEFAULT now(),
responded_at TIMESTAMPTZ
);
CREATE INDEX idx_invitations_invitee ON dive_invitations(invitee_id, status);
-- =============================================
-- SEYAHAT / TRIP GRUPLAMA
-- =============================================
CREATE TABLE trips (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
name TEXT NOT NULL, -- 'Kaş 2026', 'Kızıldeniz Turu'
description TEXT,
start_date DATE,
end_date DATE,
location TEXT,
country_code CHAR(2),
cover_image_url TEXT,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now(),
deleted_at TIMESTAMPTZ
);
CREATE INDEX idx_trips_user_id ON trips(user_id);
-- =============================================
-- SERTİFİKA KURULUŞLARI (referans)
-- =============================================
CREATE TABLE certification_agencies (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL, -- 'PADI', 'SSI', 'CMAS', 'TSSF', 'NAUI', 'BSAC', 'GUE', 'TDI'
full_name TEXT,
logo_url TEXT,
website_url TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE certification_levels (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
agency_id UUID NOT NULL REFERENCES certification_agencies(id),
name TEXT NOT NULL, -- 'Open Water Diver', 'Advanced', 'Rescue', vb.
category TEXT, -- 'recreational', 'technical', 'professional', 'specialty'
sort_order SMALLINT DEFAULT 0,
min_age SMALLINT,
min_dives_required SMALLINT,
description TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_cert_levels_agency ON certification_levels(agency_id);
-- =============================================
-- TÜP (TANK) YÖNETİMİ (ekipmandan ayrı)
-- =============================================
CREATE TABLE tanks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
name TEXT, -- 'Ana tüp', 'Stage 1'
material TEXT NOT NULL, -- 'steel', 'aluminum', 'carbon'
volume_l NUMERIC(5,2) NOT NULL,
working_pressure_bar NUMERIC(5,1) NOT NULL,
test_pressure_bar NUMERIC(5,1),
serial_number TEXT,
valve_type TEXT, -- 'din', 'yoke', 'manifold'
last_hydro_test DATE,
hydro_test_interval_years SMALLINT DEFAULT 5,
last_visual_inspection DATE,
visual_inspection_interval_months SMALLINT DEFAULT 12,
status TEXT DEFAULT 'active', -- 'active', 'condemned', 'retired'
notes TEXT,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_tanks_user_id ON tanks(user_id);
-- =============================================
-- DALIŞ PROFİLİ — ZAMAN SERİSİ VERİLERİ
-- =============================================
CREATE TABLE dive_profile_samples (
id BIGSERIAL PRIMARY KEY,
dive_log_id UUID NOT NULL REFERENCES dive_logs(id) ON DELETE CASCADE,
sample_time_sec INTEGER NOT NULL, -- dalış başlangıcından itibaren saniye
depth_m NUMERIC(6,2),
temperature_c NUMERIC(5,2),
tank_pressure_bar NUMERIC(5,1),
heartrate_bpm SMALLINT,
ndl_sec INTEGER, -- No Deco Limit kalan
ceiling_m NUMERIC(5,2), -- deko tavanı
tts_sec INTEGER, -- Time To Surface
setpoint NUMERIC(3,2), -- CCR setpoint
ppo2_sensor1 NUMERIC(3,2), -- CCR O2 sensör 1
ppo2_sensor2 NUMERIC(3,2),
ppo2_sensor3 NUMERIC(3,2),
cns_percent NUMERIC(5,2),
otu NUMERIC(7,2),
bearing SMALLINT, -- pusula yönü (0-360)
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_profile_dive_time ON dive_profile_samples(dive_log_id, sample_time_sec);
-- =============================================
-- DALIŞ OLAYLARI (events)
-- =============================================
CREATE TABLE dive_events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
dive_log_id UUID NOT NULL REFERENCES dive_logs(id) ON DELETE CASCADE,
event_time_sec INTEGER NOT NULL,
event_type TEXT NOT NULL,
-- event_type değerleri:
-- gas_switch, safety_stop_begin, safety_stop_end,
-- deco_stop_begin, deco_stop_end, bookmark, alarm,
-- heading, surface, ascent_warning, deco_violation,
-- po2_warning, low_battery, low_gas, bailout_switch
event_value TEXT,
event_description TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_events_dive_log ON dive_events(dive_log_id);
-- =============================================
-- BUDDY'LER (platformda kayıtlı olmayan)
-- =============================================
CREATE TABLE buddies (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
buddy_user_id UUID REFERENCES profiles(id), -- kayıtlı kullanıcı ise
buddy_name TEXT NOT NULL,
buddy_email TEXT,
buddy_certification TEXT,
buddy_agency TEXT,
notes TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_buddies_user_id ON buddies(user_id);
-- =============================================
-- DALIŞ-BUDDY İLİŞKİSİ (junction table)
-- =============================================
CREATE TABLE dive_buddies (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
dive_log_id UUID NOT NULL REFERENCES dive_logs(id) ON DELETE CASCADE,
buddy_id UUID REFERENCES buddies(id),
buddy_user_id UUID REFERENCES profiles(id),
role TEXT DEFAULT 'buddy', -- 'buddy', 'instructor', 'guide', 'divemaster'
is_verified BOOLEAN DEFAULT FALSE,
verified_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_dive_buddies_dive ON dive_buddies(dive_log_id);
-- =============================================
-- TAKİP SİSTEMİ
-- =============================================
CREATE TABLE user_follows (
follower_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
following_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
created_at TIMESTAMPTZ DEFAULT now(),
PRIMARY KEY (follower_id, following_id)
);
CREATE INDEX idx_follows_following ON user_follows(following_id);
-- =============================================
-- DALIŞ BEĞENİLERİ
-- =============================================
CREATE TABLE dive_likes (
dive_log_id UUID NOT NULL REFERENCES dive_logs(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
created_at TIMESTAMPTZ DEFAULT now(),
PRIMARY KEY (dive_log_id, user_id)
);
-- =============================================
-- DALIŞ YORUMLARI (nested)
-- =============================================
CREATE TABLE dive_comments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
dive_log_id UUID NOT NULL REFERENCES dive_logs(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
comment_text TEXT NOT NULL,
parent_comment_id UUID REFERENCES dive_comments(id), -- iç içe yorumlar
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now(),
deleted_at TIMESTAMPTZ
);
CREATE INDEX idx_comments_dive_log ON dive_comments(dive_log_id);
-- =============================================
-- BİLDİRİMLER
-- =============================================
CREATE TABLE notifications (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
type TEXT NOT NULL,
-- type değerleri:
-- buddy_request, dive_verified, dive_liked, dive_commented,
-- follow, equipment_maintenance_due, certification_expiring,
-- medical_exam_due, tank_inspection_due, achievement_unlocked
title TEXT NOT NULL,
body TEXT,
reference_type TEXT, -- 'dive', 'buddy', 'equipment', 'certification'
reference_id UUID,
is_read BOOLEAN DEFAULT FALSE,
read_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_notifications_user ON notifications(user_id, is_read);
-- =============================================
-- EKİPMAN HATIRLATMALARI
-- =============================================
CREATE TABLE equipment_reminders (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
equipment_id UUID NOT NULL REFERENCES equipment(id) ON DELETE CASCADE,
reminder_type TEXT NOT NULL, -- 'service_due', 'inspection_due', 'hydro_test_due', 'warranty_expiry'
reminder_date DATE NOT NULL,
is_completed BOOLEAN DEFAULT FALSE,
completed_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_reminders_equipment ON equipment_reminders(equipment_id);
-- =============================================
-- DALIŞ PLANLAMA
-- =============================================
CREATE TABLE dive_plans (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
name TEXT,
dive_site_id UUID REFERENCES dive_sites(id),
planned_date DATE,
-- Planlama parametreleri
algorithm TEXT, -- 'buhlmann_zhl16c', 'vpm_b'
gf_low INTEGER,
gf_high INTEGER,
conservatism TEXT, -- 'low', 'medium', 'high'
-- Dalış parametreleri
max_depth_m NUMERIC(6,2),
bottom_time_min INTEGER,
descent_rate NUMERIC(4,1) DEFAULT 18.0, -- m/dk
ascent_rate NUMERIC(4,1) DEFAULT 9.0,
last_stop_depth_m NUMERIC(4,1) DEFAULT 3.0,
altitude_m INTEGER DEFAULT 0,
breathing_mode TEXT DEFAULT 'open_circuit',
sac_rate NUMERIC(5,2) DEFAULT 15.0, -- L/min varsayılan
-- Hesaplanan sonuçlar
total_runtime_min INTEGER,
total_deco_min INTEGER,
total_gas_needed_l NUMERIC(8,1),
plan_output_text TEXT, -- runtime tablosu
notes TEXT,
is_template BOOLEAN DEFAULT FALSE,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_plans_user_id ON dive_plans(user_id);
-- =============================================
-- DALIŞ PLANI GAZLARI
-- =============================================
CREATE TABLE dive_plan_gases (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
dive_plan_id UUID NOT NULL REFERENCES dive_plans(id) ON DELETE CASCADE,
gas_order SMALLINT NOT NULL,
gas_type TEXT NOT NULL, -- 'air', 'nitrox', 'trimix', 'oxygen'
o2_percent NUMERIC(5,2) NOT NULL,
he_percent NUMERIC(5,2) DEFAULT 0,
gas_usage TEXT, -- 'bottom', 'deco', 'travel', 'bailout'
switch_depth_m NUMERIC(5,1),
tank_volume_l NUMERIC(5,2),
start_pressure_bar NUMERIC(5,1),
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_plan_gases_plan ON dive_plan_gases(dive_plan_id);
-- =============================================
-- ÇEVRE KORUMA RAPORU
-- =============================================
CREATE TABLE dive_environmental_reports (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
dive_log_id UUID NOT NULL REFERENCES dive_logs(id) ON DELETE CASCADE,
reef_health_rating SMALLINT CHECK (reef_health_rating BETWEEN 1 AND 5),
coral_bleaching_observed BOOLEAN DEFAULT FALSE,
coral_bleaching_severity TEXT, -- 'none', 'mild', 'moderate', 'severe'
marine_debris_observed BOOLEAN DEFAULT FALSE,
debris_types TEXT[], -- ['plastic', 'fishing_line', 'nets', 'cans', 'glass']
debris_quantity TEXT, -- 'none', 'little', 'moderate', 'lots'
debris_collected BOOLEAN DEFAULT FALSE,
debris_collected_kg NUMERIC(5,2),
invasive_species_observed BOOLEAN DEFAULT FALSE,
invasive_species_notes TEXT,
water_quality_notes TEXT,
general_notes TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_env_reports_dive ON dive_environmental_reports(dive_log_id);
-- =============================================
-- MEDYA ETİKETLERİ
-- =============================================
CREATE TABLE media_tags (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
media_id UUID NOT NULL REFERENCES dive_log_media(id) ON DELETE CASCADE,
tag_type TEXT, -- 'species', 'equipment', 'buddy', 'location', 'other'
tag_value TEXT,
species_id UUID REFERENCES marine_species(id),
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_media_tags_media ON media_tags(media_id);
-- =============================================
-- GÖRÜLEN TÜRLER LİFE LIST (VIEW)
-- =============================================
CREATE VIEW user_species_life_list AS
SELECT
dl.user_id,
ms.id AS species_id,
ms.common_name_tr,
ms.common_name_en,
ms.scientific_name,
ms.category,
COUNT(dls.id) AS times_seen,
MIN(dl.dive_date) AS first_seen_date,
MAX(dl.dive_date) AS last_seen_date
FROM dive_log_species dls
JOIN dive_logs dl ON dls.dive_log_id = dl.id
JOIN marine_species ms ON dls.species_id = ms.id
WHERE dl.deleted_at IS NULL
GROUP BY dl.user_id, ms.id, ms.common_name_tr, ms.common_name_en, ms.scientific_name, ms.category;
-- =============================================
-- RLS POLİCY'LERİ
-- =============================================
-- Ana tablolar
ALTER TABLE dive_logs ENABLE ROW LEVEL SECURITY;
ALTER TABLE dive_log_deco_stops ENABLE ROW LEVEL SECURITY;
ALTER TABLE dive_log_tanks ENABLE ROW LEVEL SECURITY;
ALTER TABLE dive_profile_samples ENABLE ROW LEVEL SECURITY;
ALTER TABLE dive_events ENABLE ROW LEVEL SECURITY;
-- Ekipman
ALTER TABLE equipment ENABLE ROW LEVEL SECURITY;
ALTER TABLE equipment_maintenance ENABLE ROW LEVEL SECURITY;
ALTER TABLE equipment_reminders ENABLE ROW LEVEL SECURITY;
ALTER TABLE dive_log_equipment ENABLE ROW LEVEL SECURITY;
ALTER TABLE equipment_kits ENABLE ROW LEVEL SECURITY;
ALTER TABLE equipment_kit_items ENABLE ROW LEVEL SECURITY;
ALTER TABLE tanks ENABLE ROW LEVEL SECURITY;
-- Deniz canlıları & çevre
ALTER TABLE dive_log_species ENABLE ROW LEVEL SECURITY;
ALTER TABLE dive_environmental_reports ENABLE ROW LEVEL SECURITY;
-- Sertifikalar
ALTER TABLE certifications ENABLE ROW LEVEL SECURITY;
-- Medya
ALTER TABLE dive_log_media ENABLE ROW LEVEL SECURITY;
ALTER TABLE media_tags ENABLE ROW LEVEL SECURITY;
-- Sosyal
ALTER TABLE buddies ENABLE ROW LEVEL SECURITY;
ALTER TABLE dive_buddies ENABLE ROW LEVEL SECURITY;
ALTER TABLE user_follows ENABLE ROW LEVEL SECURITY;
ALTER TABLE dive_likes ENABLE ROW LEVEL SECURITY;
ALTER TABLE dive_comments ENABLE ROW LEVEL SECURITY;
-- Başarımlar & bildirimler
ALTER TABLE user_achievements ENABLE ROW LEVEL SECURITY;
ALTER TABLE notifications ENABLE ROW LEVEL SECURITY;
-- Kişisel bilgiler
ALTER TABLE emergency_info ENABLE ROW LEVEL SECURITY;
ALTER TABLE trips ENABLE ROW LEVEL SECURITY;
ALTER TABLE dive_invitations ENABLE ROW LEVEL SECURITY;
ALTER TABLE dive_plans ENABLE ROW LEVEL SECURITY;
ALTER TABLE dive_plan_gases ENABLE ROW LEVEL SECURITY;
-- Örnek RLS policy'leri (dive_logs)
-- Sahip her zaman kendi dalışlarını görür
CREATE POLICY "Kullanıcı kendi loglarını görebilir"
ON dive_logs FOR SELECT
USING (auth.uid() = user_id);
-- Public dalışları herkes görür
CREATE POLICY "Public logları herkes görebilir"
ON dive_logs FOR SELECT
USING (visibility = 'public' AND deleted_at IS NULL);
-- Friends dalışlarını sadece takipçiler görür
CREATE POLICY "Friends loglarını takipçiler görebilir"
ON dive_logs FOR SELECT
USING (
visibility = 'friends'
AND deleted_at IS NULL
AND EXISTS (
SELECT 1 FROM user_follows
WHERE follower_id = auth.uid()
AND following_id = dive_logs.user_id
)
);
CREATE POLICY "Kullanıcı kendi loglarını oluşturabilir"
ON dive_logs FOR INSERT
WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Kullanıcı kendi loglarını düzenleyebilir"
ON dive_logs FOR UPDATE
USING (auth.uid() = user_id);
CREATE POLICY "Kullanıcı kendi loglarını silebilir"
ON dive_logs FOR DELETE
USING (auth.uid() = user_id);
4.2 Tablo İlişki Diyagramı (Özet)
auth.users (Supabase)
├── dive_logs (1:N) — Ana dalış kaydı
│ ├── dive_log_deco_stops (1:N)
│ ├── dive_log_tanks (1:N)
│ ├── dive_profile_samples (1:N) — zaman serisi veri noktaları
│ ├── dive_events (1:N) — dalış olayları (gaz değişimi, alarm vb.)
│ ├── dive_log_equipment (N:M → equipment)
│ ├── dive_log_species (1:N → marine_species)
│ ├── dive_log_media (1:N)
│ │ └── media_tags (1:N → marine_species)
│ ├── dive_buddies (1:N → buddies / profiles)
│ ├── dive_environmental_reports (1:1)
│ ├── dive_likes (1:N)
│ ├── dive_comments (1:N, self-ref nested)
│ └── user_achievements (N:M → achievements)
├── trips (1:N) — seyahat gruplaması
│ └── dive_logs (FK)
├── equipment (1:N)
│ ├── equipment_maintenance (1:N)
│ ├── equipment_reminders (1:N)
│ └── equipment_kit_items (N:M → equipment_kits)
├── equipment_kits (1:N)
├── tanks (1:N) — tüp yönetimi (hydro test, visual inspection)
├── buddies (1:N) — kayıtsız buddy rehberi
├── certifications (1:N)
├── emergency_info (1:1)
├── notifications (1:N)
├── dive_invitations (1:N — inviter/invitee)
├── dive_plans (1:N)
│ └── dive_plan_gases (1:N)
└── user_follows (N:M — follower/following)
dive_sites (mevcut tablo)
├── dive_logs (FK)
└── dive_plans (FK)
dive_schools (mevcut tablo)
└── dive_logs (FK)
certification_agencies (referans)
└── certification_levels (1:N)
marine_species (referans)
├── dive_log_species (FK)
└── media_tags (FK)
hyperbaric_chambers (bağımsız, PostGIS)
achievements (referans)
└── user_achievements (FK)
-- VIEW
user_species_life_list → dive_log_species + dive_logs + marine_species
4.3 Toplam Tablo/View Sayısı
| Kategori | Tablo Sayısı |
|---|
| Dalış kaydı (ana + alt tablolar) | 7 |
| Ekipman & tüp | 6 |
| Sertifika | 3 |
| Deniz canlıları & çevre | 3 |
| Medya | 2 |
| Sosyal & buddy | 5 |
| Başarımlar & bildirimler | 4 |
| Kişisel bilgiler & planlama | 5 |
| Referans | 3 |
| View | 1 |
| Toplam | 39 |
5. Rakiplerden Farklılaşma Stratejisi
| Özellik | TurkeyScuba Avantajı |
|---|
| TSSF/CMAS entegrasyonu | Hiçbir platformda yok — Türkiye dalış pazarında tek |
| Dalış merkezi + dalgıç birleşik platform | B2B+B2C model — merkez ve dalgıç aynı ekosistemde |
| Mevcut dalış noktaları DB | Zaten 100+ Türkiye dalış noktası var, logbook'la entegre |
| Hava hesaplama aracı entegre | DECO 2000 zaten var, plan → log dönüşümü yapılabilir |
| Offline-first | Su altı = internet yok. Rakiplerin çoğu bulut bağımlı |
| Modern UI | Subsurface/Diviac/divelogs.de hepsi eski — tasarım avantajı |
| Abonelik yok | Temel logbook ücretsiz — Deepblu'nun hatasını tekrarlama |
| Çoklu kuruluş sertifika | PADI + SSI + CMAS/TSSF + diğerleri tek yerde |
| Çevre verisi otomatik doldurma | Sadece Wikibubbles'da var (çok yeni, küçük) |
| Biyoçeşitlilik katkısı | Sadece Diveboard'da var — bilimsel değer |
6. Öncelik Sıralaması (Fazlar)
Faz A — MVP Logbook
dive_logs tablosu + CRUD (temel alanlar)
trips tablosu (seyahat gruplaması)
- Manuel dalış girişi formu (wizard — adım adım)
- Dalış listesi (tarih sıralı, trip bazlı gruplama)
- Dalış detay sayfası (profil grafiği, koşullar, notlar)
- Temel istatistikler (toplam dalış, maks derinlik, toplam süre)
- Dalış noktası ilişkilendirme (mevcut DB)
tanks tablosu + tüp yönetimi
Faz B — Zenginleştirme
- Ekipman yönetimi + bakım takibi + hatırlatıcılar
- Sertifika takibi (çoklu kuruluş —
certification_agencies + certification_levels)
- Buddy sistemi (
buddies + dive_buddies) + QR doğrulama
- Fotoğraf/video ekleme (R2) +
media_tags
- Derinlik profili görselleştirme (SVG —
dive_profile_samples verisinden)
- UDDF/CSV import + dosya hash kontrolü (duplikasyon önleme)
dive_events tablosu (gaz değişimi, alarm, bookmark)
Faz C — Sosyal & Topluluk
- Takip sistemi (
user_follows)
- Dalış beğenme (
dive_likes) + yorumlar (dive_comments — nested)
- Feed/akış (takip edilen kişilerin dalışları)
- 3 seviye gizlilik (public / friends / private)
- Bildirim sistemi (
notifications)
- Dalış daveti (
dive_invitations)
Faz D — Akıllı Özellikler
- Otomatik çevre verisi doldurma (OpenMeteo/StormGlass API)
- Gamifikasyon (rozetler/başarımlar)
- SAC rate trendi ve analiz dashboard
- Acil durum bilgileri + basınç odası bulucu (PostGIS)
- Deniz canlıları loglama +
user_species_life_list VIEW
- Çevre koruma raporu (
dive_environmental_reports)
Faz E — İleri Özellikler
- AI tür tanımlama (fotoğraftan otomatik tür teşhisi)
- Dalış planlama (
dive_plans + dive_plan_gases) → log dönüşümü
- Eğitmen/merkez paneli entegrasyonu (beceri değerlendirme, debrief)
- Offline-first (PWA + IndexedDB/SQLite WASM)
- Çoklu bilgisayar import (FIT, SML, Shearwater XML, Mares MDB)
- Biyoçeşitlilik veri katkısı (GBIF/OBIS)
- Akıllı dalış önerisi (hava/gelgit/görüş/deneyim)
- 3D dalış profili görselleştirme (GPS + derinlik)
- Anomali tespiti ve güvenlik uyarıları
- Export: PDF, Excel, KML/KMZ, GPX, HTML