Add to (not overwrite) a global variable from a Loop PHP - php

I'm working on a php script that adds up points from voting using the borda count. I've got files read, data set up, but I'm struggling to set up a way to put an individuals points into their array. Right now I have an array of candidates, and an array of votes. I'm attempting to add up the votes and put them inside of the candidate array. The first number in each vote index responds to the first candidate, and so on. I have the program calculating the vote points correctly, but I can't get them to add together so I have the final number once it finishes.
edit: This script is also supposed to be scalable, meaning if I have 6 candidates, rather than 4, it will work. If there's something that jumps out at the reader saying it won't work, please let me know
<?php
$file = $argv[1];
$inputFile = fopen($file,"r");
$candidates = fgets($inputFile);
$candidates = str_replace(' ','',$candidates);
echo $candidates;
$candidates = explode(',',$candidates);
print_r($candidates);
$numCandidates = count($candidates);
echo "The number of candidates is: " . $numCandidates. "\n";
/**
$testFile = file_get_contents("$argv[1]");
$testFile = explode('\n',$testFile);
print_r($testFile);
*/
while (!feof($inputFile)){
$votes[] = trim(fgets($inputFile),"\n");
}
unset($votes[count($votes)-1]);
//$votes = trim("\n",$votes);
//$votes = explode(',',$votes);
print_r($votes);
for ($i = 0; $i<count($votes); $i++){
$votes[$i] = str_replace(',','',$votes[$i]);
}
print_r($votes);
/**
for($x = 0;$x<count($candidates);$x++){
$z = 0;
for($y = 0;$y<count($votes);$y++){
$candidates[$x][$y] = $votes[$y][$z];
}
print_r($candidates[0]);
$z++;
}
*/
for ($x = 0; $x<count($votes);$x++){
global $candidates;
for ($y=0; $y<count($candidates);$y++){
$candidates[$y][0]= (($numCandidates + 1)-$votes[$x][$y]);
echo "\nThe value of candidate $y is " . $candidates[$y][0];
}
}
?>
This is where I'm attempting to add to the amount, but it just keeps overwriting.
for ($x = 0; $x<count($votes);$x++){
global $candidates;
for ($y=0; $y<count($candidates);$y++){
$candidates[$y][0]= (($numCandidates + 1)-$votes[$x][$y]);
echo "\nThe value of candidate $y is " . $candidates[$y][0];
}
}
Edit: When I attempt to use += rather than = in
$candidates[$y][0] = (($numCandidates + 1)-$votes[$x][$y]);
I get an error saying "can't use assign-op operators with overloaded objects nor string offsets"

$candidates[$y][0] = (($numCandidates + 1)-$votes[$x][$y]);
That = should be += so that your loop keeps adding the value, instead of overwriting the existing value on every iteration.
$candidates[$y][0] += (($numCandidates + 1)-$votes[$x][$y]);

Related

How to create a php variable with text and value of another variable

Want to create a php variable using text before and after the value of another variable.
variable variables. But have only seen examples of assignment with no text.
$vsBOA_W[]=$rows['vsBOA_W'];
// BOA = team 3-char abbreviation. Looking for something similar to above but insert 3-char abbreviations based on a input file.
$numOfTeams = 3; // Determined from external source
$teamAbbr = array("BOA","CAA","CHN"); // For simplicity for this example. This array would normally be created from an external source.
for($i=0; $i<$numOfTeams; $i++) { // I know I can use size of array instead of nunOfTeams. That's not the issue.
echo $teamAbbr[$i]."<br>"; // for testing
$$("vs".{'$teamAbbr[$i]'}."_W[]"} = $rows['$$("vs".{'$teamAbbr[$i]'}."_W"}']; // a total guess
}
I expect the end result to look like:
$vsBOA_W[]=$rows['vsBOA_W'];
for BOA
Update #2: I tried the following (breaking down each step) and get the same error on $$TeamWins assignment.
for($i=0; $i<$numOfTeams; $i++) {
echo $teamAbbr[$i]."<br>";
$TeamWins = 'vs' . $teamAbbr[$i] . '_W';
echo "TeamWins=$TeamWins<br>";
$TeamWinsHold = $rows[$TeamWins];
echo "TeamWinsHold=$TeamWinsHold<br>";
$$TeamWins[] = $TeamWinsHold;
}
Update #3:
for($i=0; $i<$numOfTeams; $i++) {
echo $teamAbbr[$i]."<br>";
$TeamWins = 'vs' . $teamAbbr[$i] . '_W';
echo "TeamWins=$TeamWins<br>";
$TeamWinsHold = $rows[$TeamWins];
echo "TeamWinsHold=$TeamWinsHold<br>";
${$TeamWins}[] = $TeamWinsHold;
}
foreach(${$TeamWins} as $value) {
echo "value=$value<br>"; // only displays last element or value assigned from above loop.
}
Update #4 (final):
$teamW = array();
$teamL = array();
for($i=0; $i<$numOfTeams; $i++) {
//echo $teamAbbr[$i]."<br>";
$teamWName = 'vs' . $teamAbbr[$i] . '_W';
$teamLName = 'vs' . $teamAbbr[$i] . '_L';
//echo "teamWName=$teamWName<br>";
//echo "teamLName=$teamLName<br>";
$teamW[$teamWName] = $rows[$teamWName];
$teamL[$teamLName] = $rows[$teamLName];
}
I don't quite understand the interplay with the rows in your example. But going by your guess assignment, you can always simplify, by forming the variable name upfront:
<?php
$rows = ['xFOOy'=>[], 'xBARy'=>[], 'xBAZy'=>[]];
$items = ['FOO', 'BAR', 'BAZ'];
foreach($items as $abbr)
{
$name = 'x' . $abbr . 'y';
${$name}[] = $rows[$name];
}
But, I'd say you'd be better off with a keyed array than variable variables, as it makes for easier inspection, and there is less chance of namespace clashes.

Breaking out of loop in PHP and resetting the counters

There is some logic error in my code and I am not sure what I am doing wrong here.
Setting up things first, I have a .json file that I am reading which is in this layout:
So the polygon element is at every 1, 3, 5, .. and the school name is one prior to that.
Now I have another .csv file from where I am taking different lat and long values. Basically I have to see if that lat long from the csv file is inside any of these polygons as described in the json file.
Here is my part of the PHP code that takes in the json file and csv file. My logic is that, I take one lat and long value from the CSV and then want to go over each polygon in the json file.
If you follow the code below, I take in the values and when I meet the condition that it is outside a polygon, it just breaks out of the second while loop, takes another set of lat and longs.
$string = file_get_contents("Schools.json", 0, null, null);
$json_a = json_decode($string, true);
$start_row = 4;
$rowID = 1;
$polygonIndex = 1;
$insideCheck = 0;
$file = fopen("ActiveProperty.csv", "r");
while (($row = fgetcsv($file)) !== FALSE){
if($rowID >= $start_row){
$points = array($row[52] . ' ' . $row[49]);
$polygonIndex = 1;
while ($polygonIndex < 454){
$polygon = $json_a[$polygonIndex]['Polygons'];
foreach($points as $key => $point) {
if ($pointLocation->pointInPolygon($point, $polygon) == "outside"){
echo "point " . ($key+1) . " ($point): " . $pointLocation->pointInPolygon($point, $polygon);
echo "<br>";
$polygonIndex = $polygonIndex + 2;
echo $polygonIndex;
$insideCheck = 0;
break;
}
else {
echo $json_a[$polygonIndex - 1];
echo "<br>";
echo "point " . ($key+1) . " ($point): " . $pointLocation->pointInPolygon($point, $polygon);
echo "<br>";
$insideCheck = 1;
break;
}
}
if ($insideCheck = 0) {
echo "out of foreach 0";
continue;
}
else {
echo "out of foreach";
$insideCheck = 0;
break;
}
}
}
$rowID++;
}
Here is a sample output that I have:
Lat and longs in this image is from the csv file.
The expected output should be that with that lat and long, it should go over the polygons in the json and if its inside, return the first element which is the school. Here $polygonIndex just stays 3 which I am guessing is the issue.
If this is still unclear what I am trying to do, please let me know. Thanks.

PHP create unique value compared to values from object

I need to create a unique value for $total, to be different from all other values from received object. It should compare total with order_amount from object, and then if it is the same, it should increase its value by 0.00000001, and then check again through that object to see if it matches again with another order_amount. The end result should be a unique value, with minimal increase compared to the starting $total value. All values are set to have 8 decmal places.
I have tried with the following but it won't get me the result i need. What am i doing wrong?
function unique_amount($amount, $rate) {
$total = round($amount / $rate, 8);
$other_amounts = some object...;
foreach($other_amounts as $amount) {
if ($amount->order_amount == $total) {
$total = $total + 0.00000001;
}
}
return $total;
}
<?php
define('EPSILON',0.00000001);
$total = 4.00000000;
$other_amounts = [4.00000001,4.00000000,4.00000002];
sort($other_amounts);
foreach($other_amounts as $each_amount){
if($total === $each_amount){ // $total === $each_amount->order_amount , incase of objects
$total += EPSILON;
}
}
var_dump($total);
OUTPUT
float(4.00000003)
You may add an additional break if $total < $each_amount to make it a bit more efficient.
UPDATE
To sort objects in $other_amounts based on amount, you can use usort.
usort($other_amounts,function($o1,$o2){
if($o1->order_amount < $o2->order_amount ) return -1;
else if($o1->order_amount > $o2->order_amount ) return 1;
return 0;
});
Ok, here's the solution I came up with. First I created a function to deliver random objects with random totals so I could work with, unnecessary for you but useful for the sake of this test:
function generate_objects()
{
$outputObjects = [];
for ($i=0; $i < 100; $i++) {
$object = new \stdClass();
$mainValue = random_int(1,9);
$decimalValue = random_int(1,9);
$object->order_amount = "{$mainValue}.0000000{$decimalValue}";
$outputObjects[] = $object;
}
return $outputObjects;
}
And now for the solution part, first the code, then the explanation:
function unique_amount($amount, $rate) {
$total = number_format(round($amount / $rate, 8), 4);
$searchTotal = $total;
if (strpos((string) $searchTotal, '.') !== false) {
$searchTotal = str_replace('.', '\.', $searchTotal);
}
$other_amounts = generate_objects();
$similarTotals = [];
foreach($other_amounts as $amount) {
if (preg_match("/^$searchTotal/", $amount->order_amount)) {
$similarTotals[] = $amount->order_amount;
}
}
if (!empty($similarTotals)) {
rsort($similarTotals);
$total = ($similarTotals[0] + 0.00000001);
}
// DEBUG
//echo '<pre>';
//$vars = get_defined_vars();
//unset($vars['other_amounts']);
//print_r($vars);
//die;
return $total;
}
$test = unique_amount(8,1);
echo $test;
I decided to use RegEx to find the amounts that starts with the ones I provided. Since in the exercise I provided only integers with 1-9 in the last decimal case, I tracked them and added them to one array $similarTotals.
Then I sorted this array, if not empty, descending by the values, got the first item and incremented by 0.00000001.
So, finally, returning either the $total (assuming nothing was found) or the incremented first item in the array.
PS. I did not expect this code to be this big but, well...
You can see the test here: https://3v4l.org/WGThI

Using arrays in classes PHP

I'm experimenting with classes and objects for the first time and I thought I'd make a template for a Box that can store things like Books. (Thinking in terms of real-world items)
<?php
function feetToInches($feet){
$feet = $feet * 12;
return $feet;
}
class Book{
var $l = 6;
var $w = 5;
var $h = 1;
}
class Box{
//This is a box. It has length, width, and height, and you can put things in it.
var $length = 0;
var $width = 0;
var $height = 0;
var $storedArray = array();
function setDimensions($l, $w, $h){
$this->length = feetToInches($l);
$this->width = feetToInches($w);
$this->height = feetToInches($h);
}
function storeThings($thing){
$this->storedArray[] = $thing;
}
function getThings(){
return $this->storedArray;
}
}
$thatBook = new Book;
$BookBox = new Box;
$BookBox->setDimensions(6,5,1);
for($i = 0; $i < 5; $i++){
$BookBox->storeThings($thatBook);
}
echo $BookBox->getThings() . "<br />";
/*
foreach($BookBox->getThings() as $item){
echo $item;
}
*/
var_dump($BookBox);
?>
So what I have is simple here, you have boxes of a dimension, and you throw books of a fixed dimension in them.
Putting things in it is no problem, but when I try to retrieve them, I either get errors or nothing happens. And when I try to specify a key for the array like
echo $BookBox->getThings()[2];
I get an error that it's not an array or something.
So can someone please point me in the right direction here?
And normally the class would be a separate file, but I'm just learning here.
What version of PHP are you using.
Array dereferencing (referencing into a returned array) was only added in PHP 5.4.
If you're using a previous version, you'd have to do this:
$books = $BookBox->getThings();
echo $books[2];
Edit
Since you are pushing Books into a box, $books[2] returns you an instance of the Book object. Echo is used to output a string, hence the error.
You can either echo a particular property of the book, or print out all of the properties by doing:
print_r($books[2]);
First, you cannot do echo since what you'll get is not a string but an object. Use print_r() or var_dump() instead.
Second, just like the other answers here, you should do this.
$books = $BookBox->getThings();
print_r($books[2]);
But I suggest you to make getThings() accept a variable for getting a specified array element:
function getThings($key = null) {
if ($key) {
return isset($this->storedArray[$key]) ? $this->storedArray[$key] : null;
} else {
return $this->storedArray;
}
}
// Then you can do this
// print_r($BookBox->getThings(2));
What you are calling when you call $BookBox->getThings() is actually an object and not an array.
You might try something along the lines of:
$books = $BookBox->GetThings();
echo $books[2];

continued : unable to post fields to the next page in php and HTML

So I have fields that are generated dynamically in a different page and then their results should posted to story.php page. fields is going to be : *noun1 *noun2 *noun3 and story is going to be : somebody is doing *noun1 etc. What I want to do is to replace *noun1 in the story with the *noun, I have posted from the previous page ( I have *noun1 posted from the previous page ) but the code below is not working :
$fields = $_POST['fields'];
$story = $_POST['story'];
$fieldsArray = split(' ', $fields);
for ($i = 0; $i < count($fieldsArray); $i++) {
${$fieldsArray[$i]} = $_POST[$fieldsArray[$i]];
}
// replace words in story with input
for ($i = 0; $i < count($story); $i++) {
$thisWord = $story[$i];
if ($thisWord[0] == '*')
$story[$i] = ${$thisWord.substring(1)};
}
$tokensArray = split(' ',$tokens);
echo $story;
Your problem is likely that you are trying to echo $story, which I gather is an array. You might have better luck with the following:
$storyString = '';
for ($i = 0; $i < count($story); $i++)
{
$storyString .= $story[i] . ' ';
}
echo $storyString;
echo can't print an array, but you can echo strings to your heart's content.
You almost certainly don't want variable variables (e.g. ${$fieldsArray[$i]}). Also, $thisWord.substring(1) looks like you're trying to invoke a method, but that's not what it does; . is for string concatenation. In PHP, strings aren't objects. Use the substr function to get a substring.
preg_replace_callback can replace all your code, but its use of higher order functions might be too much to get into right now. For example,
function sequence($arr) {
return function() {
static $i=0
$val = $arr[$i++];
$i %= count($arr);
return $val;
}
}
echo preg_replace_callback('/\*\w+/', sequence(array('Dog', 'man')), "*Man bites *dog.");
will produce "Dog bites man." Code sample requires PHP 5.3 for anonymous functions.

Categories