eshan6704 commited on
Commit
81bf4ef
·
verified ·
1 Parent(s): 69379e9

Create common.py

Browse files
Files changed (1) hide show
  1. app/common.py +211 -0
app/common.py ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import numpy as np
3
+ import datetime
4
+ import traceback
5
+ from backblaze import *
6
+
7
+ # ============================================================
8
+ # NUMBER FORMATTING HELPERS
9
+ # ============================================================
10
+
11
+ def format_number(num):
12
+ if num is None:
13
+ return "-"
14
+ try:
15
+ return f"{float(num):,.2f}".rstrip("0").rstrip(".")
16
+ except:
17
+ return str(num)
18
+
19
+ def format_large_number(num):
20
+ if num is None:
21
+ return "-"
22
+ try:
23
+ n = float(num)
24
+ if abs(n) >= 1_00_00_000: # Crore
25
+ return f"{n/1_00_00_000:.2f} Cr"
26
+ elif abs(n) >= 1_00_000: # Lakh
27
+ return f"{n/1_00_000:.2f} L"
28
+ elif abs(n) >= 1_000: # Thousand
29
+ return f"{n/1_000:.2f} K"
30
+ else:
31
+ return format_number(n)
32
+ except:
33
+ return str(num)
34
+
35
+ # ============================================================
36
+ # HTML UI HELPERS
37
+ # ============================================================
38
+
39
+ def html_card(title, content):
40
+ return f"""
41
+ <div style="
42
+ background:#fff;
43
+ border-radius:12px;
44
+ padding:18px;
45
+ margin:15px 0;
46
+ box-shadow:0 2px 8px rgba(0,0,0,0.1);
47
+ border-left:6px solid #0077cc;
48
+ ">
49
+ <h2 style="margin-top:0;color:#0077cc;">{title}</h2>
50
+ <div>{content}</div>
51
+ </div>
52
+ """
53
+
54
+ def html_section(title, content):
55
+ return f"""
56
+ <div style="margin:20px 0;">
57
+ <h3 style="color:#444;margin-bottom:8px;">{title}</h3>
58
+ {content}
59
+ </div>
60
+ """
61
+
62
+ def html_error(msg):
63
+ return f"""
64
+ <div style="
65
+ padding:15px;
66
+ margin:15px 0;
67
+ background:#ffe6e6;
68
+ border-left:6px solid #d9534f;
69
+ border-radius:8px;
70
+ color:#b30000;
71
+ ">
72
+ <b>Error:</b> {msg}
73
+ </div>
74
+ """
75
+
76
+ # ============================================================
77
+ # DATAFRAME CLEANING
78
+ # ============================================================
79
+
80
+ def clean_df(df):
81
+ if isinstance(df.index, pd.DatetimeIndex):
82
+ df.index = df.index.strftime("%Y-%m-%d")
83
+ df.replace([np.inf, -np.inf], np.nan, inplace=True)
84
+ df.fillna("-", inplace=True)
85
+ return df
86
+
87
+ # ============================================================
88
+ # TABLE STYLING
89
+ # ============================================================
90
+
91
+ def make_table(df):
92
+ try:
93
+ df = df.copy()
94
+ df = clean_df(df)
95
+ html = df.to_html(classes="styled-table", escape=False, border=0)
96
+ return f"""
97
+ <style>
98
+ .styled-table {{
99
+ width:100%;
100
+ border-collapse:collapse;
101
+ font-size:14px;
102
+ }}
103
+ .styled-table th {{
104
+ background:#0077cc;
105
+ color:white;
106
+ padding:8px;
107
+ text-align:left;
108
+ }}
109
+ .styled-table td {{
110
+ padding:8px;
111
+ border-bottom:1px solid #ddd;
112
+ }}
113
+ .styled-table tr:nth-child(even) {{
114
+ background:#f3f7ff;
115
+ }}
116
+ .styled-table tr:hover {{
117
+ background:#e7f1ff;
118
+ }}
119
+ </style>
120
+ {html}
121
+ """
122
+ except Exception as e:
123
+ return html_error(f"Table render failed: {e}<br><pre>{traceback.format_exc()}</pre>")
124
+
125
+ # ============================================================
126
+ # UNIVERSAL PLOT WRAPPER
127
+ # ============================================================
128
+
129
+ def wrap_plotly_html(html_chart, table_html=None):
130
+ extra = f"<div style='margin-top:20px'>{table_html}</div>" if table_html else ""
131
+ return f"""
132
+ <div style="width:98%;margin:auto;">
133
+ {html_card("Chart", html_chart)}
134
+ {extra}
135
+ </div>
136
+ """
137
+
138
+ # ============================================================
139
+ # INDICATOR SAFE EXTRACTION HELPER
140
+ # ============================================================
141
+
142
+ def safe_get(df, key, default_val="-"):
143
+ try:
144
+ return df.get(key, default_val)
145
+ except:
146
+ return default_val
147
+
148
+ def format_timestamp_to_date(timestamp):
149
+ if not isinstance(timestamp, (int, float)) or timestamp <= 0:
150
+ return "N/A"
151
+ try:
152
+ return datetime.datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d')
153
+ except:
154
+ return "Invalid Date"
155
+
156
+ # ============================================================
157
+ # HTML WRAPPER
158
+ # ============================================================
159
+
160
+ STYLE_BLOCK = """
161
+ <style>
162
+ .styled-table {border-collapse: collapse; margin: 10px 0; font-size: 0.9em; font-family: sans-serif; width: 100%; box-shadow: 0 0 10px rgba(0,0,0,0.1);}
163
+ .styled-table th, .styled-table td {padding: 8px 10px; border: 1px solid #ddd;}
164
+ .styled-table tbody tr:nth-child(even) {background-color: #f9f9f9;}
165
+ .card {display: block; width: 95%; margin: 10px auto; padding: 15px; border: 1px solid #ddd; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); background: #fafafa;}
166
+ .card-category-title {font-size: 1.1em; color: #222; margin: 0 0 8px; border-bottom: 1px solid #eee; padding-bottom: 5px;}
167
+ .card-content-grid {display: flex; flex-wrap: wrap; gap: 15px;}
168
+ .key-value-pair {flex: 1 1 calc(20% - 15px); box-sizing: border-box; min-width: 150px; background: #fff; padding: 10px; border: 1px solid #e0e0e0; border-radius: 5px; box-shadow: 0 1px 3px rgba(0,0,0,0.05);}
169
+ .key-value-pair h3 {font-size: 0.95em; color: #444; margin: 0 0 5px 0;}
170
+ .key-value-pair p {font-size: 0.9em; color: #555; margin: 0; font-weight: bold;}
171
+ .big-box {width:95%; margin:20px auto; padding:20px; border:1px solid #ccc; border-radius:8px; background:#fff; box-shadow:0 2px 8px rgba(0,0,0,0.1); font-size:0.95em; line-height:1.4em; max-height:400px; overflow-y:auto;}
172
+ </style>
173
+ """
174
+
175
+ def wrap_html(content, title="Stock Data"):
176
+ return f"""
177
+ <!DOCTYPE html>
178
+ <html>
179
+ <head>
180
+ <title>{title}</title>
181
+ {STYLE_BLOCK}
182
+ </head>
183
+ <body>
184
+ {content}
185
+ </body>
186
+ </html>
187
+ """
188
+ # ======================================================
189
+ # Scrollable HTML wrapper
190
+ # ======================================================
191
+ SCROLL_WRAP = """
192
+ <div style="
193
+ max-height: 80vh;
194
+ overflow-y: auto;
195
+ overflow-x: auto;
196
+ padding: 10px;
197
+ border: 1px solid #ccc;
198
+ border-radius: 6px;
199
+ ">
200
+ {{HTML}}
201
+ </div>
202
+ """
203
+ # ======================================================
204
+ # HTML wrapper
205
+ # ======================================================
206
+ def wrap(html):
207
+ if html is None:
208
+ return "<h3>No Data</h3>"
209
+ return SCROLL_WRAP.replace("{{HTML}}", html)
210
+ def whoisboss():
211
+ retrun "eshan"