Scratch Projects Forum
Abetment
»
Site Suggestions
»
Rating system
Username:
1 Hour
1 Day
1 Week
1 Month
Forever
Password:
Home
Help
Search
Quick Search
Advanced Search
[Close]
Login
Register
Pages: [
1
]
« previous
next »
Print
Author
Topic: Rating system (Read 5526 times)
Nathan
n00b
Karma: +0/-0
Posts: 27
Rating system
«
on:
April 16, 2006, 06:06:05 PM »
It makes sense to have the 'most popular' list being weighted by time, but since it's Score/Days, for an old article to remain in the top list, it will have to the same number of votes
each day
just to maintain its current position (unless I'm reasoning about this formula wrong). I hope you continue to get quality articles so the ancient stuff isn't your best stuff, but while this weighting system will serve to keep the best-of list fresh, it won't really be an accurate reporting of what is most popular.
As a numerical example, let's say that on the first day an article is released, it gets 5 votes. So at the end of the day, its score is 5/1 = 5. Assume the number of votes it gets drops off by 1 each day with a minimum of 1. The progression will go:
05/01 = 5
09/02 = 4.5
12/03 = 4
14/04 = 3.5
15/05 = 3
16/06 = 2 2/3
17/07 = 2.42
As you can see, even though the article continues to be quite popular, its rating drops off by .5 per day until day 5, after which it continues to drop off but at a lower rate. After a week, an article that only gets three votes on its first day will appear to be more popular than the article with 17 votes!
You could maybe maintain a list of "the best of the last 30 days" on the front page and then have an "all-time best" link on the sidebar, maybe. Or have your article search sortable by rank.
Logged
Kevin
Administrator
31337
Karma: +1/-0
Posts: 137
Rating system
«
Reply #1 on:
April 16, 2006, 09:58:26 PM »
Yeah, I definately see what you're saying. I'm going to have to play with the algorithm a little bit. I think the new one will base the penalty not on the age of the article but on the age of the vote. That way if two articles are the same age, 10 votes today will be worth more than 10 votes yesterday. I'm thinking something similar to:
SUM ([Value of Vote] / (([Age of Vote] + 1) ^ 0.5))
Logged
Kevin
Scratch Projects
Kevin
Administrator
31337
Karma: +1/-0
Posts: 137
Rating system
«
Reply #2 on:
April 16, 2006, 09:59:22 PM »
By the way... thanks for showing my why instead of just telling me what. I like that you gave some reasoning behind your request.
Logged
Kevin
Scratch Projects
Nathan
n00b
Karma: +0/-0
Posts: 27
Rating system
«
Reply #3 on:
April 17, 2006, 12:47:34 AM »
That new algorithm should help things a little. Using the same example I gave before, we get:
Day 0: 5 votes, with a score of 10
Day 1: 9 votes, with a score of 13
Day 2: 12 votes, with a score of 13 1/3
Day 3: 14 votes, with a score of 12 1/6
Day 4: 15 votes, with a score of 10
Day 5: 16 votes, with a score of 9.1
Day 6: 17 votes, with a score of 8.628
It is worth noting that fresh votes count double, so if I modified my example to say that the hypothetical article got no votes on days 6 and 7, the end would look like this:
Day 5: 15 votes, with a score of 7.1
Day 6: 15 votes, with a score of 5.628
The new algorithm does keep things a little more stable, but articles really depend on fresh votes to keep them up in the ratings. Just an observation. This issue could be solved by modifying the way age is calculated so that new votes are automatically given an age of 1 (I am assuming they are given an age of 0). I would also suggest not starting the decay immediately. For example, define the value μ(x) to be 1 if x <= δ, or x-δ otherwise.
If you take my previous example and extend it to 9 days, with the last three votes being 0, and set δ to 6 here are the results:
Day 0: 5 votes, with a score of 5
Day 1: 9 votes, with a score of 9
Day 2: 12 votes, with a score of 12
Day 3: 14 votes, with a score of 14
Day 4: 15 votes, with a score of 15
Day 5: 16 votes, with a score of 16
Day 6: 17 votes, with a score of 17
Day 7: 17 votes, with a score of 17
Day 8: 17 votes, with a score of 15 1/3
Day 9: 17 votes, with a score of 13 1/6
As you can see, the score increases linearly up with the number of votes until it reaches δ, at which point it starts decreasing slightly as old votes are devalued. This method still suffers a fairly steep dropoff, but not as steep as before.
I don't know if this method is too complex or not, but it's what I came up with off the top of my head.
Logged
Nathan
n00b
Karma: +0/-0
Posts: 27
Rating system
«
Reply #4 on:
April 17, 2006, 12:51:06 AM »
By the way, I used the following ruby code to come up with those numbers
Code:
def f(nvotes, age)
nvotes/((mu(age, 6) + 1)/2.0)
end
def mu(x, delta)
if x <= delta
return 1
end
x - delta
end
votes = [5,4,3,2,1,1,1,0,0,0]
0.upto(votes.length-1){ |x|
val = 0
sum = 0
0.upto(x){ |y|
val += f(votes[x-y],y.to_f)
sum += votes[x-y]
}
puts "Day #{x}:\t#{sum} votes, with a score of #{val}"
}
Feel free to play around with it yourself.
Logged
sparks
31337
Karma: +0/-0
Posts: 113
Rating system
«
Reply #5 on:
April 17, 2006, 12:03:00 PM »
hello and welcome nathan! also i would like to see how many votes a article has can you make it happen kevin? :lol:
Logged
Kevin
Administrator
31337
Karma: +1/-0
Posts: 137
Rating system
«
Reply #6 on:
April 17, 2006, 03:51:38 PM »
Actually sparks, Nathan wrote our first article for us, so he's the equivalant of a veteran (if we could even have such things). Before I start displaying the scores, let me get the algorithm completely worked out first.
I'm trying to get SQL to do all the work for me so that way the query returns only the number of rows we need. I intentionally want fresh votes to be required to keep the article up in the ranks, but 1/(x^.5) is a little steep. I was playing with other equations to get the slope to look the way I wanted, but then I came across a problem. 1/(-1^.5) is an imaginary number. Back to the drawing board.
Logged
Kevin
Scratch Projects
sparks
31337
Karma: +0/-0
Posts: 113
Rating system
«
Reply #7 on:
April 17, 2006, 04:15:06 PM »
can you not just pull the query get the current amoun of votes add one replace it with the old one then pull the tables in orderd results ex
Code:
$mysql = your sql stuff here
$mysqlquery = get the current votes
if ($mysquery != "") {
$i++;
}
$mysqlquery = replace old vote count with new vote count[/code]
Logged
Kevin
Administrator
31337
Karma: +1/-0
Posts: 137
Rating system
«
Reply #8 on:
April 17, 2006, 04:51:16 PM »
If I understand what you're saying... you're talking about displaying the vote total for each article. Doing that's not a problem and it looks like your table isn't keeping track of the vote history. My table keeps track of each individual vote (including articleID, vote, datetime, and IPAddress). This way someone can't vote on the same article twice (at least from the same IP). The way it is now all I have to do to get the total is:
Code:
SELECT SUM(vote) AS voteTotal FROM tblVote WHERE articleID=$articleID;
I might make this publicly available later, but right now I'm trying to determine the best way to keep track of what's most popular lately. Which means that new votes need to be worth more than dated votes. I want the decay to be a curve so that votes from yesterday are worth only a little less than today and votes from 30 days ago are worth almost nothing.
Logged
Kevin
Scratch Projects
sparks
31337
Karma: +0/-0
Posts: 113
Rating system
«
Reply #9 on:
April 17, 2006, 07:48:29 PM »
no i was talking about the vote count, what nathan said in the beginning instead of date just do amount + numeric order then have a table for ips and do an ip check like $currentuserip = getipvariable $mysql = connect to db $mysql = see if ip matchs anyothers, if not, pull the current amount of votes and add one then rewrite it back to the table.
Logged
sparks
31337
Karma: +0/-0
Posts: 113
Rating system
«
Reply #10 on:
April 17, 2006, 08:22:24 PM »
nvm im stupid i get what your saying now sorry...
Logged
Kevin
Administrator
31337
Karma: +1/-0
Posts: 137
Rating system
«
Reply #11 on:
April 17, 2006, 08:37:11 PM »
OK, this is the three options that Nathan stated at the beginning.
Quote
Option 1: You could maybe maintain a list of "the best of the last 30 days" on the front page
Option 2: have an "all-time best" link on the sidebar
Option 3: have your article search sortable by rank.
Here's what the first option would look like, without the join/group by stuff
Code:
SELECT SUM(tblVote.vote) as Score WHERE tblArticle.pubDate BEWEEN DateAdd(d, -30, date()) AND date() ORDER BY Score DESC
The second one is the same except without the WHERE clause. And the last one is the same as #2, except with MATCH AGAINST. Or are you talking about just a total of how many people have voted (whether it's a 1 or -1). If so, just replace SUM with COUNT. Sorry if I'm confused, but are you referring to option 1, 2, 3, or 4?
Logged
Kevin
Scratch Projects
Kevin
Administrator
31337
Karma: +1/-0
Posts: 137
Rating system
«
Reply #12 on:
April 25, 2006, 07:33:11 PM »
Alright, I had an epiphany this morning on my way to work. First problem I was experiencing was that I couldn't take a root of a negative. Fixed that when I realized that the vote value is either one or negative one which could be multiplied at the front of the equation to give the desired number.
The second problem was that I was trying to use exponents like this. x ^ y, when I should have been POW(x, y). After that got fixed the rest fell in place. Here's the part of the query that's used for the score.
Code:
SUM(tblVote.vote / (POW(DATEDIFF(NOW(), tblVote.datetime) + 1, .15) + (.15 * DATEDIFF(NOW(), tblVote.datetime)))) AS score
Logged
Kevin
Scratch Projects
Pages: [
1
]
Print
« previous
next »
Jump to:
Please select a destination:
-----------------------------
Abetment
-----------------------------
=> News and Announcements
=> Frequently Asked Questions
=> Support
=> Site Suggestions
=> Article Requests
-----------------------------
Programmers Corner
-----------------------------
=> Action Script
=> ASP/ASP.NET
=> Basic/Visual Basic/VB.NET
=> C
=> C++
=> C#
=> HTML/XHTML
=> Java
=> Javascript
=> Logo
=> Lua
=> Perl
=> PHP
=> Python
=> Ruby
=> SQL
=> VBScript
=> Other programming languages not listed here
-----------------------------
Open Community
-----------------------------
=> Irrelevant Discussion
=> User Created
=> User News and Announcements
Loading...