PHP Multi-incremented progress - php

I am making a solution that allows a multi incremented progressbar based on float values from a array.
I am trying to achieve this (progress illustration):
[1#####2###############3###########]
1, 2, 3 etc represents the float value (in this case, 3 floats are read from array and set as width in no specific order).
I wrote this
$i = 0;
echo '<div style="padding:5px;width:50px">';
$progress = array(99.9, 99.3, 85.9, 30.8, 30.8);
foreach ($progress as $perc) {
$i++;
$calc = count($progress) / $i * 100;
echo "<div style=\"display:inline-block;border:1px solid black;height:25px;width:$calc%\">$calc</div>";
}
echo '</div>';
Which produces this
Great, so that will work in a specified container width.
But, is the formula correct? I want to see variable progress within this container, as many keys as they are in the array.
How can I show variable width (and not just leading smaller to the last)?
Any help is appreciated

Related

How can I do calculations in base 12 in PHP

I have built a simple modular scale calculator, where I can enter a base number (say font size or line height) and an important number (maybe column width, page width, or another font size) and select a ratio (golden ratio for example) and the calculator will display a double stranded scale for use in page layout. see example below
I have been toying with the idea of allowing users to input points and picas and then displaying the scale in one or the other.
The problem is that picas are base 12 numbers (12 points to a pica), I figured if I could just convert the input (something like 16p6) to base 12 I could do the calculation and go from there.
I just can't work out how to do basic calculations in another base. I'm really just messing around to see what I can come up with, let me know if you think I'm barking up the wrong tree.
So my question is this how do I do calculations in base 12?
<?php
// basic modular scale calculation
$goldenRatio = 1.618;
$baseNumber = 16;
$i = 0;
while ($i <= 10) {
echo round($baseNumber,1). "<br>";
$baseNumber = $baseNumber * $goldenRatio;
$i++;
}
echo "<hr><br>";
// Attempt at base 12 calculation
$a=base_convert(16,10,12);
$b=base_convert(12,10,12);
$r = ($a*$b);
echo $a."*".$b."=";
echo $r;
I'm really just messing around to se what I can come up with, let me know if you think I'm barking up the wrong tree.
Update
To solve the problem of converting Picas to base points from a string like '12p6' I ended up using regex to first test if Picas and Points had been supplied the split the Picas and Points.
function isPica($data) {
if (preg_match('/^[0-9]+(?i)p([0-1]?[0-9])?$/i',$data)) {
return true;
}
return false;
}
function makePoints($data) {
$data = preg_replace('/^([0-9]+)((?i)p)(([0-1]?[0-9])?)$/i','$1.$3',$data);
$data = explode('.',$data);
$points = floor($data[0] * 12);
$points = $data[1] + $points;
return $points;
}
Modular Scale Calculator
Git Hub — Modular Scale Calculator
base_convert just converts the string representation. You can't do calculations using strings of numbers in base 12 in php. When dealing with imperial units, you usually have multiple "bases" to deal with. So it has to be done manually. When you're doing calculations, the base doesn't matter.
Convert all the different units to the smallest one (points). $a = 3*12 + 7;//3picas, 7points.
Do the calculations.
Convert back to original units.
$points = (int)$val % 12;
$picas = (int)($val / 12);
or
$picas = floor($val / 12);
$points = $val - 12*$picas;

Repeat image x number of times

Hello I am working on a site that uses expedias api. Basically I get a number of people per room, and I want to echo out a little man image for each person. So if I have occupancy of 5 for example and I need to echo 5 tags with the little man as a src. Any idea how to do this??
Well let's say you have the amount of people stored in a variable.
$occupancy = 5;
You can then plug in that number into a for loop, and have the program cycle through that many times.
for($n = 0; $n < $occupancy; $n++) {
// Disco
}
You can read more about control structures here.
You should be interested in str_repeat().
Something like this should work:
$img_multi = str_repeat('<img src="man.png" alt="man"/>', $repeat);
echo $img_multi;
Revisiting this answer, a much more efficient solution:
Assuming the image is 12px wide by 16px high - adjust for your needs.
$width = 12 * $repeat;
$height = 16;
echo '<span style="'
.'display: inline-block;'
.'width: '.$width.'px;'
.'height: '.$height.'px;'
.'background-image: url(man.png);'
.'"></span>';
This will produce a single element of the appropriate size to show $repeat copies of the image, side-by-side.
First result googling "php loops"
Might be worth trying.

Slicing / Limiting an Array by Value

Background;
to create a dropdown menu for a fun gambling game (Students can 'bet' how much that they are right) within a form.
Variables;
$balance
Students begin with £3 and play on the £10 table
$table(there is a;
£10 table, with a range of 1,2,3 etc to 10.
£100 table with a range of 10,20,30 etc to 100.
£1,000 table with a range of 100, 200, 300, 400 etc to 1000.)
I have assigned $table to equal number of zeros on max value,
eg $table = 2; for the £100 table
Limitations;
I only want the drop down menu to offer the highest 12 possible values (this could include the table below -IMP!).
Students are NOT automatically allowed to play on the 'next' table.
resources;
an array of possible values;
$a = array(1,2,3,4,5,6,7,8,9,10,20,30,40,50,60,70,80,90,10,20,30,40,50,60,70,80,90,100,200,300,400,500,600,700,800,900,1000);
I can write a way to restrict the array by table;
(the maximum key for any table is (9*$table) )//hence why i use the zeroes above (the real game goes to $1 billion!)
$arrayMaxPos = (9*$table);
$maxbyTable = array_slice($a, 0, $arrayMaxPos);
Now I need a way to make sure no VALUE in the $maxbyTable is greater than $balance.
to create a $maxBet array of all allowed bets.
THIS IS WHERE I'M STUCK!
(I would then perform "array_slice($maxBet, -12);" to present only the highest 12 in the dropdown)
EDIT - I'd prefer to NOT have to use array walk because it seems unnecessary when I know where i want the array to end.
SECOND EDIT Apologies I realised that there is a way to mathematically ascertain which KEY maps to the highest possible bid.
It would be as follows
$integerLength = strlen($balance);//number of digits in $balance
$firstDigit = substr($balance, 0, 1);
then with some trickery because of this particular pattern
$maxKeyValue = (($integerlength*9) - 10 + $firstDigit);
So for example;
$balance = 792;
$maxKeyValue = ((3*9) - 10 + 7);// (key[24] = 700)
This though works on this problem and does not solve my programming problem.
Optional!
First of all, assuming the same rule applies, you don't need the $a array to know what prices are allowed on table $n
$table = $n; //$n being an integer
for ($i = 1; $i <= 10; $i++) {
$a[] = $i * pow(10, $n);
}
Will generate a perfectly valid array (where table #1 is 1-10, table #2 is 10-100 etc).
As for slicing it according to value, use a foreach loop and generate a new array, then stop when you hit the limit.
foreach ($a as $value) {
if ($value > $balance) { break; }
$allowedByTable[] = $value;
}
This will leave you with an array $allowedByTable that only has the possible bets which are lower then the user's current balance.
Important note
Even though you set what you think is right as options, never trust the user input and always validate the input on the server side. It's fairly trivial for someone to change the value in the combobox using DOM manipulation and bet on sums he's not supposed to have. Always check that the input you're getting is what you expect it to be!

Color coding based on number

I want to display a color between red, yellow, green depending on a number between 1 to 100.
1 being green and 100 being red, 50 being yellow. I want to basically create a gradient between that.
So far, I tried:
$r = floor(255 * ($number / 100));
$g = 255 - $r;
And it somewhat does it, but gives me brownish & dark colors, & no yellow at all.
It's because you shouldn't change both channels at once but rise R in the first half and lower G in the second.
Try a function like this:
function GreenYellowRed($number) {
$number--; // working with 0-99 will be easier
if ($number < 50) {
// green to yellow
$r = floor(255 * ($number / 50));
$g = 255;
} else {
// yellow to red
$r = 255;
$g = floor(255 * ((50-$number%50) / 50));
}
$b = 0;
return "$r,$g,$b";
}
To test it:
$output = "";
for ($i = 1; $i <= 100; $i++) {
$rgb = GreenYellowRed($i);
$output .= "<div style='background-color: rgb($rgb)'>$rgb</div>";
}
echo $output;
I've found that dealing with the HSV color model is easier than the RGB model. It helps you easily choose the color you want to work with; with RGB you'd need to understand how different values of R, G and B will combine to give you the color you want/don't want.
Also, this SO question might be useful: How can I cycle through hex color codes in PHP?
I don't know of a mathematical model for a "color curve" that passes through specified RGB color values (e.g. what you describe as green/yellow/red), which would allow you to calculate any intermediate color in that curve. In any case, a model of a function (which is what that would be) is only as good as the data points it needs to fit, so you 'd have to be much more specific than green/yellow/red to get decent results even if someone points out the math.
Remember that we are not interested in mathematical interpolation here, but rather in "color-space interpolation" (a term which I just made up) -- in other words, what would look like a "natural" interpolation to a human.
An easier solution for those of us who do not have the necessary color theory knowledge, and which I 'd suggest, is to pre-select a number of colors with a color picker tool, divide the 0-100 range into as many bands as the colors you picked, and use simple integer division to project from 0-100 to a color band.
Food for thought: Indeed, how does SO decide the color of the upvote count for comments?
Update: I just asked the above over on meta. Let's see...
After a bit of looking, none of the solutions looked pleasing. As stated above, HSV is probably the way to go, since modern browsers can render color with it just fine.
To get a good idea of the colors you are working with, check out this color wheel:
http://www.colorspire.com/rgb-color-wheel/
I want to start with blue, so I use 255 for normalization.
function temp_color($temp){
$start = 40;
$end = 85;
$normal = round(255-((($temp - $start)/($end-$start))*255));
$color = "hsl($normal, 100%, 30%);";
$span = "<span style=\"color: $color\">$temp</span>";
return $span;
}

Drawing functions starting from a specific point

I have a problem drawing different functions with PHP (GD, of course).
I managed to draw different functions but whenever the parameters of the function change - the function floats wherever it wants.
Let us say that I have a first function y=x^2 and I have to draw it from -5 to 5. This means that the first point would be at (-5;25). And I can move that to whatever point I want if I know that. But if I choose y=2x^2 with an interval x=(-5;5). The first point is at (-5;50). So I need help in calculating how to move any function to, let's say, (0;0).
The functions are parabola/catenary alike.
What you want to do is find the maximum boundaries of the graph you are making. To do this you have to check each inflection point as well as the range bounds. Store each coordinate pair in an array
Part 1 [Range Bounds]:
Collect the coordinates from the range bounds.
<?php
$ybound[] = f($minX);
$ybound[] = f($maxX);
Part 2 [Inflections]:
This part is more difficult. You can either have a series of equations to solve for inflections for each type of parabola, or you can just brute force it. To do this, just choose a small increment, (what ever your small increment is for drawing the line), I will use 0.1
<?php
for($x = $minX; $x <= $maxX; $x += 0.1) {
$ybound[] = f($x);
}
Note, if you brute force, you can skip Part 1, otherwise, it would be faster if you could figure out the inflections for the scope of your project
Part 3 [Min Max]:
Now you get the min and max values from the array of possible y values.
<?php
$minY = min($ybound);
$maxY = max($ybound);
Part 4 [Shift]:
Now that you have this, it should be very simple to adjust. You take the top left corner and set that to 0,0 by adjusting each new coordinate to that value.
<?php
$shiftX = -$minX;
$shiftY = $maxY;
With this info, you can also determine your image size
<?php
$imageX = $maxX - $minX;
$imageY = $maxY - $minY;
Then as you generate your coordinates, you will shift each one, by adding the shift value to the coordinate.
<?php
for($x = -$minX; $x <= $maxX; $x += 0.1) {
$ycoor = $shiftY - f($x);
$xcoor = $x + $shiftX;
//draw ...
}
Drawing the axis is also easy,
<?php
$xaxis = $shiftY;
$yaxis = $shiftX;
(I think I have all my signs correct. Forgive me if they are off)
You first need to determine the bounding box of your function. Then, you calculate the width and the height, and you normalize so it fits into a rectangle whose top left coordinate is (0,0). Maybe you will also need to scale the figure to get it at a specific size.

Categories