Zatimm commited on
Commit
3b04ccf
·
verified ·
1 Parent(s): 6944dab

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +203 -170
app.py CHANGED
@@ -1,182 +1,215 @@
1
  import gradio as gr
2
-
3
- # -----------------------------------------------------------------------------
4
- # YERLEŞTİRME ALGORİTMASI (Bu kısım değiştirilmedi)
5
- # -----------------------------------------------------------------------------
6
- def yerlestir(parcalar, plaka_uzunlugu, plaka_genisligi, bicak_payi):
7
- # Not: Bu algoritma temel seviyededir ve optimizasyon için geliştirilebilir.
8
- # Gerçek bir 2D bin-packing algoritması daha verimli sonuçlar üretecektir.
9
- plakalar = [{'parcalar': []}]
10
- for parca in sorted(parcalar, key=lambda x: x['uzunluk'] * x['genislik'], reverse=True):
11
- # Bu basit mantık şimdilik tüm parçaları tek bir plakaya ekliyor.
12
- parca['pozisyon'] = 'N/A' # Pozisyon hesaplama devre dışı bırakıldı.
13
- plakalar[0]['parcalar'].append(parca.copy())
14
- return plakalar
15
-
16
- # -----------------------------------------------------------------------------
17
- # LİSTEYE EKLEME FONKSİYONLARI
18
- # -----------------------------------------------------------------------------
19
- def add_item_to_list(item_list, item_type, status_message, **kwargs):
20
- """Listeye yeni bir dolap veya raf ekler."""
21
- new_item = {'type': item_type}
22
- new_item.update(kwargs)
23
- item_list.append(new_item)
24
- return item_list, f"✔️ {len(item_list)}. eleman ({status_message}) listeye eklendi."
25
-
26
- # -----------------------------------------------------------------------------
27
- # ANA HESAPLAMA FONKSİYONU
28
- # -----------------------------------------------------------------------------
29
- def hesapla(item_list, plaka_uzunlugu, plaka_genisligi, bicak_payi, bant_kenari):
30
- if not item_list:
31
- return "Hesaplanacak eleman yok. Lütfen listeden dolap veya raf ekleyin.", ""
32
-
33
- tum_yerlesim_planlari = []
34
- tum_parca_listeleri = []
35
-
36
- # Listeye eklenen her bir eleman (dolap veya raf) için döngü
37
- for i, item in enumerate(item_list, 1):
38
- parcalar = []
39
- item_type = item.get('type')
40
- item_name = ""
41
-
42
- # --- ELEMAN TİPİNE GÖRE PARÇA LİSTESİ OLUŞTURMA ---
43
-
44
- if item_type == 'cabinet':
45
- # Dolap parçalarını hesapla
46
- genislik = item['genislik']
47
- yukseklik = item['yukseklik']
48
- derinlik = item['derinlik']
49
- kapak_tipi = item['kapak_tipi']
50
- item_name = f"DOLAP ({kapak_tipi})"
51
-
52
- # Dolap gövde parçaları (18mm sunta kalınlığı varsayıldı)
53
- parcalar.extend([
54
- {"ad": "Üst Tabla", "uzunluk": genislik, "genislik": derinlik},
55
- {"ad": "Alt Tabla", "uzunluk": genislik, "genislik": derinlik},
56
- {"ad": "Sol Dikey", "uzunluk": yukseklik - 36, "genislik": derinlik},
57
- {"ad": "Sağ Dikey", "uzunluk": yukseklik - 36, "genislik": derinlik},
58
- {"ad": "Raf", "uzunluk": genislik - 36, "genislik": derinlik},
59
- {"ad": "Arkalık", "uzunluk": genislik, "genislik": yukseklik}
60
- ])
61
-
62
- # Dolap kapak parçaları
63
- if kapak_tipi == "Tek Kapak":
64
- parcalar.append({"ad": "Kapak", "uzunluk": yukseklik - 4, "genislik": genislik - 4})
65
- elif kapak_tipi == "Çift Kapak":
66
- kapak_genislik = (genislik - 6) / 2
67
- parcalar.extend([
68
- {"ad": "Sol Kapak", "uzunluk": yukseklik - 4, "genislik": kapak_genislik},
69
- {"ad": "Sağ Kapak", "uzunluk": yukseklik - 4, "genislik": kapak_genislik}
70
- ])
71
-
72
- elif item_type == 'shelf':
73
- # Raf parçalarını hesapla
74
- adet = item['adet']
75
- uzunluk = item['uzunluk']
76
- derinlik = item['derinlik']
77
- item_name = f"RAF SETİ ({adet} adet)"
78
-
79
- for _ in range(adet):
80
- parcalar.append({"ad": "Raf", "uzunluk": uzunluk, "genislik": derinlik})
81
-
82
- # --- ORTAK İŞLEMLER: KENAR BANDI VE YERLEŞTİRME ---
83
-
84
- if bant_kenari:
85
- for parca in parcalar:
86
- parca["uzunluk"] += 2
87
- parca["genislik"] += 2
88
 
89
- plakalar = yerlestir(parcalar, plaka_uzunlugu, plaka_genisligi, bicak_payi)
90
-
91
- # --- ÇIKTILARI FORMATLAMA ---
92
-
93
- # 1. Yerleşim Planı Çıktısı
94
- yerlesim_plani_str = f"--- ELEMAN {i}: {item_name} / YERLEŞİM PLANI ---\n"
95
- for j, plaka in enumerate(plakalar):
96
- yerlesim_plani_str += f"Plaka {j+1}:\n"
97
- if not plaka['parcalar']:
98
- yerlesim_plani_str += " - Bu plakada yerleştirilecek parça yok.\n"
99
- else:
100
- for parca in plaka['parcalar']:
101
- yerlesim_plani_str += f" - {parca['ad']}: {parca['uzunluk']:.2f} x {parca['genislik']:.2f} mm\n"
102
- yerlesim_plani_str += "\n"
103
- tum_yerlesim_planlari.append(yerlesim_plani_str)
104
-
105
- # 2. Parça Listesi Çıktısı
106
- parca_listesi_str = f"--- ELEMAN {i}: {item_name} / PARÇA LİSTESİ ---\n"
107
- parca_ozeti = {}
108
- for parca in parcalar:
109
- anahtar = f"{parca['ad']}: {parca['uzunluk']:.2f} x {parca['genislik']:.2f} mm"
110
- parca_ozeti[anahtar] = parca_ozeti.get(anahtar, 0) + 1
111
 
112
- for anahtar, adet in parca_ozeti.items():
113
- parca_listesi_str += f"- {anahtar} (Adet: {adet})\n"
114
- tum_parca_listeleri.append(parca_listesi_str)
115
-
116
- return "\n".join(tum_yerlesim_planlari), "\n".join(tum_parca_listeleri)
117
-
118
- # -----------------------------------------------------------------------------
119
- # GRADIO ARAYÜZÜ
120
- # -----------------------------------------------------------------------------
121
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
122
- gr.Markdown("# Dolap ve Raf Parça Hesaplama ve Optimizasyonu")
123
-
124
- # Tüm eklenecek dolap ve rafların tutulduğu ana liste
125
- item_list_state = gr.State([])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
 
127
  with gr.Row():
128
- # --- SOL TARAF: GİRDİLER ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  with gr.Column(scale=2):
130
- gr.Markdown("## 1. Eleman Ekle")
 
 
 
 
 
131
 
132
- with gr.Tabs() as tabs:
133
- # DOLAP MODU SEKMESİ
134
- with gr.TabItem("Dolap Modu", id=0):
135
- c_genislik = gr.Number(label="Genişlik (mm)", value=600)
136
- c_yukseklik = gr.Number(label="Yükseklik (mm)", value=1800)
137
- c_derinlik = gr.Number(label="Derinlik (mm)", value=580)
138
- c_kapak_tipi = gr.Radio(["Kapaksız", "Tek Kapak", "Çift Kapak"], label="Kapak Tipi", value="Kapaksız")
139
- add_cabinet_btn = gr.Button("Dolabı Listeye Ekle")
140
-
141
- # RAF MODU SEKMESİ
142
- with gr.TabItem("Raf Modu", id=1):
143
- s_adet = gr.Number(label="Adet", value=5, precision=0)
144
- s_uzunluk = gr.Number(label="Raf Uzunluğu (mm)", value=800)
145
- s_derinlik = gr.Number(label="Raf Derinliği (mm)", value=300)
146
- add_shelf_btn = gr.Button("Rafları Listeye Ekle")
147
 
148
- gr.Markdown("## 2. Genel Ayarlar")
149
- with gr.Accordion("Malzeme ve Kesim Ayarları", open=True):
150
- plaka_uzunlugu = gr.Number(label="Plaka Uzunluğu (mm)", value=2800)
151
- plaka_genisligi = gr.Number(label="Plaka Genişliği (mm)", value=2100)
152
- bicak_payi = gr.Number(label="Bıçak Payı (mm)", value=4)
153
- bant_kenari = gr.Checkbox(label="Tüm Parçalara Kenar Bant Payı Ekle (2mm)")
154
-
155
- gr.Markdown("## 3. Hesapla")
156
- hesapla_btn = gr.Button("Tüm Listeyi Hesapla", variant="primary")
157
- status_text = gr.Textbox(label="Durum", interactive=False, placeholder="Eklenen elemanlar burada görünecek...")
158
-
159
- # --- SAĞ TARAF: ÇIKTILAR ---
160
- with gr.Column(scale=3):
161
- gr.Markdown("## Sonuçlar")
162
- yerlesim_plani = gr.Textbox(label="Yerleşim Planı", lines=15, interactive=False)
163
- parca_listesi = gr.Textbox(label="Parça Listesi", lines=15, interactive=False)
164
-
165
- # --- BUTON AKSİYONLARI ---
166
- add_cabinet_btn.click(
167
- fn=add_item_to_list,
168
- inputs=[item_list_state, gr.State('cabinet'), c_kapak_tipi, c_genislik, c_yukseklik, c_derinlik, c_kapak_tipi],
169
- outputs=[item_list_state, status_text]
 
 
 
 
 
170
  )
171
- add_shelf_btn.click(
172
- fn=add_item_to_list,
173
- inputs=[item_list_state, gr.State('shelf'), s_adet, s_adet, s_uzunluk, s_derinlik],
174
- outputs=[item_list_state, status_text]
 
 
 
 
 
 
175
  )
176
- hesapla_btn.click(
177
- fn=hesapla,
178
- inputs=[item_list_state, plaka_uzunlugu, plaka_genisligi, bicak_payi, bant_kenari],
179
- outputs=[yerlesim_plani, parca_listesi]
 
 
180
  )
181
 
182
- demo.launch()
 
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
+
9
+ def calculate_single_cabinet_parts(dolap_no, h, w, d, kalinlik, raf_sayisi, kapak_var, kapak_sayisi, arkalik_var):
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 (3mm çalışma boşluğu hesaba katılarak)
27
+ if kapak_var and kapak_sayisi > 0:
28
+ calisma_boslugu = 3
29
+ kapak_yukseklik = h - calisma_boslugu
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
+ if kapak_sayisi == 1:
32
+ kapak_genislik = w - calisma_boslugu
33
+ parts.append({'dolap_no': dolap_no, 'parca_adi': 'Kapak', 'adet': 1, 'uzunluk': kapak_yukseklik, 'genislik': kapak_genislik, 'malzeme': 'Sunta'})
34
+ elif kapak_sayisi > 1:
35
+ toplam_kapak_genisligi = w - calisma_boslugu
36
+ ara_bosluk = calisma_boslugu
37
+ tek_kapak_genisligi = (toplam_kapak_genisligi - ((kapak_sayisi - 1) * ara_bosluk)) / kapak_sayisi
38
+ parts.append({'dolap_no': dolap_no, 'parca_adi': 'Kapak', 'adet': kapak_sayisi, 'uzunluk': kapak_yukseklik, 'genislik': round(tek_kapak_genisligi, 1), 'malzeme': 'Sunta'})
39
+
40
+ # 4. Arkalık
41
+ if arkalik_var:
42
+ # Arkalık genellikle dış ölçülerde olur ve kanala girerse biraz daha küçük olabilir.
43
+ # Standart olarak dış ölçü veriyoruz.
44
+ parts.append({'dolap_no': dolap_no, 'parca_adi': 'Arkalık', 'adet': 1, 'uzunluk': h, 'genislik': w, 'malzeme': 'HDF/Duralit'})
 
 
 
 
 
 
 
 
45
 
46
+ return parts
47
+
48
+ def add_cabinet_to_list(
49
+ all_parts_state, cabinet_number_state,
50
+ h, w, d, kalinlik, raf_sayisi, kapak_var, kapak_sayisi, arkalik_var
51
+ ):
52
+ """Hesaplanan dolap parçalarını ana listeye ekler."""
53
+ if not all([h, w, d, kalinlik]):
54
+ raise gr.Error("Lütfen temel dolap ölçülerini ve malzeme kalınlığını girin!")
55
+
56
+ new_parts = calculate_single_cabinet_parts(
57
+ cabinet_number_state, h, w, d, kalinlik, raf_sayisi, kapak_var, kapak_sayisi, arkalik_var
58
+ )
59
+
60
+ updated_parts = all_parts_state + new_parts
61
+
62
+ # DataFrame için veriyi düzleştir
63
+ df_data = []
64
+ for part in updated_parts:
65
+ df_data.append([
66
+ part['dolap_no'], part['parca_adi'], part['adet'],
67
+ part['uzunluk'], part['genislik'], part['malzeme']
68
+ ])
69
+
70
+ df = pd.DataFrame(df_data, columns=["Dolap No", "Parça Adı", "Adet", "Uzunluk (mm)", "Genişlik (mm)", "Malzeme"])
71
+
72
+ return updated_parts, cabinet_number_state + 1, df, f"Başarılı! {cabinet_number_state}. Dolap listeye eklendi."
73
+
74
+ def clear_list():
75
+ """Tüm listeyi temizler."""
76
+ return [], 1, pd.DataFrame(), "Liste temizlendi. Yeni dolap ekleyebilirsiniz."
77
+
78
+ def run_optimization_and_export(all_parts, plaka_uzunluk, plaka_genislik):
79
+ """Parçaları plakalara yerleştirir ve Excel çıktısı oluşturur."""
80
+ if not all_parts:
81
+ raise gr.Error("Liste boş! Lütfen önce dolap ekleyin.")
82
+ if not all([plaka_uzunluk, plaka_genislik]):
83
+ raise gr.Error("Lütfen sunta plakası ölçülerini girin!")
84
+
85
+ # 1. Optimizasyon (Nesting)
86
+ sunta_parcalari = []
87
+ for part in all_parts:
88
+ if part['malzeme'] == 'Sunta':
89
+ for _ in range(part['adet']):
90
+ # Parçaları her iki yönde de dönebilir şekilde ekle
91
+ sunta_parcalari.append((part['uzunluk'], part['genislik']))
92
+
93
+ packer = newPacker(rotation=True)
94
+
95
+ for r in sunta_parcalari:
96
+ packer.add_rect(r[0], r[1])
97
+
98
+ # Plakaları ekle
99
+ packer.add_bin(plaka_uzunluk, plaka_genislik, count=100) # 100 plaka limiti
100
+
101
+ packer.pack()
102
+
103
+ plaka_sayisi = len(packer)
104
+ optimization_result = f"**Optimizasyon Sonucu:**\nToplam **{plaka_sayisi}** adet {plaka_uzunluk}x{plaka_genislik}mm sunta plakasına ihtiyaç var."
105
+
106
+ # 2. Excel Dosyası Oluşturma
107
+ df_data = []
108
+ for part in all_parts:
109
+ df_data.append([
110
+ part['dolap_no'], part['parca_adi'], part['adet'],
111
+ part['uzunluk'], part['genislik'], part['malzeme']
112
+ ])
113
+
114
+ df = pd.DataFrame(df_data, columns=["Dolap No", "Parça Adı", "Adet", "Uzunluk (mm)", "Genişlik (mm)", "Malzeme"])
115
+
116
+ # Geçici bir dosya oluştur
117
+ timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
118
+ filepath = f"kesim_listesi_{timestamp}.xlsx"
119
+ df.to_excel(filepath, index=False, engine='openpyxl')
120
+
121
+ return optimization_result, filepath
122
+
123
+ # --- Gradio Arayüzü ---
124
+
125
+ with gr.Blocks(theme=gr.themes.Soft(), title="Dolap Kesim Hesaplayıcı") as demo:
126
+ # State'ler: tüm parça listesini ve dolap numarasını tutar
127
+ all_parts_state = gr.State([])
128
+ cabinet_number_state = gr.State(1)
129
+
130
+ gr.Markdown("# Akıllı Dolap Kesim Hesaplayıcı")
131
+ gr.Markdown("Bu uygulama, dolap ölçülerinize göre net kesim listesi oluşturur, malzeme optimizasyonu yapar ve Excel çıktısı verir.")
132
 
133
  with gr.Row():
134
+ with gr.Column(scale=1):
135
+ gr.Markdown("### 1. Dolap Bilgilerini Girin")
136
+
137
+ with gr.Accordion(f"Yeni Dolap Ekle (Şu anki Dolap No: 1)", open=True) as accordion:
138
+ with gr.Row():
139
+ h_input = gr.Number(label="Yükseklik (mm)", value=1800)
140
+ w_input = gr.Number(label="Genişlik (mm)", value=800)
141
+ d_input = gr.Number(label="Derinlik (mm)", value=500)
142
+ kalinlik_input = gr.Number(label="Malzeme Kalınlığı (mm)", value=18)
143
+ raf_input = gr.Slider(minimum=0, maximum=10, step=1, label="Raf Sayısı", value=3)
144
+
145
+ with gr.Row():
146
+ kapak_var_input = gr.Checkbox(label="Kapak Olsun mu?", value=True)
147
+ kapak_sayisi_input = gr.Radio([1, 2, 3, 4], label="Kapak Sayısı", value=2, interactive=True)
148
+
149
+ arkalik_var_input = gr.Checkbox(label="Arkalık Olsun mu?", value=True)
150
+
151
+ add_button = gr.Button("Hesapla ve Listeye Ekle", variant="primary")
152
+ clear_button = gr.Button("Tüm Listeyi Temizle", variant="stop")
153
+ status_text = gr.Textbox(label="Durum", interactive=False)
154
+
155
  with gr.Column(scale=2):
156
+ gr.Markdown("### 2. Toplam Parça Kesim Listesi")
157
+ parts_df_output = gr.DataFrame(
158
+ headers=["Dolap No", "Parça Adı", "Adet", "Uzunluk (mm)", "Genişlik (mm)", "Malzeme"],
159
+ datatype=["number", "str", "number", "number", "number", "str"],
160
+ interactive=False
161
+ )
162
 
163
+ gr.Markdown("### 3. Optimizasyon ve Çıktı")
164
+ with gr.Row():
165
+ plaka_uzunluk_input = gr.Number(label="Plaka Uzunluğu (mm)", value=2800)
166
+ plaka_genislik_input = gr.Number(label="Plaka Genişliği (mm)", value=2100)
 
 
 
 
 
 
 
 
 
 
 
167
 
168
+ optimize_button = gr.Button("Optimizasyonu Çalıştır ve Excel Oluştur", variant="primary")
169
+
170
+ optimization_output = gr.Markdown()
171
+ excel_output = gr.File(label="Kesim Listesini İndir")
172
+
173
+ # --- Buton ve Fonksiyon Bağlantıları ---
174
+
175
+ # Kapak sayısı seçeneğini, kapak var checkbox'ına bağla
176
+ def toggle_kapak_sayisi(kapak_var):
177
+ return gr.update(interactive=kapak_var)
178
+
179
+ kapak_var_input.change(fn=toggle_kapak_sayisi, inputs=kapak_var_input, outputs=kapak_sayisi_input)
180
+
181
+ # Dolap ekleme butonu
182
+ add_button.click(
183
+ fn=add_cabinet_to_list,
184
+ inputs=[
185
+ all_parts_state, cabinet_number_state,
186
+ h_input, w_input, d_input, kalinlik_input, raf_input,
187
+ kapak_var_input, kapak_sayisi_input, arkalik_var_input
188
+ ],
189
+ outputs=[all_parts_state, cabinet_number_state, parts_df_output, status_text]
190
+ ).then(
191
+ # Dolap numarası eklendikten sonra Accordion başlığını güncelle
192
+ lambda cabinet_no: gr.update(label=f"Yeni Dolap Ekle (Şu anki Dolap No: {cabinet_no})"),
193
+ inputs=cabinet_number_state,
194
+ outputs=accordion
195
  )
196
+
197
+ # Listeyi temizleme butonu
198
+ clear_button.click(
199
+ fn=clear_list,
200
+ inputs=[],
201
+ outputs=[all_parts_state, cabinet_number_state, parts_df_output, status_text]
202
+ ).then(
203
+ lambda cabinet_no: gr.update(label=f"Yeni Dolap Ekle (Şu anki Dolap No: {cabinet_no})"),
204
+ inputs=cabinet_number_state,
205
+ outputs=accordion
206
  )
207
+
208
+ # Optimizasyon ve Excel butonu
209
+ optimize_button.click(
210
+ fn=run_optimization_and_export,
211
+ inputs=[all_parts_state, plaka_uzunluk_input, plaka_genislik_input],
212
+ outputs=[optimization_output, excel_output]
213
  )
214
 
215
+ demo.launch()