views:

87

answers:

4

Hello. What i want to do is that every user gets 1 points every minute. Now i have the php code in the addpoints.php, and then i have tried myself with jQuery javascript:

function addpoints()  { 
  var userid = document.getElementById('user_id_points');
  var postFile = 'addpoints.php?userid='+ userid.value;
  $.post(postFile, function(data){  
    $("#points").html(data); 
    setTimeout(addpoints, 60000);
  });
}    

This works pretty good, and gives a point every 1 minute.. BUT one issue is that if you just refresh the page where the script is on, then you will receive a point.. so you could likely just refresh the page some times and then you raise your points..

I was thinking of maybe in addpoints.php make a if() that checks for last datestamp is longer than 1 minute then give out point else error..

I was just wondering if there was any better idea/thing to make, to prevent the little issue?

+3  A: 

Storing the date+time (using a timestamp for instance) of the last time the score was incremented, next to that score (be it in $_SESSION or in database) would indeed be a solution :

  • when a request to increment the score arrives, check the timestamp
    • if it's more than 60 seconds ago, then increment the score, and update the timestamp
    • else, don't update the score nor the timestamp
Pascal MARTIN
Yes that is what i was thinking of.. can you tell more of $_session idea??
Karem
A way to not hit the database too often (i.e. for times when there is no need to update the score, as less than 1 minute has passed) might be to store the timestamp in session (see http://www.php.net/manual/en/book.session.php ) ;; but clearing cookies in the browser or using another one, or an automated script, would be enough to change session -- which means it's not as secure as storing the timestamp in the database (I would store the timestamp in the database, actually, next to the score).
Pascal MARTIN
okay thank you how should i do the if? if($row["lastpoint"] + 60 == time()) { //insert to database }else{ //dont } is this correct?
Karem
I would at least use a comparison such as `<` or `>`, and not an `==` : if the query arrives after 61 seconds, it should be taken into account ;;; and I would probably put the condition in the `update` query ; in pseudo-code : `update your_table set points = points+1, timestamp=$current_time where user_id=X and timestamp<=$current_time-60` ;;; else, starting from what you proposed, I suppose this could be ok : `if ($row['last_time'] + 60 <= time()) {insert}`
Pascal MARTIN
Hi pascal. The update line worked out perfectly. Although i got one question. I have this echo line that i ONLY want out, if it inserted, but you cant really do that when its in the query line? So right now it just echo out "You have earned +1 points" even though it doesnt inserts(60 seconds timelimit).. hope you understand me and im excusing for my english
Karem
You could try determining how many rows where affected by the update ;; if 0, then the update did not take place ;; if 1, then the update took place ;; depending on the API you are using, you might want to take a look at http://www.php.net/manual/en/function.mysql-affected-rows.php or http://www.php.net/manual/en/mysqli.affected-rows.php or http://www.php.net/manual/en/pdostatement.rowcount.php
Pascal MARTIN
Should i do it like this: if (mysql_affected_rows($result) == 1) { , but then i have no $result variable, as the query is not a variable. And if i make it to a variable then it will not execute, or? i tried to make it variable and i got "supplied argument is not a valid MySQL-Link resource i"
Karem
I'd say that you first have to run the actualy query, using `mysql_query`, and, then, call `mysql_affected_rows`, not passing it any parameter : it'll work on the last query that's been run -- see the examples on the `mysql_affected_rows`'s manual page : there is one that's with an `update` query.
Pascal MARTIN
I did like you said now, but i am getting the error Warning: Wrong parameter count for mysql_num_rows().. Here's how it is: mysql_query("UPDATE member_profile set points = points+1, lastpoint=$tid WHERE lastpoint<=$tid-60 AND user_id = '".$userid."'");if (mysql_num_rows() == 1) {No parameter as you said, but still getting error..
Karem
That's probably because you are now using `mysql_num_rows`, and not `mysql_affected_rows` like you did in the previous comment ;;; see the manual of `mysql_num_rows`, which states *"To retrieve the number of rows affected by a INSERT, UPDATE, REPLACE or DELETE query, use mysql_affected_rows()."*
Pascal MARTIN
thank you for your help, that worked perfectly!
Karem
You're welcome :-) Have fun !
Pascal MARTIN
A: 

based on the response of @Pascal MARTIN, if the solution is well, you choose @Pascal MARTIN ' response

function addpoints()  { 
  var userid = document.getElementById('user_id_points');
  var postFile = 'addpoints.php?userid='+ userid.value;
  $.post(postFile, function(data){  

    $("#points").html(data.html); 
    setTimeout(addpoints, data.ts);
  });

}   

only get Timestamp in "addpoints_get_ts"

(function(){
  var userid = document.getElementById('user_id_points');
  var postFile = 'addpoints_get_ts.php?userid='+ userid.value;
  $.get(postFile, function(data){  
      setTimeout(addpoints, data.ts);
  });
})();
andres descalzo
A: 

I'd suggest to add a column last in your MYSQL table. This way, you can make sur they won't cheat.

mysql_query('UPDATE `users` SET `points` = `points`+1, `last`='.time().' WHERE `last` < '.(time()-60).' AND `user_id` = '.intval($_GET['userid']).' LIMIT 1);

Additionally, you can use SESSION varaibles to make sure the right user calls the script, or even make sure the user is logged in. ;)

Daan
Oops!that's exactly what Pascal MARTIN said.
Daan
it just inserts .time(). into the database, which isnt correct?
Karem
That's to save the previous time so you know if they try to cheat or not. It also increments the points (only when 60 seconds have past since the last increment).Shortly, here's what you tell to MYSQL : (increment `points` by 1 and update the time stamp) only if 60 seconds passed since the last time.
Daan
A: 

You should really only store the timestamp in the $_SESSIONS and not worry about what's in the database. Another nice thing you can do to prevent automated scripts is to enable some sort of authentication to access the page, preferably with a login and a strong captcha. Also make sure to secure against form spoofing and store multiple requests of the same IP and ban them. That will prevent someone from DOS'sing your server with multiple refreshes. You can use other things to determine if it's bieng automated, like IP, referrer checking, etc.

Stanislav Palatnik