PHP - get always the same random numbers by key - php

maybe I am trying something impossible, that's why I am asking :-)
I want to get 10 random numbers in specific range. But I want to specify key or hash by which would be these random numbers generated. So when ever I specify the same key, I will always get the same random numbers.
Is it possible, if yes, how ? Thanks for any help or hints.
Explanation: If is someone interested why I want to do this - it's for recipes site, where I want all day display exact same randomly picked recipes (day number = key) so they change every day, but stay the same all day long.

I would personnaly go for a stored version of what you are suggesting.
Every day, the first request made to the website will pick n random recipes and store them in the database, in a "recipe_by_days" table, containing the day (2013-09-16) and the list of picked recipes.
Then the next visitors will get the list just by querying that table with the day being today.
That made, it would be possible to list the randomly picked recipes that was out y days before.
But then, this implementation is useful if you want to keep the randomly picked recipes more than for today only.
Now if you are interested in just showing the same randomly picked recipes for the current day only, and not keep an history, you can then just add a column to your recipe table that can be null.
Every day, the first request will set this column to null, pick n random recipes, and update the column of theses to the current date.
The algo is quite simple :
Select the recipes that have "today_random" set to "today".
If none is returned (because they are in "yesterday" state) :
Set the column "today_random" from all the recipes to null
Pick n random recipes, update the "today_random" column of these to "today"
Return these selected recipes
else return the result

It looks like this post has the function you want:
http://www.php.net/manual/en/function.srand.php#90215

Just create an array of days, let's assume for week days, and just get the current day's recipies:
$recipies = array(
0 => array(...), // sunday
1 => array(...), // monday
2 => array(...), // tuesday
...
);
print_r($recipies[date("w")]); // current weekday's recipies
Then you can randomise for that particular array with array_shuffle or some other way.

This will consistently pick 10 random numbers between $lowerRange and $upperRange, based on a key:
mt_srand(crc32('your-key'));
$lowerRange = 100;
$upperRange = 200;
for ($i = 0; $i < 10; $i++) {
$choices[] = mt_rand($lowerRange, $upperRange);
}
print_r($choices);

Related

php set daily number in range for each ID

I'm trying to calculate a sort or "daily random number" in a range, wich can't be guessed, for each user in our site but can't figure out how to do it.
I don't want a random number either, it must be a calculated number in PHP, not an additional database field or anything similar.
I tought at a function who can take the user's ID and the day of year and calculate this number.
Example:
USERID: 12345, Range: 0-7 (constant values for every user)
DayOfYear: 250 (change every day)
Then something like: ((12345 + 250) MODULO 8) (so I've range from 0 to 7 for each user). The problem is that the same number will come out every 8 days in a loop that user will find very fast.
Each user don't necessarly need a different number for every day, even the same number would be OK for a few days but not all users must have the same number. Also, most important, no loop scenario, so user can't guess his his daily number.
Thank you for your help.
There are so many answers to this question and none would be the best ... but I'm in a funny mood:
$id = hexdec(substr(md5($userId . date('z')), 0, 3)) % 8;
Use the md5-function to get a hex-string from a string. Then use a part of this string to calculate the mod 8.
For the next 10 days the id will be 5,7,5,3,6,0,2,0,2,4 when using your user id
But to guess a number between 0 and 7 isn't so hard, don't uses this for security ...

How can I find the range of a field covered by each page of a paginated set?

I have a model Task(id, start_date, end_date, description). I use Paginator like
$this->Paginator->settings = array(
'Task'=>array(
'contain'=>$contain,
'limit'=> $limit,
'conditions'=>$conditions,
'order'=>'Task.start_date ASC',
'page'=> $page,
));
What I'm after is to be able to know the range of start_date covered by each page of the paged set. Instead of page numbers (i.e. in view generated by $this->Paginator->numbers()) I'd like to create links like "2 weeks ago" and "Today" that jump to the page containing the first Task with start_date > NOW()-14Days, for example.
I fully understand I could alter my $conditions and set a range on the start_date, but I want the whole set.
Open to other ideas on how to achieve the same result, or any pointers in the right direction.
You need to calculate the records before and after the given start date of your condition and then divide it by the number of records per page to get the page it is on.
However, this is not very user friendly, instead I would do this:
Pass your start date and range in the URL and based on the passed values build your query that you then use within your pagination settings.
/something/index?range=last-two-weeks
And check for the range value and do a switch for that value to set the right conditions. This will directly filter only the records the user is really interested in by a clear to understand URL.
I ended up running my search twice, once paginated, once not. I then went through the unpaged results
$pgStarts = array();
$pgCounter = 1;
foreach($tasks as $k => $task){
if(($k % $limit) == 0){
$pgStarts[$pgCounter] = $task['Task']['start_time'];
$pgCounter++;
}
}
Once I had the array of start dates for each page I could easily change the way the paging numbers were labeled. I was even able to break down the key event day by hour (most tasks are on this day).
I'm happy with the result, as I think it gives the paging more context. I'll continue to look for a better way of doing it, but this will do for now.

PHP / Mysql, N number of timestamps + value, cut down to 24 / 1 per 2 weeks

This might be a weird question but let me try to explain best I can.
I have a table in my database and this table contains N number of records the table is simple its laid out as follows:
ID, Time, Data
So the end goal is to out put a Graph for a yearly period based off the values in this table. Now this wouldn't usually be such a big deal but the values in the table are limitless for a year, but there is no pattern to how frequent these will be entered.
In theory the person responsible for updating this table will be doing it once per 2 weeks but this can not be relied upon because I know they wont, so I want to dump all the values from the table then create and array from the results with only 2 values per month one for the 14th and one for the 28th so this will cover all months.
Anyway so I figure,
Select * FROM table
For each
.... take value closest to 14th
.... take value closest to 28th
.... Dump each into new array
But how would you go about doing this in PHP I can't work out how you would get the closest value to each day for that month only and limit it to 2, the hard thing for me is getting my head around if they didn't update it in say 4 weeks what then? use the last value I guess.
Has anyone done this before?

Unique document number for the month

I need to create an invoice number in format:
CONSTANT_STRING/%d/mm/yyyy
mm - Month (two digits)
yyyy - Year
Now, the %d is the number of the invoice in the specific month. Another words, this number is reseted every month.
Now I am checking in database what is the highest number in current month. Then after its incrementation I am saving the row.
I need the whole number to be unique. However, it sometimes happens that it is being duplicated (two users save in the same time).
Any suggestions?
Put a unique index on the field and catch the database error when trying to save the second instance. Also, defer getting the value until the last possible moment.
One solution is SELECT ... FOR UPDATE, which blocks the row until you update it, but can cause deadlocks with a serios multitasking application.
The best way is to fetch the number and increment it in a transaction and then start the work.
This way, the row is not locked for long.
Look into BEGIN WORK and COMMIT.
Use the primary key (preferably an INT) of the invoice table or assign a unique number to each invoice, e.g. via uniqid.
PS. If you are using uniqid, you can increase the uniqueness by setting more_entropy parameter to true.
set the id all in one query.
$query = 'INSERT INTO table (invoice_number) VALUES (CONCAT(\''.CONSTANT.'\', \'/\', (SELECT COUNT(*) + 1 AS current_id FROM table WHERE MONTH(entry_date) = \''.date('n').'\' AND YEAR(entry_date) = \''.date('Y').'\'), \'/\', \''.date('m/Y').'\'))';

How do I retrieve a random (but unique for a date) primary key value?

I have about 10,000 products in the product table. I want to retrieve one of those items and display it in a section of a web page which stays the same for that particular day. Something like "Product of the day".
For example, if today I get product_id 100, then all of the visitors should be viewing this product item for today. Tomorrow it may fetch any random valid primary key, say, 1289 and visitors get 1289 product all day tomorrow.
Any ideas/suggestions?
Thanks for your help.
SELECT id
FROM products
ORDER BY
RAND(UNIX_TIMESTAMP(CURRENT_DATE()))
LIMIT 1
Maybe you can store the id of the item of the day in a table in the database?
How about create a cache file and invalidate it at midnight?
The benefit of this is you don't make unnecessary calls to your DB as you're only checking the timestamp on the cache file - only once per day do you make DB requests to populate a new cache file.
You don't need a CRON job for this:
if(date_of_file(potd_cache_file) != today){
potd_cache_file = generate_from_db();
}
load_file(potd_cache_file);
This will mean only the first visitor of the day to your website will trigger the regeneration, and every subsequent visitor will have a fast loading cache file served to them.
The idea is pretty simple,
Set a table up call ProductOfTheDay with a product ID and a date field
On the product of the day page when a user visits check the date field
If it is todays date then show the product
If it is not then randonly pick a new product and save it to the field.
Its not that complex of an operation.
SELECT id
FROM products
ORDER BY (id + RAND(UNIX_TIMESTAMP(CURRENT_DATE()))) MOD some_reasonable_value
LIMIT 1
You can start random number generators with a seed value.
Make the seed value be the day (21st) + month(10) + year(2009) so today's seed is 2041.
You will get the same random number all day, and tomorrow a different one. This is more how it works in .net. The random function takes a max and min value (this is your min and max ID values) then an optional seed value and returns a number. For the same seed number you get the same random number generated. It's possible if you change the max and min this can affect the number generated. You would have to look up how php works.
total = SELECT COUNT(id) FROM products;
day_product = SELECT id FROM products WHERE id = (UNIX_TIMESTAMP(CURRENT_DATE()) MOD total) LIMIT 1;
See also this question.

Categories