Merge pull request 'Set attitude to None if no votes cast (fixes #405)' (#410) from h3ndrik/pyfedi:attitude into main

Reviewed-on: https://codeberg.org/rimu/pyfedi/pulls/410
This commit is contained in:
rimu 2025-01-06 07:58:23 +00:00
commit 1c4452b667
5 changed files with 11 additions and 14 deletions

View file

@ -687,7 +687,7 @@ class User(UserMixin, db.Model):
bounces = db.Column(db.SmallInteger, default=0) bounces = db.Column(db.SmallInteger, default=0)
timezone = db.Column(db.String(20)) timezone = db.Column(db.String(20))
reputation = db.Column(db.Float, default=0.0) reputation = db.Column(db.Float, default=0.0)
attitude = db.Column(db.Float, default=1.0) # (upvotes cast - downvotes cast) / (upvotes + downvotes). A number between 1 and -1 is the ratio between up and down votes they cast attitude = db.Column(db.Float, default=None) # (upvotes cast - downvotes cast) / (upvotes + downvotes). A number between 1 and -1 is the ratio between up and down votes they cast
post_count = db.Column(db.Integer, default=0) post_count = db.Column(db.Integer, default=0)
post_reply_count = db.Column(db.Integer, default=0) post_reply_count = db.Column(db.Integer, default=0)
stripe_customer_id = db.Column(db.String(50)) stripe_customer_id = db.Column(db.String(50))
@ -934,13 +934,10 @@ class User(UserMixin, db.Model):
total_upvotes = upvotes + comment_upvotes total_upvotes = upvotes + comment_upvotes
total_downvotes = downvotes + comment_downvotes total_downvotes = downvotes + comment_downvotes
if total_downvotes == 0: # guard against division by zero if total_upvotes + total_downvotes > 2: # Only calculate attitude if they've done 3 or more votes as anything less than this could be an outlier and not representative of their overall attitude (also guard against division by zero)
self.attitude = 1.0
else:
if total_upvotes + total_downvotes > 2: # Only calculate attitude if they've done 3 or more votes as anything less than this could be an outlier and not representative of their overall attitude
self.attitude = (total_upvotes - total_downvotes) / (total_upvotes + total_downvotes) self.attitude = (total_upvotes - total_downvotes) / (total_upvotes + total_downvotes)
else: else:
self.attitude = 1.0 self.attitude = None
def recalculate_post_stats(self, posts=True, replies=True): def recalculate_post_stats(self, posts=True, replies=True):
if posts: if posts:

View file

@ -50,9 +50,9 @@
</button> </button>
</th> </th>
<th> <th>
<button form="searchUsers" name="sort_by_btn" value="attitude{{' ASC' if sort_by == 'attitude DESC' else ' DESC' }}" class="btn" title="{{ _('Attitude: Percentage of up votes vs. down votes the account made.') }}"> <button form="searchUsers" name="sort_by_btn" value="attitude{{' ASC' if sort_by == 'attitude DESC NULLS LAST' else ' DESC' }} NULLS LAST" class="btn" title="{{ _('Attitude: Percentage of up votes vs. down votes the account made.') }}">
{{ _('Attitude') }} {{ _('Attitude') }}
<span class="{{ 'fe fe-chevron-up' if sort_by == 'attitude ASC' }}{{ 'fe fe-chevron-down' if sort_by == 'attitude DESC' }}"></span> <span class="{{ 'fe fe-chevron-up' if sort_by == 'attitude ASC NULLS LAST' }}{{ 'fe fe-chevron-down' if sort_by == 'attitude DESC NULLS LAST' }}"></span>
</button> </button>
</th> </th>
<th> <th>
@ -77,7 +77,7 @@
{{ '<span class="red">Banned posts</span>'|safe if user.ban_posts }} {{ '<span class="red">Banned posts</span>'|safe if user.ban_posts }}
{{ '<span class="red">Banned comments</span>'|safe if user.ban_comments }}</td> {{ '<span class="red">Banned comments</span>'|safe if user.ban_comments }}</td>
<td>{{ user.reports if user.reports > 0 }} </td> <td>{{ user.reports if user.reports > 0 }} </td>
<td>{% if user.attitude != 1 %}{{ (user.attitude * 100) | round | int }}%{% endif %}</td> <td>{% if user.attitude %}{{ (user.attitude * 100) | round | int }}%{% endif %}</td>
<td>{% if user.reputation %}R {{ user.reputation | round | int }}{% endif %}</td> <td>{% if user.reputation %}R {{ user.reputation | round | int }}{% endif %}</td>
<td><span title="{{ user.last_seen }}">{{ arrow.get(user.last_seen).humanize(locale=locale) }}</span></td> <td><span title="{{ user.last_seen }}">{{ arrow.get(user.last_seen).humanize(locale=locale) }}</span></td>
<td><a href="{{ url_for('admin.admin_user_edit', user_id=user.id) }}">Edit</a>, <td><a href="{{ url_for('admin.admin_user_edit', user_id=user.id) }}">Edit</a>,

View file

@ -116,7 +116,7 @@
{% if user.bot %} {% if user.bot %}
{{ _('Bot Account') }}<br /> {{ _('Bot Account') }}<br />
{% endif %} {% endif %}
{{ _('Attitude') }}: <span title="{{ _('Ratio of upvotes cast to downvotes cast. Higher is more positive.') }}">{{ (user.attitude * 100) | round | int }}%</span><br /> {{ _('Attitude') }}: <span title="{{ _('Ratio of upvotes cast to downvotes cast. Higher is more positive.') }}">{% if user.attitude %}{{ (user.attitude * 100) | round | int }}%{% endif %}</span><br />
{% if current_user.is_authenticated and current_user.is_admin() and user.reputation %}{{ _('Reputation') }}: <span title="{{ _('Reputation: The Karma of the account. Total up votes minus down votes they got.') }}">{{ user.reputation | round | int }}</span><br />{% endif %} {% if current_user.is_authenticated and current_user.is_admin() and user.reputation %}{{ _('Reputation') }}: <span title="{{ _('Reputation: The Karma of the account. Total up votes minus down votes they got.') }}">{{ user.reputation | round | int }}</span><br />{% endif %}
{{ _('Posts') }}: {{ user.post_count }}<br /> {{ _('Posts') }}: {{ user.post_count }}<br />
{{ _('Comments') }}: {{ user.post_reply_count }}<br /> {{ _('Comments') }}: {{ user.post_reply_count }}<br />

View file

@ -22,7 +22,7 @@
{% if user.bot %} {% if user.bot %}
{{ _('Bot Account') }}<br /> {{ _('Bot Account') }}<br />
{% endif %} {% endif %}
{{ _('Attitude') }}: <span title="{{ _('Ratio of upvotes cast to downvotes cast. Higher is more positive.') }}">{{ (user.attitude * 100) | round | int }}%</span><br /> {{ _('Attitude') }}: <span title="{{ _('Ratio of upvotes cast to downvotes cast. Higher is more positive.') }}">{% if user.attitude %}{{ (user.attitude * 100) | round | int }}%{% endif %}</span><br />
{% if current_user.is_authenticated and current_user.is_admin() and user.reputation %}{{ _('Reputation') }}: <span title="{{ _('Reputation: The Karma of the account. Total up votes minus down votes they got.') }}">{{ user.reputation | round | int }}</span><br />{% endif %} {% if current_user.is_authenticated and current_user.is_admin() and user.reputation %}{{ _('Reputation') }}: <span title="{{ _('Reputation: The Karma of the account. Total up votes minus down votes they got.') }}">{{ user.reputation | round | int }}</span><br />{% endif %}
{{ _('Posts') }}: {{ user.post_count }}<br /> {{ _('Posts') }}: {{ user.post_count }}<br />
{{ _('Comments') }}: {{ user.post_reply_count }}<br /> {{ _('Comments') }}: {{ user.post_reply_count }}<br />

View file

@ -706,7 +706,7 @@ def can_downvote(user, community: Community, site=None) -> bool:
if community.local_only and not user.is_local(): if community.local_only and not user.is_local():
return False return False
if user.attitude < -0.40 or user.reputation < -10: # this should exclude about 3.7% of users. if (user.attitude and user.attitude < -0.40) or user.reputation < -10: # this should exclude about 3.7% of users.
return False return False
if community.id in communities_banned_from(user.id): if community.id in communities_banned_from(user.id):