eshan6704 commited on
Commit
7f8521c
·
verified ·
1 Parent(s): a6d803d

Update common.py

Browse files
Files changed (1) hide show
  1. common.py +153 -104
common.py CHANGED
@@ -1,108 +1,157 @@
1
- # common.py
2
- import datetime
3
-
4
- # --- Shared CSS for all modules ---
5
- STYLE_BLOCK = """
6
- <style>
7
- .styled-table {
8
- border-collapse: collapse;
9
- margin: 10px 0;
10
- font-size: 0.9em;
11
- font-family: sans-serif;
12
- width: 100%;
13
- box-shadow: 0 0 10px rgba(0,0,0,0.1);
14
- }
15
- .styled-table th, .styled-table td {
16
- padding: 8px 10px;
17
- border: 1px solid #ddd;
18
- }
19
- .styled-table tbody tr:nth-child(even) {
20
- background-color: #f9f9f9;
21
- }
22
- .card {
23
- width: 95%;
24
- margin: 10px auto;
25
- padding: 15px;
26
- border: 1px solid #ddd;
27
- border-radius: 8px;
28
- background: #fafafa;
29
- box-shadow: 0 2px 5px rgba(0,0,0,0.1);
30
- }
31
- .card h2 {
32
- margin-top:0;
33
- }
34
- .big-box {
35
- width:95%;
36
- margin:20px auto;
37
- padding:20px;
38
- border:1px solid #ccc;
39
- border-radius:8px;
40
- background:#fff;
41
- box-shadow:0 2px 8px rgba(0,0,0,0.1);
42
- font-size:0.95em;
43
- line-height:1.4em;
44
- max-height:400px;
45
- overflow-y:auto;
46
- }
47
- .key-value-pair {
48
- flex: 1 1 calc(20% - 15px);
49
- box-sizing: border-box;
50
- min-width: 150px;
51
- background: #fff;
52
- padding: 10px;
53
- border: 1px solid #e0e0e0;
54
- border-radius: 5px;
55
- box-shadow: 0 1px 3px rgba(0,0,0,0.05);
56
- }
57
- .key-value-pair h3 {
58
- font-size: 0.95em;
59
- color: #444;
60
- margin: 0 0 5px 0;
61
- }
62
- .key-value-pair p {
63
- font-size: 0.9em;
64
- color: #555;
65
- margin: 0;
66
- font-weight: bold;
67
- }
68
- </style>
69
- """
70
-
71
- # --- Shared utility functions ---
72
  def format_large_number(num):
73
- if not isinstance(num, (int, float)):
74
- return num
75
- sign = '-' if num < 0 else ''
76
- num = abs(float(num))
77
- if num >= 1_000_000_000_000:
78
- return f"{sign}{num / 1_000_000_000_000:.2f} LCr"
79
- elif num >= 10_000_000:
80
- return f"{sign}{num / 10_000_000:.2f} Cr"
81
- elif num >= 100_000:
82
- return f"{sign}{num / 100_000:.2f} Lac"
83
- else:
84
- return f"{sign}{num:,.0f}"
85
-
86
- def format_timestamp_to_date(timestamp):
87
- if not isinstance(timestamp, (int, float)) or timestamp <= 0:
88
- return "N/A"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  try:
90
- return datetime.datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d')
91
- except ValueError:
92
- return "Invalid Date"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
 
94
- def wrap_html(title, content_html, style_block=None):
95
- """Wrap content in a full HTML page with optional CSS."""
96
- style = style_block if style_block else STYLE_BLOCK
97
  return f"""
98
- <!DOCTYPE html>
99
- <html>
100
- <head>
101
- <title>{title}</title>
102
- {style}
103
- </head>
104
- <body>
105
- {content_html}
106
- </body>
107
- </html>
108
- """
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import numpy as np
3
+ import traceback
4
+
5
+ # ============================================================
6
+ # NUMBER FORMATTING HELPERS
7
+ # ============================================================
8
+
9
+ def format_number(num):
10
+ """Format numbers with commas, handle None, remove trailing zeros."""
11
+ if num is None:
12
+ return "-"
13
+ try:
14
+ return f"{float(num):,.2f}".rstrip("0").rstrip(".")
15
+ except:
16
+ return str(num)
17
+
18
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  def format_large_number(num):
20
+ """Format large numbers into K, Lakh, Crore."""
21
+ if num is None:
22
+ return "-"
23
+ try:
24
+ n = float(num)
25
+ if abs(n) >= 1_00_00_000: # Crore
26
+ return f"{n/1_00_00_000:.2f} Cr"
27
+ elif abs(n) >= 1_00_000: # Lakh
28
+ return f"{n/1_00_000:.2f} L"
29
+ elif abs(n) >= 1_000: # Thousand
30
+ return f"{n/1_000:.2f} K"
31
+ else:
32
+ return format_number(n)
33
+ except:
34
+ return str(num)
35
+
36
+ # ============================================================
37
+ # HTML UI HELPERS
38
+ # ============================================================
39
+
40
+ def html_card(title, content):
41
+ """Beautiful card-style container."""
42
+ return f"""
43
+ <div style="
44
+ background:#fff;
45
+ border-radius:12px;
46
+ padding:18px;
47
+ margin:15px 0;
48
+ box-shadow:0 2px 8px rgba(0,0,0,0.1);
49
+ border-left:6px solid #0077cc;
50
+ ">
51
+ <h2 style="margin-top:0;color:#0077cc;">{title}</h2>
52
+ <div>{content}</div>
53
+ </div>
54
+ """
55
+
56
+
57
+ def html_section(title, content):
58
+ """Simple titled section."""
59
+ return f"""
60
+ <div style="margin:20px 0;">
61
+ <h3 style="color:#444;margin-bottom:8px;">{title}</h3>
62
+ {content}
63
+ </div>
64
+ """
65
+
66
+
67
+ def html_error(msg):
68
+ """Red error block with message."""
69
+ return f"""
70
+ <div style="
71
+ padding:15px;
72
+ margin:15px 0;
73
+ background:#ffe6e6;
74
+ border-left:6px solid #d9534f;
75
+ border-radius:8px;
76
+ color:#b30000;
77
+ ">
78
+ <b>Error:</b> {msg}
79
+ </div>
80
+ """
81
+
82
+ # ============================================================
83
+ # DATAFRAME CLEANING
84
+ # ============================================================
85
+
86
+ def clean_df(df):
87
+ """Standard cleanup for all results."""
88
+ if isinstance(df.index, pd.DatetimeIndex):
89
+ df.index = df.index.strftime("%Y-%m-%d")
90
+ df.replace([np.inf, -np.inf], np.nan, inplace=True)
91
+ df.fillna("-", inplace=True)
92
+ return df
93
+
94
+ # ============================================================
95
+ # TABLE STYLING
96
+ # ============================================================
97
+
98
+ def make_table(df):
99
+ """Convert DataFrame to pretty HTML table."""
100
  try:
101
+ df = df.copy()
102
+ df = clean_df(df)
103
+ html = df.to_html(classes="styled-table", escape=False, border=0)
104
+
105
+ return f"""
106
+ <style>
107
+ .styled-table {{
108
+ width:100%;
109
+ border-collapse:collapse;
110
+ font-size:14px;
111
+ }}
112
+ .styled-table th {{
113
+ background:#0077cc;
114
+ color:white;
115
+ padding:8px;
116
+ text-align:left;
117
+ }}
118
+ .styled-table td {{
119
+ padding:8px;
120
+ border-bottom:1px solid #ddd;
121
+ }}
122
+ .styled-table tr:nth-child(even) {{
123
+ background:#f3f7ff;
124
+ }}
125
+ .styled-table tr:hover {{
126
+ background:#e7f1ff;
127
+ }}
128
+ </style>
129
+ {html}
130
+ """
131
+ except Exception as e:
132
+ return html_error(f"Table render failed: {e}<br><pre>{traceback.format_exc()}</pre>")
133
+
134
+ # ============================================================
135
+ # UNIVERSAL PLOT WRAPPER
136
+ # ============================================================
137
 
138
+ def wrap_plotly_html(html_chart, table_html=None):
139
+ """Wrap chart + optional table into same styled page."""
140
+ extra = f"<div style='margin-top:20px'>{table_html}</div>" if table_html else ""
141
  return f"""
142
+ <div style="width:98%;margin:auto;">
143
+ {html_card("Chart", html_chart)}
144
+ {extra}
145
+ </div>
146
+ """
147
+
148
+ # ============================================================
149
+ # INDICATOR SAFE EXTRACTION HELPER
150
+ # ============================================================
151
+
152
+ def safe_get(df, key, default_val="-"):
153
+ """Sometimes JSON keys are missing; avoid crash."""
154
+ try:
155
+ return df.get(key, default_val)
156
+ except:
157
+ return default_val