DawnC commited on
Commit
7c51341
·
1 Parent(s): 5d0a07e

Upload 2 files

Browse files
Files changed (2) hide show
  1. history_manager.py +92 -0
  2. search_history.py +158 -0
history_manager.py ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from datetime import datetime
3
+ import json
4
+ import os
5
+ import pytz
6
+ import traceback
7
+
8
+ class UserHistoryManager:
9
+ def __init__(self):
10
+ """初始化歷史紀錄管理器"""
11
+ self.history_file = "user_history.json"
12
+ print(f"Initializing UserHistoryManager with file: {os.path.abspath(self.history_file)}")
13
+ self._init_file()
14
+
15
+ def _init_file(self):
16
+ """初始化JSON檔案"""
17
+ try:
18
+ if not os.path.exists(self.history_file):
19
+ print(f"Creating new history file: {self.history_file}")
20
+ with open(self.history_file, 'w', encoding='utf-8') as f:
21
+ json.dump([], f)
22
+ else:
23
+ print(f"History file exists: {self.history_file}")
24
+ # 驗證檔案內容
25
+ with open(self.history_file, 'r', encoding='utf-8') as f:
26
+ data = json.load(f)
27
+ print(f"Current history entries: {len(data)}")
28
+ except Exception as e:
29
+ print(f"Error in _init_file: {str(e)}")
30
+ print(traceback.format_exc())
31
+
32
+
33
+ def save_history(self, user_preferences: dict, results: list) -> bool:
34
+ """儲存搜尋歷史,使用台北時間"""
35
+ try:
36
+ print("\nSaving history:")
37
+ print("Results to save:", results)
38
+
39
+ # 使用 pytz 創建台北時區
40
+ taipei_tz = pytz.timezone('Asia/Taipei')
41
+ # 獲取當前時間並轉換為台北時間
42
+ taipei_time = datetime.now(taipei_tz)
43
+
44
+ history_entry = {
45
+ "timestamp": taipei_time.strftime("%Y-%m-%d %H:%M:%S"),
46
+ "preferences": user_preferences,
47
+ "results": results
48
+ }
49
+
50
+ with open(self.history_file, 'r', encoding='utf-8') as f:
51
+ history = json.load(f)
52
+
53
+ # 添加新紀錄
54
+ history.append(history_entry)
55
+
56
+ # 限制保存最近的20筆記錄
57
+ if len(history) > 20:
58
+ history = history[-20:]
59
+
60
+ with open(self.history_file, 'w', encoding='utf-8') as f:
61
+ json.dump(history, f, ensure_ascii=False, indent=2)
62
+
63
+ return True
64
+ except Exception as e:
65
+ print(f"Error saving history: {str(e)}")
66
+ return False
67
+
68
+ def get_history(self) -> list:
69
+ """獲取搜尋歷史"""
70
+ try:
71
+ print("Attempting to read history") # Debug
72
+ with open(self.history_file, 'r', encoding='utf-8') as f:
73
+ data = json.load(f)
74
+ print(f"Read {len(data)} history entries") # Debug
75
+ return data if isinstance(data, list) else []
76
+ except Exception as e:
77
+ print(f"Error reading history: {str(e)}")
78
+ print(traceback.format_exc())
79
+ return []
80
+
81
+ def clear_all_history(self) -> bool:
82
+ """清除所有歷史紀錄"""
83
+ try:
84
+ print("Attempting to clear all history") # Debug
85
+ with open(self.history_file, 'w', encoding='utf-8') as f:
86
+ json.dump([], f)
87
+ print("History cleared successfully") # Debug
88
+ return True
89
+ except Exception as e:
90
+ print(f"Error clearing history: {str(e)}")
91
+ print(traceback.format_exc())
92
+ return False
search_history.py ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import traceback
3
+ from typing import Optional, Dict, List
4
+ from history_manager import UserHistoryManager
5
+
6
+ class SearchHistoryComponent:
7
+ def __init__(self):
8
+ """初始化搜索歷史組件"""
9
+ self.history_manager = UserHistoryManager()
10
+
11
+ def format_history_html(self, history_data: Optional[List[Dict]] = None) -> str:
12
+ """將歷史記錄格式化為HTML"""
13
+ try:
14
+ if history_data is None:
15
+ history_data = self.history_manager.get_history()
16
+
17
+ if not history_data:
18
+ return """
19
+ <div style='text-align: center; padding: 20px; color: #666;'>
20
+ No search history yet. Try making some breed recommendations!
21
+ </div>
22
+ """
23
+
24
+ html = "<div class='history-container'>"
25
+
26
+ for entry in reversed(history_data):
27
+ timestamp = entry.get('timestamp', 'Unknown time')
28
+ prefs = entry.get('preferences', {})
29
+ results = entry.get('results', [])
30
+
31
+ html += f"""
32
+ <div class="history-entry">
33
+ <div class="history-header">
34
+ <span class="timestamp">🕒 {timestamp}</span>
35
+ </div>
36
+
37
+ <div class="params-list">
38
+ <h4>Search Parameters:</h4>
39
+ <ul>
40
+ <li><span class="param-label">Living Space:</span> {prefs.get('living_space', 'N/A')}</li>
41
+ <li><span class="param-label">Exercise Time:</span> {prefs.get('exercise_time', 'N/A')} minutes</li>
42
+ <li><span class="param-label">Grooming:</span> {prefs.get('grooming_commitment', 'N/A')}</li>
43
+ <li><span class="param-label">Experience:</span> {prefs.get('experience_level', 'N/A')}</li>
44
+ <li><span class="param-label">Children at Home:</span> {"Yes" if prefs.get('has_children') else "No"}</li>
45
+ <li><span class="param-label">Noise Tolerance:</span> {prefs.get('noise_tolerance', 'N/A')}</li>
46
+ </ul>
47
+ </div>
48
+
49
+ <div class="results-list">
50
+ <h4>Top 5 Breed Matches:</h4>
51
+ <div class="breed-list">
52
+ """
53
+
54
+ if results:
55
+ for i, result in enumerate(results[:5], 1):
56
+ breed_name = result.get('breed', 'Unknown breed').replace('_', ' ')
57
+ score = result.get('overall_score', result.get('final_score', 0))
58
+ html += f"""
59
+ <div class="breed-item">
60
+ <div class="breed-info">
61
+ <span class="breed-rank">#{i}</span>
62
+ <span class="breed-name">{breed_name}</span>
63
+ <span class="breed-score">{score*100:.1f}%</span>
64
+ </div>
65
+ </div>
66
+ """
67
+
68
+ html += """
69
+ </div>
70
+ </div>
71
+ </div>
72
+ """
73
+
74
+ html += "</div>"
75
+ return html
76
+
77
+ except Exception as e:
78
+ print(f"Error formatting history: {str(e)}")
79
+ print(traceback.format_exc())
80
+ return f"""
81
+ <div style='text-align: center; padding: 20px; color: #dc2626;'>
82
+ Error formatting history. Please try refreshing the page.
83
+ <br>Error details: {str(e)}
84
+ </div>
85
+ """
86
+
87
+ def clear_history(self) -> str:
88
+ """清除所有搜尋歷史"""
89
+ try:
90
+ success = self.history_manager.clear_all_history()
91
+ print(f"Clear history result: {success}")
92
+ return self.format_history_html()
93
+ except Exception as e:
94
+ print(f"Error in clear_history: {str(e)}")
95
+ print(traceback.format_exc())
96
+ return "Error clearing history"
97
+
98
+ def refresh_history(self) -> str:
99
+ """刷新歷史記錄顯示"""
100
+ try:
101
+ return self.format_history_html()
102
+ except Exception as e:
103
+ print(f"Error in refresh_history: {str(e)}")
104
+ return "Error refreshing history"
105
+
106
+ def save_search(self, user_preferences: dict, results: list) -> bool:
107
+ """保存搜索結果"""
108
+ return self.history_manager.save_history(user_preferences, results)
109
+
110
+ def create_history_component():
111
+ """只创建历史组件实例,不创建UI"""
112
+ return SearchHistoryComponent()
113
+
114
+ def create_history_tab(history_component: SearchHistoryComponent):
115
+ """创建历史记录标签页
116
+
117
+ Args:
118
+ history_component: 已创建的历史组件实例
119
+ """
120
+ with gr.TabItem("Recommendation Search History"):
121
+ gr.HTML("""
122
+ <div style='text-align: center; padding: 20px;'>
123
+ <h3 style='color: #2D3748; margin-bottom: 10px;'>Search History</h3>
124
+ <p style='color: #4A5568;'>View your previous breed recommendations and search preferences</p>
125
+ </div>
126
+ """)
127
+
128
+ with gr.Row():
129
+ with gr.Column(scale=4):
130
+ history_display = gr.HTML()
131
+
132
+ with gr.Row():
133
+ with gr.Column(scale=1):
134
+ clear_history_btn = gr.Button(
135
+ "🗑️ Clear History",
136
+ variant="secondary",
137
+ size="sm"
138
+ )
139
+ with gr.Column(scale=1):
140
+ refresh_btn = gr.Button(
141
+ "🔄 Refresh",
142
+ variant="secondary",
143
+ size="sm"
144
+ )
145
+
146
+ history_display.value = history_component.format_history_html()
147
+
148
+ clear_history_btn.click(
149
+ fn=history_component.clear_history,
150
+ outputs=[history_display],
151
+ api_name="clear_history"
152
+ )
153
+
154
+ refresh_btn.click(
155
+ fn=history_component.refresh_history,
156
+ outputs=[history_display],
157
+ api_name="refresh_history"
158
+ )