openfree commited on
Commit
b378e61
ยท
verified ยท
1 Parent(s): 08e687f

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +386 -0
app.py ADDED
@@ -0,0 +1,386 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import numpy as np
4
+ from datetime import datetime
5
+ import plotly.graph_objects as go
6
+
7
+ class StartupValuationCalculator:
8
+ def __init__(self):
9
+ # ์—…์ข…๋ณ„ ๋ฒค์น˜๋งˆํฌ ๋ฉ€ํ‹ฐํ”Œ (EV/ARR)
10
+ self.industry_multiples = {
11
+ "SaaS - B2B": {"low": 3, "mid": 6, "high": 10},
12
+ "SaaS - B2C": {"low": 2, "mid": 4, "high": 7},
13
+ "๋งˆ์ผ“ํ”Œ๋ ˆ์ด์Šค": {"low": 2, "mid": 5, "high": 8},
14
+ "์ด์ปค๋จธ์Šค": {"low": 1, "mid": 2.5, "high": 4},
15
+ "ํ•€ํ…Œํฌ": {"low": 3, "mid": 5, "high": 8},
16
+ "ํ—ฌ์Šค์ผ€์–ด": {"low": 4, "mid": 7, "high": 12},
17
+ "AI/๋”ฅํ…Œํฌ": {"low": 5, "mid": 8, "high": 15},
18
+ "๊ธฐํƒ€": {"low": 2, "mid": 4, "high": 6}
19
+ }
20
+
21
+ # ์„ฑ์žฅ๋ฅ  ์กฐ์ • ๊ณ„์ˆ˜
22
+ self.growth_adjustments = {
23
+ "0-20%": 0.7,
24
+ "20-50%": 0.9,
25
+ "50-100%": 1.1,
26
+ "100-200%": 1.3,
27
+ "200%+": 1.5
28
+ }
29
+
30
+ # ๋‹จ์œ„๊ฒฝ์ œ ์ ์ˆ˜ ๊ฐ€์ค‘์น˜
31
+ self.unit_economics_weights = {
32
+ "ltv_cac_ratio": 0.3,
33
+ "gross_margin": 0.3,
34
+ "retention": 0.2,
35
+ "payback": 0.2
36
+ }
37
+
38
+ def calculate_arr(self, monthly_revenue, revenue_type):
39
+ """์›” ๋งค์ถœ์„ ์—ฐ๊ฐ„ ๋ฐ˜๋ณต ๋งค์ถœ(ARR)๋กœ ๋ณ€ํ™˜"""
40
+ if revenue_type == "๊ตฌ๋…ํ˜• (SaaS)":
41
+ return monthly_revenue * 12
42
+ elif revenue_type == "๊ฑฐ๋ž˜์ˆ˜์ˆ˜๋ฃŒํ˜•":
43
+ return monthly_revenue * 12 * 0.8 # ๊ฑฐ๋ž˜์ˆ˜์ˆ˜๋ฃŒ๋Š” ๋ณ€๋™์„ฑ ๊ณ ๋ ค
44
+ else:
45
+ return monthly_revenue * 12 * 0.6 # ์ผํšŒ์„ฑ ๋งค์ถœ์€ ๋” ํ• ์ธ
46
+
47
+ def calculate_ltv(self, arpu, gross_margin, monthly_churn):
48
+ """LTV ๊ณ„์‚ฐ"""
49
+ if monthly_churn == 0:
50
+ monthly_churn = 0.01 # ์ตœ์†Œ ์ดํƒˆ๋ฅ 
51
+ return arpu * (gross_margin / 100) / monthly_churn
52
+
53
+ def calculate_cac(self, monthly_marketing, monthly_sales, new_customers):
54
+ """CAC ๊ณ„์‚ฐ"""
55
+ if new_customers == 0:
56
+ return 0
57
+ return (monthly_marketing + monthly_sales) / new_customers
58
+
59
+ def calculate_payback(self, cac, arpu, gross_margin):
60
+ """Payback Period ๊ณ„์‚ฐ (๊ฐœ์›”)"""
61
+ if arpu * (gross_margin / 100) == 0:
62
+ return 999
63
+ return cac / (arpu * (gross_margin / 100))
64
+
65
+ def get_unit_economics_score(self, ltv_cac_ratio, gross_margin, retention_rate, payback_months):
66
+ """๋‹จ์œ„๊ฒฝ์ œ ์ ์ˆ˜ ๊ณ„์‚ฐ (0-100)"""
67
+ scores = {
68
+ "ltv_cac_ratio": min(100, (ltv_cac_ratio / 3) * 100) if ltv_cac_ratio > 0 else 0,
69
+ "gross_margin": min(100, gross_margin * 1.25),
70
+ "retention": retention_rate,
71
+ "payback": max(0, 100 - (payback_months / 24) * 100) if payback_months < 999 else 0
72
+ }
73
+
74
+ total_score = sum(scores[key] * self.unit_economics_weights[key] for key in scores)
75
+ return total_score
76
+
77
+ def get_growth_category(self, growth_rate):
78
+ """์„ฑ์žฅ๋ฅ  ์นดํ…Œ๊ณ ๋ฆฌ ๊ฒฐ์ •"""
79
+ if growth_rate < 20:
80
+ return "0-20%"
81
+ elif growth_rate < 50:
82
+ return "20-50%"
83
+ elif growth_rate < 100:
84
+ return "50-100%"
85
+ elif growth_rate < 200:
86
+ return "100-200%"
87
+ else:
88
+ return "200%+"
89
+
90
+ def calculate_valuation(self, data):
91
+ """์ข…ํ•ฉ ๊ฐ€์น˜ํ‰๊ฐ€ ๊ณ„์‚ฐ"""
92
+ # ARR ๊ณ„์‚ฐ
93
+ arr = self.calculate_arr(data["monthly_revenue"], data["revenue_type"])
94
+
95
+ # ๋‹จ์œ„๊ฒฝ์ œ ๊ณ„์‚ฐ
96
+ ltv = self.calculate_ltv(data["arpu"], data["gross_margin"], data["monthly_churn"])
97
+ cac = self.calculate_cac(data["monthly_marketing"], data["monthly_sales"], data["new_customers"])
98
+ ltv_cac_ratio = ltv / cac if cac > 0 else 0
99
+ payback = self.calculate_payback(cac, data["arpu"], data["gross_margin"])
100
+
101
+ # ๋‹จ์œ„๊ฒฝ์ œ ์ ์ˆ˜
102
+ ue_score = self.get_unit_economics_score(
103
+ ltv_cac_ratio, data["gross_margin"], data["retention_rate"], payback
104
+ )
105
+
106
+ # ๊ธฐ๋ณธ ๋ฉ€ํ‹ฐํ”Œ ์„ ํƒ
107
+ multiples = self.industry_multiples[data["industry"]]
108
+ if ue_score >= 80:
109
+ base_multiple = multiples["high"]
110
+ elif ue_score >= 50:
111
+ base_multiple = multiples["mid"]
112
+ else:
113
+ base_multiple = multiples["low"]
114
+
115
+ # ์„ฑ์žฅ๋ฅ  ์กฐ์ •
116
+ growth_adj = self.growth_adjustments[self.get_growth_category(data["growth_rate"])]
117
+ adjusted_multiple = base_multiple * growth_adj
118
+
119
+ # ์Šคํ…Œ์ด์ง€ ์กฐ์ •
120
+ stage_adj = {
121
+ "MVP/๋ฒ ํƒ€": 0.7,
122
+ "์ดˆ๊ธฐ ๋งค์ถœ": 0.85,
123
+ "์„ฑ์žฅ ๋‹จ๊ณ„": 1.0,
124
+ "์ˆ˜์ต์„ฑ ํ™•๋ณด": 1.2
125
+ }
126
+ final_multiple = adjusted_multiple * stage_adj[data["stage"]]
127
+
128
+ # ์ตœ์ข… ๊ฐ€์น˜ํ‰๊ฐ€
129
+ valuation = arr * final_multiple
130
+
131
+ # ๋Ÿฐ์›จ์ด ๊ณ„์‚ฐ
132
+ runway = data["cash_balance"] / data["burn_rate"] if data["burn_rate"] > 0 else 999
133
+
134
+ return {
135
+ "valuation": valuation,
136
+ "arr": arr,
137
+ "multiple": final_multiple,
138
+ "ltv": ltv,
139
+ "cac": cac,
140
+ "ltv_cac_ratio": ltv_cac_ratio,
141
+ "payback": payback,
142
+ "ue_score": ue_score,
143
+ "runway": runway
144
+ }
145
+
146
+ def create_comparison_chart(self, valuation, industry, arr):
147
+ """๋™์ข…์—…๊ณ„ ๋น„๊ต ์ฐจํŠธ ์ƒ์„ฑ"""
148
+ multiples = self.industry_multiples[industry]
149
+
150
+ fig = go.Figure()
151
+
152
+ # ์—…๊ณ„ ๋ฒ”์œ„
153
+ low_val = arr * multiples["low"]
154
+ mid_val = arr * multiples["mid"]
155
+ high_val = arr * multiples["high"]
156
+
157
+ # ๋ง‰๋Œ€ ๊ทธ๋ž˜ํ”„
158
+ fig.add_trace(go.Bar(
159
+ x=["ํ•˜์œ„ 25%", "์ค‘๊ฐ„๊ฐ’", "์ƒ์œ„ 25%", "ํ˜„์žฌ ๊ธฐ์—…"],
160
+ y=[low_val, mid_val, high_val, valuation],
161
+ text=[f"${low_val/1000000:.1f}M", f"${mid_val/1000000:.1f}M",
162
+ f"${high_val/1000000:.1f}M", f"${valuation/1000000:.1f}M"],
163
+ textposition="outside",
164
+ marker_color=["lightgray", "gray", "darkgray", "blue"]
165
+ ))
166
+
167
+ fig.update_layout(
168
+ title=f"{industry} ์—…๊ณ„ ๊ฐ€์น˜ํ‰๊ฐ€ ๋น„๊ต",
169
+ yaxis_title="๊ธฐ์—…๊ฐ€์น˜ (USD)",
170
+ showlegend=False,
171
+ height=400
172
+ )
173
+
174
+ return fig
175
+
176
+ def create_ui():
177
+ calculator = StartupValuationCalculator()
178
+
179
+ def process_valuation(
180
+ company_name, founded_year, industry, stage, revenue_type,
181
+ monthly_revenue, growth_rate, arpu, gross_margin, monthly_churn,
182
+ retention_rate, new_customers, monthly_marketing, monthly_sales,
183
+ cash_balance, burn_rate
184
+ ):
185
+ # ์ž…๋ ฅ๊ฐ’ ๊ฒ€์ฆ
186
+ if monthly_revenue <= 0:
187
+ return "์›” ๋งค์ถœ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.", None, None
188
+
189
+ # ๋ฐ์ดํ„ฐ ์ค€๋น„
190
+ data = {
191
+ "company_name": company_name,
192
+ "founded_year": founded_year,
193
+ "industry": industry,
194
+ "stage": stage,
195
+ "revenue_type": revenue_type,
196
+ "monthly_revenue": monthly_revenue * 1000, # ์ฒœ ๋‹ฌ๋Ÿฌ ๋‹จ์œ„๋กœ ์ž…๋ ฅ๋ฐ›์Œ
197
+ "growth_rate": growth_rate,
198
+ "arpu": arpu,
199
+ "gross_margin": gross_margin,
200
+ "monthly_churn": monthly_churn / 100,
201
+ "retention_rate": retention_rate,
202
+ "new_customers": new_customers,
203
+ "monthly_marketing": monthly_marketing * 1000,
204
+ "monthly_sales": monthly_sales * 1000,
205
+ "cash_balance": cash_balance * 1000,
206
+ "burn_rate": burn_rate * 1000
207
+ }
208
+
209
+ # ๊ฐ€์น˜ํ‰๊ฐ€ ๊ณ„์‚ฐ
210
+ results = calculator.calculate_valuation(data)
211
+
212
+ # ๊ฒฐ๊ณผ ํฌ๋งทํŒ…
213
+ valuation_text = f"""
214
+ # ๐Ÿš€ {company_name} ๊ฐ€์น˜ํ‰๊ฐ€ ๊ฒฐ๊ณผ
215
+
216
+ ## ๐Ÿ“Š ์ฃผ์š” ์ง€ํ‘œ
217
+ - **๊ธฐ์—…๊ฐ€์น˜**: ${results['valuation']/1000000:.1f}M (โ‚ฉ{results['valuation']/1000000*1300:.0f}์–ต)
218
+ - **ARR**: ${results['arr']/1000000:.1f}M
219
+ - **์ ์šฉ ๋ฉ€ํ‹ฐํ”Œ**: {results['multiple']:.1f}x
220
+
221
+ ## ๐Ÿ’ฐ ๋‹จ์œ„๊ฒฝ์ œ
222
+ - **LTV**: ${results['ltv']:.0f}
223
+ - **CAC**: ${results['cac']:.0f}
224
+ - **LTV/CAC**: {results['ltv_cac_ratio']:.1f}x
225
+ - **Payback Period**: {results['payback']:.1f}๊ฐœ์›”
226
+ - **๋‹จ์œ„๊ฒฝ์ œ ์ ์ˆ˜**: {results['ue_score']:.0f}/100
227
+
228
+ ## ๐Ÿƒ ์žฌ๋ฌด ๊ฑด์ „์„ฑ
229
+ - **ํ˜„๊ธˆ ๋Ÿฐ์›จ์ด**: {results['runway']:.1f}๊ฐœ์›”
230
+ - **์›”๊ฐ„ ๋ฒˆ๋ ˆ์ดํŠธ**: ${burn_rate}K
231
+
232
+ ## ๐Ÿ’ก ํ‰๊ฐ€ ์ธ์‚ฌ์ดํŠธ
233
+ """
234
+ # ์ธ์‚ฌ์ดํŠธ ์ถ”๊ฐ€
235
+ if results['ltv_cac_ratio'] < 1:
236
+ valuation_text += "- โš ๏ธ LTV/CAC ๋น„์œจ์ด 1 ๋ฏธ๋งŒ์ž…๋‹ˆ๋‹ค. ๋งˆ์ผ€ํŒ… ํšจ์œจ์„ฑ ๊ฐœ์„ ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.\n"
237
+ elif results['ltv_cac_ratio'] > 3:
238
+ valuation_text += "- โœ… ์šฐ์ˆ˜ํ•œ LTV/CAC ๋น„์œจ์„ ๋ณด์ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.\n"
239
+
240
+ if results['runway'] < 12:
241
+ valuation_text += "- โš ๏ธ ๋Ÿฐ์›จ์ด๊ฐ€ 12๊ฐœ์›” ๋ฏธ๋งŒ์ž…๋‹ˆ๋‹ค. ์ถ”๊ฐ€ ์ž๊ธˆ์กฐ๋‹ฌ์„ ๊ณ ๋ คํ•˜์„ธ์š”.\n"
242
+
243
+ if gross_margin < 60:
244
+ valuation_text += "- ๐Ÿ“ˆ ๋งค์ถœ์ด์ด์ต๋ฅ  ๊ฐœ์„  ์—ฌ์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. (์—…๊ณ„ ํ‰๊ท : 70-80%)\n"
245
+
246
+ # ๋น„๊ต ์ฐจํŠธ ์ƒ์„ฑ
247
+ comparison_chart = calculator.create_comparison_chart(
248
+ results['valuation'], industry, results['arr']
249
+ )
250
+
251
+ # ์ƒ์„ธ ๋ถ„์„ ํ…Œ์ด๋ธ”
252
+ metrics_df = pd.DataFrame({
253
+ "์ง€ํ‘œ": ["์›” ๋งค์ถœ", "์—ฐ ์„ฑ์žฅ๋ฅ ", "๋งค์ถœ์ด์ด์ต๋ฅ ", "์›” ์ดํƒˆ๋ฅ ", "๊ณ ๊ฐ ์œ ์ง€์œจ"],
254
+ "ํ˜„์žฌ ๊ฐ’": [f"${monthly_revenue}K", f"{growth_rate}%", f"{gross_margin}%",
255
+ f"{monthly_churn}%", f"{retention_rate}%"],
256
+ "์—…๊ณ„ ํ‰๊ท ": ["N/A", "50-100%", "70-80%", "2-5%", "80-90%"]
257
+ })
258
+
259
+ return valuation_text, comparison_chart, metrics_df
260
+
261
+ # Gradio UI
262
+ with gr.Blocks(title="์Šคํƒ€ํŠธ์—… ๊ฐ€์น˜ํ‰๊ฐ€ ๊ณ„์‚ฐ๊ธฐ", theme=gr.themes.Soft()) as demo:
263
+ gr.Markdown("""
264
+ # ๐Ÿฆ„ ์Šคํƒ€ํŠธ์—… ๊ฐ€์น˜ํ‰๊ฐ€ ์ž๋™ํ™” ์‹œ์Šคํ…œ
265
+
266
+ ๊ฐ„๋‹จํ•œ ์ •๋ณด ์ž…๋ ฅ๋งŒ์œผ๋กœ ๊ท€์‚ฌ์˜ ์˜ˆ์ƒ ๊ธฐ์—…๊ฐ€์น˜๋ฅผ ์‚ฐ์ถœํ•˜๊ณ  ๋™์ข…์—…๊ณ„์™€ ๋น„๊ตํ•ด๋“œ๋ฆฝ๋‹ˆ๋‹ค.
267
+ """)
268
+
269
+ with gr.Tab("๊ธฐ๋ณธ ์ •๋ณด"):
270
+ with gr.Row():
271
+ company_name = gr.Textbox(label="ํšŒ์‚ฌ๋ช…", value="์šฐ๋ฆฌ ์Šคํƒ€ํŠธ์—…")
272
+ founded_year = gr.Slider(2015, 2024, value=2022, step=1, label="์„ค๋ฆฝ์—ฐ๋„")
273
+
274
+ with gr.Row():
275
+ industry = gr.Dropdown(
276
+ choices=list(calculator.industry_multiples.keys()),
277
+ value="SaaS - B2B",
278
+ label="์‚ฐ์—… ๋ถ„๋ฅ˜"
279
+ )
280
+ stage = gr.Radio(
281
+ choices=["MVP/๋ฒ ํƒ€", "์ดˆ๊ธฐ ๋งค์ถœ", "์„ฑ์žฅ ๋‹จ๊ณ„", "์ˆ˜์ต์„ฑ ํ™•๋ณด"],
282
+ value="์ดˆ๊ธฐ ๋งค์ถœ",
283
+ label="์‚ฌ์—… ๋‹จ๊ณ„"
284
+ )
285
+
286
+ revenue_type = gr.Radio(
287
+ choices=["๊ตฌ๋…ํ˜• (SaaS)", "๊ฑฐ๋ž˜์ˆ˜์ˆ˜๋ฃŒํ˜•", "์ผํšŒ์„ฑ ํŒ๋งค"],
288
+ value="๊ตฌ๋…ํ˜• (SaaS)",
289
+ label="์ˆ˜์ต ๋ชจ๋ธ"
290
+ )
291
+
292
+ with gr.Tab("๋งค์ถœ ๋ฐ ์„ฑ์žฅ"):
293
+ gr.Markdown("### ๐Ÿ’ฐ ๋งค์ถœ ์ •๋ณด (๋‹จ์œ„: ์ฒœ ๋‹ฌ๋Ÿฌ)")
294
+ with gr.Row():
295
+ monthly_revenue = gr.Number(label="์›” ๋งค์ถœ ($K)", value=50)
296
+ growth_rate = gr.Slider(0, 300, value=100, step=10,
297
+ label="์—ฐ๊ฐ„ ์„ฑ์žฅ๋ฅ  (%)")
298
+
299
+ with gr.Row():
300
+ arpu = gr.Number(label="๊ณ ๊ฐ๋‹น ํ‰๊ท  ๋งค์ถœ (ARPU) ($)", value=100)
301
+ gross_margin = gr.Slider(0, 100, value=70, step=5,
302
+ label="๋งค์ถœ์ด์ด์ต๋ฅ  (%)")
303
+
304
+ with gr.Tab("๊ณ ๊ฐ ๋ฐ ๋งˆ์ผ€ํŒ…"):
305
+ gr.Markdown("### ๐Ÿ‘ฅ ๊ณ ๊ฐ ์ง€ํ‘œ")
306
+ with gr.Row():
307
+ retention_rate = gr.Slider(0, 100, value=85, step=5,
308
+ label="์›”๊ฐ„ ๊ณ ๊ฐ ์œ ์ง€์œจ (%)")
309
+ monthly_churn = gr.Slider(0, 20, value=3, step=0.5,
310
+ label="์›” ์ดํƒˆ๋ฅ  (%)")
311
+
312
+ gr.Markdown("### ๐Ÿ“ข ๋งˆ์ผ€ํŒ… ํšจ์œจ์„ฑ")
313
+ with gr.Row():
314
+ new_customers = gr.Number(label="์›” ์‹ ๊ทœ ๊ณ ๊ฐ ์ˆ˜", value=50)
315
+ monthly_marketing = gr.Number(label="์›” ๋งˆ์ผ€ํŒ… ๋น„์šฉ ($K)", value=20)
316
+ monthly_sales = gr.Number(label="์›” ์˜์—… ๋น„์šฉ ($K)", value=15)
317
+
318
+ with gr.Tab("์žฌ๋ฌด ํ˜„ํ™ฉ"):
319
+ gr.Markdown("### ๐Ÿ’ธ ํ˜„๊ธˆ ์ƒํ™ฉ (๋‹จ์œ„: ์ฒœ ๋‹ฌ๋Ÿฌ)")
320
+ with gr.Row():
321
+ cash_balance = gr.Number(label="ํ˜„๊ธˆ ์ž”๊ณ  ($K)", value=1000)
322
+ burn_rate = gr.Number(label="์›” ๋ฒˆ๋ ˆ์ดํŠธ ($K)", value=80)
323
+
324
+ # ํ‰๊ฐ€ ์‹คํ–‰ ๋ฒ„ํŠผ
325
+ evaluate_btn = gr.Button("๐Ÿ” ๊ฐ€์น˜ํ‰๊ฐ€ ์‹คํ–‰", variant="primary", size="lg")
326
+
327
+ # ๊ฒฐ๊ณผ ์ถœ๋ ฅ
328
+ with gr.Row():
329
+ with gr.Column(scale=2):
330
+ valuation_output = gr.Markdown(label="ํ‰๊ฐ€ ๊ฒฐ๊ณผ")
331
+ with gr.Column(scale=1):
332
+ metrics_table = gr.DataFrame(label="์ฃผ์š” ์ง€ํ‘œ ๋น„๊ต")
333
+
334
+ comparison_chart = gr.Plot(label="๋™์ข…์—…๊ณ„ ๋น„๊ต")
335
+
336
+ # ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
337
+ evaluate_btn.click(
338
+ process_valuation,
339
+ inputs=[
340
+ company_name, founded_year, industry, stage, revenue_type,
341
+ monthly_revenue, growth_rate, arpu, gross_margin, monthly_churn,
342
+ retention_rate, new_customers, monthly_marketing, monthly_sales,
343
+ cash_balance, burn_rate
344
+ ],
345
+ outputs=[valuation_output, comparison_chart, metrics_table]
346
+ )
347
+
348
+ # ์˜ˆ์‹œ ๋ฐ์ดํ„ฐ ๋ฒ„ํŠผ๋“ค
349
+ gr.Markdown("### ๐Ÿ“ ์˜ˆ์‹œ ๋ฐ์ดํ„ฐ๋กœ ํ…Œ์ŠคํŠธํ•˜๊ธฐ")
350
+ with gr.Row():
351
+ gr.Button("SaaS ์Šคํƒ€ํŠธ์—… ์˜ˆ์‹œ").click(
352
+ lambda: [
353
+ "ํ…Œํฌ ์Šคํƒ€ํŠธ์—…", 2021, "SaaS - B2B", "์„ฑ์žฅ ๋‹จ๊ณ„", "๊ตฌ๋…ํ˜• (SaaS)",
354
+ 100, 150, 200, 75, 2,
355
+ 90, 40, 30, 20,
356
+ 2000, 120
357
+ ],
358
+ outputs=[
359
+ company_name, founded_year, industry, stage, revenue_type,
360
+ monthly_revenue, growth_rate, arpu, gross_margin, monthly_churn,
361
+ retention_rate, new_customers, monthly_marketing, monthly_sales,
362
+ cash_balance, burn_rate
363
+ ]
364
+ )
365
+
366
+ gr.Button("์ด์ปค๋จธ์Šค ์˜ˆ์‹œ").click(
367
+ lambda: [
368
+ "์˜จ๋ผ์ธ ์‡ผํ•‘๋ชฐ", 2022, "์ด์ปค๋จธ์Šค", "์ดˆ๊ธฐ ๋งค์ถœ", "์ผํšŒ์„ฑ ํŒ๋งค",
369
+ 80, 80, 50, 40, 5,
370
+ 70, 100, 25, 10,
371
+ 500, 70
372
+ ],
373
+ outputs=[
374
+ company_name, founded_year, industry, stage, revenue_type,
375
+ monthly_revenue, growth_rate, arpu, gross_margin, monthly_churn,
376
+ retention_rate, new_customers, monthly_marketing, monthly_sales,
377
+ cash_balance, burn_rate
378
+ ]
379
+ )
380
+
381
+ return demo
382
+
383
+ # ์‹คํ–‰
384
+ if __name__ == "__main__":
385
+ demo = create_ui()
386
+ demo.launch(share=True)