Skip to content

Commit 00dd177

Browse files
authored
Create HousePrice_Sentinel.py
1 parent c937391 commit 00dd177

1 file changed

Lines changed: 242 additions & 0 deletions

File tree

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
"""
2+
HousePrice Sentinel v1.0 - Enterprise Edition
3+
Smart Real Estate Price Prediction Tool
4+
ML-powered house valuation with modern UI
5+
"""
6+
7+
import os, sys, threading
8+
import tkinter as tk
9+
from tkinter import filedialog, messagebox
10+
from tkinter import ttk
11+
12+
import pandas as pd
13+
import numpy as np
14+
15+
import ttkbootstrap as tb
16+
from ttkbootstrap.constants import *
17+
18+
from sklearn.linear_model import LinearRegression
19+
from sklearn.model_selection import train_test_split
20+
21+
22+
# ---------------------- UTIL ----------------------
23+
def resource_path(file_name):
24+
base_path = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__)))
25+
return os.path.join(base_path, file_name)
26+
27+
28+
# ---------------------- ML WORKER ----------------------
29+
class PriceModelWorker:
30+
def __init__(self, csv_path, callbacks):
31+
self.csv_path = csv_path
32+
self.callbacks = callbacks
33+
self.model = LinearRegression()
34+
35+
def run(self):
36+
try:
37+
df = pd.read_csv(self.csv_path)
38+
39+
X = df[["Area", "Bedrooms", "Bathrooms"]]
40+
y = df["Price"]
41+
42+
X_train, X_test, y_train, y_test = train_test_split(
43+
X, y, test_size=0.2, random_state=42
44+
)
45+
46+
self.model.fit(X_train, y_train)
47+
score = self.model.score(X_test, y_test)
48+
49+
if "trained" in self.callbacks:
50+
self.callbacks["trained"](score, self.model)
51+
52+
except Exception as e:
53+
if "error" in self.callbacks:
54+
self.callbacks["error"](str(e))
55+
56+
57+
# ---------------------- MAIN APP ----------------------
58+
class HousePriceApp:
59+
APP_NAME = "HousePrice Sentinel"
60+
APP_VERSION = "1.0"
61+
62+
def __init__(self):
63+
self.root = tb.Window(themename="darkly")
64+
self.root.title(f"{self.APP_NAME} v{self.APP_VERSION}")
65+
self.root.minsize(1100, 650)
66+
67+
try:
68+
self.root.iconbitmap(resource_path("logo.ico"))
69+
except:
70+
pass
71+
72+
self.model = None
73+
self._build_ui()
74+
75+
# ---------------------- UI ----------------------
76+
def _build_ui(self):
77+
main = tb.Frame(self.root, padding=10)
78+
main.pack(fill=BOTH, expand=True)
79+
80+
tb.Label(
81+
main,
82+
text="🏠 HousePrice Sentinel",
83+
font=("Segoe UI", 22, "bold")
84+
).pack(pady=(0, 4))
85+
86+
tb.Label(
87+
main,
88+
text="AI-Powered Real Estate Price Prediction",
89+
font=("Segoe UI", 10, "italic"),
90+
foreground="#9ca3af"
91+
).pack(pady=(0, 20))
92+
93+
# Dataset row
94+
row1 = tb.Frame(main)
95+
row1.pack(fill=X, pady=6)
96+
97+
self.dataset_entry = tb.Entry(row1, width=90)
98+
self.dataset_entry.pack(side=LEFT, fill=X, expand=True, padx=(0, 6))
99+
self.dataset_entry.insert(0, "Load CSV dataset (Area, Bedrooms, Bathrooms, Price)")
100+
101+
tb.Button(
102+
row1,
103+
text="📂 Load Dataset",
104+
bootstyle=INFO,
105+
command=self.load_dataset
106+
).pack(side=LEFT, padx=3)
107+
108+
tb.Button(
109+
row1,
110+
text="🧠 Train Model",
111+
bootstyle=SUCCESS,
112+
command=self.train_model
113+
).pack(side=LEFT, padx=3)
114+
115+
# Stats
116+
self.stats_label = tb.Label(
117+
main,
118+
text="Model Status: Not trained",
119+
font=("Segoe UI", 10)
120+
)
121+
self.stats_label.pack(anchor=W, pady=(10, 10))
122+
123+
# Prediction inputs
124+
form = tb.Labelframe(main, text="Price Prediction", padding=15)
125+
form.pack(fill=X, pady=10)
126+
127+
self.area_var = tk.DoubleVar()
128+
self.bed_var = tk.IntVar()
129+
self.bath_var = tk.IntVar()
130+
131+
tb.Label(form, text="Area (sqft)").grid(row=0, column=0, padx=5, pady=5)
132+
tb.Entry(form, textvariable=self.area_var).grid(row=0, column=1, padx=5)
133+
134+
tb.Label(form, text="Bedrooms").grid(row=0, column=2, padx=5)
135+
tb.Entry(form, textvariable=self.bed_var).grid(row=0, column=3, padx=5)
136+
137+
tb.Label(form, text="Bathrooms").grid(row=0, column=4, padx=5)
138+
tb.Entry(form, textvariable=self.bath_var).grid(row=0, column=5, padx=5)
139+
140+
tb.Button(
141+
form,
142+
text="💰 Predict Price",
143+
bootstyle=PRIMARY,
144+
command=self.predict_price
145+
).grid(row=0, column=6, padx=10)
146+
147+
tb.Button(
148+
form,
149+
text="ℹ️ About",
150+
bootstyle=INFO,
151+
command=self.show_about
152+
).grid(row=0, column=7, padx=10)
153+
154+
self.result_label = tb.Label(
155+
main,
156+
text="Predicted Price: —",
157+
font=("Segoe UI", 16, "bold"),
158+
foreground="#4ade80"
159+
)
160+
self.result_label.pack(pady=20)
161+
162+
# ---------------------- Actions ----------------------
163+
def load_dataset(self):
164+
path = filedialog.askopenfilename(
165+
filetypes=[("CSV Files", "*.csv")]
166+
)
167+
if path:
168+
self.dataset_entry.delete(0, END)
169+
self.dataset_entry.insert(0, path)
170+
171+
def train_model(self):
172+
path = self.dataset_entry.get()
173+
if not os.path.isfile(path):
174+
messagebox.showerror("Error", "Invalid dataset path")
175+
return
176+
177+
self.stats_label.config(text="Training model...")
178+
179+
threading.Thread(
180+
target=self._train_worker,
181+
args=(path,),
182+
daemon=True
183+
).start()
184+
185+
def _train_worker(self, path):
186+
worker = PriceModelWorker(
187+
path,
188+
callbacks={
189+
"trained": self.on_trained,
190+
"error": self.on_error
191+
}
192+
)
193+
worker.run()
194+
195+
def on_trained(self, score, model):
196+
self.model = model
197+
self.stats_label.config(
198+
text=f"Model trained successfully | Accuracy: {score:.2f}"
199+
)
200+
201+
def on_error(self, msg):
202+
messagebox.showerror("Training Error", msg)
203+
self.stats_label.config(text="Training failed")
204+
205+
def predict_price(self):
206+
if not self.model:
207+
messagebox.showwarning("Model", "Train the model first")
208+
return
209+
210+
X = pd.DataFrame([{
211+
"Area": self.area_var.get(),
212+
"Bedrooms": self.bed_var.get(),
213+
"Bathrooms": self.bath_var.get()
214+
}])
215+
216+
price = self.model.predict(X)[0]
217+
218+
self.result_label.config(
219+
text=f"Predicted Price: ${price:,.2f}"
220+
)
221+
222+
# ---------------------- About ----------------------
223+
def show_about(self):
224+
messagebox.showinfo(
225+
f"About {self.APP_NAME}",
226+
f"{self.APP_NAME} v{self.APP_VERSION}\n\n"
227+
"• CSV-based ML training\n"
228+
"• Real-time house price prediction\n"
229+
"• Clean enterprise UI\n"
230+
"• Built with Python & Scikit-Learn\n\n"
231+
"🏢 Mate Technologies"
232+
)
233+
234+
# ---------------------- Run ----------------------
235+
def run(self):
236+
self.root.mainloop()
237+
238+
239+
# ---------------------- RUN ----------------------
240+
if __name__ == "__main__":
241+
app = HousePriceApp()
242+
app.run()

0 commit comments

Comments
 (0)