How can I get X amount of files per folder with math? - php

I actually have it done, I did this math equation about 2 years ago and I am having trouble understanding it now.
Basicly I use this so that when users upload photos to my site, I can balance them out with only X amount of photo per folder.
This gives me something like this 1/1 1/2 1/3 1/4 ----1/10 2/1 2/2 2/3 and so on but I need to modify it to go 3 folders deep, each folder should have a limit of the number 1-9 or 1-10 then it will increase that number to the next
So if a large enough number is entered into my function below and the result is 3/10 then when the right number of objects is reached it would bump up to 4/1 then when so many thousands objects go by again it will jump to 4/2. What I am wanting to do is make it 3 numbers/levels deep 3/10/2 would go to 3/10/3 when it got to 3/10/10 it would go 4/1/1 4/1/2 4/1/3 when the third place got to 10 it would make it got to 4/2/1
<?PHP
function uploadfolder($x) {
$dir = floor($x/18001) + 1;
$sdir = ceil($x/2000) % 9;
return "$dir/$sdir";
}
?>
I spent a lot of time 2 years ago to get it to do this with 2 levels deep and I just kind of got lucky and now it is somewhat confusing for me looking back at it

It seems to do roughly this:
It will package 2000 pictures into a subdirectory (0..8) using the line
$sdir = ceil($x/2000) % 9
Spelled out: how many times does 2000 fit into $x. As you limit this to 9 subdirectories using the modulo 9, you would get the 18001rst photo into subdirectory 0 again.
The upper level changes therefore using 18001 as limit. All photos from 1..18000 go into directory 1. (The +1 just shifts the interval to start from 1. That is the line
$dir = floor($x/18001) + 1;
Now you could go about it like this for 3 levels (pseudocode, as I do not know PHP):
function uploadfolder($x) {
$numOfPics = 2000;
$numOfFolders = 9;
$topdir = ceil($x / ($numOfPics * $numOfFolders * $numOfFolders));
$middir = floor($x / ($numOfPics * $numOfFolders)) % $numOfFolders + 1;
$botdir = (floor($x / $numOfPics) % $numOfFolders) + 1;
return "$topdir/$middir/$botdir";
}

Related

How to get web server average load level in percentages using PHP function sys_getloadavg()?

PHP function sys_getloadavg() returns an array with three values showing average number of processes in the system run-queue over the last 1, 5 and 15 minutes, respectively.
How to convert this production to percentages?
Percentages are relative measurement units. This means that we must know a range or minimum and maximum values of the measured quantity. Function sys_getloadavg() evaluates performance of whole system, not separate CPU load level, or usage of memory, file system or database. It returns float numbers showing how many processes were in run-queue for the last interval of time.
I did some experiment with my MacBook Pro (8 CPU cores) and PHP 7.0 to figure out range of values produced by sys_getloadavg(). I've got average figures between 1.3 and 3.2. When I run video conversion program in parallel, the maximum result jumped up to 18.9. By the way, in all cases I didn't fix substantial losses in web page loading speed. It means that whole system was not overloaded.
Let's take for 100% of system load situation when web page don't load for reasonable time, let say 10 sec. I don't know what values will return sys_getloadavg() in this case, but I think it will be something big.
My solution is very simple. Let's measure system average load level and persistently store results as minimum and maximum values. When system works faster or slower we will update min and max by new values. So, our program will 'learn' the system and becomes more and more precise. The value of the last minute will be compared with stored range and converted to percents like (loadavg - min)/((max - min) / 100):
$performance = sys_getloadavg();
try {
$rangeFile = 'sys_load_level.txt';
$range = file($rangeFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$performance = array_merge($performance, $range);
$min = min($performance);
$max = max($performance);
if ($range[0] > $min || $range[1] < $max)
file_put_contents($rangeFile, [$min.PHP_EOL, $max.PHP_EOL]);
}
catch (Exception $e) {
$min = min($performance);
$max = max($performance);
file_put_contents($rangeFile, [$min.PHP_EOL, $max.PHP_EOL]);
}
$level = intval(($performance[0] - $min) / (($max - $min) / 100.0));

Format money, calculated by multiplying hours * rate (multiple entries in db)

I am facing a difficult problem here, and i don't know how to solve it.
I have 2 different tables. A Tasks table and Projects table. The tasks table holds time spent(in seconds), the rate per hour for that specific task, and in which project does that entry belong to. So basically something like this:
{id} - {seconds} - {rate} - {projectId}
Now, i am calculating the billing rate per hour for a specific task like this:
function calc ($Totalseconds, $rate){
$minutes = $Totalseconds/60; //minutes
$money = $rate * ($minutes / 60); //hours
return $money;
}
...
$money = calc($task['seconds'], $task['rate']);
$value = number_format($money,2); //ex. 1,824.69
This of course works well....For example:
task1 is 1,824.69
task2 is 24.33
etc....
As long as a project has only a few tasks, then the total billing rate for that project is correct. But when a project has more than a few tasks under it, then the total value is a bit different than when i am adding them all manually with a calculator...So in another page i am showing the total billing rate for a specific project by calculating all tasks and rates for that specific projec.
I am 'selecting' all tasks from the db for a specific projectId in an array, then do:
//array projArray has the sum of all seconds and rate for every task under a specific project
//for example a project has 10 tasks with rate $12 p/h and 2 task with $10 p/h
//so projArray has 2 arrays. One for the total time in seconds for the 10 tasks + their rate and one for the 2 tasks + their rate.
$total = 0;
foreach($projArray as $value) {
$total += calc($value['TotalTime'], $value['rate']);
}
$Totalvalue = number_format($total,2);
And here is the problem...When i am manually adding all the task's billing rate, for a specific project, with a calculator i get 2,426.91 but this last function returns 2,426.92 instead.
The seconds and rates are correct in both cases. I dont get it why is there a difference with the final value ?
I guess the more tasks i have under a project the bigger the difference ? Right now i am testing things with 1-50 tasks...for each project
Example data:
a: 1,233
b: 1,233
c: 1,233
number_format((a + b + c), 2) = 3,70
number_format(a, 2) + number_format(b, 2) + number_format(c, 2) = 3,69
When you call number_format on each task individually, 0,003 is being rounded off.
Something similar is probably happening in your calculations.

PHP more efficient if else conditional logic

I'm not very skilled when it comes to PHP but I've created this and it's probably not the best way to put it together but the only one that came to my mind right now.
What are we looking at?
It's the Apple Watch 'standing up in each hour' activity ring. This ring holds 12 image slices so called 'steps' because you have to stand up at least 12 times a day till you reach your goal (100% full circle) this means when you stand for 14 or 16 times a day the ring will loop further around 100% but the only difference between slide 2 and 14 is the background behind the circle will already be filled.
Because I don't like to create 24 slices but only 12, I will rotate slide number 12 (full circle) X degree when the value gets over 12+ this will keep the amount of used images on the page low because we keep using slide number 12 most of the time only rotate it around for step 12 till 24.
Example: the blue middle ring
PHP wise everything is working so far but you can imagine how tall those if else list will become when I start the red 'move' or calories burned circle. This circle has 100 slices or better called steps. The green circle has 30 slices.
That's why I was wondering if there is maybe a more lean way to make those if else steps. Maybe performance wise this can be done a lot better.
Thanks already..
This looks like a simple math problem. Without looking at all the details and making it even shorter (there is probably no need for an if statement at all...), you can already see that:
if ($stand > 12) {
$stanr = ($stand % 12) * 30;
$stand = 12;
}
Erm...
$stanr = 0;
if ($stand <= 12) {
} elseif (($stand > 12) and ($stand < 24) {
$stanr = ($stand - 12) * 30;
$stand = 12;
else {
$stand = 0;
}

How do I find all peaks and troughs of tidal data?

I'm working with some ocean tide data that's structured like this:
$data = array('date' => array('time' => array('predicted','observed')));
Here's a sample of real data that I'm using: http://pastebin.com/raw.php?i=bRc2rmpG
And this is my attempt at finding the high/low values: http://pastebin.com/8PS1frc0
Current issues with my code:
When the readings fluctuate (as seen in the 11/14/2010=>11:30:00 to 11/14/2010=>11:54:00 span in the sample data), it creates a "wobble" in the direction logic. This creates an erroneous Peak and Trough. How can I avoid/correct this?
Note: My method is very "ad-hoc".. I assumed I wouldn't need any awesome math stuff since I'm not trying to find any averages, approximations, or future estimations. I'd really appreciate a code example of a better method, even if it means throwing away the code I've written so far.
I've had to perform similar tasks on a noisy physiological data. In my opinion, you have a signal conditioning problem. Here is a process that worked for me.
Convert your time values to seconds, i.e. (HH*3600)+(MM*60)+(SS), to generate a numeric "X" value.
Smooth the resulting X and Y arrays with a sliding window, say 10 points in width. You might also consider filtering data with redundant and/or bogus timestamps in this step.
Perform an indication phase detection by comparing the smoothed Y[1] and Y[0]. Similar to the post above, if (Y[1] > Y[0]), you may assume the data are climbing to a peak. If (Y[1] < Y[0]), you may assume the data are descending to a trough.
Once you know the initial phase, peak and trough detection may be performed as described above: if Y[i] > Y[i+1] and Y[i] < Y[i-1], you have encountered a peak.
You can estimate the peak/trough time by projecting the smoothed X value back to the original X data by considering the sliding window size (in order to compensate for "signal lag induced" by the sliding window). The resulting time value (in seconds) can then be converted back to an HH:MM:SS format for reporting.
You're looking for local minima and maxima, I presume? That's really easy to do:
<?php
$data = array(1, 9, 4, 5, 6, 9, 9, 1);
function minima($data, $radius = 2)
{
$minima = array();
for ($i = 0; $i < count($data); $i += $radius)
{
$minima[] = min(array_slice($data, $i, $radius));
}
return $minima;
}
function maxima($data, $radius = 2)
{
$maxima = array();
for ($i = 0; $i < count($data); $i += $radius)
{
$maxima[] = max(array_slice($data, $i, $radius));
}
return $maxima;
}
print_r(minima($data));
print_r(maxima($data));
?>
You just have to specify a radius of search, and it will give you back an array of local minima and maxima of the data. It works in a simple way: it cuts the array into segments of length $radius and finds the minimum of that segment. This process is repeated for the whole set of data.
Be careful with the radius: usually, you want to select the radius to be the average distance from peak to trough of the data, but you will have to find that manually. It is defaulted to 2, and that will only search for minima/maxima within a radius of 2, which will probably give false positives with your set of data. Select the radius wisely.
You'll have to hack it into your script, but that shouldn't be too hard at all.
I haven't read it in detail, but your approach seems very ad-hoc. A more correct way would probably be to fit it to a function
f(A,B,w,p;t)=Asin(wt+p)+B
using a method such as non-linear least squares (which unfortunately has to be solved using an iterative method). Looking at your sample data, it seems like it would be a good fit. When you have calculated w and p, it's easy to locate the peaks and valleys by just taking the time derivative of the function and solving for zero:
t = (pi(1+2n)-2p)/w
But I suppose, that if your code really does what you want, there's no use to complicate things. Stop second-guessing yourself. :)
A problem is I think that the observations are observations and can contain small errors. That at least needs to be accounted for. For example:
Only change direction if at least the next 2 entries are also in the same direction.
Don't let decisions be made by data on a too small difference. Throw away insignificant numbers. It will be a lot better probably when you say $error = 0.10; and change your conditions to if $previous - $error > $current etcetera.
How accurate does the peak/valley detection have to be? If you just need to find the exact record where a peak or valley occurs, isn't it enough to check for inflection points?
e.g. considering a record at position 'i', if record[i-1] and record[i+1] are both "higher" than record[i], you've got a valley. and if record[i-1] and record[i+1] are both lower than record[i], you've got a peak. As long as your sampling rate is faster than the tide changes (look up Nyquist frequency), that process should get you your data's peaks/troughs.
If you need to generate a graph from this and try to extrapolate more accurate time points for the peaks/troughs, then you're in for more work.
One way may be to define an absolute or relative deviation past which you classify further peaks/troughs as new ones rather than fluctuations around an existing peak/trough.
Currently, $direction determines whether you are finding a peak or trough, so instead of transiting to the other state (finding the trough or peak) once the derivative changes in sign, you can consider changing the state only when the deviation from the current peak/trough is "large" enough.
Given that you should never see two max or 2 min in less than about 12 hours, a simple solution would be to use a sliding windows of 3-5 hr or so and find the max and min. If it ends up being the in the first or last 30 min, ignore it.
As an example, given the following data:
1 2 3 4 5 6 5 6 7 8 7 6 5 4 3 2 1 2
and a window of size 8, with the first and last 2 ignored and only looking a peeks you would see:
1 2 | 3 4 5 6 | 5 6, max = 6, ignore = Y
2 3 | 4 5 6 5 | 6 7, max = 7, ignore = Y
3 4 | 5 6 5 6 | 7 8, max = 8, ignore = Y
4 5 | 6 5 6 7 | 8 7, max = 8, ignore = Y
5 6 | 5 6 7 8 | 7 6, max = 8, ignore = N
6 5 | 6 7 8 7 | 6 5, max = 8, ignore = N
5 6 | 7 8 7 6 | 5 4, max = 8, ignore = N
6 7 | 8 7 6 5 | 4 3, max = 8, ignore = N
7 8 | 7 6 5 4 | 3 2, max = 8, ignore = Y
8 7 | 6 5 4 3 | 2 1, max = 8, ignore = Y
7 6 | 5 4 3 2 | 1 2, max = 7, ignore = Y

How can I create a specified amount of random values that all equal up to a specified number in PHP?

For example, say I enter '10' for the amount of values, and '10000' as a total amount.
The script would need to randomize 10 different numbers that all equal up to 10000. No more, no less.
But it needs to be dynamic, as well. As in, sometimes I might enter '5' or '6' or even '99' for the amount of values, and any number (up to a billion or even higher) as the total amount.
How would I go about doing this?
EDIT: I should also mention that all numbers need to be a positive integer
The correct answer here is unbelievably simple.
Just imagine a white line, let's say 1000 units long.
You want to divide the line in to ten parts, using red marks.
VERY SIMPLY, CHOOSE NINE RANDOM NUMBERS and put a red paint mark at each of those points.
It's just that simple. You're done!
Thus, the algorithm is:
(1) pick nine random numbers between 0 and 1000
(2) put the nine numbers, a zero, and a 1000, in an array
(3) sort the array
(4) using subtraction get the ten "distances" between array values
You're done.
(Obviously if you want to have no zeros in your final set, in part (1) simply rechoose another random number if you get a collision.)
Ideally as programmers, we can "see" visual algorithms like this in our heads -- try to think visually whatever we do!
Footnote - for any non-programmers reading this, just to be clear pls note that this is like "the first thing you ever learn when studying computer science!" i.e. I do not get any credit for this, I just typed in the answer since I stumbled on the page. No kudos to me!
Just for the record another common approach (depending on the desired outcome, whether you're dealing with real or whole numbers, and other constraints) is also very "ah hah!" elegant. All you do is this: get 10 random numbers. Add them up. Remarkably simply, just: multiply or divide them all by some number, so that, the total is the desired total! It's that easy!
maybe something like this:
set max amount remaining to the target number
loop for 1 to the number of values you want - 1
get a random number from 0 to the max amount remaining
set new max amount remaining to old max amount remaining minus the current random number
repeat loop
you will end up with a 'remainder' so the last number is determined by whatever is left over to make up the original total.
Generate 10 random numbers till 10000 .
Sort them from big to small : g0 to g9
g0 = 10000 - r0
g1 = r0 - r1
...
g8 = r8 - r9
g9 = r9
This will yield 10 random numbers over the full range which add up to 10000.
I believe the answer provided by #JoeBlow is largely correct, but only if the 'randomness' desired requires uniform distribution. In a comment on that answer, #Artefacto said this:
It may be simple but it does not generate uniformly distributed numbers...
Itis biased in favor of numbers of size 1000/10 (for a sum of 1000 and 10 numbers).
This begs the question which was mentioned previously regarding the desired distribution of these numbers. JoeBlow's method does ensure a that element 1 has the same chance at being number x as element 2, which means that it must be biased towards numbers of size Max/n. Whether the OP wanted a more likely shot at a single element approaching Max or wanted a uniform distribution was not made clear in the question. [Apologies - I am not sure from a terminology perspective whether that makes a 'uniform distribution', so I refer to it in layman's terms only]
In all, it is incorrect to say that a 'random' list of elements is necessarily uniformly distributed. The missing element, as stated in other comments above, is the desired distribution.
To demonstrate this, I propose the following solution, which contains sequential random numbers of a random distribution pattern. Such a solution would be useful if the first element should have an equal chance at any number between 0-N, with each subsequent number having an equal chance at any number between 0-[Remaining Total]:
[Pseudo code]:
Create Array of size N
Create Integer of size Max
Loop through each element of N Except the last one
N(i) = RandomBetween (0, Max)
Max = Max - N(i)
End Loop
N(N) = Max
It may be necessary to take these elements and randomize their order after they have been created, depending on how they will be used [otherwise, the average size of each element decreases with each iteration].
Update: #Joe Blow has the perfect answer. My answer has the special feature of generating chunks of approximately the same size (or at least a difference no bigger than (10000 / 10)), leaving it in place for that reason.
The easiest and fastest approach that comes to my mind is:
Divide 10000 by 10 and store the values in an array. (10 times the value 10000)
Walk through every one of the 10 elements in a for loop.
From each element, subtract a random number between (10000 / 10).
Add that number to the following element.
This will give you a number of random values that, when added, will result in the end value (ignoring floating point issues).
Should be half-way easy to implement.
You'll reach PHP's maximum integer limit at some point, though. Not sure how far this can be used for values towards a billion and beyond.
Related: http://www.mathworks.cn/matlabcentral/newsreader/view_thread/141395
See this MATLAB package. It is accompanied with a file with the theory behind the implementation.
This function generates random, uniformly distributed vectors, x = [x1,x2,x3,...,xn]', which have a specified sum s, and for which we have a <= xi <= b, for specified values a and b. It is helpful to regard such vectors as points belonging to n-dimensional Euclidean space and lying in an n-1 dimensional hyperplane constrained to the sum s. Since, for all a and b, the problem can easily be rescaled to the case where a = 0 and b = 1, we will henceforth assume in this description that this is the case, and that we are operating within the unit n-dimensional "cube".
This is the implementation (© Roger Stafford):
function [x,v] = randfixedsum(n,m,s,a,b)
% Rescale to a unit cube: 0 <= x(i) <= 1
s = (s-n*a)/(b-a);
% Construct the transition probability table, t.
% t(i,j) will be utilized only in the region where j <= i + 1.
k = max(min(floor(s),n-1),0); % Must have 0 <= k <= n-1
s = max(min(s,k+1),k); % Must have k <= s <= k+1
s1 = s - [k:-1:k-n+1]; % s1 & s2 will never be negative
s2 = [k+n:-1:k+1] - s;
w = zeros(n,n+1); w(1,2) = realmax; % Scale for full 'double' range
t = zeros(n-1,n);
tiny = 2^(-1074); % The smallest positive matlab 'double' no.
for i = 2:n
tmp1 = w(i-1,2:i+1).*s1(1:i)/i;
tmp2 = w(i-1,1:i).*s2(n-i+1:n)/i;
w(i,2:i+1) = tmp1 + tmp2;
tmp3 = w(i,2:i+1) + tiny; % In case tmp1 & tmp2 are both 0,
tmp4 = (s2(n-i+1:n) > s1(1:i)); % then t is 0 on left & 1 on right
t(i-1,1:i) = (tmp2./tmp3).*tmp4 + (1-tmp1./tmp3).*(~tmp4);
end
% Derive the polytope volume v from the appropriate
% element in the bottom row of w.
v = n^(3/2)*(w(n,k+2)/realmax)*(b-a)^(n-1);
% Now compute the matrix x.
x = zeros(n,m);
if m == 0, return, end % If m is zero, quit with x = []
rt = rand(n-1,m); % For random selection of simplex type
rs = rand(n-1,m); % For random location within a simplex
s = repmat(s,1,m);
j = repmat(k+1,1,m); % For indexing in the t table
sm = zeros(1,m); pr = ones(1,m); % Start with sum zero & product 1
for i = n-1:-1:1 % Work backwards in the t table
e = (rt(n-i,:)<=t(i,j)); % Use rt to choose a transition
sx = rs(n-i,:).^(1/i); % Use rs to compute next simplex coord.
sm = sm + (1-sx).*pr.*s/(i+1); % Update sum
pr = sx.*pr; % Update product
x(n-i,:) = sm + pr.*e; % Calculate x using simplex coords.
s = s - e; j = j - e; % Transition adjustment
end
x(n,:) = sm + pr.*s; % Compute the last x
% Randomly permute the order in the columns of x and rescale.
rp = rand(n,m); % Use rp to carry out a matrix 'randperm'
[ig,p] = sort(rp); % The values placed in ig are ignored
x = (b-a)*x(p+repmat([0:n:n*(m-1)],n,1))+a; % Permute & rescale x
return

Categories