591Analyzer / utils.py
54justin's picture
Upload 7 files
f205f47 verified
# �� Copilot �ͦ�
import time
import json
from datetime import datetime
def log_message(message: str, level: str = "INFO"):
"""�O����x�T��"""
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"[{timestamp}] {level}: {message}")
def save_json(data, filename: str, output_dir: str = "output"):
"""�x�sJSON�榡���"""
try:
filepath = f"{output_dir}/{filename}"
with open(filepath, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
log_message(f"��Ƥw�x�s�� {filepath}")
return True
except Exception as e:
log_message(f"�x�s��Ʈɵo�Ϳ��~: {e}", "ERROR")
return False
def load_json(filename: str, output_dir: str = "output"):
"""���JJSON�榡���"""
try:
filepath = f"{output_dir}/{filename}"
with open(filepath, 'r', encoding='utf-8') as f:
data = json.load(f)
log_message(f"���\���J {filepath}")
return data
except Exception as e:
log_message(f"���J��Ʈɵo�Ϳ��~: {e}", "ERROR")
return None
def format_currency(amount: float) -> str:
"""�榡�ƪ��B���"""
if amount >= 10000:
return f"{amount:,.0f}"
else:
return f"{amount:.0f}"
def safe_divide(numerator: float, denominator: float, default: float = 0.0) -> float:
"""�w�����k�A�קK���s���~"""
try:
if denominator == 0:
return default
return numerator / denominator
except:
return default
def clean_text(text: str) -> str:
"""�M�z��r���e"""
if not text:
return ""
# �����h�l�ť�
text = " ".join(text.split())
# �����S���r�š]�O�d����B�^��B�Ʀr�M�`�μ��I�^
import re
text = re.sub(r'[^\u4e00-\u9fff\w\s.,!?;:()�]�^�i�j�u�v\-]', '', text)
return text.strip()
def retry_request(func, max_retries: int = 3, delay: float = 1.0):
"""���վ���"""
for attempt in range(max_retries):
try:
return func()
except Exception as e:
if attempt == max_retries - 1:
raise e
log_message(f"�ШD���ѡA{delay}���᭫��... (���� {attempt + 1}/{max_retries})", "WARNING")
time.sleep(delay)
delay *= 2 # ���ưh��
def validate_price(price_str: str) -> bool:
"""���һ���榡�O�_�X�z"""
try:
import re
# �����Ʀr
price_match = re.search(r'[\d,]+', price_str.replace(',', ''))
if price_match:
price = int(price_match.group().replace(',', ''))
# �X�z�������d��G5000 - 100000
return 5000 <= price <= 100000
except:
pass
return False
def validate_area(area_str: str) -> bool:
"""���ҩW�Ʈ榡�O�_�X�z"""
try:
import re
area_match = re.search(r'(\d+(?:\.\d+)?)', area_str)
if area_match:
area = float(area_match.group(1))
# �X�z���W�ƽd��G10 - 100�W
return 10 <= area <= 100
except:
pass
return False
def create_output_directories():
"""�Ыؿ�X�ؿ�"""
import os
directories = ['output', 'output/images', 'output/data', 'output/reports']
for directory in directories:
if not os.path.exists(directory):
os.makedirs(directory)
log_message(f"�Ыإؿ�: {directory}")
def get_current_timestamp() -> str:
"""������e�ɶ��W"""
return datetime.now().strftime("%Y%m%d_%H%M%S")
def calculate_statistics(data_list):
"""�p��έp�ƾ�"""
if not data_list:
return {}
import numpy as np
data_array = np.array(data_list)
return {
'count': len(data_array),
'mean': float(np.mean(data_array)),
'median': float(np.median(data_array)),
'std': float(np.std(data_array)),
'min': float(np.min(data_array)),
'max': float(np.max(data_array)),
'q25': float(np.percentile(data_array, 25)),
'q75': float(np.percentile(data_array, 75))
}
def progress_bar(current: int, total: int, length: int = 50):
"""��ܶi�ױ�"""
if total == 0:
return
percent = (current / total) * 100
filled = int(length * current // total)
bar = '�i' * filled + '-' * (length - filled)
print(f'\r�i��: |{bar}| {percent:.1f}% ({current}/{total})', end='', flush=True)
if current >= total:
print() # �����ᴫ��