repeaters and room servers in stats

This commit is contained in:
ajvpot
2025-08-23 07:40:04 +02:00
parent de010fc4ac
commit 8382a583a5
2 changed files with 36 additions and 24 deletions

View File

@@ -12,7 +12,7 @@ export async function GET(req: Request) {
const query = `
WITH all_nodes AS (
SELECT toDate(ingest_timestamp) AS day, public_key, latitude, longitude
SELECT toDate(ingest_timestamp) AS day, public_key, latitude, longitude, is_repeater, is_room_server
FROM meshcore_adverts
${regionWhereClause}
),
@@ -25,14 +25,18 @@ export async function GET(req: Request) {
d.day,
n.public_key,
n.latitude,
n.longitude
n.longitude,
n.is_repeater,
n.is_room_server
FROM all_days d
INNER JOIN all_nodes n ON n.day BETWEEN (d.day - INTERVAL 6 DAY) AND d.day
)
SELECT day,
count(DISTINCT public_key) AS cumulative_unique_nodes,
count(DISTINCT CASE WHEN latitude IS NOT NULL AND longitude IS NOT NULL THEN public_key END) AS nodes_with_location,
count(DISTINCT CASE WHEN latitude IS NULL OR longitude IS NULL THEN public_key END) AS nodes_without_location
count(DISTINCT CASE WHEN latitude IS NOT NULL AND longitude IS NOT NULL AND latitude != 0 AND longitude != 0 THEN public_key END) AS nodes_with_location,
count(DISTINCT CASE WHEN latitude IS NULL OR longitude IS NULL OR latitude = 0 OR longitude = 0 THEN public_key END) AS nodes_without_location,
count(DISTINCT CASE WHEN is_repeater = 1 THEN public_key END) AS repeaters,
count(DISTINCT CASE WHEN is_room_server = 1 THEN public_key END) AS room_servers
FROM rolling_window
GROUP BY day
ORDER BY day ASC
@@ -42,7 +46,9 @@ export async function GET(req: Request) {
day: string,
cumulative_unique_nodes: number,
nodes_with_location: number,
nodes_without_location: number
nodes_without_location: number,
repeaters: number,
room_servers: number
}>;
return NextResponse.json({ data: rows });
} catch (error) {

View File

@@ -64,26 +64,32 @@ export default function StatsPage() {
<p className="text-sm text-gray-600 dark:text-gray-400 mb-3">
Shows nodes heard within the last 7 days by date.
</p>
<table className="w-full text-sm border">
<thead>
<tr>
<th className="border px-2 py-1">Day</th>
<th className="border px-2 py-1">Total Nodes</th>
<th className="border px-2 py-1">With Location</th>
<th className="border px-2 py-1">Without Location</th>
</tr>
</thead>
<tbody>
{nodesOverTime.map((row, i) => (
<tr key={i}>
<td className="border px-2 py-1">{row.day}</td>
<td className="border px-2 py-1">{row.cumulative_unique_nodes}</td>
<td className="border px-2 py-1">{row.nodes_with_location}</td>
<td className="border px-2 py-1">{row.nodes_without_location}</td>
<div className="w-full overflow-x-auto">
<table className="w-full text-sm border rounded">
<thead>
<tr className="bg-gray-100 dark:bg-gray-800 font-semibold">
<th className="border px-3 py-2 text-center min-w-[120px]">Day</th>
<th className="border px-3 py-2 text-center">Total Nodes</th>
<th className="border px-3 py-2 text-center">With Location</th>
<th className="border px-3 py-2 text-center">Without Location</th>
<th className="border px-3 py-2 text-center">Repeaters</th>
<th className="border px-3 py-2 text-center">Room Servers</th>
</tr>
))}
</tbody>
</table>
</thead>
<tbody>
{nodesOverTime.map((row, i) => (
<tr key={i} className="border-t">
<td className="border px-3 py-2 text-center min-w-[120px]">{row.day}</td>
<td className="border px-3 py-2 text-center">{row.cumulative_unique_nodes}</td>
<td className="border px-3 py-2 text-center">{row.nodes_with_location}</td>
<td className="border px-3 py-2 text-center">{row.nodes_without_location}</td>
<td className="border px-3 py-2 text-center">{row.repeaters}</td>
<td className="border px-3 py-2 text-center">{row.room_servers}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
<div className="mb-6">