Zatimm commited on
Commit
9b4608f
·
verified ·
1 Parent(s): bc57583

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +144 -140
app.py CHANGED
@@ -2,6 +2,8 @@ import gradio as gr
2
  from PIL import Image, ImageDraw, ImageFont
3
  from collections import Counter
4
 
 
 
5
  def does_overlap(part1, part2):
6
  """İki parçanın çakışıp çakışmadığını kontrol eder."""
7
  return not (part1['x'] + part1['w'] <= part2['x'] or
@@ -20,198 +22,200 @@ def pack_and_draw(parts, plate_w, plate_h):
20
  for part in parts:
21
  can_fit = (part['w'] <= plate_w and part['h'] <= plate_h) or (part['h'] <= plate_w and part['w'] <= plate_h)
22
  if not can_fit:
23
- return f"HATA: '{part['label']}' ({part['w']}x{part['h']}) parçası plaka boyutlarından ({plate_w}x{plate_h}) daha büyük.", None
 
24
 
25
- # Parçaları alana göre büyükten küçüğe sırala
26
- parts.sort(key=lambda p: p['w'] * p['h'], reverse=True)
27
  sheets = []
28
 
29
  for part in parts:
30
  placed = False
31
- best_sheet = -1
32
- best_point = None
33
- best_rotation = False
34
-
35
- # Mevcut plakalarda yer ara
36
- for i, sheet in enumerate(sheets):
37
- candidate_points = [(0, 0)]
38
- for p in sheet['parts']:
39
- candidate_points.append((p['x'] + p['w'], p['y']))
40
- candidate_points.append((p['x'], p['y'] + p['h']))
41
-
42
- # Orijinal ve döndürülmüş oryantasyonları dene
43
  for rotation in [False, True]:
44
- if rotation:
45
- part['w'], part['h'] = part['h'], part['w']
46
 
47
- for point in candidate_points:
48
  part['x'], part['y'] = point
49
- if (part['x'] + part['w'] <= plate_w) and (part['y'] + part['h'] <= plate_h):
50
  if not any(does_overlap(part, p) for p in sheet['parts']):
51
  sheet['parts'].append(part.copy())
52
  placed = True
53
  break
54
 
55
- if rotation:
56
- part['w'], part['h'] = part['h'], part['w'] # Geri döndür
57
-
58
- if placed:
59
- break
60
- if placed:
61
- break
62
 
63
- # Eğer parça yerleştirilemediyse yeni plaka aç
64
  if not placed:
65
  new_sheet = {'parts': []}
66
  part['x'], part['y'] = 0, 0
67
- # Döndürmeden sığıyor mu kontrol et
68
  if part['w'] <= plate_w and part['h'] <= plate_h:
69
- new_sheet['parts'].append(part.copy())
70
- sheets.append(new_sheet)
71
- # Döndürerek sığıyor mu kontrol et
72
  elif part['h'] <= plate_w and part['w'] <= plate_h:
73
- part['w'], part['h'] = part['h'], part['w']
74
- new_sheet['parts'].append(part.copy())
75
- sheets.append(new_sheet)
76
 
77
  # --- GÖRSELLEŞTİRME ---
78
  images = []
79
  font_size = 14
80
- try:
81
- font = ImageFont.truetype("arial.ttf", font_size)
82
- except IOError:
83
- font = ImageFont.load_default()
84
 
85
  for i, sheet_data in enumerate(sheets):
86
  img = Image.new('RGB', (int(plate_w), int(plate_h)), color=(240, 240, 240))
87
  draw = ImageDraw.Draw(img)
88
- total_area = plate_w * plate_h
89
- used_area = 0
90
 
91
  for p in sheet_data['parts']:
92
  x, y, w, h = p['x'], p['y'], p['w'], p['h']
93
  draw.rectangle([x, y, x + w, y + h], outline=(50, 50, 50), fill=(200, 220, 255))
94
  text = f"{p['label']}\n{p['w']:.1f}x{p['h']:.1f}"
95
-
96
  bbox = draw.textbbox((0, 0), text, font=font)
97
  text_w, text_h = bbox[2] - bbox[0], bbox[3] - bbox[1]
98
-
99
- text_x = x + (w - text_w) / 2
100
- text_y = y + (h - text_h) / 2
101
  draw.text((text_x, text_y), text, fill=(0, 0, 0), font=font, align="center")
102
  used_area += w * h
103
 
104
  efficiency = (used_area / total_area) * 100
105
- info_text = f"Plaka {i+1} | Verimlilik: %{efficiency:.1f}"
106
- draw.text((10, 10), info_text, fill=(0, 0, 0), font=font)
107
  images.append(img)
108
 
109
  summary = f"**{len(sheets)}** adet sunta plakası gerekmektedir. Parçaların yerleşim düzeni aşağıda gösterilmiştir."
110
  return summary, images
111
 
 
 
 
 
 
 
 
 
 
 
112
 
113
- def calculate_all_dimensions(genislik, yukseklik, derinlik, malzeme_kalinligi, kapak_sayisi, kapak_araligi, pvc_payi, raf_adedi, plaka_g, plaka_y):
114
- if not all([genislik, yukseklik, derinlik, malzeme_kalinligi, kapak_sayisi, kapak_araligi, pvc_payi, raf_adedi is not None, plaka_g, plaka_y]):
115
- return "Lütfen tüm alanları doldurun.", "", None, ""
116
-
117
- try:
118
- genislik, yukseklik, derinlik = float(genislik), float(yukseklik), float(derinlik)
119
- malzeme_kalinligi = float(malzeme_kalinligi)
120
- kapak_sayisi, raf_adedi = int(kapak_sayisi), int(raf_adedi)
121
- kapak_araligi, pvc_payi = float(kapak_araligi), float(pvc_payi)
122
- plaka_g, plaka_y = float(plaka_g), float(plaka_y)
123
-
124
- if kapak_sayisi < 0 or malzeme_kalinligi <= 0 or raf_adedi < 0 or plaka_g <= 0 or plaka_y <= 0:
125
- return "Sayısal değerler pozitif olmalıdır (Kapak/Raf hariç).", "", None, ""
126
-
127
- all_parts = []
128
- # Yan Paneller
129
- yan_panel_y, yan_panel_d = yukseklik, derinlik
130
- all_parts.extend([{'label': 'Yan Panel', 'w': yan_panel_d, 'h': yan_panel_y} for _ in range(2)])
131
- # Alt/Üst Paneller
132
- alt_ust_panel_g = genislik - (2 * malzeme_kalinligi)
133
- alt_ust_panel_d = derinlik
134
- all_parts.extend([{'label': 'Üst/Alt', 'w': alt_ust_panel_g, 'h': alt_ust_panel_d} for _ in range(2)])
135
- # Arkalık
136
- arkalik_g = genislik - (2 * malzeme_kalinligi)
137
- arkalik_y = yukseklik - (2 * malzeme_kalinligi)
138
- all_parts.append({'label': 'Arkarlık', 'w': arkalik_g, 'h': arkalik_y})
139
- # Raflar
140
- if raf_adedi > 0:
141
- raf_g, raf_d = alt_ust_panel_g, alt_ust_panel_d
142
- all_parts.extend([{'label': 'Raf', 'w': raf_g, 'h': raf_d} for _ in range(raf_adedi)])
143
-
144
- if kapak_sayisi > 0:
145
- toplam_aralik_genislik = kapak_araligi * (kapak_sayisi - 1) if kapak_sayisi > 1 else 0
146
- nihai_kapak_genisligi = (genislik - toplam_aralik_genislik) / kapak_sayisi - pvc_payi
147
- nihai_kapak_yuksekligi = yukseklik - 0.4
148
- if nihai_kapak_genisligi > 0 and nihai_kapak_yuksekligi > 0:
149
- all_parts.extend([{'label': 'Kapak', 'w': nihai_kapak_genisligi, 'h': nihai_kapak_yuksekligi} for _ in range(kapak_sayisi)])
150
 
151
- # YENİ: Excel Listesi Oluşturma
152
- excel_listesi = ""
153
- if all_parts:
154
- # Parçaları (isim, genişlik, yükseklik) olarak say
155
- part_tuples = [(p['label'], f"{p['w']:.2f}", f"{p['h']:.2f}") for p in all_parts]
156
- part_counts = Counter(part_tuples)
 
 
 
 
157
 
158
- excel_listesi = "### Parça Listesi (Excel'e Kopyalamak İçin)\n"
159
- excel_listesi += "| Parça Adı | Adet | Genişlik (cm) | Yükseklik (cm) |\n"
160
- excel_listesi += "|:---|:---:|:---:|:---:|\n"
161
- # Sayılan parçaları sırala
162
- sorted_parts = sorted(part_counts.items())
163
- for (label, w, h), count in sorted_parts:
164
- excel_listesi += f"| {label} | {count} | {w} | {h} |\n"
165
-
166
- summary, images = pack_and_draw(all_parts, plaka_g, plaka_y)
167
- kapak_sonucu = f"Tüm parçalar aşağıdaki yerleşim planına ve özet listesine dahil edilmiştir."
168
- parca_listesi = summary
169
-
170
- return kapak_sonucu, parca_listesi, images, excel_listesi
171
-
172
- except ValueError:
173
- return "Lütfen tüm alanlara geçerli sayılar girin.", "", None, ""
174
- except Exception as e:
175
- return f"Beklenmedik bir hata oluştu: {e}", "", None, ""
176
-
177
- with gr.Blocks(theme=gr.themes.Soft(), title="Gelişmiş Optimizasyonlu Dolap Hesaplayıcı") as demo:
178
- gr.Markdown("# Gelişmiş Optimizasyonlu Dolap Hesaplayıcı")
179
- gr.Markdown("Dolap ölçülerini ve sunta plaka boyutlarını girerek, **kesim listesini** ve **optimize edilmiş plaka yerleşim planını** oluşturun.")
 
 
 
 
180
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  with gr.Row():
182
- with gr.Column():
183
- gr.Markdown("### 1. Dolap Dış Ölçüleri ve Malzeme")
184
- genislik_input = gr.Textbox(label="Toplam Genişlik (cm)", placeholder="Örn: 80")
185
- yukseklik_input = gr.Textbox(label="Toplam Yükseklik (cm)", placeholder="Örn: 180")
186
- derinlik_input = gr.Textbox(label="Toplam Derinlik (cm)", placeholder="Örn: 50")
187
- malzeme_kalinligi_input = gr.Slider(minimum=1.6, maximum=3.0, value=1.8, step=0.1, label="Malzeme Kalınlığı (cm)")
188
-
189
- with gr.Column():
190
- gr.Markdown("### 2. Kapak ve İç Raf Ayarları")
191
- kapak_sayisi_input = gr.Number(label="Kapak Sayısı", value=2, minimum=0, step=1)
192
- raf_adedi_input = gr.Number(label="Raf Adedi", value=2, minimum=0, step=1)
193
- kapak_araligi_input = gr.Slider(minimum=0.1, maximum=1.0, value=0.3, step=0.1, label="Kapak Arası Boşluk (cm)")
194
- pvc_payi_input = gr.Slider(minimum=0.1, maximum=0.5, value=0.2, step=0.1, label="Her Kapak İçin PVC Payı (cm)")
195
-
196
- gr.Markdown("### 3. Sunta Plaka Bilgileri")
197
- with gr.Row():
198
- plaka_genislik_input = gr.Textbox(label="Plaka Genişliği (cm)", value="280")
199
- plaka_yukseklik_input = gr.Textbox(label="Plaka Yüksekliği (cm)", value="210")
200
 
201
- calculate_button = gr.Button("Hesapla ve Yerleşim Planı Oluştur", variant="primary")
202
 
203
  gr.Markdown("---")
204
- gr.Markdown("### 📝 Hesaplama Sonuçları")
205
-
206
- kapak_output_text = gr.Markdown()
207
- govde_output_markdown = gr.Markdown()
208
  gallery_output = gr.Gallery(label="Optimize Edilmiş Plaka Yerleşim Planı", columns=2, object_fit="contain", height="auto")
209
- excel_output_markdown = gr.Markdown(label="Parça Listesi") # YENİ EKLENDİ
210
-
 
 
 
 
 
 
211
  calculate_button.click(
212
- fn=calculate_all_dimensions,
213
- inputs=[genislik_input, yukseklik_input, derinlik_input, malzeme_kalinligi_input, kapak_sayisi_input, kapak_araligi_input, pvc_payi_input, raf_adedi_input, plaka_genislik_input, plaka_yukseklik_input],
214
- outputs=[kapak_output_text, govde_output_markdown, gallery_output, excel_output_markdown] # YENİ ÇIKTI EKLENDİ
215
  )
216
 
217
- demo.launch()
 
2
  from PIL import Image, ImageDraw, ImageFont
3
  from collections import Counter
4
 
5
+ MAX_CABINETS = 5 # Desteklenecek maksimum dolap sayısı
6
+
7
  def does_overlap(part1, part2):
8
  """İki parçanın çakışıp çakışmadığını kontrol eder."""
9
  return not (part1['x'] + part1['w'] <= part2['x'] or
 
22
  for part in parts:
23
  can_fit = (part['w'] <= plate_w and part['h'] <= plate_h) or (part['h'] <= plate_w and part['w'] <= plate_h)
24
  if not can_fit:
25
+ error_message = f"HATA: '{part['label']}' ({part['w']:.1f}x{part['h']:.1f} cm) parçası plaka boyutlarından ({plate_w}x{plate_h} cm) daha büyük. Lütfen ölçüleri kontrol edin."
26
+ return error_message, None
27
 
28
+ parts.sort(key=lambda p: max(p['w'], p['h']), reverse=True)
 
29
  sheets = []
30
 
31
  for part in parts:
32
  placed = False
33
+ for sheet in sheets:
34
+ candidate_points = [(0, 0)] + [(p['x'] + p['w'], p['y']) for p in sheet['parts']] + [(p['x'], p['y'] + p['h']) for p in sheet['parts']]
35
+
 
 
 
 
 
 
 
 
 
36
  for rotation in [False, True]:
37
+ if rotation: part['w'], part['h'] = part['h'], part['w']
 
38
 
39
+ for point in sorted(candidate_points, key=lambda p: p[1]**2 + p[0]**2):
40
  part['x'], part['y'] = point
41
+ if (part['x'] + part['w'] <= plate_w + 0.1) and (part['y'] + part['h'] <= plate_h + 0.1):
42
  if not any(does_overlap(part, p) for p in sheet['parts']):
43
  sheet['parts'].append(part.copy())
44
  placed = True
45
  break
46
 
47
+ if rotation: part['w'], part['h'] = part['h'], part['w']
48
+ if placed: break
49
+ if placed: break
 
 
 
 
50
 
 
51
  if not placed:
52
  new_sheet = {'parts': []}
53
  part['x'], part['y'] = 0, 0
 
54
  if part['w'] <= plate_w and part['h'] <= plate_h:
55
+ new_sheet['parts'].append(part.copy())
56
+ sheets.append(new_sheet)
 
57
  elif part['h'] <= plate_w and part['w'] <= plate_h:
58
+ part['w'], part['h'] = part['h'], part['w']
59
+ new_sheet['parts'].append(part.copy())
60
+ sheets.append(new_sheet)
61
 
62
  # --- GÖRSELLEŞTİRME ---
63
  images = []
64
  font_size = 14
65
+ try: font = ImageFont.truetype("arial.ttf", font_size)
66
+ except IOError: font = ImageFont.load_default()
 
 
67
 
68
  for i, sheet_data in enumerate(sheets):
69
  img = Image.new('RGB', (int(plate_w), int(plate_h)), color=(240, 240, 240))
70
  draw = ImageDraw.Draw(img)
71
+ total_area, used_area = plate_w * plate_h, 0
 
72
 
73
  for p in sheet_data['parts']:
74
  x, y, w, h = p['x'], p['y'], p['w'], p['h']
75
  draw.rectangle([x, y, x + w, y + h], outline=(50, 50, 50), fill=(200, 220, 255))
76
  text = f"{p['label']}\n{p['w']:.1f}x{p['h']:.1f}"
 
77
  bbox = draw.textbbox((0, 0), text, font=font)
78
  text_w, text_h = bbox[2] - bbox[0], bbox[3] - bbox[1]
79
+ text_x, text_y = x + (w - text_w) / 2, y + (h - text_h) / 2
 
 
80
  draw.text((text_x, text_y), text, fill=(0, 0, 0), font=font, align="center")
81
  used_area += w * h
82
 
83
  efficiency = (used_area / total_area) * 100
84
+ draw.text((10, 10), f"Plaka {i+1} | Verimlilik: %{efficiency:.1f}", fill=(0, 0, 0), font=font)
 
85
  images.append(img)
86
 
87
  summary = f"**{len(sheets)}** adet sunta plakası gerekmektedir. Parçaların yerleşim düzeni aşağıda gösterilmiştir."
88
  return summary, images
89
 
90
+ def calculate_all_cabinets(*args):
91
+ plate_g = float(args[-3] or 0)
92
+ plate_y = float(args[-2] or 0)
93
+ num_visible = args[-1]
94
+
95
+ if not all([plate_g, plate_y]):
96
+ return "Lütfen Sunta Plaka Bilgilerini girin.", None, ""
97
+
98
+ master_part_list = []
99
+ inputs_per_cabinet = 8 # Her dolap için girdi sayısı (gen, yük, der, mal, raf, kapak_var_mi, kapak_sayisi, pvc)
100
 
101
+ for i in range(num_visible):
102
+ start_index = i * inputs_per_cabinet
103
+ cab_inputs = args[start_index : start_index + inputs_per_cabinet]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
 
105
+ genislik_str, yukseklik_str, derinlik_str, malzeme_kalinligi, raf_adedi, kapak_eklensin_mi, kapak_sayisi, pvc_payi = cab_inputs
106
+
107
+ if not all([genislik_str, yukseklik_str, derinlik_str]):
108
+ continue
109
+
110
+ try:
111
+ genislik, yukseklik, derinlik = float(genislik_str), float(yukseklik_str), float(derinlik_str)
112
+
113
+ yan_panel_y, yan_panel_d = yukseklik, derinlik
114
+ master_part_list.extend([{'label': f'D{i+1}-Yan', 'w': yan_panel_d, 'h': yan_panel_y} for _ in range(2)])
115
 
116
+ alt_ust_panel_g = genislik - (2 * malzeme_kalinligi)
117
+ alt_ust_panel_d = derinlik
118
+ master_part_list.extend([{'label': f'D{i+1}-Üst/Alt', 'w': alt_ust_panel_g, 'h': alt_ust_panel_d} for _ in range(2)])
119
+
120
+ arkalik_g = genislik - (2 * malzeme_kalinligi)
121
+ arkalik_y = yukseklik - (2 * malzeme_kalinligi)
122
+ master_part_list.append({'label': f'D{i+1}-Arka', 'w': arkalik_g, 'h': arkalik_y})
123
+
124
+ if raf_adedi > 0:
125
+ raf_g, raf_d = alt_ust_panel_g, alt_ust_panel_d
126
+ master_part_list.extend([{'label': f'D{i+1}-Raf', 'w': raf_g, 'h': raf_d} for _ in range(int(raf_adedi))])
127
+
128
+ # Sadece kapak isteniyorsa kapakları hesapla ve ekle
129
+ if kapak_eklensin_mi and kapak_sayisi > 0:
130
+ kapak_araligi = 0.3
131
+ toplam_aralik_genislik = kapak_araligi * (kapak_sayisi - 1) if kapak_sayisi > 1 else 0
132
+ nihai_kapak_genisligi = (genislik - toplam_aralik_genislik) / kapak_sayisi - pvc_payi
133
+ nihai_kapak_yuksekligi = yukseklik - 0.4
134
+ if nihai_kapak_genisligi > 0 and nihai_kapak_yuksekligi > 0:
135
+ master_part_list.extend([{'label': f'D{i+1}-Kapak', 'w': nihai_kapak_genisligi, 'h': nihai_kapak_yuksekligi} for _ in range(int(kapak_sayisi))])
136
+
137
+ except (ValueError, TypeError) as e:
138
+ return f"Dolap {i+1} için geçersiz bir değer girdiniz. Lütfen kontrol edin. Hata: {e}", None, ""
139
+
140
+ if not master_part_list:
141
+ return "Hesaplanacak parça bulunamadı. Lütfen en az bir dolap için ölçüleri tam girin.", None, ""
142
 
143
+ part_tuples = [(p['label'], f"{p['w']:.2f}", f"{p['h']:.2f}") for p in master_part_list]
144
+ part_counts = Counter(part_tuples)
145
+ excel_listesi = "### Toplam Parça Listesi (Excel'e Kopyalamak İçin)\n| Parça Adı | Adet | Genişlik (cm) | Yükseklik (cm) |\n|:---|:---:|:---:|:---:|\n"
146
+ for (label, w, h), count in sorted(part_counts.items()):
147
+ excel_listesi += f"| {label} | {count} | {w} | {h} |\n"
148
+
149
+ summary, images = pack_and_draw(master_part_list, plate_g, plate_y)
150
+
151
+ return summary, images, excel_listesi
152
+
153
+ def add_cabinet_form(current_visible):
154
+ current_visible += 1
155
+ updates = [gr.update(value=current_visible)]
156
+ for i in range(MAX_CABINETS):
157
+ updates.append(gr.update(visible=i < current_visible))
158
+ return updates
159
+
160
+ with gr.Blocks(theme=gr.themes.Soft(), title="Çoklu Dolap Optimizasyon Hesaplayıcı") as demo:
161
+ gr.Markdown("# Çoklu Dolap Optimizasyon Hesaplayıcı")
162
+ gr.Markdown("Birden fazla dolap ekleyerek tüm parçaları tek bir sunta yerleşim planında optimize edin.")
163
+
164
+ cabinet_forms_accordions = []
165
+ all_inputs = []
166
+ visible_cabinets_state = gr.State(1)
167
+
168
+ for i in range(MAX_CABINETS):
169
+ with gr.Accordion(f"Dolap {i+1}", open=True, visible=i < 1) as accordion:
170
+ with gr.Row():
171
+ genislik = gr.Textbox(label="Genişlik (cm)", placeholder="80")
172
+ yukseklik = gr.Textbox(label="Yükseklik (cm)", placeholder="180")
173
+ derinlik = gr.Textbox(label="Derinlik (cm)", placeholder="50")
174
+ with gr.Row():
175
+ malzeme_kalinligi = gr.Slider(1.6, 3.0, 1.8, step=0.1, label="Malzeme Kalınlığı (cm)")
176
+ raf_adedi = gr.Number(label="Raf Adedi", value=2, minimum=0, step=1)
177
+
178
+ kapak_eklensin_mi = gr.Checkbox(label="Bu Dolaba Kapak Eklensin mi?", value=True)
179
+
180
+ with gr.Row(visible=True) as kapak_ayarlari_row:
181
+ kapak_sayisi = gr.Number(label="Kapak Sayısı", value=2, minimum=1, step=1)
182
+ pvc_payi = gr.Slider(0.1, 0.5, 0.2, step=0.1, label="Kapak PVC Payı (cm)")
183
+
184
+ # Checkbox'ın durumuna göre kapak ayarları satırını göster/gizle
185
+ kapak_eklensin_mi.change(
186
+ fn=lambda x: gr.update(visible=x),
187
+ inputs=kapak_eklensin_mi,
188
+ outputs=kapak_ayarlari_row,
189
+ )
190
+
191
+ cabinet_forms_accordions.append(accordion)
192
+ all_inputs.extend([genislik, yukseklik, derinlik, malzeme_kalinligi, raf_adedi, kapak_eklensin_mi, kapak_sayisi, pvc_payi])
193
+
194
+ add_button = gr.Button("Başka Bir Dolap Ekle", variant="secondary")
195
+
196
+ gr.Markdown("### Sunta Plaka Bilgileri")
197
  with gr.Row():
198
+ plaka_g_input = gr.Textbox(label="Plaka Genişliği (cm)", value="280")
199
+ plaka_y_input = gr.Textbox(label="Plaka Yüksekliği (cm)", value="210")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
 
201
+ calculate_button = gr.Button("Tüm Dolapları Hesapla ve Yerleşim Planı Oluştur", variant="primary")
202
 
203
  gr.Markdown("---")
204
+ gr.Markdown("### 📝 Toplam Sonuçlar")
205
+ summary_output = gr.Markdown()
 
 
206
  gallery_output = gr.Gallery(label="Optimize Edilmiş Plaka Yerleşim Planı", columns=2, object_fit="contain", height="auto")
207
+ excel_output = gr.Markdown(label="Parça Listesi")
208
+
209
+ add_button.click(
210
+ fn=add_cabinet_form,
211
+ inputs=[visible_cabinets_state],
212
+ outputs=[visible_cabinets_state] + cabinet_forms_accordions
213
+ )
214
+
215
  calculate_button.click(
216
+ fn=calculate_all_cabinets,
217
+ inputs=all_inputs + [plaka_g_input, plaka_y_input, visible_cabinets_state],
218
+ outputs=[summary_output, gallery_output, excel_output]
219
  )
220
 
221
+ demo.launch()