File size: 5,708 Bytes
6861124
6c07b9b
 
f2b55bf
f134785
 
6c07b9b
 
f134785
 
 
 
 
d066503
 
 
 
 
 
 
6861124
 
60fa8f9
f2b55bf
6861124
 
 
d066503
 
 
 
 
 
f134785
d066503
 
 
f2b55bf
d066503
 
60fa8f9
 
63cd5eb
 
f2b55bf
 
63cd5eb
f2b55bf
 
 
 
 
 
 
f134785
f2b55bf
60fa8f9
d066503
60fa8f9
f2b55bf
d066503
f2b55bf
 
 
 
 
60fa8f9
d066503
60fa8f9
f2b55bf
f134785
f2b55bf
 
d066503
 
 
 
 
 
 
 
 
f2b55bf
d066503
 
f134785
d066503
 
 
 
 
 
f2b55bf
d066503
 
f134785
 
d066503
f2b55bf
 
 
d066503
f2b55bf
d066503
 
f2b55bf
 
63cd5eb
 
f2b55bf
63cd5eb
 
 
f2b55bf
d066503
 
63cd5eb
f134785
63cd5eb
d066503
f2b55bf
d066503
 
f134785
d066503
 
 
 
 
f134785
d066503
f2b55bf
d066503
6c07b9b
f134785
67391f5
d066503
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import os
import warnings

# --- TİTREMEYİ VE GEREKSİZ LOGLARI ENGELLE ---
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' 
os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
warnings.filterwarnings('ignore')

import streamlit as st
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import pickle
from tensorflow.keras.models import load_model

# Sayfa Yapılandırması
st.set_page_config(page_title="Hotel AI Decision Support", layout="wide")

@st.cache_resource
def load_assets():
    model_file = "hotel_model.keras"
    scaler_file = "scaler.pkl"
    if not os.path.exists(model_file) or not os.path.exists(scaler_file):
        st.error("❌ Dosyalar bulunamadı! Lütfen Hugging Face klasörünüzü kontrol edin.")
        st.stop()
    model = load_model(model_file)
    with open(scaler_file, "rb") as f:
        sc = pickle.load(f)
    return model, sc

try:
    model, sc = load_assets()
except Exception as e:
    st.error(f"⚠️ Yükleme Hatası: {e}")
    st.stop()

# ==========================================
# SIDEBAR / SOL PANEL (TÜM BİLGİLER BURADA)
# ==========================================
with st.sidebar:
    st.markdown("<h2 style='color: #2980b9;'>📖 User Guide / Rehber</h2>", unsafe_allow_html=True)
    
    # 1. NASIL YÜKLENMELİ?
    st.markdown("### 📥 How to Upload? / Nasıl Yüklenmeli?")
    st.info("""
    **Format:** Sütun adı **'bookings'** olan bir CSV yükleyin.
    
    | bookings |
    | :--- |
    | 120 |
    | 155 |
    """)
    
    # 2. ANALİZİ BAŞLAT (İstediğin yer: Rehberin hemen altı)
    st.markdown("### 🚀 Start Analysis / Analizi Başlat")
    file = st.file_uploader("Upload CSV / CSV Yükle", type=["csv"])
    
    st.markdown("---")
    
    # 3. BOOKINGS NEDİR?
    st.markdown("### ❓ What is 'Bookings'? / 'Bookings' Nedir?")
    st.write("""
    **EN:** Total daily reservations. (Example: 150 means 150 rooms sold)
    
    **TR:** Günlük toplam rezervasyon. (Örn: 150 değeri o gün 150 oda satıldığını gösterir)
    """)
    
    st.markdown("---")
    
    # 4. YOĞUNLUK MANTIĞI
    st.markdown("### 📊 Thresholds / Yoğunluk")
    st.warning("**High (Yoğun):** > Ortalamadan %20 fazla")
    st.success("**Stable (Stabil):** Normal aralıkta")

# ==========================================
# MAIN CONTENT / ANA SAYFA
# ==========================================
st.markdown("<h1 style='text-align: center;'>🏨 Hotel Demand Forecasting / Otel Talep Tahmini</h1>", unsafe_allow_html=True)

if file is not None:
    df = pd.read_csv(file)
    
    # AI TAHMİN SÜRECİ
    raw_data = df[["bookings"]].values
    data_scaled = sc.transform(raw_data)
    predictions_scaled = model.predict(data_scaled, verbose=0) 
    predictions = sc.inverse_transform(predictions_scaled).flatten().astype(int)

    avg_val = int(predictions.mean())
    busy_limit = int(avg_val * 1.2)
    current_max = int(predictions.max())

    # 1. METRİKLER (EN ÜSTTE)
    st.markdown("---")
    c1, c2, c3 = st.columns(3)
    with c1: st.markdown(f"<div style='text-align: center;'><strong>Avg Forecast / Ort. Tahmin</strong><br><span style='font-size: 45px; color: #2980b9;'>{avg_val}</span></div>", unsafe_allow_html=True)
    with c2: st.markdown(f"<div style='text-align: center;'><strong>Busy Threshold / Yoğunluk Sınırı</strong><br><span style='font-size: 45px; color: #e74c3c;'>{busy_limit}</span></div>", unsafe_allow_html=True)
    with c3:
        status_color = "#e67e22" if current_max >= busy_limit else "#27ae60"
        status_text = "HIGH / YOĞUN" if current_max >= busy_limit else "STABLE / STABİL"
        st.markdown(f"<div style='text-align: center;'><strong>Status / Durum</strong><br><span style='font-size: 40px; color: {status_color}; font-weight: bold;'>{status_text}</span></div>", unsafe_allow_html=True)

    # 2. YÖNETİM TAVSİYESİ (ÜSTTE)
    st.markdown("---")
    st.markdown("<h3 style='text-align: center;'>👔 Management Advice / Yönetim Tavsiyesi</h3>", unsafe_allow_html=True)
    adv_en, adv_tr = st.columns(2)
    with adv_en:
        if current_max >= busy_limit: st.warning("**High Demand Advice:** Peak days detected. Increase staff.")
        else: st.success("**Stable Demand Advice:** Demand is normal. Focus on maintenance.")
    with adv_tr:
        if current_max >= busy_limit: st.warning("**Yoğun Talep Tavsiyesi:** Zirve günler tespit edildi. Personel artırın.")
        else: st.success("**Stabil Talep Tavsiyesi:** Talep normal. Bakım işlerine odaklanılabilir.")

    # 3. SONUÇ TABLOSU (GRAFİK ÜSTÜNDE)
    st.markdown("---")
    st.subheader("📋 Results Table / Sonuç Tablosu")
    res_df = pd.DataFrame({"Actual / Gerçek": raw_data.flatten(), "Predicted / Tahmin": predictions})
    st.dataframe(res_df, width=1200, height=250)
    st.download_button("📥 Download Results", res_df.to_csv(index=False).encode('utf-8'), "hotel_results.csv", "text/csv")

    # 4. GRAFİK
    st.markdown("---")
    st.subheader("📈 Prediction Graph / Tahmin Grafiği")
    plt.clf()
    fig, ax = plt.subplots(figsize=(10, 3.5)) 
    ax.plot(raw_data, label="Actual / Gerçek", color="#bdc3c7", alpha=0.6, linestyle='--')
    ax.plot(predictions, label="AI Forecast / YZ Tahmini", color="#2980b9", linewidth=2)
    ax.axhline(y=busy_limit, color='#e74c3c', linestyle=':', label="Limit")
    ax.legend(prop={'size': 8})
    st.pyplot(fig, clear_figure=True)

    # 5. VERİ ÖN İZLEME (EN ALTTA)
    st.markdown("---")
    st.subheader("📊 Data Preview / Veri Ön İzleme")
    st.dataframe(df, width=1200, height=150)

else:
    st.warning("👈 Please upload a CSV file from the left panel. / Lütfen sol panelden bir CSV dosyası yükleyin.")