add: great post average

This commit is contained in:
trisua 2025-06-09 20:56:32 -04:00
parent 11fb131b8b
commit 15dc2e5d71
5 changed files with 122 additions and 0 deletions

View file

@ -510,6 +510,80 @@ impl DataManager {
Ok(res.unwrap())
}
/// Calculate the GPA (great post average) of a given user.
///
/// To be considered a "great post", a post must have a score ((likes - dislikes) / (likes + dislikes))
/// of at least 0.6.
///
/// GPA is calculated based on the user's last 250 posts.
pub async fn calculate_user_gpa(&self, id: usize) -> usize {
// just for note, this is SUPER bad for performance... which is why we
// only calculate this when it expires in the cache (every week)
if let Some(cached) = self.0.1.get(format!("atto.user.gpa:{}", id)).await {
if let Ok(c) = cached.parse() {
return c;
}
}
// ...
let conn = match self.0.connect().await {
Ok(c) => c,
Err(_) => return 0,
};
let res = query_rows!(
&conn,
&format!("SELECT * FROM posts WHERE owner = $1 ORDER BY created DESC LIMIT 250",),
&[&(id as i64)],
|x| { Self::get_post_from_row(x) }
);
if res.is_err() {
return 0;
}
// ...
let mut real_posts_count: usize = 0; // posts which can be scored
let mut good_posts: usize = 0;
// let mut bad_posts: usize = 0;
let posts = res.unwrap();
for post in posts {
if post.likes == 0 && post.dislikes == 0 {
// post has no likes or dislikes... doesn't count
continue;
}
real_posts_count += 1;
// likes percentage / total likes
let score: f32 = (post.likes as f32 - post.dislikes as f32)
/ (post.likes as f32 + post.dislikes as f32);
if score.is_sign_negative() {
// bad_posts += 1;
continue;
}
if score > 0.6 {
good_posts += 1;
}
// } else {
// bad_posts += 1;
// }
}
let gpa = ((good_posts as f32 / real_posts_count as f32) * 4.0).round() as usize;
self.0
.1
.set(format!("atto.user.gpa:{}", id), gpa.to_string())
.await;
gpa
}
/// Get all replies from the given user (from most recent).
///
/// # Arguments