ff14_tw_market / src /utils.py
Daniel246's picture
新增雇員名稱篩選功能至市場資訊顯示,並更新相關處理函數以支援此功能
a38bf22
"""工具函數."""
from datetime import datetime
import pandas as pd
from .config import WORLDS
def format_price(price: int) -> str:
"""格式化價格顯示.
Args:
price: 價格數值
Returns:
格式化後的價格字串
"""
if price >= 1_000_000:
return f"{price / 1_000_000:.2f}M"
if price >= 1_000:
return f"{price / 1_000:.1f}K"
return str(price)
def format_timestamp(timestamp: int) -> str:
"""格式化時間戳.
Args:
timestamp: Unix 時間戳(秒或毫秒)
Returns:
格式化後的時間字串
"""
if not timestamp:
return "N/A"
# 如果 timestamp 超過合理範圍,可能是毫秒,需要轉換為秒
if timestamp > 9999999999:
timestamp = timestamp // 1000
dt = datetime.fromtimestamp(timestamp)
return dt.strftime("%Y-%m-%d %H:%M")
def format_relative_time(timestamp: int) -> str:
"""格式化相對時間.
Args:
timestamp: Unix 時間戳(秒或毫秒)
Returns:
相對時間字串(如「3 小時前」)
"""
if not timestamp:
return "N/A"
# 如果 timestamp 超過合理範圍,可能是毫秒,需要轉換為秒
if timestamp > 9999999999:
timestamp = timestamp // 1000
now = datetime.now()
dt = datetime.fromtimestamp(timestamp)
diff = now - dt
if diff.days > 0:
return f"{diff.days} 天前"
if diff.seconds >= 3600:
return f"{diff.seconds // 3600} 小時前"
if diff.seconds >= 60:
return f"{diff.seconds // 60} 分鐘前"
return "剛剛"
def process_listings(
listings: list,
quality: str = "all",
default_world: str = None,
retainer_filter: str = None,
) -> pd.DataFrame:
"""處理上架列表.
Args:
listings: 上架資料列表
quality: 品質篩選("all", "nq", "hq")
default_world: 預設伺服器名稱(當 API 未返回 worldID 時使用)
retainer_filter: 雇員名稱篩選(部分匹配,不區分大小寫)
Returns:
處理後的 DataFrame
"""
if not listings:
return pd.DataFrame()
data = []
for listing in listings:
if quality == "hq" and not listing.get("hq"):
continue
if quality == "nq" and listing.get("hq"):
continue
retainer_name = listing.get("retainerName", "")
# 雇員名稱篩選(部分匹配,不區分大小寫)
if retainer_filter:
if retainer_filter.lower() not in retainer_name.lower():
continue
# 優先使用 worldName,其次使用 worldID 對應,最後使用預設值
world_name = listing.get("worldName")
if not world_name:
world_id = listing.get("worldID")
if world_id:
world_name = WORLDS.get(world_id, str(world_id))
else:
world_name = default_world or "-"
data.append({
"品質": "HQ" if listing.get("hq") else "NQ",
"單價": listing.get("pricePerUnit", 0),
"數量": listing.get("quantity", 0),
"總價": listing.get("total", 0),
"雇員": retainer_name,
"伺服器": world_name,
"更新時間": format_relative_time(listing.get("lastReviewTime", 0)),
})
return pd.DataFrame(data)
def process_history(
entries: list,
quality: str = "all",
default_world: str = None,
) -> pd.DataFrame:
"""處理交易歷史.
Args:
entries: 交易記錄列表
quality: 品質篩選("all", "nq", "hq")
default_world: 預設伺服器名稱(當 API 未返回 worldID 時使用)
Returns:
處理後的 DataFrame
"""
if not entries:
return pd.DataFrame()
data = []
for entry in entries:
if quality == "hq" and not entry.get("hq"):
continue
if quality == "nq" and entry.get("hq"):
continue
# 優先使用 worldName,其次使用 worldID 對應,最後使用預設值
world_name = entry.get("worldName")
if not world_name:
world_id = entry.get("worldID")
if world_id:
world_name = WORLDS.get(world_id, str(world_id))
else:
world_name = default_world or "-"
data.append({
"品質": "HQ" if entry.get("hq") else "NQ",
"單價": entry.get("pricePerUnit", 0),
"數量": entry.get("quantity", 0),
"總價": entry.get("total", 0),
"買家": entry.get("buyerName", ""),
"伺服器": world_name,
"成交時間": format_timestamp(entry.get("timestamp", 0)),
})
return pd.DataFrame(data)