<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">import tkinter as tk
from tkinter import ttk
import pandas as pd
import os
import re
from datetime import datetime

# CSV �뚯씪 遺덈윭�ㅻ뒗 �⑥닔 (�ъ슜�� 寃쎈줈�� 留욊쾶 �섏젙)
def load_csv(filename):
    return pd.read_csv(f'C:/Users/user/projects/st/sorted_parts/{filename}.csv')

# 媛� 遺��� CSV 遺덈윭�ㅺ린
cpu_data = load_csv('sorted_cpu')
gpu_data = load_csv('sorted_gpu')
mainboard_data = load_csv('sorted_mainboard')
memory_data = load_csv('sorted_memory')
ssd_data = load_csv('sorted_ssd')
hdd_data = load_csv('sorted_hdd')
psu_data = load_csv('sorted_psu')
case_data = load_csv('sorted_case')
cooler_data = load_csv('sorted_cooler')
software_data = load_csv('sorted_software')

# CPU 釉뚮옖�쒕� �뺤씤�섎뒗 �⑥닔 (�쒓�怨� �곸뼱 紐⑤몢 �몄떇)
def get_cpu_brand(cpu_name):
    if "intel" in cpu_name.lower() or "�명뀛" in cpu_name:
        return "Intel"
    elif "amd" in cpu_name.lower() or "�먯씠�좊뵒" in cpu_name or "AMD" in cpu_name:
        return "AMD"
    else:
        return "Unknown"

# 媛�寃⑹쓣 媛��몄삤�� �⑥닔 (NaN 媛믪쓣 0�쇰줈 泥섎━)
def get_price(component_name, data):
    if component_name:
        try:
            price = data[data['name'] == component_name]['price'].values[0]
            return 0 if pd.isna(price) else price  # NaN 媛믪� 0�쇰줈 泥섎━
        except IndexError:
            print(f"{component_name}�� 媛�寃⑹쓣 李얠쓣 �� �놁뒿�덈떎.")
            return 0
    return 0

# �レ옄留� 異붿텧�섎뒗 �⑥닔 (諛붿씠�� 媛앹껜 泥섎━ 諛� 臾몄옄�� 蹂���)
def extract_numbers(name):
    if isinstance(name, bytes):
        name = name.decode('utf-8')  # 諛붿씠�� 媛앹껜瑜� 臾몄옄�대줈 蹂���
    return ''.join(re.findall(r'\d+', str(name)))  # �뺢퇋�앹쓣 �ъ슜�섏뿬 �レ옄留� 異붿텧

# 媛�寃⑹쓣 �ㅼ떆媛꾩쑝濡� 怨꾩궛�섏뿬 �쒖떆�섎뒗 �⑥닔
def update_total_price():
    try:
        total_price = 0  # 珥� 媛�寃� 珥덇린��

        # �좏깮�� 遺��덈뱾�� 媛�寃⑹쓣 媛��몄샂
        total_price += get_price(drop_downs['CPU'].get(), cpu_data)
        total_price += get_price(drop_downs['荑⑤윭/�쒕떇'].get(), cooler_data)
        total_price += get_price(drop_downs['硫붿씤蹂대뱶'].get(), mainboard_data)
        total_price += get_price(drop_downs['硫붾え由�'].get(), memory_data)
        total_price += get_price(drop_downs['洹몃옒�쎌뭅��'].get(), gpu_data)
        total_price += get_price(drop_downs['SSD'].get(), ssd_data)
        total_price += get_price(drop_downs['HDD'].get(), hdd_data)
        total_price += get_price(drop_downs['耳��댁뒪'].get(), case_data)
        total_price += get_price(drop_downs['�뚯썙'].get(), psu_data)
        total_price += get_price(drop_downs['�뚰봽�몄썾��'].get(), software_data)

        # 怨듭엫鍮꾨� �뷀븿
        labor_cost = int(drop_downs['怨듭엫'].get())
        total_price += labor_cost

        # 珥앺빀 媛�寃⑹쓣 �붾㈃�� �쒖떆
        total_label.config(text=f"珥앺빀 媛�寃�: {total_price:,}��")
    
    except Exception as e:
        print(f"媛�寃� 怨꾩궛 以� �ㅻ쪟 諛쒖깮: {e}")

import os
import pandas as pd

# 寃ъ쟻 �뚯씪 ���� �⑥닔
def save_estimate(selected_components):
    try:
        total_price = 0  # 珥앺빀 媛�寃�

        # �좏깮�� 遺��덈뱾�� 媛��몄삤湲�
        cpu_name = selected_components['CPU'].get()
        gpu_name = selected_components['洹몃옒�쎌뭅��'].get() if selected_components['洹몃옒�쎌뭅��'].get() else None

        # 遺��덈퀎 媛�寃� �⑹궛
        total_price += get_price(cpu_name, cpu_data)
        total_price += get_price(gpu_name, gpu_data) if gpu_name else 0
        total_price += get_price(selected_components['硫붿씤蹂대뱶'].get(), mainboard_data)
        total_price += get_price(selected_components['硫붾え由�'].get(), memory_data)
        total_price += get_price(selected_components['SSD'].get(), ssd_data)
        total_price += get_price(selected_components['HDD'].get(), hdd_data)
        total_price += get_price(selected_components['�뚯썙'].get(), psu_data)
        total_price += get_price(selected_components['耳��댁뒪'].get(), case_data)
        total_price += get_price(selected_components['荑⑤윭/�쒕떇'].get(), cooler_data)
        total_price += get_price(selected_components['�뚰봽�몄썾��'].get(), software_data)

        # 怨듭엫鍮� 異붽�
        labor_cost = int(selected_components['怨듭엫'].get())
        total_price += labor_cost

        # CPU�� GPU �대쫫�먯꽌 �レ옄留� 異붿텧
        cpu_numbers = extract_numbers(cpu_name)
        gpu_numbers = extract_numbers(gpu_name) if gpu_name else None

        # CPU 釉뚮옖�� �뺤씤
        cpu_brand = get_cpu_brand(cpu_name)

        # �뚯씪紐� �ㅼ젙 (GPU �좏깮 �щ��� �곕씪 �뚯씪紐� �ㅻⅤ寃� 泥섎━)
        timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
        if gpu_numbers:
            new_filename = f"{cpu_brand}_{cpu_numbers}_{gpu_numbers}_{str(total_price)}_{timestamp}.csv"
        else:
            new_filename = f"{cpu_brand}_{cpu_numbers}_{str(total_price)}_{timestamp}.csv"
        
        save_path = f"C:/Users/user/projects/st/data/naver_good/{new_filename}"

        # �좏깮�� 遺��덇낵 珥앺빀 媛�寃⑹쓣 ����
        estimate_data = {
            'CPU': cpu_name,
            '洹몃옒�쎌뭅��': gpu_name if gpu_name else "None",
            '硫붿씤蹂대뱶': selected_components['硫붿씤蹂대뱶'].get(),
            '硫붾え由�': selected_components['硫붾え由�'].get(),
            'SSD': selected_components['SSD'].get(),
            'HDD': selected_components['HDD'].get(),
            '�뚯썙': selected_components['�뚯썙'].get(),
            '耳��댁뒪': selected_components['耳��댁뒪'].get(),
            '荑⑤윭/�쒕떇': selected_components['荑⑤윭/�쒕떇'].get(),
            '�뚰봽�몄썾��': selected_components['�뚰봽�몄썾��'].get(),
            '怨듭엫': labor_cost,
            'Total Price': total_price
        }

        # �곗씠�고봽�덉엫�쇰줈 蹂��� �� CSV ����
        estimate_df = pd.DataFrame([estimate_data])
        estimate_df.to_csv(save_path, index=False)
        
        print(f"寃ъ쟻 ���� �꾨즺: {save_path}")
        
        # ���λ맂 �뚯씪�� 遺덈윭�ㅺ린
        loaded_df = pd.read_csv(save_path)

        # �대뜑 �앹꽦 (new_estimates �대뜑媛� �놁쑝硫� �앹꽦)
        new_folder = f"C:/Users/user/projects/st/data/naver_good/new_estimates/"
        os.makedirs(new_folder, exist_ok=True)

        # �몃줈濡� �뺣젹�섏뿬 ���ν븷 �뚯씪紐� �ㅼ젙 (�먮옒 �뚯씪紐� �좎�)
        new_save_path = os.path.join(new_folder, new_filename)

        # �뚯씪�� �몃줈濡� 蹂��섑븯�� ����
        transposed_df = loaded_df.T
        transposed_df.to_csv(new_save_path, header=False)  # �몃줈濡� 蹂���, header �쒓굅

        print(f"�덈줈�� �대뜑�� �몃줈濡� �뺣젹�� 寃ъ쟻 ���� �꾨즺: {new_save_path}")
    
    except Exception as e:
        print(f"寃ъ쟻 ���� 以� �ㅻ쪟 諛쒖깮: {e}")

import os
import pandas as pd
import re

# CPU �대쫫�� �뚯떛�섏뿬 遺덊븘�뷀븳 遺�遺� �쒓굅�섍퀬, �쎄린 �ъ슫 �뺤떇�쇰줈 蹂���
def get_cpu_info(cpu_name):
    # 愿꾪샇 �덉쓽 �댁슜 �쒓굅, "�명뀛 肄붿뼱" �쒓굅
    cpu_name = re.sub(r'\([^)]*\)', '', cpu_name).strip()  # 愿꾪샇 �덉쓽 �댁슜 �쒓굅
    cpu_name = cpu_name.replace('�명뀛 肄붿뼱', '').strip()  # '�명뀛 肄붿뼱' �쒓굅
    # ��: 'i5-12400F' -&gt; 'i5-12�몃� 12400F'
    cpu_pattern = re.compile(r'(i[3579]|Ryzen [3579])[- ]?(\d{2})(\d{3,4})([A-Za-z]*)')
    match = cpu_pattern.search(cpu_name)
    
    if match:
        series = match.group(1)  # i5, i7, Ryzen 5 ��
        generation = match.group(2)  # �몃� �뺣낫 異붿텧 (��: 12�몃�)
        model = match.group(3) + match.group(4)  # 紐⑤뜽紐� (��: 12400F)
        return f'{series}-{generation}�몃�_{model}'
    return re.sub(r'\s+', '_', cpu_name).strip('_')  # 怨듬갚�� _濡� 蹂��섑븯怨� �묐걹�� _ �쒓굅

# GPU �대쫫�� �뚯떛�섏뿬 紐⑤뜽紐낃낵 硫붾え由� �⑸웾留� 異붿텧�섍퀬 遺덊븘�뷀븳 怨듬갚 �쒓굅
def get_gpu_info(gpu_name):
    # 愿꾪샇 �덉쓽 �댁슜 諛� 遺덊븘�뷀븳 �ㅻ챸 �쒓굅
    gpu_name = re.sub(r'\([^)]*\)', '', gpu_name).strip()  # 愿꾪샇 �덉쓽 �댁슜 �쒓굅
    # 釉뚮옖�쒕굹 異붽� �ㅻ챸 �쒓굅 (��: 'MSI 吏��ъ뒪 RTX 4060 踰ㅽ닾�� 2X 釉붾옓 OC D6 8GB' -&gt; 'RTX 4060 8GB')
    gpu_name = re.sub(r'(吏��ъ뒪|GeForce|MSI|踰ㅽ닾��|OC|釉붾옓|D6|2X|X)', '', gpu_name).strip()  # 遺덊븘�뷀븳 �⑥뼱 �쒓굅
    # ��: 'RTX 4060 8GB' 異붿텧
    gpu_pattern = re.compile(r'(RTX \d{3,4}) ?(\d{1,2}G?B)')
    match = gpu_pattern.search(gpu_name)
    
    if match:
        model = match.group(1).replace(' ', '_')  # GPU 紐⑤뜽紐� (��: 4060), 怨듬갚�� _濡� 蹂���
        memory = match.group(2).replace(' ', '_')  # 硫붾え由� �ш린 (��: 8GB), 怨듬갚�� _濡� 蹂���
        return f'{model}_{memory}'  # 紐⑤뜽紐낃낵 硫붾え由� �⑸웾�� _濡� 寃고빀
    return re.sub(r'\s+', '_', gpu_name).strip('_')  # 怨듬갚�� _濡� 蹂��섑븯怨� �묐걹�� _ �쒓굅

# 硫붾え由� �대쫫�� �뚯떛�섏뿬 �⑸웾 �뺣낫留� 異붿텧
def get_memory_info(memory_name):
    # 愿꾪샇 �덉쓽 �댁슜�먯꽌 �⑸웾 �뺣낫留� 異붿텧
    memory_pattern = re.compile(r'\((\d{1,2}GB)\)')  # 愿꾪샇 �덉뿉 �덈뒗 �⑸웾 �뺣낫留� 異붿텧
    match = memory_pattern.search(memory_name)
    
    if match:
        memory_size = match.group(1).replace('GB', 'G')  # 硫붾え由� �ш린 (16GB -&gt; 16G)
        return f'DDR4_{memory_size}'  # �띾룄 �쒓굅�섍퀬 �⑸웾留� �쒖떆
    return re.sub(r'\s+', '_', memory_name).strip('_')  # 怨듬갚�� _濡� 蹂��섑븯怨� �묐걹�� _ �쒓굅

# 媛�寃� 媛깆떊 �⑥닔
def update_price(estimate_filename):
    try:
        # 湲곗〈 寃ъ쟻 �뚯씪 �쎄린
        estimate_path = f'C:/Users/user/projects/st/data/naver_good/{estimate_filename}'
        estimate = pd.read_csv(estimate_path)

        # �좏깮�� 遺��덈챸�� 媛��몄� 媛�寃⑹쓣 理쒖떊�쇰줈 媛깆떊
        cpu_name = estimate['CPU'].values[0]
        gpu_name = estimate['洹몃옒�쎌뭅��'].values[0] if '洹몃옒�쎌뭅��' in estimate.columns else None
        memory_name = estimate['硫붾え由�'].values[0]
        mainboard_name = estimate['硫붿씤蹂대뱶'].values[0]
        ssd_name = estimate['SSD'].values[0]
        hdd_name = estimate['HDD'].values[0]
        psu_name = estimate['�뚯썙'].values[0]
        case_name = estimate['耳��댁뒪'].values[0]
        cooler_name = estimate['荑⑤윭/�쒕떇'].values[0]
        software_name = estimate['�뚰봽�몄썾��'].values[0]
        labor_cost = estimate['怨듭엫'].values[0]

        # 理쒖떊 媛�寃⑹쓣 怨꾩궛
        total_price = 0
        total_price += get_price(cpu_name, cpu_data)
        total_price += get_price(gpu_name, gpu_data) if gpu_name else 0
        total_price += get_price(mainboard_name, mainboard_data)
        total_price += get_price(memory_name, memory_data)
        total_price += get_price(ssd_name, ssd_data)
        total_price += get_price(hdd_name, hdd_data)
        total_price += get_price(psu_name, psu_data)
        total_price += get_price(case_name, case_data)
        total_price += get_price(cooler_name, cooler_data)
        total_price += get_price(software_name, software_data)
        total_price += labor_cost

        # 珥앺빀 媛�寃� 媛깆떊
        estimate['Total Price'] = total_price

        # CPU, GPU, 硫붾え由� �뺣낫瑜� �뚯떛�섏뿬 �쎄린 醫뗭� �뺤떇�쇰줈 蹂�寃�
        cpu_info = get_cpu_info(cpu_name)
        gpu_info = get_gpu_info(gpu_name) if gpu_name else 'None'
        memory_info = get_memory_info(memory_name)

        # �덈줈�� �뚯씪紐� �앹꽦 (�덉떆: i5-12�몃�_12400F_RTX_4060_8GB_DDR4_16G_1079000)
        new_filename = f"{cpu_info}_{gpu_info}_{memory_info}_{total_price}.csv"

        # 湲곗〈 �뚯씪紐낆쓣 �덈줈�� �뚯씪紐낆쑝濡� 蹂�寃쏀븯湲� �꾩뿉, 湲곗〈 �뚯씪 ��젣
        new_save_path = f'C:/Users/user/projects/st/data/naver_good/{new_filename}'
        if estimate_path != new_save_path and os.path.exists(estimate_path):
            os.remove(estimate_path)  # 湲곗〈 �뚯씪 ��젣
            print(f"湲곗〈 �뚯씪 ��젣: {estimate_path}")

        # �덈줈�� �뚯씪濡� ����
        estimate.to_csv(new_save_path, index=False)  # �섏젙�� �뚯씪紐낆쑝濡� ����
        print(f"寃ъ쟻 �뚯씪 媛깆떊 �꾨즺: {new_save_path}")

        # �몃줈濡� �뺣젹�� �곗씠�곕룄 媛깆떊�섏뿬 ��뼱�곌린 (new_estimates �대뜑)
        new_folder = f"C:/Users/user/projects/st/data/naver_good/new_estimates/"
        os.makedirs(new_folder, exist_ok=True)

        new_vertical_save_path = os.path.join(new_folder, new_filename)
        estimate_transposed = estimate.T

        # 湲곗〈 �몃줈 �뚯씪�� 議댁옱�섎㈃ ��젣
        old_vertical_path = os.path.join(new_folder, estimate_filename)
        if old_vertical_path != new_vertical_save_path and os.path.exists(old_vertical_path):
            os.remove(old_vertical_path)  # 湲곗〈 �몃줈 �뚯씪 ��젣
            print(f"湲곗〈 �몃줈 �뚯씪 ��젣: {old_vertical_path}")

        # �몃줈 �뚯씪 ����
        estimate_transposed.to_csv(new_vertical_save_path, header=False)
        print(f"�몃줈濡� �뺣젹�� �뚯씪 媛깆떊 �꾨즺: {new_vertical_save_path}")

    except Exception as e:
        print(f"媛깆떊 以� �ㅻ쪟 諛쒖깮: {e}")


# 寃ъ쟻 �뚯씪 �좏깮 諛� 媛깆떊 �ㅽ뻾
def refresh_all_estimates():
    estimate_files = [f for f in os.listdir('C:/Users/user/projects/st/data/naver_good') if f.endswith('.csv')]  # 寃ъ쟻 �뚯씪�� 李얠쓬
    for estimate_file in estimate_files:
        update_price(estimate_file)

# �쒕∼�ㅼ슫 寃��� �꾪꽣留�
def filter_combobox(event, data, dropdown):
    value = event.widget.get()
    if value == '':
        dropdown['values'] = list(data['name'])  # �꾪꽣瑜� �댁젣�섍퀬 �꾩껜 由ъ뒪�몃� �ㅼ떆 �ㅼ젙
    else:
        filtered_values = [item for item in list(data['name']) if value.lower() in item.lower()]
        dropdown['values'] = filtered_values  # �꾪꽣留곷맂 由ъ뒪�몃줈 �ㅼ젙

    # �뷀꽣 �ㅻ� �뚮��� �� �쒕∼�ㅼ슫 �먮룞�쇰줈 �대━湲�
    if event.keysym == "Return":
        dropdown.event_generate("&lt;Down&gt;")  # �쒕∼�ㅼ슫�� �댁뼱二쇰뒗 紐낅졊

# �쒕∼�ㅼ슫 硫붾돱 �앹꽦 �⑥닔
def create_dropdown(category, data):
    label = tk.Label(root, text=category)
    label.pack(padx=10, pady=5)  # 媛꾧꺽 議곗젙
    
    if category == '怨듭엫':
        # 怨듭엫 �쒕∼�ㅼ슫�� 80,000�� �먮뒗 120,000�� �좏깮 媛���
        drop_down = ttk.Combobox(root, values=[80000, 120000], width=40)
        drop_down.set(80000)  # 湲곕낯媛� �ㅼ젙
    else:
        # 遺��� �쒕∼�ㅼ슫 �앹꽦, �� 議곗젙
        drop_down = ttk.Combobox(root, values=list(data['name']), width=50)
    
    drop_down.pack(padx=10, pady=5)  # 媛꾧꺽 異붽�
    drop_downs[category] = drop_down

    # �쒕∼�ㅼ슫 �꾪꽣留� �대깽�� 諛붿씤��
    drop_down.bind("&lt;KeyRelease&gt;", lambda event: filter_combobox(event, data, drop_down))

    # �쒕∼�ㅼ슫 蹂�寃� �� 媛�寃� �낅뜲�댄듃
    drop_down.bind("&lt;&lt;ComboboxSelected&gt;&gt;", lambda event: update_total_price())

# Tkinter GUI 援ъ꽦
root = tk.Tk()
root.title("議곕┰ 而댄벂�� 寃ъ쟻 媛깆떊")

# �쒕∼�ㅼ슫 硫붾돱 �꾨젅��
categories = ['CPU', '荑⑤윭/�쒕떇', '硫붿씤蹂대뱶', '硫붾え由�', '洹몃옒�쎌뭅��', 'SSD', 'HDD', '耳��댁뒪', '�뚯썙', '�뚰봽�몄썾��', '怨듭엫']
drop_downs = {}

# 媛� 移댄뀒怨좊━蹂� �쒕∼�ㅼ슫 �앹꽦
create_dropdown('CPU', cpu_data)
create_dropdown('荑⑤윭/�쒕떇', cooler_data)
create_dropdown('硫붿씤蹂대뱶', mainboard_data)
create_dropdown('硫붾え由�', memory_data)
create_dropdown('洹몃옒�쎌뭅��', gpu_data)
create_dropdown('SSD', ssd_data)
create_dropdown('HDD', hdd_data)
create_dropdown('耳��댁뒪', case_data)
create_dropdown('�뚯썙', psu_data)
create_dropdown('�뚰봽�몄썾��', software_data)
create_dropdown('怨듭엫', None)  # 怨듭엫 �쒕∼�ㅼ슫 �앹꽦

# 珥앺빀 媛�寃� �쒖떆
total_label = tk.Label(root, text="珥앺빀 媛�寃�: 0��", width=40)
total_label.pack(pady=10)

# ���� 踰꾪듉
save_button = tk.Button(root, text="寃ъ쟻 ����", command=lambda: save_estimate(drop_downs))
save_button.pack(pady=10)

# 媛깆떊 踰꾪듉
refresh_button = tk.Button(root, text="紐⑤뱺 寃ъ쟻 媛깆떊", command=refresh_all_estimates)
refresh_button.pack(pady=10)

root.mainloop()
</pre></body></html>