So the goal is to be able to create a dynamic value for my progress bar based on dynamic variables from the database. Below is a pseudo code for what i am looking for if its possible:
//League rank names
['bronze_V','bronze_IV','bronze_III','bronze_II','bronze_I'];
Lets say i start at bronze_IV to bronze_II i need to calculate that to 100?
and then i need to store that value is that possible to be dynamic?
are you trying something like this,
$data = ['bronze_V','bronze_IV','bronze_III','bronze_II','bronze_I'];
$start = $end = 0;
while($element = current($data)) {
if ($element == 'bronze_IV') $start = key($data);
if ($element == 'bronze_I') $end = key($data);
next($data);
}
$percentage = ( (($end-$start) + 1) / count($data) ) * 100;
var_dump($percentage); //float(80)
example with multiple tiers,
#note : badge count for each tier has to be 5 for this to work,
#if you change the count change change the value inside the loop
$data = array(
['silver_V','silver_IV','silver_III','silver_II','silver_I'],
['bronze_V','bronze_IV','bronze_III','bronze_II','bronze_I']
);
$start = $end = 0;
$start_badge = 'silver_V';
$end_badge = 'bronze_II';
//loop through tiers
foreach ($data as $key => $tier) {
//loop through badges
while($badge = current($tier)){
//position of the start badge
if ($badge == $start_badge) $start = ($key * 5) + key($tier)+1; //see note
//position of the end badge
if ($badge == $end_badge) $end = ($key * 5) + key($tier)+1; //see note
next($tier);
}
}
//count badges
$badges_count = (count($data, COUNT_RECURSIVE) - count($data));
//calculate percentage
$percentage = ( (($end-$start) + 1) / $badges_count ) * 100;
var_dump($percentage); //float(90)
Related
I need to generate random IDs that validate against the criteria for Saudi IDs shown in this question:
Saudi Iqama/National Identity number field validation
I've tried the following code:
$random_numbers = [];
while(count($random_numbers) < 1000000000){
do {
$random_number = mt_rand(1000000000,9000000000);
}
while (in_array($random_number, $random_numbers));{
$type = substr ( $random_number, 0, 1 );
if($type != 2 && $type != 1 ) break;
$sum = 0;
for( $i = 0 ; $i<10 ; $i++ ) {
if ( $i % 2 == 0){
$ZFOdd = str_pad ( ( substr($random_number, $i, 1) * 2 ), 2, "0", STR_PAD_LEFT );
$sum += substr ( $ZFOdd, 0, 1 ) + substr ( $ZFOdd, 1, 1 );
}else{
$sum += substr ( $random_number, $i, 1 );
}
}
return $sum%10 ? break : echo $random_number;
----------
echo "<br>";
$random_numbers[] = $random_number;}
}
Disclaimer: I'm not 100% sure on the validation required etc. for Saudi ID numbers and have only briefly looked at the answers supplied in the linked question
Okay, so, my understanding is that you need to generate a random id that:
Matches the pattern/format:
[12]\d{9}
Validates against the criteria show in the linked question:
Saudi Iqama/National Identity number field validation
To do this we need to create a couple of functions; one to generate IDs and one to validate the IDs against the given criteria.
Generate the ID
Simply generating an ID is simple enough. We can use the random_int function in PHP with a loop. If we enclose the code to generate the ID inside of a do...while... loop then we can execute the code and validate the ID repeatedly until we get a valid one.
function getRandomSaudiId() : int
{
do {
$saudiId = (string) random_int(1,2);
for($i = 0; $i < 9; $i++){
$saudiId .= random_int(0,9);
}
} while(validateSaudiId($saudiId) === false);
return (int) $saudiId;
}
Validate the ID
Note: we convert to string so that we can access the numbers based on their index.
function validateSaudiId(string $id) : bool
{
$sum = 0;
for($i = 0; $i < 9; $i++){
if( $i % 2 ){
// Even number
$sum += $id[$i];
}
else{
//Odd number
$increment = $id[$i] * 2;
while($increment > 9){
$increment = (string) $increment;
$increment = $increment[0] + $increment[1];
}
$sum += $increment;
}
}
$sum = (string) $sum;
return ($sum[1] == $id[9] || $id[9] == (10 - $sum[1])) ? true : false;
}
Example use
for($i = 0; $i < 10; $i++) var_dump(getRandomSaudiId());
/*
Output:
int(2933617506)
int(2409806096)
int(1072585118)
int(2891306413)
int(1810304558)
int(2591965856)
int(1363032527)
int(1031823269)
int(1265954048)
int(2498099472)
int(1134172537)
*/
I have a number of participants and a number of groups, and I have to organize the participants into groups.
Example:
10/3 = 3, 3 and 4.
10/9 = 2,2,2 and 4.
23/3 = 6,6,6 and 5.
I have tried with array_chunk using the size paramether as a rounded result of participants/groups but it Did not work well.
Edit with my problem solved.
$groups = $this->request->data['phases_limit'];
$classified_lmt = $this->request->data['classified_limit'];
$participants = count($game->user_has_game);
$participants_lmt = floor($participants / $groups);
$remainders = $participants % $groups;
if ($groups > $participants) {
throw new \Exception("Há mais grupos que participantes");
}
for ($i=0; $i < $groups; $i++) {
$p = $this->Phase->newEntity();
$p->name = 'Grupo #' . $game->id;
$p->game_id = $game->id;
$p->classified_limit = $classified_lmt;
$this->Phase->save($p);
// add the number of participants per group
for ($j=0; $j < $participants_lmt; $j++) {
$user_has_game = array_pop($game->user_has_game);
$g = $this->Phase->GroupUserHasGame->newEntity();
$g->group_id = $p->id;
$g->user_has_game_id = $user_has_game->id;
$this->Phase->GroupUserHasGame->save($g);
}
// check if it is the last iteration
if (($groups - 1) == $i) {
// add the remainders on the last iteration
for ($k=0; $k < $remainders; $k++) {
$user_has_game = array_pop($game->user_has_game);
$g = $this->Phase->GroupUserHasGame->newEntity();
$g->group_id = $p->id;
$g->user_has_game_id = $user_has_game->id;
$this->Phase->GroupUserHasGame->save($g);
}
}
}
Have you tried the modulus operator? It gives you the remainder after dividing the numerator by the denominator.
For example, if you want to split 10 people into 3 groups:
floor(10 / 3) = 3; // people per group
10 % 3 = 1; // 1 person left over to add to an existing group.
Edit - I included the following function as part of my original answer. This doesn't work for OP, however I want to leave it here, as it may help others.
function group($total, $groups)
{
// Calculate participants per group and remainder
$group = floor($total / $groups);
$remainder = $total % $groups;
// Prepare groupings and append remaining participant to first group
$groupings = array_fill(0, $groups, $group);
$groupings[0] += $remainder;
return $groupings;
}
Not sure there are off-the-shelf libraries for that. I just implemented something similar in Java if you need some ideas:
public List<Integer> createDistribution(int population_size, int groups) {
List<Integer> lst = new LinkedList();
int total = 0;
for (double d : createDistribution(groups)) {
// this makes smaller groups first int i = new Double(population_size * d).intValue();
int i = (int)Math.round(population_size * d);
total += i;
lst.add(i);
}
// Fix rounding errors
while (total < population_size) {
int i = r.nextInt(groups);
lst.set(i, lst.get(i) + 1);
total += 1;
}
while (total > population_size) {
int i = r.nextInt(groups);
if (lst.get(i) > 0) {
lst.set(i, lst.get(i) - 1);
total -= 1;
}
}
return lst;
}
Related to question from this Pearson correlation in PHP , now I'm using that function too for calculate similarity between 2 users with pearson correlation. What I wanna ask is :
I have database name ta_db
And I want to retrieve data from table interest which have 9 attributes into array
After that I want to calculate it with pearson correlation function.
public function similarity($user1, $user2) {
$sharedItem = array();
$pref1 = array();
$pref2 = array();
$result1 = $user1->fetchAllPreferences();
$result2 = $user2->fetchAllPreferences();
foreach($result1 as $pref){
$pref1[$pref->item_id] = $pref->rate;
}
foreach($result2 as $pref){
$pref2[$pref->item_id] = $pref->rate;
}
foreach ($pref1 as $item => $preferenza){
if(key_exists($item,$pref2)){
$sharedItem[$item] = 1;
}
}
$n = count($sharedItem);
if ($n == 0) return 0;
$sum1 = 0;$sum2 = 0;$sumSq1 = 0;$sumSq2 = 0;$pSum = 0;
foreach ($sharedItem as $item_id => $pre) {
$sum1 += $pref1[$item_id];
$sum2 += $pref2[$item_id];
$sumSq1 += pow($pref1[$item_id],2);
$sumSq2 += pow($pref2[$item_id],2);
$pSum += $pref1[$item_id] * $pref2[$item_id];
}
$num = $pSum - (($sum1 * $sum2) / $n);
$den = sqrt(($sumSq1 - pow($sum1,2)/$n) * ($sumSq2 - pow($sum2,2)/$n));
if ($den == 0) return 0;
return $num/$den;
}
From my explanation above, could you please tell me how to retrieve the data into Array? Thank you in advance for your help and clear explanation.
I have foreach which consist of the list of candidates. I'm trying to compute the percentage inside the foreach then output the result. I don't know the problem, I want the program to compute the first if statement(talent), after going to the next if statement(distance), then continue the computation. The echo will display the overall computation of percentage. Please help. Thanks in advance
$counter = 0;
$status = array();
foreach($candidate as $c){
$queryResult = mysql_query("SELECT * FROM candidates WHERE id = '$c'");
$row = mysql_fetch_assoc($queryResult);
if($talent == "good"){
$status[$counter] = + 0.10;
}else if($talent == "better"){
$status[$counter] = + 0.05;
}
if($distance == "1200m"){
$status[$counter] = + 0.10;
}else if($distance == "1400m"){
$status[$counter] = + 0.05;
}
echo $status[$counter] * 100 . "%<br>";
$counter ++;
}//foreach end
how about changing those =+ with +=, perhaps that is what you want ..? (e.g., $status[$counter] += 0.10;)
and try to initialize this before the foreach loop..
$array = array_fill(0,$number_of_candidates, 0);
Ok what i'm wanting to do is split a number ($row['count']) into 5, this is easy enough if you want equal numbers:
$sum = ($row['count'] / 5);
$fsum = floor($sum);
but I want each number to be different and still add up to total ie $row['count'] how can this be achieved?
Update:
If this helps its to be used to update 5 rows in a database:
$query = "SELECT * FROM foo";
$result = mysql_query($query);
while ($row = mysql_fetch_array($result)) {
$sum = ($row['count'] / 5);
$fsum = floor($sum);
$id = $row['id'];
$update = "UPDATE foo SET foo1='$fsum', foo2='$fsum', foo3='$fsum', foo4='$fsum', foo5='$fsum' WHERE id='$id'";
mysql_query($update);
}// while
so ideally the $update query would be something like:
$update = "UPDATE foo SET foo1='$fsum1', foo2='$fsum2', foo3='$fsum3', foo4='$fsum4', foo5='$fsum5' WHERE id='$id'";
This is my take:
function randomize($sum, $parts) {
$part_no = count($parts);
$continnue_counter = 0;
while (count(array_unique($parts)) != $part_no) {
$changing = array_rand($parts, 2);
if (($parts[$changing[0]] - 1) == 0 || ($parts[$changing[1]] - 1) == 0) { // don't let them go under 1
++$continnue_counter;
// sometime one element get everything and others even out on 1
// just throw away everything you got so far and start over
if ($continnue_counter > 10) {
$parts = setup($sum, $part_no);
$continnue_counter = 0;
}
continue;
}
$continnue_counter = 0;
$signum = mt_rand(0, 100) % 2 ? 1 : -1;
$delta = $signum * mt_rand(1, min($parts[$changing[0]] - 1, $parts[$changing[1]] - 1)); // -1 to make sure they don't go under 0
$parts[$changing[0]] += $delta;
$parts[$changing[1]] -= $delta;
}
return $parts;
}
function setup($sum, $part_no) {
$parts = array_fill(0, $part_no, (int)($sum / $part_no));
// acount for the reminder of (int) cast
$reminder = $sum - array_sum($parts);
while ($reminder) {
$parts[array_rand($parts)] += 1;
--$reminder;
}
return $parts;
}
$part_no = 5;
$sum = 42;
$parts = randomize($sum, setup($sum, $part_no));
var_export($parts);
print array_sum($parts)
Update:
I've added a version that introduces a little more entropy.
Update2:
The more random one had a tendency to decrement everything to 1 except one part, added an explicit detection to deal with this. Still the algorithm behind it has unknown termination time.