cho2-0923 commited on
Commit
014a313
·
1 Parent(s): 95ee8a8

Refactor app structure by separating data management and node functions into dedicated modules. Implement data initialization on app start and streamline node and idea handling. Update UI interactions for improved functionality.

Browse files
Files changed (4) hide show
  1. app.py +13 -283
  2. data_manager.py +48 -0
  3. idea_functions.py +48 -0
  4. node_functions.py +105 -0
app.py CHANGED
@@ -3,288 +3,18 @@ import json
3
  import os
4
  import pandas as pd
5
  from typing import List, Dict, Any
6
-
7
- # 노드 데이터를 저장할 전역 변수
8
- nodes_data = []
9
- # 아이디어 데이터를 저장할 전역 변수
10
- ideas_data = []
11
-
12
- def save_nodes():
13
- """노드 데이터를 JSON 파일로 저장"""
14
- with open('nodes_data.json', 'w', encoding='utf-8') as f:
15
- json.dump(nodes_data, f, ensure_ascii=False, indent=2)
16
-
17
- def save_ideas():
18
- """아이디어 데이터를 JSON 파일로 저장"""
19
- with open('ideas_data.json', 'w', encoding='utf-8') as f:
20
- json.dump(ideas_data, f, ensure_ascii=False, indent=2)
21
-
22
- def load_nodes():
23
- """저장된 노드 데이터 불러오기"""
24
- global nodes_data
25
- if os.path.exists('nodes_data.json'):
26
- try:
27
- with open('nodes_data.json', 'r', encoding='utf-8') as f:
28
- nodes_data = json.load(f)
29
- except (json.JSONDecodeError, ValueError):
30
- nodes_data = []
31
- print("nodes_data.json 파일이 손상되었거나 비어있습니다. 새로 시작합니다.")
32
- else:
33
- nodes_data = []
34
-
35
- def load_ideas():
36
- """저장된 아이디어 데이터 불러오기"""
37
- global ideas_data
38
- if os.path.exists('ideas_data.json'):
39
- try:
40
- with open('ideas_data.json', 'r', encoding='utf-8') as f:
41
- ideas_data = json.load(f)
42
- except (json.JSONDecodeError, ValueError):
43
- ideas_data = []
44
- print("ideas_data.json 파일이 손상되었거나 비어있습니다. 새로 시작합니다.")
45
- else:
46
- ideas_data = []
47
-
48
- # 1. 포폴 업로드 탭 함수들
49
- def upload_portfolio_files(files):
50
- """포트폴리오 파일 업로드 처리"""
51
- if not files:
52
- return "파일을 선택해주세요.", ""
53
-
54
- uploaded_files = []
55
- for file in files:
56
- if file:
57
- uploaded_files.append(f"📄 {file.name}")
58
-
59
- files_display = "\n".join(uploaded_files)
60
- return f"업로드된 파일:\n{files_display}", files_display
61
-
62
- def process_uploaded_files(files_display):
63
- """업로드된 파일들을 AI로 분석하여 노드 생성"""
64
- if not files_display:
65
- return "업로드된 파일이 없습니다."
66
-
67
- # TODO: 실제 AI 분석 로직 구현
68
- sample_node = {
69
- "title": "AI 분석된 프로젝트",
70
- "solution": "업로드된 파일에서 분석된 솔루션과 핵심 기능들을 포함한 상세 설명",
71
- "tags": ["AI", "데이터분석", "웹개발"],
72
- "source": "파일 업로드"
73
- }
74
-
75
- nodes_data.append(sample_node)
76
- save_nodes()
77
-
78
- return "파일 분석이 완료되어 노드가 생성되었습니다!"
79
-
80
- # 2. 노드 입력하기 탭 함수들
81
- def add_keyword(keyword, current_tags):
82
- """키워드 추가"""
83
- if not keyword:
84
- return current_tags, "키워드를 입력해주세요."
85
-
86
- if current_tags:
87
- tags_list = [tag.strip() for tag in current_tags.split(',') if tag.strip()]
88
- else:
89
- tags_list = []
90
-
91
- if keyword not in tags_list:
92
- tags_list.append(keyword)
93
- updated_tags = ', '.join(tags_list)
94
- return updated_tags, f"'{keyword}' 키워드가 추가되었습니다."
95
- else:
96
- return current_tags, "이미 존재하는 키워드입니다."
97
-
98
- def create_node(title, solution, tags):
99
- """사용자 입력으로 새 노드 생성"""
100
- if not title or not solution:
101
- return "프로젝트 제목과 솔루션을 모두 입력해주세요."
102
-
103
- # 태그를 리스트로 변환
104
- tags_list = [tag.strip() for tag in tags.split(',') if tag.strip()]
105
-
106
- new_node = {
107
- "title": title,
108
- "solution": solution,
109
- "tags": tags_list,
110
- "source": "직접 입력"
111
- }
112
-
113
- nodes_data.append(new_node)
114
- save_nodes()
115
-
116
- return "새 노드가 성공적으로 생성되었습니다!"
117
-
118
- # 3. 내 노드 확인하기 탭 함수들
119
- def get_nodes_dataframe(filter_tag=""):
120
- """저장된 노드들을 데이터프레임으로 변환"""
121
- if not nodes_data:
122
- return pd.DataFrame()
123
-
124
- # 필터링된 노드들
125
- filtered_nodes = []
126
- for node in nodes_data:
127
- if not filter_tag or filter_tag in node.get('tags', []):
128
- filtered_nodes.append({
129
- "프로젝트 제목": node['title'],
130
- "솔루션 소개": node['solution'][:100] + "..." if len(node['solution']) > 100 else node['solution'],
131
- "태그": ', '.join(node.get('tags', [])),
132
- "출처": node.get('source', '직접 입력')
133
- })
134
-
135
- return pd.DataFrame(filtered_nodes)
136
-
137
- def filter_nodes(filter_tag):
138
- """태그로 노드 필터링"""
139
- return get_nodes_dataframe(filter_tag)
140
-
141
- def get_all_tags():
142
- """모든 노드의 태그 목록 반환"""
143
- all_tags = set()
144
- for node in nodes_data:
145
- all_tags.update(node.get('tags', []))
146
- return [""] + sorted(list(all_tags))
147
-
148
- # 4. AI 아이디어 생성 탭 함수들
149
- def add_team_member(member_code, current_members):
150
- """팀원 추가"""
151
- if not member_code:
152
- return current_members, "팀원 코드를 입력해주세요."
153
-
154
- new_member = f"👤 {member_code} (닉네임)"
155
-
156
- if current_members:
157
- updated_members = current_members + f"\n{new_member}"
158
- else:
159
- updated_members = new_member
160
-
161
- return updated_members, "팀원이 추가되었습니다!"
162
-
163
- def generate_idea_chatgpt(competition_name, is_development, category, team_members):
164
- """ChatGPT로 아이디어 생성"""
165
- if not competition_name:
166
- return "공모전 이름을 입력해주세요."
167
-
168
- idea_content = f"""## 🤖 ChatGPT 생성 아이디어
169
-
170
- **공모전:** {competition_name}
171
- **개발 여부:** {is_development}
172
- **분야:** {category}
173
-
174
- ### 아이디어: "스마트 환경 모니터링 시스템"
175
-
176
- **핵심 컨셉:**
177
- 당신의 노드에서 분석한 IoT와 데이터 분석 경험을 활용하여, 실시간 환경 데이터를 수집하고 예측 분석을 제공하는 시스템을 제안합니다.
178
-
179
- **주요 기능:**
180
- 1. 다중 센서 기반 환경 데이터 수집
181
- 2. AI 기반 환경 변화 예측
182
- 3. 실시간 알림 및 대응 방안 제시
183
- 4. 커뮤니티 기반 환경 개선 참여 플랫폼
184
-
185
- **활용된 노드:**
186
- • 이전 IoT 프로젝트의 센서 활용 경험
187
- • 데이터 분석 및 시각화 기술
188
- • 웹/앱 개발 경험
189
-
190
- **차별점:**
191
- 기존 환경 모니터링 시스템과 달리, 개인 사용자도 쉽게 참여할 수 있는 접근성과 AI 예측 기능을 결합"""
192
-
193
- # 아이디어 저장
194
- new_idea = {
195
- "title": "스마트 환경 모니터링 시스템",
196
- "competition": competition_name,
197
- "generator": "ChatGPT",
198
- "summary": "IoT와 데이터 분석을 활용한 실시간 환경 모니터링 및 예측 시스템",
199
- "content": idea_content,
200
- "category": category,
201
- "development_type": is_development
202
- }
203
-
204
- ideas_data.append(new_idea)
205
- save_ideas()
206
-
207
- return idea_content
208
-
209
- def generate_idea_gemini(competition_name, is_development, category, team_members):
210
- """Gemini로 아이디어 생성"""
211
- if not competition_name:
212
- return "공모전 이름을 입력해주세요."
213
-
214
- idea_content = f"""## 🎯 Gemini 생성 아이디어
215
-
216
- **공모전:** {competition_name}
217
- **개발 여부:** {is_development}
218
- **분야:** {category}
219
-
220
- ### 아이디어: "협업 기반 지역 문제 해결 플랫폼"
221
-
222
- **핵심 컨셉:**
223
- 지역 주민들이 직면한 실질적 문제를 발굴하고, 다양한 배경의 사람들이 협업하여 해결책을 찾는 플랫폼입니다.
224
-
225
- **주요 기능:**
226
- 1. 지역 문제 제보 및 검증 시스템
227
- 2. 스킬 기반 팀 매칭 알고리즘
228
- 3. 프로젝트 진행 관리 및 리소스 공유
229
- 4. 성과 측정 및 영향력 분석 도구
230
-
231
- **활용된 노드:**
232
- • 커뮤니티 플랫폼 개발 경험
233
- • 사용자 경험 설계 역량
234
- • 데이터 기반 의사결정 경험
235
-
236
- **혁신성:**
237
- 단순한 아이디어 제안을 넘어서, 실제 실행 가능한 프로젝트로 연결하는 구조적 접근"""
238
-
239
- # 아이디어 저장
240
- new_idea = {
241
- "title": "협업 기반 지역 문제 해결 플랫폼",
242
- "competition": competition_name,
243
- "generator": "Gemini",
244
- "summary": "지역 주민과 다양한 배경의 사람들이 협업하여 실질적 문제를 해결하는 플랫폼",
245
- "content": idea_content,
246
- "category": category,
247
- "development_type": is_development
248
- }
249
-
250
- ideas_data.append(new_idea)
251
- save_ideas()
252
-
253
- return idea_content
254
-
255
- # 5. 생성된 아이디어 확인하기 탭 함수들
256
- def get_ideas_display():
257
- """생성된 아이디어들을 표시용으로 변환"""
258
- if not ideas_data:
259
- return "아직 생성된 아이디어가 없습니다."
260
-
261
- display_items = []
262
- for i, idea in enumerate(ideas_data):
263
- card = f"""
264
- <div style="border: 1px solid #ddd; border-radius: 8px; padding: 16px; margin: 8px 0; background: #f9f9f9;">
265
- <h3>💡 {idea['title']}</h3>
266
- <p><strong>생성 AI:</strong> {idea['generator']} | <strong>공모전:</strong> {idea['competition']}</p>
267
- <p><strong>요약:</strong> {idea['summary']}</p>
268
- <details>
269
- <summary>자세한 내용 보기</summary>
270
- <div style="margin-top: 12px; padding: 12px; background: white; border-radius: 4px;">
271
- {idea['content'].replace('\n', '<br>')}
272
- </div>
273
- </details>
274
- </div>
275
- """
276
- display_items.append(card)
277
-
278
- return "".join(display_items)
279
-
280
- def refresh_ideas():
281
- """아이디어 목록 새로고침"""
282
- load_ideas()
283
- return get_ideas_display()
284
-
285
- # 앱 시작 시 데이터 로드
286
- load_nodes()
287
- load_ideas()
288
 
289
  # Gradio 인터페이스 구성
290
  with gr.Blocks(title="노드폴리오", theme=gr.themes.Soft()) as app:
@@ -385,7 +115,7 @@ with gr.Blocks(title="노드폴리오", theme=gr.themes.Soft()) as app:
385
 
386
  # 이벤트 연결
387
  refresh_btn.click(
388
- lambda: [get_nodes_dataframe(), get_all_tags()],
389
  outputs=[nodes_dataframe, tag_filter]
390
  )
391
 
 
3
  import os
4
  import pandas as pd
5
  from typing import List, Dict, Any
6
+ from data_manager import initialize_data
7
+ from node_functions import (
8
+ upload_portfolio_files, process_uploaded_files, add_keyword, create_node,
9
+ get_nodes_dataframe, filter_nodes, get_all_tags, refresh_nodes
10
+ )
11
+ from idea_functions import (
12
+ add_team_member, generate_idea_chatgpt, generate_idea_gemini,
13
+ get_ideas_display, refresh_ideas
14
+ )
15
+
16
+ # 앱 시작 시 데이터 초기화
17
+ initialize_data()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  # Gradio 인터페이스 구성
20
  with gr.Blocks(title="노드폴리오", theme=gr.themes.Soft()) as app:
 
115
 
116
  # 이벤트 연결
117
  refresh_btn.click(
118
+ refresh_nodes,
119
  outputs=[nodes_dataframe, tag_filter]
120
  )
121
 
data_manager.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ from typing import List, Dict, Any
4
+
5
+ # 전역 변수
6
+ nodes_data = []
7
+ ideas_data = []
8
+
9
+ def save_nodes():
10
+ """노드 데이터를 JSON 파일로 저장"""
11
+ with open('nodes_data.json', 'w', encoding='utf-8') as f:
12
+ json.dump(nodes_data, f, ensure_ascii=False, indent=2)
13
+
14
+ def save_ideas():
15
+ """아이디어 데이터를 JSON 파일로 저장"""
16
+ with open('ideas_data.json', 'w', encoding='utf-8') as f:
17
+ json.dump(ideas_data, f, ensure_ascii=False, indent=2)
18
+
19
+ def load_nodes():
20
+ """저장된 노드 데이터 불러오기"""
21
+ global nodes_data
22
+ if os.path.exists('nodes_data.json'):
23
+ try:
24
+ with open('nodes_data.json', 'r', encoding='utf-8') as f:
25
+ nodes_data = json.load(f)
26
+ except (json.JSONDecodeError, ValueError):
27
+ nodes_data = []
28
+ print("nodes_data.json 파일이 손상되었거나 비어있습니다. 새로 시작합니다.")
29
+ else:
30
+ nodes_data = []
31
+
32
+ def load_ideas():
33
+ """저장된 아이디어 데이터 불러오기"""
34
+ global ideas_data
35
+ if os.path.exists('ideas_data.json'):
36
+ try:
37
+ with open('ideas_data.json', 'r', encoding='utf-8') as f:
38
+ ideas_data = json.load(f)
39
+ except (json.JSONDecodeError, ValueError):
40
+ ideas_data = []
41
+ print("ideas_data.json 파일이 손상되었거나 비어있습니다. 새로 시작합니다.")
42
+ else:
43
+ ideas_data = []
44
+
45
+ def initialize_data():
46
+ """앱 시작 시 데이터 초기화"""
47
+ load_nodes()
48
+ load_ideas()
idea_functions.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ from typing import List, Dict, Any
4
+
5
+ # 전역 변수
6
+ nodes_data = []
7
+ ideas_data = []
8
+
9
+ def save_nodes():
10
+ """노드 데이터를 JSON 파일로 저장"""
11
+ with open('nodes_data.json', 'w', encoding='utf-8') as f:
12
+ json.dump(nodes_data, f, ensure_ascii=False, indent=2)
13
+
14
+ def save_ideas():
15
+ """아이디어 데이터를 JSON 파일로 저장"""
16
+ with open('ideas_data.json', 'w', encoding='utf-8') as f:
17
+ json.dump(ideas_data, f, ensure_ascii=False, indent=2)
18
+
19
+ def load_nodes():
20
+ """저장된 노드 데이터 불러오기"""
21
+ global nodes_data
22
+ if os.path.exists('nodes_data.json'):
23
+ try:
24
+ with open('nodes_data.json', 'r', encoding='utf-8') as f:
25
+ nodes_data = json.load(f)
26
+ except (json.JSONDecodeError, ValueError):
27
+ nodes_data = []
28
+ print("nodes_data.json 파일이 손상되었거나 비어있습니다. 새로 시작합니다.")
29
+ else:
30
+ nodes_data = []
31
+
32
+ def load_ideas():
33
+ """저장된 아이디어 데이터 불러오기"""
34
+ global ideas_data
35
+ if os.path.exists('ideas_data.json'):
36
+ try:
37
+ with open('ideas_data.json', 'r', encoding='utf-8') as f:
38
+ ideas_data = json.load(f)
39
+ except (json.JSONDecodeError, ValueError):
40
+ ideas_data = []
41
+ print("ideas_data.json 파일이 손상되었거나 비어있습니다. 새로 시작합니다.")
42
+ else:
43
+ ideas_data = []
44
+
45
+ def initialize_data():
46
+ """앱 시작 시 데이터 초기화"""
47
+ load_nodes()
48
+ load_ideas()
node_functions.py ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ from data_manager import nodes_data, save_nodes
3
+
4
+ def upload_portfolio_files(files):
5
+ """포트폴리오 파일 업로드 처리"""
6
+ if not files:
7
+ return "파일을 선택해주세요.", ""
8
+
9
+ uploaded_files = []
10
+ for file in files:
11
+ if file:
12
+ uploaded_files.append(f"📄 {file.name}")
13
+
14
+ files_display = "\n".join(uploaded_files)
15
+ return f"업로드된 파일:\n{files_display}", files_display
16
+
17
+ def process_uploaded_files(files_display):
18
+ """업로드된 파일들을 AI로 분석하여 노드 생성"""
19
+ if not files_display:
20
+ return "업로드된 파일이 없습니다."
21
+
22
+ # TODO: 실제 AI 분석 로직 구현
23
+ sample_node = {
24
+ "title": "AI 분석된 프로젝트",
25
+ "solution": "업로드된 파일에서 분석된 솔루션과 핵심 기능들을 포함한 상세 설명",
26
+ "tags": ["AI", "데이터분석", "웹개발"],
27
+ "source": "파일 업로드"
28
+ }
29
+
30
+ nodes_data.append(sample_node)
31
+ save_nodes()
32
+
33
+ return "파일 분석이 완료되어 노드가 생성되었습니다!"
34
+
35
+ def add_keyword(keyword, current_tags):
36
+ """키워드 추가"""
37
+ if not keyword:
38
+ return current_tags, "키워드를 입력해주세요."
39
+
40
+ if current_tags:
41
+ tags_list = [tag.strip() for tag in current_tags.split(',') if tag.strip()]
42
+ else:
43
+ tags_list = []
44
+
45
+ if keyword not in tags_list:
46
+ tags_list.append(keyword)
47
+ updated_tags = ', '.join(tags_list)
48
+ return updated_tags, f"'{keyword}' 키워드가 추가되었습니다."
49
+ else:
50
+ return current_tags, "이미 존재하는 키워드입니다."
51
+
52
+ def create_node(title, solution, tags):
53
+ """사용자 입력으로 새 노드 생성"""
54
+ if not title or not solution:
55
+ return "프로젝트 제목과 솔루션을 모두 입력해주세요."
56
+
57
+ # 태그를 리스트로 변환
58
+ tags_list = [tag.strip() for tag in tags.split(',') if tag.strip()]
59
+
60
+ new_node = {
61
+ "title": title,
62
+ "solution": solution,
63
+ "tags": tags_list,
64
+ "source": "직접 입력"
65
+ }
66
+
67
+ nodes_data.append(new_node)
68
+ save_nodes()
69
+
70
+ return "새 노드가 성공적으로 생성되었습니다!"
71
+
72
+ def get_nodes_dataframe(filter_tag=""):
73
+ """저장된 노드들을 데이터프레임으로 변환"""
74
+ if not nodes_data:
75
+ return pd.DataFrame()
76
+
77
+ # 필터링된 노드들
78
+ filtered_nodes = []
79
+ for node in nodes_data:
80
+ if not filter_tag or filter_tag in node.get('tags', []):
81
+ filtered_nodes.append({
82
+ "프로젝트 제목": node['title'],
83
+ "솔루션 소개": node['solution'][:100] + "..." if len(node['solution']) > 100 else node['solution'],
84
+ "태그": ', '.join(node.get('tags', [])),
85
+ "출처": node.get('source', '직접 입력')
86
+ })
87
+
88
+ return pd.DataFrame(filtered_nodes)
89
+
90
+ def filter_nodes(filter_tag):
91
+ """태그로 노드 필터링"""
92
+ return get_nodes_dataframe(filter_tag)
93
+
94
+ def get_all_tags():
95
+ """모든 노드의 태그 목록 반환"""
96
+ all_tags = set()
97
+ for node in nodes_data:
98
+ all_tags.update(node.get('tags', []))
99
+ return [""] + sorted(list(all_tags))
100
+
101
+ def refresh_nodes():
102
+ """노드 목록 새로고침"""
103
+ from data_manager import load_nodes
104
+ load_nodes()
105
+ return get_nodes_dataframe(), get_all_tags()