I have created a lottery script in php. My problem is now selecting more then one winner. Because it is possible for players to have the same number on their tickets. Here I am supplying the two table structures and the source code.
lotto_game {
id(int)
jackpot(int)
status(varchar10)
pick_1(int)
pick_2(int)
pick_3(int)
pick_4(int)
pick_5(int)
tickets_sold(int)
winner(text)
}
lotto_picks {
lotto_id(int)
user_id(int)
choice_1(int)
choice_2(int)
choice_3(int)
choice_4(int)
choice_5(int)
ticket_status(int)
}
These are my two tables with in my database. For examples sake we will create 2 users with the id's 1, and 2. So what happens is when the script runs it is suppose to change the lotto_game status from 'active' to 'finished' then add the random lottery numbers into each pick_* column.
$one = rand(1,30);
$two = rand(1,30);
$three = rand(1,30);
$four = rand(1,30);
$five = rand(1,30);
mysql_query("UPDATE `lotto_game` SET
pick_1 = '$one',
pick_2 = '$two',
pick_3 = '$three',
pick_4 = '$four',
pick_5 = '$five',
status = 'finished'
WHERE status = 'active'");
That wasn't too hard I will admit. But this is just the beginning of the end.
$lotto['tickets'] = mysql_query("SELECT ticket_id FROM `lotto_picks` WHERE ticket_status='valid'");
#$lotto[winners] = mysql_query("SELECT ticket_id,user_id FROM `lotto_picks` WHERE choice_1 = '$one' AND choice_2 = '$two' AND choice_3 = '$three' AND choice_4 = '$four' AND choice_5 = '$five'");
$lotto['num_tickets'] = mysql_num_rows($lotto['tickets']);
#$lotto[winner_id] = mysql_fetch_array(#$lotto[winners]);
$lotto['jackpot'] = mysql_query("SELECT jackpot FROM `lotto_game` WHERE status='active'");
$lotto['winner_jackpot'] = mysql_fetch_array($lotto['jackpot']);
$lotto['num_winners'] = mysql_num_rows($lotto['winners']);
//echo #$lotto['num_tickets'];
//echo #$lotto['num_winners'];
$winner = $lotto['num_winners'];
//echo #$lotto['winner_id']['user_id'];
$jackpot = $lotto['winner_jackpot']['jackpot'];
$id = #$lotto[winner_id][user_id];
if ($winner == 1) {
mysql_query("UPDATE `character` SET
decivers = decivers +'$jackpot'
WHERE user_id='$id'");
}
This is what I have come up with and it really seems to work with one winner. But I just cant figure out where to go from here. I have tried using some arrays but nothing works. I know what needs to be done but can't figure out how to do it.
When I search for winners I need to put into an array all their user id's.
so extra decivers is money, if anyone is confused on that. The status on the tickets doesn't really matter here but if you must know it just determines if the ticket_status is 'valid' or 'invalid'
i think you've chosen the wrong storage formats for your picked numbers. The standard approach is to use binary values which have N-th bit set if the number N is choosen.
Consider this example: user chooses numbers "2 4 5 9 11". Setting corresponding bits to 1 gives '10100011010' which is decimal 1306. Now the lottery picks "4 7 9 12 13" which is '1100101001000' == 6472. Perform a bitwise AND on both values and count the number of bits set in the result:
SELECT BIT_COUNT(1306 & 6472)
this immediately tells us that the user has 2 correct picks. Just as easy you can select "full" winners:
SELECT * FROM tickets WHERE BIT_COUNT(tickets.pick & lotto.pick) = 5
or sort the tickets by the number of correct picks
SELECT * FROM tickets ORDER BY BIT_COUNT(tickets.pick & lotto.pick) DESC
$winners_array = array();
if(mysql_num_rows($lotto['winners'])!=0){
while($row =mysql_fetch_array($lotto['winners'])){
if(!in_array($row['user_id'],$winners)) $winners[] = $row['user_id'];
}
}
$winners will be an array with all the winners user_ids
Related
I have a table called feedbacks that looks like this:
id user type
1 JOhnT Positive
2 JOhnT Negative
3 Sarah Positive
4 JOhnT Positive
5 JOhnT Neutral
....................
I need to get the percentage of POSITIVE feedback for each user using PHP.
I tried something like this which i know it is wrong:
$sql = "SELECT type, count(*),
concat(round(( count(*)/(SELECT count(*) FROM feedbacks WHERE user='JOhnT' AND type='POSITIVE') * 100 ),2),'%') AS percentage
FROM feedback
WHERE user='$email' AND type='positive' GROUP BY type";
$query = mysqli_query($db_conx, $sqlJ);
echo $sql;
Could someone please advice on how to achieve this?
EDIT:
Based on the comments, this is what i have so far:
$sql = "SELECT * FROM feedbacks WHERE user='JOhnT' AND type='POSITIVE'";
$query = mysqli_query($db_conx, $sql) or die(mysqli_error($db_conx));
$productCount = mysqli_num_rows($query);
if ($productCount > 0) {
while($row = mysqli_fetch_array($query, MYSQLI_ASSOC)){
///do I need to calculate the percentage here?//
//if so, how?////
}
}
I ended up creating an array and push each $row in my whole loop into the array and then calculate the percentage like this:
$c = count($values);
$array = $values;
function array_avg($array, $round=1){
$num = count($array);
return array_map(
function($val) use ($num,$round){
return array('count'=>$val,'avg'=>round($val/$num*100, $round));
},
array_count_values($array));
}
$rating = 0;
if($c > 0){
$avgs = array_avg($array);
$rating = $avgs["positive"]["avg"];
}
This works fine for now.
You can do this a conditional average. In MySQL, you could phrase this as:
select user, avg(type = 'Positive') positive_ratio
from feedback
group by user
This gives you, for each user, a value between 0 and 1 that represents the ratio of positive types. You can multiply that by 100 if you want a percentage.
If you want this information for a single user, you can filter with a where clause (and there is no need to group by):
select user, avg(type = 'Positive') positive_ratio
from feedback
where user = 'JOhnT'
Side note: user is a MySQL keyword, hence not a good choice for a column name.
I am trying to make a function where the following should happen:
Retrieve the ID value of all users in database.
Retrieve all numbers belonging to each user from an other table in the same database.
Add all the numbers belonging to each user together.
By using my code (see below), step 1 and 3 is working. At step 2, it is looping the correct amount of times but in every loop it retrieves the numbers belonging to the first ID from step 1.
Example:
Step 1 finds the following IDs: 1, 2, 3 and 4.
Step 2 loops 4 times, but retrieves the numbers belonging to ID 1 every time instead of retrieving the numbers to ID 1 in the first loop, ID 2 in the second etc.
My PHP:
$users_get = mysqli_query($conn,"SELECT id FROM users");
$users_num = mysqli_num_rows($users_get);
$users_list = array();
while($users_row = mysqli_fetch_array($users_get)){
$users_list[] = $users_row;
}
foreach($users_list as $users_row){
$users_items[] = array(
'id' => $users_row['id']
);
}
for($loop1 = 0; $loop1 < $users_num; $loop1++){
$numbers_get = mysqli_query($conn,"SELECT number FROM users_numbers WHERE userid = '".$users_items[$loop1]['id']."'");
$numbers_num = mysqli_num_rows($numbers_get);
$numbers_list = array();
while($numbers_row = mysqli_fetch_array($numbers_get)){
$numbers_list[] = $numbers_row;
}
foreach($numbers_list as $numbers_row){
$numbers_items[] = array(
'number' => $numbers_row['number']
);
}
$numbers_added = 0;
for($loop2 = 0; $loop2 < $numbers_num; $loop2++){
$numbers_added = $numbers_added + $numbers_items[$loop2]['number'];
}
}
I later added som echos to display the IDs and numbers that is retrieved and got the following result:
User ID: 1
Amount of numbers: 4
Numbers:
4 (Belonging to ID 1)
7 (Belonging to ID 1)
5 (Belonging to ID 1)
2 (Belonging to ID 1)
Total: 18
User ID: 2
Amount of numbers: 0
User ID: 3
Amount of numbers: 3
Numbers:
4 (Belonging to ID 1)
7 (Belonging to ID 1)
5 (Belonging to ID 1)
Total: 16
The amount of numbers for ID 3 is correct, however the 3 retrieved numbers belongs to ID 1.
Another observation I made was if I edit the SELECT query inside loop 1:
"SELECT number FROM users_numbers WHERE userid = '".$users_items[$loop1]['id']."'"
And manually selects an ID, example:
"SELECT number FROM users_numbers WHERE userid = '3'"
Then it retrieves the correct numbers belonging to ID 3.
After hours of trying to figure out what I'm doing wrong I still haven't found anything, so any help is really appreciated! Is there something I can do with my current code to fix it, or maybe there is some other ways to achieve the desired function?
Based on the comments on my question, I ended up with the following code:
$users_get = mysqli_query($conn,"SELECT a.id, SUM(b.number) AS number FROM users AS a INNER JOIN users_numbers AS b ON a.id = b.userid GROUP BY a.id ASC");
$loop1 = 0;
while($users_items[] = mysqli_fetch_array($users_get){
echo "ID: ".$users_items[$loop1]['id']." - Num total: ".$users_items[$loop1]['number']."<br />";
$loop1++;
}
The echo inside the while is only for testing purposes. When I run this, it displays a nice list with all the user IDs and the sum of each users numbers.
sorry about the title, i really did not know what I should call it, but hopefully you will be able to aid me with my script.
What I am trying to achieve (with my less than 5 hour total experience with any sort of "programming", hence the horrid coding) is to send one query X times, and then put a new query into those newly created rows.
if(isset($_SESSION['email'])) { // IF LOGGED IN
$sql = mysql_query("SELECT max(ordrenr) FROM antalstabel") or die(mysql_error());
$maxordrenr = mysql_query($sql);
$nextnumber = $maxordrenr + 1;
$maxplusantal = $maxordrenr + $antal;
$antal = count($items); // COUNTS DIFFERENT ITEMS IN CART.
for ($i = $maxordrenr; $i <= $maxplusantal; $i++) {
$sql = mysql_query("INSERT INTO antalstabel (ordrenr) VALUES ('$nextnumber')") or die(mysql_error());
}
}
This is my first query, what this does (or what I want it to do) is to get the max ID of the table "antalstabel" add +1 and then count a certain amount up which is defined as $items untill it has executed X rows.
My first issue here, is the fact that my table consists of two key primaries, so returning a query like this would result in an error since after one return the two rows would be identical and will not execute.
The second issue is the fact that the next value in the table should not be inserted X times after each other, but rather be certain IDs added in afterwards.
What I am trying to achieve ultimately (not only by this script, but this is the current issue) is something like this:
ordrenr(key)varenr(key) antal
1 3 1
1 2 2
2 1 4
3 1 1
3 2 1
3 3 1
Does this make any sense whatsoever for anyone and can anyone tell me whether my method of doing this is jsut hopeless or have some better ideas for me to use as execution for ending up with something like this?
Should I not use primary keys or how does this work?
Thank you for even taking the time to read this :)
-Victor
EDIT for future:
changed script to this for it to work:
if(isset($_SESSION['email'])) { // IF LOGGED IN
$sql = mysql_query("SELECT * FROM antalstabel ORDER BY ordrenr DESC LIMIT 1") or die(mysql_error());
$row = mysql_fetch_assoc($sql);
$maxordrenr = $row['ordrenr'];
$nextnumber = $maxordrenr + 1;
$maxplusantal = $maxordrenr + $antal;
$antal = count($items); // COUNTS DIFFERENT ITEMS IN CART.
for ($i = $maxordrenr; $i <= $maxplusantal; $i++) {
$sql = mysql_query("INSERT INTO antalstabel (ordrenr, varenr) VALUES ('$nextnumber','1236')") or die(mysql_error());
}
$maxordrenr = mysql_query($sql);
should be
$maxordrenr = mysql_result($sql,0);
I'm having a problem in getting an array of a users ratings. The scenario is, I have a function that compares two arrays of numbers, and calculates how similar they are using cosine similarity.
I want to use this, to calculate the similarity of ratings from one user, to x number of other users in the database, finding the user with the most similar ratings.
The two tables relevant to this are films and ratings. Rows relevant for Film are filmID, and ratings has rows filmID, userID, and rating. for example:
filmId userID rating
1 1 3
1 3 4
2 1 2
3 1 2
2 3 3
So for user 1, I'd want an array $user1[3, 2, 2] and for user 3 $user3[4, 3, 0]
Notice that in the array for user 3, the film they HAVEN'T rated is now a zero. These arrays will then be passed to the function to calculate similarity.
I don't know how to get the user arrays from the tables I have. I wrote some code, but am fairly stumped. So far I have:
$users = mysql_query("SELECT * FROM user");
$ratings = mysql_query("SELECT * FROM ratings");
while ($userRow = mysql_fetch_assoc($users)) {
$similarCheck = mysql_query("SELECT * FROM ratings WHERE userID =".$userRow['userID']);
$similarArray = mysql_fetch_assoc($similarCheck);
$count = 0;
while ($similarArray = mysql_fetch_assoc($similarCheck)){
$count++;
}
for ($i=0; $i < $count; $i++){
$user1 = array();
$user1[$i] = $similarArray['rating'];
}
}
Thanks for any help I do receive. If you require any further information, please let me know.
You're not actually doing anything with your query:
while ($similarArray = mysql_fetch_assoc($similarCheck)){
$count++;
}
This code simply loops through the query results and assigns each row to a variable, which is then overwritten over and over. When the loop exits, you'll have a FALSE value assigned to $similarArray, since mysql_fetch calls return a boolean false when there's no more results.
You then try to use this boolean false value in ANOTHER loop as an array which will throw all sorts of warnings.
Most likely you want something like this:
$similarCheck = mysql_query("SELECT * FROM ratings WHERE userID =".$userRow['userID']) or die(mysql_error());
$similarArray = array();
while($row = mysql_fetch_assoc($similarcheck)) {
$similarArray[] = $row['rating'];
}
I have a problem selecting 6 random friends
This is the query I've got so far:
$result = num_rows("SELECT * FROM friends WHERE member_id = '".$_SESSION['userid']."'");
if($result >= 6) {
$f_num = 6;
} else {
$f_num = $result;
}
for($i = 1; $i <= $f_num; $i++) {
$q_get_member_friends = mysql_query("SELECT * FROM friends WHERE member_id = '".$_SESSION['userid']."' ORDER BY rand() LIMIT 1");
$r_get_member_friends = mysql_fetch_array($q_get_member_friends);
echo $r_get_member_friends['friend_with'];
}
I want to select 6 random friends if the logged in user has more or equal to 6 friends
Stuck on this for a while now :/
Thanks for any help :)
If you use:
SELECT *
FROM friends
WHERE member_id = '".$_SESSION['userid']."'
ORDER BY rand()
LIMIT 6
If the person only has 3 friends, the query will only show those three - it doesn't mean that the query will always return six rows.
The best way I've found to select any number of random records is with OFFSET in the query.
Let's say you want 6 random records, so I'll borrow from an answer above and count the total number of friends in the database.
$sql = mysql_query("SELECT COUNT(*) AS total FROM friends WHERE member_id='". $_SESSION['userid'] ."'");
$get_count = mysql_fetch_array($sql); // Fetch the results
$numfriends = $get_count['total']; // We've gotten the total number
Now we'll get the 6 random records out of the total above (hopefully it's > 6),
$query = mysql_query("SELECT * FROM friends WHERE member_id='". $_SESSION['userid'] ."' LIMIT 6 OFFSET " . (rand(0, $numFriends));
while ($rows = mysql_fetch_array($query))
{
/// show your $rows here
}
Using OFFSET may not be the best or most efficient, but it's worked for me on large databases without bogging them down.
Never mind, I figured it out :)
Had to use while not for :'D
First select the number of friends that the user has:
"SELECT COUNT(*) as numFriends FROM friends WHERE member_id='".$_SESSION['userid']."'
...put that into a variable, let's call it "$numFriends"
Then:
for($z=0;$z<6;$z++)
{
$randomFriendIndex = rand(1,$numFriends);
//Get the friend at that index
}
change limit 1 to limit 6 on the eighth line.
Instead of SELECT * at the beginning, try SELECT COUNT(*) and use the actual return value instead of num_rows().
Your loop could generate duplicates. I would suggest trying OMG Ponies answer.
There is a whole chapter about random selection in the book SQL Antipatterns.