adding availability
Some checks failed
Build and Deploy (internal) / Build Transmission Manager Image (push) Failing after 0s
Build and Deploy (internal) / Deploy Transmission Manager (internal) (push) Has been skipped

This commit is contained in:
2026-07-08 20:01:02 -03:00
parent a57002bf44
commit 7d1b868107
4 changed files with 59 additions and 10 deletions

View File

@@ -250,9 +250,50 @@ function activitySpeed(t) {
return (t.rateDownload || 0) + (t.rateUpload || 0);
}
function availabilityValue(t) {
if (typeof t.availability === "number" && Number.isFinite(t.availability)) {
return t.availability;
}
const pieces = Array.isArray(t.availability) ? t.availability : [];
if (!pieces.length) return null;
const counts = [];
let min = Infinity;
for (const piece of pieces) {
const raw = Number(piece);
if (!Number.isFinite(raw)) continue;
const count = raw < 0 ? 1 : raw;
counts.push(count);
if (count < min) min = count;
}
if (!counts.length) return null;
let aboveMin = 0;
for (const count of counts) {
if (count > min) aboveMin += 1;
}
return min + (aboveMin / counts.length);
}
function availabilitySortValue(t) {
const value = availabilityValue(t);
return value == null ? -1 : value;
}
function humanAvailability(value) {
if (value == null || !Number.isFinite(value) || value < 0) return "—";
return `${value.toFixed(value < 10 ? 2 : 1)}x`;
}
function sortTorrents(list) {
const key = state.sortKey;
const sorted = list.slice();
const availabilityValues = key === "availability"
? new Map(sorted.map((t) => [t, availabilitySortValue(t)]))
: null;
sorted.sort((a, b) => {
switch (key) {
case "name":
@@ -268,14 +309,10 @@ function sortTorrents(list) {
|| ((b.rateDownload || 0) - (a.rateDownload || 0))
|| ((b.rateUpload || 0) - (a.rateUpload || 0))
|| compareName(a, b);
case "peer100": {
const pa = peerStatus(a);
const pb = peerStatus(b);
return (pb.at100 - pa.at100)
|| (pb.connected - pa.connected)
case "availability":
return (availabilityValues.get(b) - availabilityValues.get(a))
|| ((b.percentDone || 0) - (a.percentDone || 0))
|| compareName(a, b);
}
case "status": {
const ra = STATUS_RANK[classify(a).key] ?? 99;
const rb = STATUS_RANK[classify(b).key] ?? 99;
@@ -359,6 +396,10 @@ function createCard() {
<span class="k">ETA</span>
<span class="v" data-field="eta"></span>
</div>
<div class="stat-cell">
<span class="k">Availability</span>
<span class="v mono" data-field="availability"></span>
</div>
<div class="stat-cell">
<span class="k">Peers @ 100%</span>
<span class="v mono" data-field="peers-100"></span>
@@ -397,6 +438,7 @@ function updateCard(card, t) {
const pctText = (pct * 100).toFixed(pct === 1 ? 0 : 1) + "%";
const isDone = pct >= 1.0;
const ps = peerStatus(t);
const availability = availabilityValue(t);
const dl = t.rateDownload || 0;
const ul = t.rateUpload || 0;
const eta = (dl > 0 && !isDone) ? formatETA(t.eta) : (isDone ? "—" : "∞");
@@ -444,6 +486,11 @@ function updateCard(card, t) {
setValueClass(ulEl, ul > 0 ? "success" : "dim");
setText(field(card, "eta"), eta);
const availabilityEl = field(card, "availability");
setText(availabilityEl, humanAvailability(availability));
setValueClass(availabilityEl, availability == null ? "dim" : availability >= 1 ? "success" : "warn");
setText(field(card, "peers-100"), `${ps.at100}/${ps.connected}`);
setText(field(card, "finished"), formatDate(t.doneDate));

View File

@@ -54,7 +54,7 @@
<button class="sort-btn" data-sort="ratio">Ratio</button>
<button class="sort-btn" data-sort="size">Size</button>
<button class="sort-btn" data-sort="speed">Speed</button>
<button class="sort-btn" data-sort="peer100">100% Peers</button>
<button class="sort-btn" data-sort="availability">Availability</button>
</div>
<div class="toolbar-actions">
<label class="interval-control" for="refresh-interval">