Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1441,7 +1441,8 @@ setTimeout(() => {
|
|
| 1441 |
""", unsafe_allow_html=True)
|
| 1442 |
|
| 1443 |
#bloob line
|
| 1444 |
-
|
|
|
|
| 1445 |
if not data or len(data) == 0:
|
| 1446 |
return "<span class='spark' style='color:#999;'>—</span>"
|
| 1447 |
|
|
@@ -1451,31 +1452,30 @@ def sparkline_trend_pln(data):
|
|
| 1451 |
if n == 1:
|
| 1452 |
return "<span class='spark' style='color:#666;'>•</span>"
|
| 1453 |
|
| 1454 |
-
# Hitung slope linear
|
| 1455 |
-
# b = slope → menentukan warna
|
| 1456 |
xs = list(range(n))
|
| 1457 |
x_mean = sum(xs) / n
|
| 1458 |
y_mean = sum(data) / n
|
| 1459 |
numerator = sum((x - x_mean) * (y - y_mean) for x, y in zip(xs, data))
|
| 1460 |
denominator = sum((x - x_mean) ** 2 for x in xs)
|
| 1461 |
-
slope = numerator / (denominator + 1e-12)
|
| 1462 |
|
| 1463 |
-
# Tentukan warna berdasarkan slope
|
| 1464 |
if slope > 0.001:
|
| 1465 |
-
color = "#2E7D32" #
|
| 1466 |
label = "↑"
|
| 1467 |
elif slope < -0.001:
|
| 1468 |
-
color = "#C62828" #
|
| 1469 |
label = "↓"
|
| 1470 |
else:
|
| 1471 |
-
color = "#546E7A" #
|
| 1472 |
label = "→"
|
| 1473 |
|
| 1474 |
-
# Normalisasi
|
| 1475 |
-
min_y, max_y = min(data), max(data)
|
| 1476 |
height = 16
|
| 1477 |
margin = 2
|
| 1478 |
usable_h = height - 2 * margin
|
|
|
|
| 1479 |
|
| 1480 |
if max_y == min_y:
|
| 1481 |
y_coords = [margin + usable_h / 2] * n
|
|
@@ -1485,19 +1485,18 @@ def sparkline_trend_pln(data):
|
|
| 1485 |
for v in data
|
| 1486 |
]
|
| 1487 |
|
| 1488 |
-
#
|
| 1489 |
points = " ".join(f"{i * 8},{y:.1f}" for i, y in enumerate(y_coords))
|
| 1490 |
width = max(24, (n - 1) * 8 + 4)
|
| 1491 |
|
| 1492 |
-
# SVG
|
| 1493 |
svg = (
|
| 1494 |
f'<svg class="sparkline" width="{width + 6}" height="{height}" '
|
| 1495 |
-
f'viewBox="-2 0 {width + 6} {height}" style="vertical-align:middle
|
| 1496 |
-
f'xmlns="http://www.w3.org/2000/svg">'
|
| 1497 |
f'<polyline points="{points}" fill="none" stroke="{color}" '
|
| 1498 |
f'stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>'
|
| 1499 |
-
|
| 1500 |
-
f'<text x="{(n-1)*8 + 2}" y="14" font-size="10" fill="{color}" '
|
| 1501 |
f'dominant-baseline="middle">{label}</text>'
|
| 1502 |
f'</svg>'
|
| 1503 |
)
|
|
@@ -1505,6 +1504,7 @@ def sparkline_trend_pln(data):
|
|
| 1505 |
|
| 1506 |
except Exception:
|
| 1507 |
return "<span class='spark' style='color:#999;'>⚠</span>"
|
|
|
|
| 1508 |
# ——————— 1. Creators: ONLY Coverage < 90% AND Slope < 0 ———————
|
| 1509 |
def predict_creators(df):
|
| 1510 |
# ❌ Tidak ada filter Non-Positive
|
|
|
|
| 1441 |
""", unsafe_allow_html=True)
|
| 1442 |
|
| 1443 |
#bloob line
|
| 1444 |
+
# 🔹 Helper: Sparkline ala chart saham — hijau kalau naik, merah kalau turun
|
| 1445 |
+
def ascii_sparkline_pln(data):
|
| 1446 |
if not data or len(data) == 0:
|
| 1447 |
return "<span class='spark' style='color:#999;'>—</span>"
|
| 1448 |
|
|
|
|
| 1452 |
if n == 1:
|
| 1453 |
return "<span class='spark' style='color:#666;'>•</span>"
|
| 1454 |
|
| 1455 |
+
# Hitung slope (linear trend)
|
|
|
|
| 1456 |
xs = list(range(n))
|
| 1457 |
x_mean = sum(xs) / n
|
| 1458 |
y_mean = sum(data) / n
|
| 1459 |
numerator = sum((x - x_mean) * (y - y_mean) for x, y in zip(xs, data))
|
| 1460 |
denominator = sum((x - x_mean) ** 2 for x in xs)
|
| 1461 |
+
slope = numerator / (denominator + 1e-12)
|
| 1462 |
|
| 1463 |
+
# Tentukan warna & label berdasarkan slope
|
| 1464 |
if slope > 0.001:
|
| 1465 |
+
color = "#2E7D32" # hijau (naik)
|
| 1466 |
label = "↑"
|
| 1467 |
elif slope < -0.001:
|
| 1468 |
+
color = "#C62828" # merah (turun)
|
| 1469 |
label = "↓"
|
| 1470 |
else:
|
| 1471 |
+
color = "#546E7A" # abu-abu (datar)
|
| 1472 |
label = "→"
|
| 1473 |
|
| 1474 |
+
# Normalisasi koordinat Y untuk SVG
|
|
|
|
| 1475 |
height = 16
|
| 1476 |
margin = 2
|
| 1477 |
usable_h = height - 2 * margin
|
| 1478 |
+
min_y, max_y = min(data), max(data)
|
| 1479 |
|
| 1480 |
if max_y == min_y:
|
| 1481 |
y_coords = [margin + usable_h / 2] * n
|
|
|
|
| 1485 |
for v in data
|
| 1486 |
]
|
| 1487 |
|
| 1488 |
+
# Buat polyline
|
| 1489 |
points = " ".join(f"{i * 8},{y:.1f}" for i, y in enumerate(y_coords))
|
| 1490 |
width = max(24, (n - 1) * 8 + 4)
|
| 1491 |
|
| 1492 |
+
# SVG inline
|
| 1493 |
svg = (
|
| 1494 |
f'<svg class="sparkline" width="{width + 6}" height="{height}" '
|
| 1495 |
+
f'viewBox="-2 0 {width + 6} {height}" style="vertical-align:middle; '
|
| 1496 |
+
f'font-family:sans-serif;" xmlns="http://www.w3.org/2000/svg">'
|
| 1497 |
f'<polyline points="{points}" fill="none" stroke="{color}" '
|
| 1498 |
f'stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>'
|
| 1499 |
+
f'<text x="{(n-1)*8 + 1}" y="14" font-size="9" fill="{color}" '
|
|
|
|
| 1500 |
f'dominant-baseline="middle">{label}</text>'
|
| 1501 |
f'</svg>'
|
| 1502 |
)
|
|
|
|
| 1504 |
|
| 1505 |
except Exception:
|
| 1506 |
return "<span class='spark' style='color:#999;'>⚠</span>"
|
| 1507 |
+
|
| 1508 |
# ——————— 1. Creators: ONLY Coverage < 90% AND Slope < 0 ———————
|
| 1509 |
def predict_creators(df):
|
| 1510 |
# ❌ Tidak ada filter Non-Positive
|