Zatimm commited on
Commit
c1f2907
·
verified ·
1 Parent(s): 0496fb1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -127
app.py CHANGED
@@ -1,8 +1,9 @@
1
  import gradio as gr
2
  import pandas as pd
3
  from rectpack import newPacker
4
- import os
5
- import datetime
 
6
 
7
  # --- Hesaplama Fonksiyonları ---
8
 
@@ -10,156 +11,132 @@ def calculate_single_cabinet_parts(dolap_no, h, w, d, kalinlik, raf_sayisi, kapa
10
  """Tek bir dolabın parçalarını hesaplar."""
11
  parts = []
12
 
13
- # 1. Ana Gövde Parçaları
14
- # Yan Tablalar (2 adet)
15
- parts.append({'dolap_no': dolap_no, 'parca_adi': 'Yan Tabla', 'adet': 2, 'uzunluk': h, 'genislik': d, 'malzeme': 'Sunta'})
16
- # Alt ve Üst Tablalar (2 adet)
17
  ic_genislik = w - (2 * kalinlik)
 
18
  parts.append({'dolap_no': dolap_no, 'parca_adi': 'Alt/Üst Tabla', 'adet': 2, 'uzunluk': ic_genislik, 'genislik': d, 'malzeme': 'Sunta'})
19
 
20
- # 2. Raflar
21
  if raf_sayisi > 0:
22
- # Raflar için genellikle 1mm derinlik toleransı bırakılır.
23
  raf_derinlik = d - 1
24
  parts.append({'dolap_no': dolap_no, 'parca_adi': 'Raf', 'adet': raf_sayisi, 'uzunluk': ic_genislik, 'genislik': raf_derinlik, 'malzeme': 'Sunta'})
25
 
26
- # 3. Kapaklar (KULLANICI İSTEĞİNE GÖRE REVİZE EDİLMİŞ HESAPLAMA MANTIĞI)
27
  if kapak_var and kapak_sayisi > 0:
28
  calisma_boslugu = 3
29
- bant_payi = 1 # Her bir kenar için 1mm bant payı
30
-
31
- # Yükseklik hesabı: Toplam yükseklikten çalışma boşluğu düşülür.
32
  kapak_yukseklik = h - calisma_boslugu
33
-
34
- # Genişlik hesabı:
35
- # Adım 1: Toplam genişlikten çalışma boşluğunu düş.
36
  toplam_kullanilabilir_genislik = w - calisma_boslugu
37
-
38
- # Adım 2: Kullanılabilir genişliği kapak sayısına bölerek her bir kapağın 'bitmiş' halini bul.
39
  bitmis_kapak_genisligi = toplam_kullanilabilir_genislik / kapak_sayisi
40
-
41
- # Adım 3: Bitmiş ölçüden her iki yanın bant payını (toplam 2mm) düşerek net kesim ölçüsünü bul.
42
  net_kesim_genisligi = bitmis_kapak_genisligi - (2 * bant_payi)
 
43
 
44
- parts.append({
45
- 'dolap_no': dolap_no,
46
- 'parca_adi': 'Kapak',
47
- 'adet': kapak_sayisi,
48
- 'uzunluk': kapak_yukseklik,
49
- 'genislik': round(net_kesim_genisligi, 2), # Küsuratlı çıkabilir, yuvarla
50
- 'malzeme': 'Sunta'
51
- })
52
-
53
- # 4. Arkalık
54
  if arkalik_var:
55
- # Arkalık genellikle dış ölçülerde olur.
56
  parts.append({'dolap_no': dolap_no, 'parca_adi': 'Arkalık', 'adet': 1, 'uzunluk': h, 'genislik': w, 'malzeme': 'HDF/Duralit'})
57
 
58
  return parts
59
 
60
- def add_cabinet_to_list(
61
- all_parts_state, cabinet_number_state,
62
- h, w, d, kalinlik, raf_sayisi, kapak_var, kapak_sayisi, arkalik_var
63
- ):
64
  """Hesaplanan dolap parçalarını ana listeye ekler."""
65
  if not all([h, w, d, kalinlik]):
66
  raise gr.Error("Lütfen temel dolap ölçülerini ve malzeme kalınlığını girin!")
67
-
68
- new_parts = calculate_single_cabinet_parts(
69
- cabinet_number_state, h, w, d, kalinlik, raf_sayisi, kapak_var, kapak_sayisi, arkalik_var
70
- )
71
-
72
  updated_parts = all_parts_state + new_parts
73
-
74
- # DataFrame için veriyi düzleştir
75
- df_data = []
76
- for part in updated_parts:
77
- df_data.append([
78
- part['dolap_no'], part['parca_adi'], part['adet'],
79
- part['uzunluk'], part['genislik'], part['malzeme']
80
- ])
81
-
82
- df = pd.DataFrame(df_data, columns=["Dolap No", "Parça Adı", "Adet", "Uzunluk (mm)", "Genişlik (mm)", "Malzeme"])
83
-
84
  return updated_parts, cabinet_number_state + 1, df, f"Başarılı! {cabinet_number_state}. Dolap listeye eklendi."
85
 
86
  def clear_list():
87
  """Tüm listeyi temizler."""
88
  return [], 1, pd.DataFrame(), "Liste temizlendi. Yeni dolap ekleyebilirsiniz."
89
 
90
- def run_optimization_and_export(all_parts, plaka_uzunluk, plaka_genislik):
91
- """Parçaları plakalara yerleştirir ve Excel çıktısı oluşturur."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  if not all_parts:
93
  raise gr.Error("Liste boş! Lütfen önce dolap ekleyin.")
94
  if not all([plaka_uzunluk, plaka_genislik]):
95
  raise gr.Error("Lütfen sunta plakası ölçülerini girin!")
96
 
97
- # 1. Optimizasyon (Nesting)
98
  sunta_parcalari = []
99
  for part in all_parts:
100
  if part['malzeme'] == 'Sunta':
101
  for _ in range(part['adet']):
102
- # Parçaları her iki yönde de dönebilir şekilde ekle
103
  sunta_parcalari.append((part['uzunluk'], part['genislik']))
104
 
105
- packer = newPacker(rotation=True)
 
106
 
 
107
  for r in sunta_parcalari:
108
  packer.add_rect(r[0], r[1])
109
 
110
- # Plakaları ekle
111
- packer.add_bin(plaka_uzunluk, plaka_genislik, count=100) # 100 plaka limiti
112
-
113
  packer.pack()
114
 
115
  plaka_sayisi = len(packer)
116
  optimization_result = f"**Optimizasyon Sonucu:**\nToplam **{plaka_sayisi}** adet {plaka_uzunluk}x{plaka_genislik}mm sunta plakasına ihtiyaç var."
117
-
118
- # 2. Excel Dosyası Oluşturma
119
- df_data = []
120
- for part in all_parts:
121
- df_data.append([
122
- part['dolap_no'], part['parca_adi'], part['adet'],
123
- part['uzunluk'], part['genislik'], part['malzeme']
124
- ])
125
 
126
- df = pd.DataFrame(df_data, columns=["Dolap No", "Parça Adı", "Adet", "Uzunluk (mm)", "Genişlik (mm)", "Malzeme"])
127
-
128
- # Geçici bir dosya oluştur
129
- timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
130
- filepath = f"kesim_listesi_{timestamp}.xlsx"
131
- df.to_excel(filepath, index=False, engine='openpyxl')
132
 
133
- return optimization_result, filepath
134
 
135
  # --- Gradio Arayüzü ---
136
 
137
  with gr.Blocks(theme=gr.themes.Soft(), title="Dolap Kesim Hesaplayıcı") as demo:
138
- # State'ler: tüm parça listesini ve dolap numarasını tutar
139
  all_parts_state = gr.State([])
140
  cabinet_number_state = gr.State(1)
141
 
142
- gr.Markdown("# Akıllı Dolap Kesim Hesaplayıcı (Revize Edilmiş)")
143
- gr.Markdown("Bu uygulama, dolap ölçülerinize göre net kesim listesi oluşturur, malzeme optimizasyonu yapar ve Excel çıktısı verir.")
144
 
145
  with gr.Row():
146
  with gr.Column(scale=1):
147
  gr.Markdown("### 1. Dolap Bilgilerini Girin")
148
-
149
- with gr.Accordion(f"Yeni Dolap Ekle (Şu anki Dolap No: 1)", open=True) as accordion:
150
  with gr.Row():
151
  h_input = gr.Number(label="Yükseklik (mm)", value=1800)
152
  w_input = gr.Number(label="Genişlik (mm)", value=800)
153
  d_input = gr.Number(label="Derinlik (mm)", value=500)
154
  kalinlik_input = gr.Number(label="Malzeme Kalınlığı (mm)", value=18)
155
  raf_input = gr.Slider(minimum=0, maximum=10, step=1, label="Raf Sayısı", value=3)
156
-
157
  with gr.Row():
158
  kapak_var_input = gr.Checkbox(label="Kapak Olsun mu?", value=True)
159
  kapak_sayisi_input = gr.Radio([1, 2, 3, 4], label="Kapak Sayısı", value=2, interactive=True)
160
-
161
  arkalik_var_input = gr.Checkbox(label="Arkalık Olsun mu?", value=True)
162
-
163
  add_button = gr.Button("Hesapla ve Listeye Ekle", variant="primary")
164
  clear_button = gr.Button("Tüm Listeyi Temizle", variant="stop")
165
  status_text = gr.Textbox(label="Durum", interactive=False)
@@ -167,61 +144,32 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Dolap Kesim Hesaplayıcı") as dem
167
  with gr.Column(scale=2):
168
  gr.Markdown("### 2. Toplam Parça Kesim Listesi")
169
  parts_df_output = gr.DataFrame(
170
- headers=["Dolap No", "Parça Adı", "Adet", "Uzunluk (mm)", "Genişlik (mm)", "Malzeme"],
171
- datatype=["number", "str", "number", "number", "number", "str"],
172
  interactive=False
173
  )
174
 
175
- gr.Markdown("### 3. Optimizasyon ve Çıktı")
176
- with gr.Row():
177
- plaka_uzunluk_input = gr.Number(label="Plaka Uzunluğu (mm)", value=2800)
178
- plaka_genislik_input = gr.Number(label="Plaka Genişliği (mm)", value=2100)
179
-
180
- optimize_button = gr.Button("Optimizasyonu Çalıştır ve Excel Oluştur", variant="primary")
181
-
182
- optimization_output = gr.Markdown()
183
- excel_output = gr.File(label="Kesim Listesini İndir")
184
-
185
- # --- Buton ve Fonksiyon Bağlantıları ---
186
-
187
- # Kapak sayısı seçeneğini, kapak var checkbox'ına bağla
188
- def toggle_kapak_sayisi(kapak_var):
189
- return gr.update(interactive=kapak_var)
190
 
191
- kapak_var_input.change(fn=toggle_kapak_sayisi, inputs=kapak_var_input, outputs=kapak_sayisi_input)
 
 
192
 
193
- # Dolap ekleme butonu
 
194
  add_button.click(
195
  fn=add_cabinet_to_list,
196
- inputs=[
197
- all_parts_state, cabinet_number_state,
198
- h_input, w_input, d_input, kalinlik_input, raf_input,
199
- kapak_var_input, kapak_sayisi_input, arkalik_var_input
200
- ],
201
  outputs=[all_parts_state, cabinet_number_state, parts_df_output, status_text]
202
- ).then(
203
- # Dolap numarası eklendikten sonra Accordion başlığını güncelle
204
- lambda cabinet_no: gr.update(label=f"Yeni Dolap Ekle (Şu anki Dolap No: {cabinet_no})"),
205
- inputs=cabinet_number_state,
206
- outputs=accordion
207
- )
208
-
209
- # Listeyi temizleme butonu
210
- clear_button.click(
211
- fn=clear_list,
212
- inputs=[],
213
- outputs=[all_parts_state, cabinet_number_state, parts_df_output, status_text]
214
- ).then(
215
- lambda cabinet_no: gr.update(label=f"Yeni Dolap Ekle (Şu anki Dolap No: {cabinet_no})"),
216
- inputs=cabinet_number_state,
217
- outputs=accordion
218
- )
219
-
220
- # Optimizasyon ve Excel butonu
221
- optimize_button.click(
222
- fn=run_optimization_and_export,
223
  inputs=[all_parts_state, plaka_uzunluk_input, plaka_genislik_input],
224
- outputs=[optimization_output, excel_output]
225
  )
226
 
227
  demo.launch()
 
1
  import gradio as gr
2
  import pandas as pd
3
  from rectpack import newPacker
4
+ import matplotlib.pyplot as plt
5
+ import matplotlib.patches as patches
6
+ import random
7
 
8
  # --- Hesaplama Fonksiyonları ---
9
 
 
11
  """Tek bir dolabın parçalarını hesaplar."""
12
  parts = []
13
 
14
+ # Ana Gövde Parçaları
 
 
 
15
  ic_genislik = w - (2 * kalinlik)
16
+ parts.append({'dolap_no': dolap_no, 'parca_adi': 'Yan Tabla', 'adet': 2, 'uzunluk': h, 'genislik': d, 'malzeme': 'Sunta'})
17
  parts.append({'dolap_no': dolap_no, 'parca_adi': 'Alt/Üst Tabla', 'adet': 2, 'uzunluk': ic_genislik, 'genislik': d, 'malzeme': 'Sunta'})
18
 
19
+ # Raflar
20
  if raf_sayisi > 0:
 
21
  raf_derinlik = d - 1
22
  parts.append({'dolap_no': dolap_no, 'parca_adi': 'Raf', 'adet': raf_sayisi, 'uzunluk': ic_genislik, 'genislik': raf_derinlik, 'malzeme': 'Sunta'})
23
 
24
+ # Kapaklar (Revize Edilmiş Hesaplama)
25
  if kapak_var and kapak_sayisi > 0:
26
  calisma_boslugu = 3
27
+ bant_payi = 1
 
 
28
  kapak_yukseklik = h - calisma_boslugu
 
 
 
29
  toplam_kullanilabilir_genislik = w - calisma_boslugu
 
 
30
  bitmis_kapak_genisligi = toplam_kullanilabilir_genislik / kapak_sayisi
 
 
31
  net_kesim_genisligi = bitmis_kapak_genisligi - (2 * bant_payi)
32
+ parts.append({'dolap_no': dolap_no, 'parca_adi': 'Kapak', 'adet': kapak_sayisi, 'uzunluk': kapak_yukseklik, 'genislik': round(net_kesim_genisligi, 2), 'malzeme': 'Sunta'})
33
 
34
+ # Arkalık
 
 
 
 
 
 
 
 
 
35
  if arkalik_var:
 
36
  parts.append({'dolap_no': dolap_no, 'parca_adi': 'Arkalık', 'adet': 1, 'uzunluk': h, 'genislik': w, 'malzeme': 'HDF/Duralit'})
37
 
38
  return parts
39
 
40
+ def add_cabinet_to_list(all_parts_state, cabinet_number_state, h, w, d, kalinlik, raf_sayisi, kapak_var, kapak_sayisi, arkalik_var):
 
 
 
41
  """Hesaplanan dolap parçalarını ana listeye ekler."""
42
  if not all([h, w, d, kalinlik]):
43
  raise gr.Error("Lütfen temel dolap ölçülerini ve malzeme kalınlığını girin!")
44
+ new_parts = calculate_single_cabinet_parts(cabinet_number_state, h, w, d, kalinlik, raf_sayisi, kapak_var, kapak_sayisi, arkalik_var)
 
 
 
 
45
  updated_parts = all_parts_state + new_parts
46
+ df = pd.DataFrame(updated_parts)
 
 
 
 
 
 
 
 
 
 
47
  return updated_parts, cabinet_number_state + 1, df, f"Başarılı! {cabinet_number_state}. Dolap listeye eklendi."
48
 
49
  def clear_list():
50
  """Tüm listeyi temizler."""
51
  return [], 1, pd.DataFrame(), "Liste temizlendi. Yeni dolap ekleyebilirsiniz."
52
 
53
+ def create_layout_plot(packer, plaka_uzunluk, plaka_genislik):
54
+ """Matplotlib kullanarak plaka yerleşimini çizer."""
55
+ images = []
56
+ plaka_alani = plaka_uzunluk * plaka_genislik
57
+
58
+ for i, b in enumerate(packer):
59
+ fig, ax = plt.subplots(1, figsize=(10, 7))
60
+ ax.set_xlim(0, plaka_uzunluk)
61
+ ax.set_ylim(0, plaka_genislik)
62
+
63
+ # Plaka sınırını çiz
64
+ ax.add_patch(patches.Rectangle((0, 0), plaka_uzunluk, plaka_genislik, fill=False, edgecolor='black', lw=2))
65
+
66
+ toplam_kullanilan_alan = 0
67
+ for r in b:
68
+ # Rastgele bir renk oluştur
69
+ color = "#{:06x}".format(random.randint(0, 0xFFFFFF))
70
+ ax.add_patch(patches.Rectangle((r.x, r.y), r.width, r.height, facecolor=color, edgecolor='black', lw=1, alpha=0.7))
71
+ # Parça ölçülerini yaz
72
+ ax.text(r.x + r.width/2, r.y + r.height/2, f"{int(r.width)}x{int(r.height)}", ha='center', va='center', fontsize=8)
73
+ toplam_kullanilan_alan += r.width * r.height
74
+
75
+ kullanim_orani = (toplam_kullanilan_alan / plaka_alani) * 100
76
+ ax.set_title(f"Plaka {i+1} - Kullanım: {kullanim_orani:.2f}%")
77
+ plt.gca().set_aspect('equal', adjustable='box')
78
+
79
+ filepath = f"/tmp/plaka_{i+1}.png"
80
+ plt.savefig(filepath)
81
+ plt.close(fig)
82
+ images.append(filepath)
83
+
84
+ return images
85
+
86
+ def run_optimization_and_visualize(all_parts, plaka_uzunluk, plaka_genislik):
87
+ """Parçaları plakalara yerleştirir ve görselleştirir."""
88
  if not all_parts:
89
  raise gr.Error("Liste boş! Lütfen önce dolap ekleyin.")
90
  if not all([plaka_uzunluk, plaka_genislik]):
91
  raise gr.Error("Lütfen sunta plakası ölçülerini girin!")
92
 
 
93
  sunta_parcalari = []
94
  for part in all_parts:
95
  if part['malzeme'] == 'Sunta':
96
  for _ in range(part['adet']):
 
97
  sunta_parcalari.append((part['uzunluk'], part['genislik']))
98
 
99
+ if not sunta_parcalari:
100
+ return "Optimize edilecek 'Sunta' malzemesi bulunamadı.", None
101
 
102
+ packer = newPacker(rotation=True)
103
  for r in sunta_parcalari:
104
  packer.add_rect(r[0], r[1])
105
 
106
+ packer.add_bin(plaka_uzunluk, plaka_genislik, count=100)
 
 
107
  packer.pack()
108
 
109
  plaka_sayisi = len(packer)
110
  optimization_result = f"**Optimizasyon Sonucu:**\nToplam **{plaka_sayisi}** adet {plaka_uzunluk}x{plaka_genislik}mm sunta plakasına ihtiyaç var."
 
 
 
 
 
 
 
 
111
 
112
+ # Görselleştirmeyi oluştur
113
+ image_paths = create_layout_plot(packer, plaka_uzunluk, plaka_genislik)
 
 
 
 
114
 
115
+ return optimization_result, image_paths
116
 
117
  # --- Gradio Arayüzü ---
118
 
119
  with gr.Blocks(theme=gr.themes.Soft(), title="Dolap Kesim Hesaplayıcı") as demo:
 
120
  all_parts_state = gr.State([])
121
  cabinet_number_state = gr.State(1)
122
 
123
+ gr.Markdown("# Akıllı Dolap Kesim Hesaplayıcı ve Görselleştirici")
124
+ gr.Markdown("Bu uygulama, dolap ölçülerinize göre kesim listesi oluşturur ve parçaların plaka üzerindeki yerleşimini görselleştirir.")
125
 
126
  with gr.Row():
127
  with gr.Column(scale=1):
128
  gr.Markdown("### 1. Dolap Bilgilerini Girin")
129
+ with gr.Accordion(f"Yeni Dolap Ekle (No: 1)", open=True) as accordion:
 
130
  with gr.Row():
131
  h_input = gr.Number(label="Yükseklik (mm)", value=1800)
132
  w_input = gr.Number(label="Genişlik (mm)", value=800)
133
  d_input = gr.Number(label="Derinlik (mm)", value=500)
134
  kalinlik_input = gr.Number(label="Malzeme Kalınlığı (mm)", value=18)
135
  raf_input = gr.Slider(minimum=0, maximum=10, step=1, label="Raf Sayısı", value=3)
 
136
  with gr.Row():
137
  kapak_var_input = gr.Checkbox(label="Kapak Olsun mu?", value=True)
138
  kapak_sayisi_input = gr.Radio([1, 2, 3, 4], label="Kapak Sayısı", value=2, interactive=True)
 
139
  arkalik_var_input = gr.Checkbox(label="Arkalık Olsun mu?", value=True)
 
140
  add_button = gr.Button("Hesapla ve Listeye Ekle", variant="primary")
141
  clear_button = gr.Button("Tüm Listeyi Temizle", variant="stop")
142
  status_text = gr.Textbox(label="Durum", interactive=False)
 
144
  with gr.Column(scale=2):
145
  gr.Markdown("### 2. Toplam Parça Kesim Listesi")
146
  parts_df_output = gr.DataFrame(
147
+ headers=["dolap_no", "parca_adi", "adet", "uzunluk", "genislik", "malzeme"],
 
148
  interactive=False
149
  )
150
 
151
+ gr.Markdown("---")
152
+ gr.Markdown("### 3. Optimizasyon ve Görselleştirme")
153
+ with gr.Row():
154
+ plaka_uzunluk_input = gr.Number(label="Plaka Uzunluğu (mm)", value=2800)
155
+ plaka_genislik_input = gr.Number(label="Plaka Genişliği (mm)", value=2100)
 
 
 
 
 
 
 
 
 
 
156
 
157
+ visualize_button = gr.Button("Optimizasyonu Çalıştır ve Görselleştir", variant="primary")
158
+ optimization_output = gr.Markdown()
159
+ layout_gallery = gr.Gallery(label="Plaka Yerleşim Planları", elem_id="gallery", columns=[2], object_fit="contain", height="auto")
160
 
161
+ # Fonksiyon Bağlantıları
162
+ kapak_var_input.change(lambda x: gr.update(interactive=x), kapak_var_input, kapak_sayisi_input)
163
  add_button.click(
164
  fn=add_cabinet_to_list,
165
+ inputs=[all_parts_state, cabinet_number_state, h_input, w_input, d_input, kalinlik_input, raf_input, kapak_var_input, kapak_sayisi_input, arkalik_var_input],
 
 
 
 
166
  outputs=[all_parts_state, cabinet_number_state, parts_df_output, status_text]
167
+ ).then(lambda cabinet_no: gr.update(label=f"Yeni Dolap Ekle (No: {cabinet_no})"), cabinet_number_state, accordion)
168
+ clear_button.click(fn=clear_list, outputs=[all_parts_state, cabinet_number_state, parts_df_output, status_text]).then(lambda cabinet_no: gr.update(label=f"Yeni Dolap Ekle (No: {cabinet_no})"), cabinet_number_state, accordion)
169
+ visualize_button.click(
170
+ fn=run_optimization_and_visualize,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  inputs=[all_parts_state, plaka_uzunluk_input, plaka_genislik_input],
172
+ outputs=[optimization_output, layout_gallery]
173
  )
174
 
175
  demo.launch()