Coots commited on
Commit
5277275
ยท
verified ยท
1 Parent(s): 016bcdf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +31 -61
app.py CHANGED
@@ -3,8 +3,6 @@ import joblib
3
  import json
4
  import math
5
  import re
6
- from fpdf import FPDF
7
- import tempfile
8
  from deep_translator import GoogleTranslator
9
  import warnings
10
  import xgboost as xgb
@@ -23,7 +21,7 @@ with open("tile_catalog.json", "r", encoding="utf-8") as f:
23
  with open("tile_sizes.json", "r", encoding="utf-8") as f:
24
  tile_sizes = json.load(f)
25
 
26
- tile_size_map = {s["label"].lower().replace(" ", ""): s["area_sqft"] for s in tile_sizes]
27
 
28
  def translate(text, lang="en"):
29
  try:
@@ -31,22 +29,6 @@ def translate(text, lang="en"):
31
  except:
32
  return text
33
 
34
- def remove_emojis(text):
35
- return re.sub(r'[^\x00-\x7F]+', '', text)
36
-
37
- def create_pdf(text):
38
- pdf = FPDF()
39
- pdf.add_page()
40
- pdf.add_font("FreeSans", "", "FreeSans.ttf", uni=True)
41
- pdf.set_font("FreeSans", size=12)
42
- pdf.cell(0, 10, "Tile Estimate Report", ln=True, align="C")
43
- pdf.ln(5)
44
- for line in text.strip().split("\n"):
45
- pdf.multi_cell(0, 10, remove_emojis(line))
46
- tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf")
47
- pdf.output(tmp.name)
48
- return tmp.name
49
-
50
  def extract_tile_area(msg, unit):
51
  msg = msg.lower().replace("feet", "").replace("ft", "").replace("mm", "").strip()
52
  msg = re.sub(r"\s*(x|ร—|\*|into)\s*", "x", msg)
@@ -66,11 +48,10 @@ def extract_tile_area(msg, unit):
66
  return None
67
 
68
  def chat_fn(message, history, user_state={}):
69
- # Only reset if not mid-conversation
70
  if "step" not in user_state and message.strip().lower() in ["floor", "wall"]:
71
  user_state.clear()
72
 
73
- # Detect language
74
  if "lang" not in user_state:
75
  try:
76
  user_state["lang"] = GoogleTranslator(source="auto", target="en").detect(message)
@@ -79,32 +60,31 @@ def chat_fn(message, history, user_state={}):
79
  lang = user_state["lang"]
80
  def reply(text): return translate(text, lang)
81
 
82
- # Handle PDF request
83
- if message.strip().lower() in ["pdf", "report", "download"]:
84
- if "summary" in user_state:
85
- pdf_path = create_pdf(user_state["summary"])
86
- return reply("Hereโ€™s your PDF report ๐Ÿ“„"), [pdf_path], user_state
87
- else:
88
- return reply("No estimate yet. Please start by typing 'Floor' or 'Wall'."), None, user_state
89
-
90
- # Begin conversation
91
  if "step" not in user_state:
92
  if message.lower() in ["floor", "wall"]:
93
  user_state["tile_type"] = message.capitalize()
94
- user_state["step"] = "get_area"
95
- return reply(f"Great! You chose {user_state['tile_type']} tiles.\nWhatโ€™s the total area to cover (in sq.ft)?"), None, user_state
96
- return reply("Hi there! Are you planning for Floor or Wall tiles?"), None, user_state
 
 
 
 
 
 
 
 
97
 
98
- # Area input
99
- if user_state["step"] == "get_area":
100
  try:
101
- user_state["area"] = float(message)
 
102
  user_state["step"] = "get_unit"
103
- return reply("Would you like to enter the tile size in mm or ft?"), None, user_state
104
  except:
105
- return reply("That doesn't look like a number. Please enter the area in sq.ft (e.g. 120)."), None, user_state
106
 
107
- # Unit input
108
  if user_state["step"] == "get_unit":
109
  if message.lower() not in ["mm", "ft"]:
110
  return reply("Please type either mm or ft to choose your preferred unit."), None, user_state
@@ -113,7 +93,6 @@ def chat_fn(message, history, user_state={}):
113
  unit_label = "mm" if user_state["unit"] == "mm" else "feet"
114
  return reply(f"Please enter the tile size in {unit_label} (e.g. 600 x 600, 2 x 2, or 4):"), None, user_state
115
 
116
- # Tile size input
117
  if user_state["step"] == "get_tile_size":
118
  area = extract_tile_area(message, user_state["unit"])
119
  if not area or area <= 0:
@@ -147,34 +126,33 @@ def chat_fn(message, history, user_state={}):
147
 
148
  summary = f"""
149
  ๐Ÿงฑ Tile Type: {tile_type}
150
- ๐Ÿ“ Area to Cover: {area_needed} sq.ft
 
151
  ๐Ÿงฎ Tile Size Area: {round(area, 2)} sq.ft
152
  ๐Ÿ”ข Estimated Tiles Needed: {tile_needed} (with 10% buffer)
153
 
154
- ๐ŸŽฏ Suggested Products:
155
  """
156
  for i, t in enumerate(top3, 1):
157
  summary += f"\n{i}. {t['name']} ({t['size']})\n โ‚น{t['price']} per box โ†’ ~{t['boxes']} boxes\n {t['url']}\n"
158
 
159
- summary += "\nYou can type 'pdf' to download the report, or start fresh with 'Floor' or 'Wall'."
160
 
161
- user_state["summary"] = summary
162
- pdf_path = create_pdf(summary)
163
- return reply(summary), [pdf_path], user_state
164
 
165
  return reply("I didn't understand that. Please continue or type 'Floor' or 'Wall' to start over."), None, user_state
166
 
167
- # Gradio Interface
168
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", radius_size="lg")) as demo:
169
  gr.Markdown(
170
  """
171
  # ๐Ÿงฑ <span style="color:#3B82F6">TileBot</span> โ€“ Smart Tile Estimator
172
- Welcome! I'm here to help you estimate tile needs for your floor or wall.
173
 
174
- ๐Ÿ‘‰ Start by typing **"Floor"** or **"Wall"**
175
- ๐Ÿ“ Then give me the **area** and **tile size** in `mm` or `ft`
176
- โœ๏ธ Examples: `600 x 600`, `2 x 2`, `4`, `200 * 200`
177
- ๐Ÿ“‹ Iโ€™ll recommend tiles and generate a **PDF Report**
178
  """,
179
  elem_id="header"
180
  )
@@ -183,16 +161,8 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", radius_size="lg")) as de
183
  fn=chat_fn,
184
  type="messages",
185
  chatbot=gr.Chatbot(height=500, bubble_full_width=False),
186
- additional_outputs=[gr.File(label="๐Ÿ“„ Download Report")]
187
  )
188
 
189
- gr.Markdown(
190
- """
191
- ---
192
- ๐Ÿ’ก Tip: Type `"pdf"` anytime to get a downloadable report.
193
- ๐Ÿš€ Need a new estimate? Just say `"Floor"` or `"Wall"` to start over.
194
- """,
195
- elem_id="footer"
196
- )
197
 
198
  demo.launch()
 
3
  import json
4
  import math
5
  import re
 
 
6
  from deep_translator import GoogleTranslator
7
  import warnings
8
  import xgboost as xgb
 
21
  with open("tile_sizes.json", "r", encoding="utf-8") as f:
22
  tile_sizes = json.load(f)
23
 
24
+ tile_size_map = {s["label"].lower().replace(" ", ""): s["area_sqft"] for s in tile_sizes}
25
 
26
  def translate(text, lang="en"):
27
  try:
 
29
  except:
30
  return text
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  def extract_tile_area(msg, unit):
33
  msg = msg.lower().replace("feet", "").replace("ft", "").replace("mm", "").strip()
34
  msg = re.sub(r"\s*(x|ร—|\*|into)\s*", "x", msg)
 
48
  return None
49
 
50
  def chat_fn(message, history, user_state={}):
 
51
  if "step" not in user_state and message.strip().lower() in ["floor", "wall"]:
52
  user_state.clear()
53
 
54
+ # Language detection
55
  if "lang" not in user_state:
56
  try:
57
  user_state["lang"] = GoogleTranslator(source="auto", target="en").detect(message)
 
60
  lang = user_state["lang"]
61
  def reply(text): return translate(text, lang)
62
 
63
+ # Start conversation
 
 
 
 
 
 
 
 
64
  if "step" not in user_state:
65
  if message.lower() in ["floor", "wall"]:
66
  user_state["tile_type"] = message.capitalize()
67
+ user_state["step"] = "get_length"
68
+ return reply(f"You selected {user_state['tile_type']} tiles.\nEnter the length of the space in feet:"), None, user_state
69
+ return reply("Hi! Are you planning for Floor or Wall tiles?"), None, user_state
70
+
71
+ if user_state["step"] == "get_length":
72
+ try:
73
+ user_state["length"] = float(message)
74
+ user_state["step"] = "get_width"
75
+ return reply("Now enter the width of the space in feet:"), None, user_state
76
+ except:
77
+ return reply("That doesn't seem like a number. Please enter the length in feet (e.g. 12)."), None, user_state
78
 
79
+ if user_state["step"] == "get_width":
 
80
  try:
81
+ user_state["width"] = float(message)
82
+ user_state["area"] = round(user_state["length"] * user_state["width"], 2)
83
  user_state["step"] = "get_unit"
84
+ return reply("Got it! Would you like to enter tile size in mm or ft?"), None, user_state
85
  except:
86
+ return reply("Please enter a valid width in feet (e.g. 10)."), None, user_state
87
 
 
88
  if user_state["step"] == "get_unit":
89
  if message.lower() not in ["mm", "ft"]:
90
  return reply("Please type either mm or ft to choose your preferred unit."), None, user_state
 
93
  unit_label = "mm" if user_state["unit"] == "mm" else "feet"
94
  return reply(f"Please enter the tile size in {unit_label} (e.g. 600 x 600, 2 x 2, or 4):"), None, user_state
95
 
 
96
  if user_state["step"] == "get_tile_size":
97
  area = extract_tile_area(message, user_state["unit"])
98
  if not area or area <= 0:
 
126
 
127
  summary = f"""
128
  ๐Ÿงฑ Tile Type: {tile_type}
129
+ ๐Ÿ“ Space: {user_state['length']} ft x {user_state['width']} ft
130
+ ๐Ÿ“ Area to Cover: {area_needed} sq.ft
131
  ๐Ÿงฎ Tile Size Area: {round(area, 2)} sq.ft
132
  ๐Ÿ”ข Estimated Tiles Needed: {tile_needed} (with 10% buffer)
133
 
134
+ ๐ŸŽฏ Top Suggestions:
135
  """
136
  for i, t in enumerate(top3, 1):
137
  summary += f"\n{i}. {t['name']} ({t['size']})\n โ‚น{t['price']} per box โ†’ ~{t['boxes']} boxes\n {t['url']}\n"
138
 
139
+ summary += "\nType 'Floor' or 'Wall' to start another estimate."
140
 
141
+ return reply(summary), None, user_state
 
 
142
 
143
  return reply("I didn't understand that. Please continue or type 'Floor' or 'Wall' to start over."), None, user_state
144
 
145
+ # Interface
146
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", radius_size="lg")) as demo:
147
  gr.Markdown(
148
  """
149
  # ๐Ÿงฑ <span style="color:#3B82F6">TileBot</span> โ€“ Smart Tile Estimator
150
+ Welcome! I'm here to help you estimate tiles for your floor or wall.
151
 
152
+ ๐Ÿ‘‰ Start with **"Floor"** or **"Wall"**
153
+ ๐Ÿ“ Enter **length and width** (in feet)
154
+ ๐Ÿ“ Then your tile size (in `mm` or `ft`) โ€“ like `600 x 600`, `2x2`, or `4`
155
+ ๐Ÿ“‹ Iโ€™ll recommend tiles and calculate how many you need.
156
  """,
157
  elem_id="header"
158
  )
 
161
  fn=chat_fn,
162
  type="messages",
163
  chatbot=gr.Chatbot(height=500, bubble_full_width=False),
 
164
  )
165
 
166
+ gr.Markdown("---\nNeed to start over? Just type **Floor** or **Wall** again.")
 
 
 
 
 
 
 
167
 
168
  demo.launch()