|
import streamlit as st
|
|
import joblib
|
|
import pandas as pd
|
|
import numpy as np
|
|
from preprocess_pipeline import SingleInstancePreprocessor
|
|
from get_real_home_listing import get_home_listings
|
|
from home_listing_display import display_home_listings
|
|
|
|
model = joblib.load('random_forest.joblib')
|
|
preprocessor = SingleInstancePreprocessor()
|
|
|
|
|
|
temp = {}
|
|
st.set_page_config(
|
|
page_title="🏠 Ev Fiyatı Tahmin ve Öneri aracı",
|
|
page_icon="🏠",
|
|
layout="wide",
|
|
initial_sidebar_state="expanded",
|
|
)
|
|
|
|
st.markdown("""
|
|
<style>
|
|
:root {
|
|
--primary: #2A3950;
|
|
--secondary: #00C0A3;
|
|
--background: #1A1A1A;
|
|
--surface: #2D2D2D;
|
|
--text-primary: #FFFFFF;
|
|
}
|
|
|
|
body {
|
|
font-family: 'Arial', sans-serif;
|
|
background-color: var(--background);
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.stApp {
|
|
background: var(--background);
|
|
color: var(--text-primary);
|
|
font-family: 'Inter', sans-serif;
|
|
}
|
|
|
|
.header-container {
|
|
background: var(--surface);
|
|
padding: 3rem;
|
|
border-radius: 15px;
|
|
margin-bottom: 2.5rem;
|
|
box-shadow: 0 6px 25px rgba(0,0,0,0.3);
|
|
text-align: center;
|
|
}
|
|
|
|
.input-card {
|
|
background: var(--surface);
|
|
border-radius: 12px;
|
|
padding: 2rem;
|
|
margin: 1.2rem 0;
|
|
border: 1px solid rgba(255,255,255,0.1);
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.input-card:hover {
|
|
transform: translateY(-5px);
|
|
box-shadow: 0 8px 20px rgba(0,0,0,0.4);
|
|
}
|
|
|
|
.stSelectbox, .stNumberInput, .stTextInput {
|
|
background: var(--primary) !important;
|
|
border-radius: 10px !important;
|
|
border: none !important;
|
|
color: var(--text-primary) !important;
|
|
padding: 0.75rem !important;
|
|
}
|
|
|
|
.stButton>button {
|
|
background: var(--secondary) !important;
|
|
color: var(--text-primary) !important;
|
|
border: none;
|
|
padding: 16px 36px;
|
|
border-radius: 10px;
|
|
font-weight: 600;
|
|
transition: all 0.3s;
|
|
box-shadow: 0 5px 15px rgba(0,192,163,0.4);
|
|
}
|
|
|
|
.stButton>button:hover {
|
|
opacity: 0.9;
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 6px 20px rgba(0,192,163,0.5);
|
|
}
|
|
|
|
.prediction-card {
|
|
background: linear-gradient(135deg, var(--primary) 0%, #1B2838 100%);
|
|
border-radius: 15px;
|
|
padding: 2.5rem;
|
|
text-align: center;
|
|
margin: 2.5rem 0;
|
|
border: 1px solid rgba(255,255,255,0.15);
|
|
box-shadow: 0 8px 25px rgba(0,0,0,0.3);
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 1.4rem;
|
|
font-weight: 700;
|
|
color: var(--secondary);
|
|
margin: 1.8rem 0;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: 1px;
|
|
}
|
|
|
|
.footer {
|
|
text-align: center;
|
|
padding: 2rem;
|
|
color: rgba(255,255,255,0.7);
|
|
font-size: 0.95rem;
|
|
margin-top: 3.5rem;
|
|
border-top: 1px solid rgba(255,255,255,0.1);
|
|
}
|
|
|
|
/* Ek olarak, mobil uyumluluk için medya sorguları ekleyebilirsiniz */
|
|
@media (max-width: 768px) {
|
|
.header-container {
|
|
padding: 2rem;
|
|
margin-bottom: 2rem;
|
|
}
|
|
.section-title {
|
|
font-size: 1.2rem;
|
|
margin: 1.5rem 0;
|
|
}
|
|
}
|
|
</style>
|
|
""", unsafe_allow_html=True)
|
|
|
|
with st.container():
|
|
st.markdown("""
|
|
<div class="header-container">
|
|
<h1 style="margin:0;font-size:2.5rem">🏠 Ev Tahmin</h1>
|
|
<p style="color:rgba(255,255,255,0.8);margin-top:0.5rem">Ev Fiyatı Tahmin Ve Öneri Aracı</p>
|
|
</div>
|
|
""", unsafe_allow_html=True)
|
|
|
|
with st.container():
|
|
col1, col2 = st.columns([1, 1.2])
|
|
|
|
with col1:
|
|
st.markdown('<div class="section-title">📍 Lokasyon Bilgileri</div>', unsafe_allow_html=True)
|
|
st.markdown('<div style="color:rgba(255,255,255,0.8);margin-bottom:1rem">Ev fiyatı tahmini yapmak için lütfen aşağıdaki bilgileri doldurun.</div>', unsafe_allow_html=True)
|
|
|
|
with st.container():
|
|
st.markdown('<div class="input-card">', unsafe_allow_html=True)
|
|
il_listesi = list(preprocessor.location_map.keys())
|
|
selected_il = st.selectbox('İl', options=il_listesi)
|
|
ilceler = list(preprocessor.location_map.get(selected_il, {}).keys())
|
|
selected_ilce = st.selectbox('İlçe', options=ilceler)
|
|
mahalleler = preprocessor.location_map.get(selected_il, {}).get(selected_ilce, [])
|
|
selected_mahalle = st.selectbox('Mahalle', options=mahalleler)
|
|
st.markdown('</div>', unsafe_allow_html=True)
|
|
|
|
st.markdown('<div class="section-title">📐 Temel Özellikler</div>', unsafe_allow_html=True)
|
|
with st.container():
|
|
st.markdown('<div class="input-card">', unsafe_allow_html=True)
|
|
tipi = st.selectbox('Konut Tipi', options=['Daire', 'Residence', 'Villa', 'Müstakil Ev', 'Yazlık'])
|
|
brut_metrekare = st.number_input('Brüt Metrekare (m²)', min_value=30, max_value=500, value=100)
|
|
binanin_yasi = st.number_input('Bina Yaşı', min_value=0, max_value=100, value=5)
|
|
st.markdown('</div>', unsafe_allow_html=True)
|
|
|
|
with col2:
|
|
st.markdown('<div class="section-title">📊 Detaylı Özellikler</div>', unsafe_allow_html=True)
|
|
with st.container():
|
|
st.markdown('<div class="input-card">', unsafe_allow_html=True)
|
|
cols = st.columns(2)
|
|
with cols[0]:
|
|
oda_sayisi = st.selectbox('Oda', options=['1+1', '2+1', '3+1', '4+1', '5+1'])
|
|
banyo_sayisi = st.number_input('Banyo', min_value=1, max_value=5, value=1)
|
|
isitma_tipi = st.selectbox('Isıtma Tipi', options=['Doğalgaz', 'Merkezi Sistem', 'Elektrikli', 'Soba'])
|
|
with cols[1]:
|
|
bulundugu_kat = 3
|
|
binanin_kat_sayisi = 10
|
|
esya_durumu = st.selectbox('Eşya Durumu', options=['Eşyalı', 'Eşyasız'])
|
|
st.markdown('</div>', unsafe_allow_html=True)
|
|
|
|
st.markdown('<div class="section-title">⚙️ Diğer Ayarlar</div>', unsafe_allow_html=True)
|
|
with st.container():
|
|
st.markdown('<div class="input-card">', unsafe_allow_html=True)
|
|
cols = st.columns(2)
|
|
with cols[0]:
|
|
site_icerisinde = st.selectbox('Site İçinde', options=['Evet', 'Hayır'])
|
|
with cols[1]:
|
|
kullanim_durumu = st.selectbox('Kullanım Durumu', options=['Konut', 'İş Yeri', 'Diğer'])
|
|
st.markdown('</div>', unsafe_allow_html=True)
|
|
|
|
if st.button('💵 Tahmin Yap', use_container_width=True):
|
|
input_data = {
|
|
'Oda Sayısı': oda_sayisi,
|
|
'Bulunduğu Kat': bulundugu_kat,
|
|
'Isıtma Tipi': isitma_tipi,
|
|
'Eşya Durumu': esya_durumu,
|
|
'Site İçerisinde': site_icerisinde,
|
|
'Tipi': tipi,
|
|
'Brüt Metrekare': brut_metrekare,
|
|
'Binanın Yaşı': binanin_yasi,
|
|
'Binanın Kat Sayısı': binanin_kat_sayisi,
|
|
'Kullanım Durumu': kullanim_durumu,
|
|
'Banyo Sayısı': banyo_sayisi,
|
|
'İl': selected_il,
|
|
'İlçe': selected_ilce,
|
|
'Mahalle': selected_mahalle
|
|
}
|
|
|
|
|
|
with st.spinner('AI analiz yapıyor...'):
|
|
input_array = preprocessor.transform(input_data)
|
|
|
|
tahmin = model.predict(input_array)
|
|
|
|
st.markdown(f'''
|
|
<div class="prediction-card">
|
|
<h3 style="margin:0 0 1rem 0;color:rgba(255,255,255,0.9)">TAHMİN EDİLEN DEĞER</h3>
|
|
<div style="font-size:2.8rem;font-weight:700;color:var(--secondary);margin:1rem 0">{tahmin[0]:,.0f} TL</div>
|
|
<p style="color:rgba(255,255,255,0.7);margin:0">*Gerçek değerler piyasa koşullarına göre değişiklik gösterebilir</p>
|
|
</div>
|
|
''', unsafe_allow_html=True)
|
|
|
|
predicted_price = tahmin[0]
|
|
with st.spinner("Seçim ile benzer özelliğe sahip ilanlar getiriliyor..."):
|
|
home_listings = get_home_listings(selected_il, predicted_price)
|
|
display_home_listings(home_listings)
|
|
|
|
st.markdown('''
|
|
<div class="footer">
|
|
<div> @yusufenes || Konut Fiyatı Tahmin ve Konut Öneri Sistemi || Tüm veriler İnternet Üzerinden Alınmıştır Ticari Kullanım Hakkı Yoktur.</div>
|
|
<div style="margin-top:0.5rem;font-size:0.8rem">
|
|
<span style="opacity:0.7">Geliştirici: Yusuf Enes</span> •
|
|
<span style="opacity:0.7">🧑💻 <a href="https://github.com/yusuffenes">Github</a> </span>
|
|
</div>
|
|
</div>
|
|
''', unsafe_allow_html=True)
|
|
|
|
|