Skip to content

Commit

Permalink
Use Weighted Rating Formula for stars sorting
Browse files Browse the repository at this point in the history
  • Loading branch information
Xpirix committed Nov 4, 2024
1 parent b8ae92a commit 9f22dc2
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 9 deletions.
42 changes: 36 additions & 6 deletions qgis-app/plugins/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
class BasePluginManager(models.Manager):
"""
Adds a score
* average_vote provides a simple average rating.
* latest_version_date fetches the date of the
most recent approved plugin version.
* weighted_rating uses the Bayesian Average formula
to provide a more balanced rating that mitigates the effect of low vote counts.
"""

def get_queryset(self):
Expand All @@ -36,13 +41,18 @@ def get_queryset(self):
.get_queryset()
.extra(
select={
"average_vote": "rating_score/(rating_votes+0.001)",
"average_vote": "rating_score / (rating_votes + 0.001)",
"latest_version_date": (
"SELECT created_on FROM plugins_pluginversion WHERE "
"plugins_pluginversion.plugin_id = plugins_plugin.id "
"AND approved = TRUE "
"ORDER BY created_on DESC LIMIT 1"
),
"weighted_rating": (
"((rating_votes::FLOAT / (rating_votes + 5)) * "
"(rating_score::FLOAT / (rating_votes + 0.001))) + "
"((5::FLOAT / (rating_votes + 5)) * 3)"
),
}
)
)
Expand Down Expand Up @@ -172,12 +182,17 @@ def get_queryset(self):
.filter(pluginversion__approved=False, deprecated=False)
.extra(
select={
"average_vote": "rating_score/(rating_votes+0.001)",
"average_vote": "rating_score / (rating_votes + 0.001)",
"latest_version_date": (
"SELECT created_on FROM plugins_pluginversion WHERE "
"plugins_pluginversion.plugin_id = plugins_plugin.id "
"ORDER BY created_on DESC LIMIT 1"
),
"weighted_rating": (
"((rating_votes::FLOAT / (rating_votes + 5)) * "
"(rating_score::FLOAT / (rating_votes + 0.001))) + "
"((5::FLOAT / (rating_votes + 5)) * 3)"
),
}
)
.distinct()
Expand Down Expand Up @@ -258,7 +273,7 @@ def get_queryset(self):
super(MostRatedPlugins, self)
.get_queryset()
.filter(deprecated=False)
.order_by("-average_vote")
.order_by("-weighted_rating")
.distinct()
)

Expand Down Expand Up @@ -314,12 +329,17 @@ def get_queryset(self):
)
.extra(
select={
"average_vote": "rating_score/(rating_votes+0.001)",
"average_vote": "rating_score / (rating_votes + 0.001)",
"latest_version_date": (
"SELECT created_on FROM plugins_pluginversion WHERE "
"plugins_pluginversion.plugin_id = plugins_plugin.id "
"ORDER BY created_on DESC LIMIT 1"
),
"weighted_rating": (
"((rating_votes::FLOAT / (rating_votes + 5)) * "
"(rating_score::FLOAT / (rating_votes + 0.001))) + "
"((5::FLOAT / (rating_votes + 5)) * 3)"
),
}
).distinct()
)
Expand Down Expand Up @@ -351,12 +371,17 @@ def get_queryset(self):
)
.extra(
select={
"average_vote": "rating_score/(rating_votes+0.001)",
"average_vote": "rating_score / (rating_votes + 0.001)",
"latest_version_date": (
"SELECT created_on FROM plugins_pluginversion WHERE "
"plugins_pluginversion.plugin_id = plugins_plugin.id "
"ORDER BY created_on DESC LIMIT 1"
),
"weighted_rating": (
"((rating_votes::FLOAT / (rating_votes + 5)) * "
"(rating_score::FLOAT / (rating_votes + 0.001))) + "
"((5::FLOAT / (rating_votes + 5)) * 3)"
),
}
).distinct()
)
Expand All @@ -382,12 +407,17 @@ def get_queryset(self):
)
.extra(
select={
"average_vote": "rating_score/(rating_votes+0.001)",
"average_vote": "rating_score / (rating_votes + 0.001)",
"latest_version_date": (
"SELECT created_on FROM plugins_pluginversion WHERE "
"plugins_pluginversion.plugin_id = plugins_plugin.id "
"ORDER BY created_on DESC LIMIT 1"
),
"weighted_rating": (
"((rating_votes::FLOAT / (rating_votes + 5)) * "
"(rating_score::FLOAT / (rating_votes + 0.001))) + "
"((5::FLOAT / (rating_votes + 5)) * 3)"
),
}
).distinct()
)
Expand Down
8 changes: 7 additions & 1 deletion qgis-app/plugins/templates/plugins/plugin_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,13 @@ <h2 class="title is-4">{% if title %}{{title}}{% else %}{% trans "All plugins" %
{% endif %}
<td>{{ object.latest_version_date|local_timezone:"SHORT_NATURAL_DAY" }}</td>
<td>{{ object.created_on|local_timezone:"SHORT" }}</td>
<td><div><div class="star-ratings"><span style="width:{% widthratio object.average_vote 5 100 %}%" class="rating"></span></div> ({{ object.rating_votes }})</div></td>
<td>
<div>
<div class="star-ratings">
<span style="width:{% widthratio object.average_vote 5 100 %}%" class="rating"></span>
</div> ({{ object.rating_votes }})
</div>
</td>

<td>{% if object.stable %}<a href="{% url "version_download" object.package_name object.stable.version %}" title="{% trans "Download the stable version" %}" >{{ object.stable.version }}</a>{% else %}&mdash;{% endif %}</td>
<td>{% if object.experimental %}<a href="{% url "version_download" object.package_name object.experimental.version %}" title="{% trans "Download the experimental version" %}" >{{ object.experimental.version }}</a>{% else %}&mdash;{% endif %}</td>
Expand Down
2 changes: 1 addition & 1 deletion qgis-app/plugins/templates/plugins/plugin_list_sort.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<option value="downloads" {% if request.GET.sort == 'downloads' %}selected{% endif %}>{% trans "Downloads" %}</option>
<option value="author" {% if request.GET.sort == 'author' %}selected{% endif %}>{% trans "Author" %}</option>
<option value="latest_version_date" {% if request.GET.sort == 'latest_version_date' %}selected{% endif %}>{% trans "Latest Version" %}</option>
<option value="average_vote" {% if request.GET.sort == 'average_vote' %}selected{% endif %}>{% trans "Stars" %}</option>
<option value="weighted_rating" {% if request.GET.sort == 'weighted_rating' %}selected{% endif %}>{% trans "Stars" %}</option>
</select>
</span>
</p>
Expand Down
2 changes: 1 addition & 1 deletion qgis-app/plugins/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,7 @@ def get_queryset(self):
sort_by = '-' + sort_by # Prepend '-' to sort in descending order

# Validate the sort field
if sort_by.lstrip('-') in ['average_vote', 'latest_version_date'] or self._is_valid_field(sort_by.lstrip('-')):
if sort_by.lstrip('-') in ['average_vote', 'latest_version_date', 'weighted_rating'] or self._is_valid_field(sort_by.lstrip('-')):
qs = qs.order_by(sort_by)
elif not qs.ordered:
qs = qs.order_by(Lower("name"))
Expand Down

0 comments on commit 9f22dc2

Please sign in to comment.