File size: 5,708 Bytes
00d02e3
a2c0c93
 
78ff1a7
e8bf1c6
 
a2c0c93
 
e8bf1c6
 
 
 
 
00d02e3
 
 
 
 
 
 
 
 
80e16b6
78ff1a7
00d02e3
 
 
 
 
 
 
 
 
e8bf1c6
00d02e3
 
 
78ff1a7
00d02e3
 
80e16b6
 
d39e80f
 
78ff1a7
 
d39e80f
78ff1a7
 
 
 
 
 
 
e8bf1c6
78ff1a7
80e16b6
00d02e3
80e16b6
78ff1a7
00d02e3
78ff1a7
 
 
 
 
80e16b6
00d02e3
80e16b6
78ff1a7
e8bf1c6
78ff1a7
 
00d02e3
 
 
 
 
 
 
 
 
78ff1a7
00d02e3
 
e8bf1c6
00d02e3
 
 
 
 
 
78ff1a7
00d02e3
 
e8bf1c6
 
00d02e3
78ff1a7
 
 
00d02e3
78ff1a7
00d02e3
 
78ff1a7
 
d39e80f
 
78ff1a7
d39e80f
 
 
78ff1a7
00d02e3
 
d39e80f
e8bf1c6
d39e80f
00d02e3
78ff1a7
00d02e3
 
e8bf1c6
00d02e3
 
 
 
 
e8bf1c6
00d02e3
78ff1a7
00d02e3
a2c0c93
e8bf1c6
00d02e3
 
1a11cfc
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.")