mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-08-21 05:43:32 -07:00
Add importance metric
Importance is a useful metric for tracking which torrents are more important to keep and which can be 'safely' discarded, as it is not helpful to delete unpopular torrents if there is only a handful of seeds.
This commit is contained in:
parent
b79ac0d716
commit
29be2c350a
15 changed files with 95 additions and 0 deletions
|
@ -282,6 +282,7 @@ namespace BitTorrent
|
|||
virtual int maxInactiveSeedingTime() const = 0;
|
||||
virtual qreal realRatio() const = 0;
|
||||
virtual qreal popularity() const = 0;
|
||||
virtual qreal importance() const = 0;
|
||||
virtual int uploadPayloadRate() const = 0;
|
||||
virtual int downloadPayloadRate() const = 0;
|
||||
virtual qlonglong totalPayloadUpload() const = 0;
|
||||
|
|
|
@ -1563,6 +1563,25 @@ qreal TorrentImpl::popularity() const
|
|||
return (activeMonths > 0) ? (realRatio() / activeMonths) : 0;
|
||||
}
|
||||
|
||||
qreal TorrentImpl::importance() const
|
||||
{
|
||||
// Popularity divided by seed count is a much better measure of how important you are as a seed for a torrent than popularity alone
|
||||
const qreal pop = popularity();
|
||||
const int seeds = totalSeedsCount();
|
||||
|
||||
if (seeds > 0)
|
||||
{
|
||||
return pop / seeds;
|
||||
}
|
||||
|
||||
if (pop > 0)
|
||||
{
|
||||
return Torrent::MAX_RATIO;
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void TorrentImpl::setName(const QString &name)
|
||||
{
|
||||
if (m_name != name)
|
||||
|
|
|
@ -209,6 +209,7 @@ namespace BitTorrent
|
|||
int maxInactiveSeedingTime() const override;
|
||||
qreal realRatio() const override;
|
||||
qreal popularity() const override;
|
||||
qreal importance() const override;
|
||||
int uploadPayloadRate() const override;
|
||||
int downloadPayloadRate() const override;
|
||||
qlonglong totalPayloadUpload() const override;
|
||||
|
|
|
@ -227,6 +227,7 @@ void PropertiesWidget::clear()
|
|||
m_ui->labelReannounceInVal->clear();
|
||||
m_ui->labelShareRatioVal->clear();
|
||||
m_ui->labelPopularityVal->clear();
|
||||
m_ui->labelImportanceVal->clear();
|
||||
m_ui->listWebSeeds->clear();
|
||||
m_ui->labelETAVal->clear();
|
||||
m_ui->labelSeedsVal->clear();
|
||||
|
@ -446,6 +447,9 @@ void PropertiesWidget::loadDynamicData()
|
|||
const qreal popularity = m_torrent->popularity();
|
||||
m_ui->labelPopularityVal->setText(popularity >= BitTorrent::Torrent::MAX_RATIO ? C_INFINITY : Utils::String::fromDouble(popularity, 2));
|
||||
|
||||
const qreal importance = m_torrent->importance();
|
||||
m_ui->labelImportanceVal->setText(importance >= BitTorrent::Torrent::MAX_RATIO ? C_INFINITY : Utils::String::fromDouble(importance, 2));
|
||||
|
||||
m_ui->labelSeedsVal->setText(tr("%1 (%2 total)", "%1 and %2 are numbers, e.g. 3 (10 total)")
|
||||
.arg(QString::number(m_torrent->seedsCount())
|
||||
, QString::number(m_torrent->totalSeedsCount())));
|
||||
|
|
|
@ -633,6 +633,41 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="labelImportance">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Popularity / Total Seeds, shows how important the specific seeder is.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Importance:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3">
|
||||
<widget class="QLabel" name="labelImportanceVal">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Popularity / Total Seeds, shows how important the specific seeder is.</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::TextFormat::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -168,6 +168,7 @@ QVariant TransferListModel::headerData(const int section, const Qt::Orientation
|
|||
case TR_UPSPEED: return tr("Up Speed", "i.e: Upload speed");
|
||||
case TR_RATIO: return tr("Ratio", "Share ratio");
|
||||
case TR_POPULARITY: return tr("Popularity");
|
||||
case TR_IMPORTANCE: return tr("Importance");
|
||||
case TR_ETA: return tr("ETA", "i.e: Estimated Time of Arrival / Time left");
|
||||
case TR_CATEGORY: return tr("Category");
|
||||
case TR_TAGS: return tr("Tags");
|
||||
|
@ -202,6 +203,7 @@ QVariant TransferListModel::headerData(const int section, const Qt::Orientation
|
|||
switch (section)
|
||||
{
|
||||
case TR_POPULARITY: return tr("Ratio / Time Active (in months), indicates how popular the torrent is");
|
||||
case TR_IMPORTANCE: return tr("Popularity / Total Seeds, shows how important the specific seeder is.");
|
||||
default: return {};
|
||||
}
|
||||
}
|
||||
|
@ -227,6 +229,7 @@ QVariant TransferListModel::headerData(const int section, const Qt::Orientation
|
|||
case TR_RATIO_LIMIT:
|
||||
case TR_RATIO:
|
||||
case TR_POPULARITY:
|
||||
case TR_IMPORTANCE:
|
||||
case TR_QUEUE_POSITION:
|
||||
case TR_LAST_ACTIVITY:
|
||||
case TR_AVAILABILITY:
|
||||
|
@ -395,6 +398,8 @@ QString TransferListModel::displayValue(const BitTorrent::Torrent *torrent, cons
|
|||
return ratioString(torrent->maxRatio());
|
||||
case TR_POPULARITY:
|
||||
return ratioString(torrent->popularity());
|
||||
case TR_IMPORTANCE:
|
||||
return ratioString(torrent->importance());
|
||||
case TR_CATEGORY:
|
||||
return torrent->category();
|
||||
case TR_TAGS:
|
||||
|
@ -476,6 +481,8 @@ QVariant TransferListModel::internalValue(const BitTorrent::Torrent *torrent, co
|
|||
return torrent->realRatio();
|
||||
case TR_POPULARITY:
|
||||
return torrent->popularity();
|
||||
case TR_IMPORTANCE:
|
||||
return torrent->importance();
|
||||
case TR_CATEGORY:
|
||||
return torrent->category();
|
||||
case TR_TAGS:
|
||||
|
@ -588,6 +595,7 @@ QVariant TransferListModel::data(const QModelIndex &index, const int role) const
|
|||
case TR_RATIO_LIMIT:
|
||||
case TR_RATIO:
|
||||
case TR_POPULARITY:
|
||||
case TR_IMPORTANCE:
|
||||
case TR_QUEUE_POSITION:
|
||||
case TR_LAST_ACTIVITY:
|
||||
case TR_AVAILABILITY:
|
||||
|
|
|
@ -63,6 +63,7 @@ public:
|
|||
TR_ETA,
|
||||
TR_RATIO,
|
||||
TR_POPULARITY,
|
||||
TR_IMPORTANCE,
|
||||
TR_CATEGORY,
|
||||
TR_TAGS,
|
||||
TR_ADD_DATE,
|
||||
|
|
|
@ -210,6 +210,9 @@ int TransferListSortModel::compare(const QModelIndex &left, const QModelIndex &r
|
|||
case TransferListModel::TR_POPULARITY:
|
||||
return customCompare(leftValue.toReal(), rightValue.toReal());
|
||||
|
||||
case TransferListModel::TR_IMPORTANCE:
|
||||
return customCompare(leftValue.toReal(), rightValue.toReal());
|
||||
|
||||
case TransferListModel::TR_STATUS:
|
||||
return threeWayCompare(leftValue.toInt(), rightValue.toInt());
|
||||
|
||||
|
|
|
@ -187,6 +187,7 @@ TransferListWidget::TransferListWidget(IGUIApplication *app, QWidget *parent)
|
|||
setColumnHidden(TransferListModel::TR_COMPLETED, true);
|
||||
setColumnHidden(TransferListModel::TR_RATIO_LIMIT, true);
|
||||
setColumnHidden(TransferListModel::TR_POPULARITY, true);
|
||||
setColumnHidden(TransferListModel::TR_IMPORTANCE, true);
|
||||
setColumnHidden(TransferListModel::TR_SEEN_COMPLETE_DATE, true);
|
||||
setColumnHidden(TransferListModel::TR_LAST_ACTIVITY, true);
|
||||
setColumnHidden(TransferListModel::TR_TOTAL_SIZE, true);
|
||||
|
|
|
@ -154,6 +154,7 @@ QVariantMap serialize(const BitTorrent::Torrent &torrent)
|
|||
{KEY_TORRENT_RATIO, adjustRatio(torrent.realRatio())},
|
||||
{KEY_TORRENT_RATIO_LIMIT, torrent.ratioLimit()},
|
||||
{KEY_TORRENT_POPULARITY, torrent.popularity()},
|
||||
{KEY_TORRENT_IMPORTANCE, torrent.importance()},
|
||||
{KEY_TORRENT_SEEDING_TIME_LIMIT, torrent.seedingTimeLimit()},
|
||||
{KEY_TORRENT_INACTIVE_SEEDING_TIME_LIMIT, torrent.inactiveSeedingTimeLimit()},
|
||||
{KEY_TORRENT_LAST_SEEN_COMPLETE_TIME, Utils::DateTime::toSecsSinceEpoch(torrent.lastSeenComplete())},
|
||||
|
|
|
@ -55,6 +55,7 @@ inline const QString KEY_TORRENT_LEECHS = u"num_leechs"_s;
|
|||
inline const QString KEY_TORRENT_NUM_INCOMPLETE = u"num_incomplete"_s;
|
||||
inline const QString KEY_TORRENT_RATIO = u"ratio"_s;
|
||||
inline const QString KEY_TORRENT_POPULARITY = u"popularity"_s;
|
||||
inline const QString KEY_TORRENT_IMPORTANCE = u"importance"_s;
|
||||
inline const QString KEY_TORRENT_ETA = u"eta"_s;
|
||||
inline const QString KEY_TORRENT_STATE = u"state"_s;
|
||||
inline const QString KEY_TORRENT_SEQUENTIAL_DOWNLOAD = u"seq_dl"_s;
|
||||
|
|
|
@ -98,6 +98,7 @@ const QString KEY_PROP_PEERS = u"peers"_s;
|
|||
const QString KEY_PROP_PEERS_TOTAL = u"peers_total"_s;
|
||||
const QString KEY_PROP_RATIO = u"share_ratio"_s;
|
||||
const QString KEY_PROP_POPULARITY = u"popularity"_s;
|
||||
const QString KEY_PROP_IMPORTANCE = u"importance"_s;
|
||||
const QString KEY_PROP_REANNOUNCE = u"reannounce"_s;
|
||||
const QString KEY_PROP_TOTAL_SIZE = u"total_size"_s;
|
||||
const QString KEY_PROP_PIECES_NUM = u"pieces_num"_s;
|
||||
|
@ -459,6 +460,7 @@ void TorrentsController::infoAction()
|
|||
// - "peers_total": Torrent total number of peers
|
||||
// - "share_ratio": Torrent share ratio
|
||||
// - "popularity": Torrent popularity
|
||||
// - "importance": Torrent importance
|
||||
// - "reannounce": Torrent next reannounce time
|
||||
// - "total_size": Torrent total size
|
||||
// - "pieces_num": Torrent pieces count
|
||||
|
@ -494,6 +496,7 @@ void TorrentsController::propertiesAction()
|
|||
const int uploadLimit = torrent->uploadLimit();
|
||||
const qreal ratio = torrent->realRatio();
|
||||
const qreal popularity = torrent->popularity();
|
||||
const qreal importance = torrent->importance();
|
||||
const bool hasMetadata = torrent->hasMetadata();
|
||||
const bool isPrivate = torrent->isPrivate();
|
||||
|
||||
|
@ -525,6 +528,7 @@ void TorrentsController::propertiesAction()
|
|||
{KEY_PROP_PEERS_TOTAL, torrent->totalLeechersCount()},
|
||||
{KEY_PROP_RATIO, ((ratio >= BitTorrent::Torrent::MAX_RATIO) ? -1 : ratio)},
|
||||
{KEY_PROP_POPULARITY, ((popularity >= BitTorrent::Torrent::MAX_RATIO) ? -1 : popularity)},
|
||||
{KEY_PROP_IMPORTANCE, ((importance >= BitTorrent::Torrent::MAX_RATIO) ? -1 : importance)},
|
||||
{KEY_PROP_REANNOUNCE, torrent->nextAnnounce()},
|
||||
{KEY_PROP_TOTAL_SIZE, torrent->totalSize()},
|
||||
{KEY_PROP_PIECES_NUM, torrent->piecesCount()},
|
||||
|
|
|
@ -1124,6 +1124,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
this.newColumn("eta", "", "QBT_TR(ETA)QBT_TR[CONTEXT=TransferListModel]", 100, true);
|
||||
this.newColumn("ratio", "", "QBT_TR(Ratio)QBT_TR[CONTEXT=TransferListModel]", 100, true);
|
||||
this.newColumn("popularity", "", "QBT_TR(Popularity)QBT_TR[CONTEXT=TransferListModel]", 100, true);
|
||||
this.newColumn("importance", "", "QBT_TR(Importance)QBT_TR[CONTEXT=TransferListModel]", 100, true);
|
||||
this.newColumn("category", "", "QBT_TR(Category)QBT_TR[CONTEXT=TransferListModel]", 100, true);
|
||||
this.newColumn("tags", "", "QBT_TR(Tags)QBT_TR[CONTEXT=TransferListModel]", 100, true);
|
||||
this.newColumn("added_on", "", "QBT_TR(Added On)QBT_TR[CONTEXT=TransferListModel]", 100, true);
|
||||
|
@ -1447,6 +1448,14 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
td.title = popularity;
|
||||
};
|
||||
|
||||
// importance
|
||||
this.columns["importance".updateId] = function(td, row) {
|
||||
const value = this.getRowValue(row);
|
||||
const importance = (value === -1) ? "∞" : window.qBittorrent.Misc.toFixedPointString(value, 2);
|
||||
td.textContent = importance;
|
||||
td.title = importance;
|
||||
};
|
||||
|
||||
// added on
|
||||
this.columns["added_on"].updateTd = function(td, row) {
|
||||
const date = new Date(this.getRowValue(row) * 1000).toLocaleString();
|
||||
|
|
|
@ -58,6 +58,7 @@ window.qBittorrent.PropGeneral ??= (() => {
|
|||
document.getElementById("peers").textContent = "";
|
||||
document.getElementById("share_ratio").textContent = "";
|
||||
document.getElementById("popularity").textContent = "";
|
||||
document.getElementById("importance").textContent = "";
|
||||
document.getElementById("reannounce").textContent = "";
|
||||
document.getElementById("last_seen").textContent = "";
|
||||
document.getElementById("total_size").textContent = "";
|
||||
|
@ -174,6 +175,8 @@ window.qBittorrent.PropGeneral ??= (() => {
|
|||
|
||||
document.getElementById("popularity").textContent = data.popularity.toFixed(2);
|
||||
|
||||
document.getElementById("importance").textContent = data.importance.toFixed(2);
|
||||
|
||||
document.getElementById("reannounce").textContent = window.qBittorrent.Misc.friendlyDuration(data.reannounce);
|
||||
|
||||
const lastSeen = (data.last_seen >= 0)
|
||||
|
|
|
@ -53,6 +53,10 @@
|
|||
<td class="generalLabel" title="QBT_TR(Ratio / Time Active (in months), indicates how popular the torrent is)QBT_TR[CONTEXT=PropertiesWidget]">QBT_TR(Popularity:)QBT_TR[CONTEXT=PropertiesWidget]</td>
|
||||
<td id="popularity" title="QBT_TR(Ratio / Time Active (in months), indicates how popular the torrent is)QBT_TR[CONTEXT=PropertiesWidget]"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="generalLabel" title="QBT_TR(Popularity / Total Seeds (Higher number implies it is more 'important' to seed the torrent))QBT_TR[CONTEXT=PropertiesWidget]">QBT_TR(Importance:)QBT_TR[CONTEXT=PropertiesWidget]</td>
|
||||
<td id="importance" title="QBT_TR(Popularity / Total Seeds (Higher number implies it is more 'important' to seed the torrent))QBT_TR[CONTEXT=PropertiesWidget]"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue