Weighted Load Balancing Algorithm into PHP Application - php

I want to resolve weighted an Adapter from an factory which could be configured by user (enable/disable and weight %).
Example:
AdapterW ≃ 20% of transaction
AdapterX ≃ 30% of transaction
AdapterY ≃ 40% of transaction
AdapterZ ≃ 10% of transaction
I can grant that all items will never sum more than one hundred (100%), but sometimes any adapter could be deactivated.
I have the following parameters:
public function handleAdapter()
{
$isWActive = (boolean)$this->_config[self::W];
$isXActive = (boolean)$this->_config[self::X];
$isYActive = (boolean)$this->_config[self::Y];
$isZActive = (boolean)$this->_config[self::Z];
$WPercentage = (int)$this->_config[self::LOAD_BALANCE_W];
$XPercentage = (int)$this->_config[self::LOAD_BALANCE_X];
$YPercentage = (int)$this->_config[self::LOAD_BALANCE_Y];
$ZPercentage = (int)$this->_config[self::LOAD_BALANCE_Z];
.
.
.
return (self::W | self::X | self::Y | self::Z);
}
How can i balance weighted between this adapters dynamically?
Edit
created a gist to a executable code: https://gist.github.com/markomafs/5d892d06d6670909f9b4

This may not be the best approach, but you can try something like this:
public function handleAdapter()
{
//an array to return the balanced entries
$balancedEntries[] = false;
//verifies which of the options are active
$isWActive = (boolean)$this->_config[self::W];
$isXActive = (boolean)$this->_config[self::X];
$isYActive = (boolean)$this->_config[self::Y];
$isZActive = (boolean)$this->_config[self::Z];
//get configured percentage of each
$WPercentage = (int)$this->_config[self::LOAD_BALANCE_W];
$XPercentage = (int)$this->_config[self::LOAD_BALANCE_X];
$YPercentage = (int)$this->_config[self::LOAD_BALANCE_Y];
$ZPercentage = (int)$this->_config[self::LOAD_BALANCE_Z];
//here you fill the array according to the proportion defined by the percentages
if ($isWActive) {
for ($i = 0; $i < $WPercentage; $i++) {
$balancedEntries[] = self::W;
}
}
if ($isXActive) {
for ($i = 0; $i < $XPercentage; $i++) {
$balancedEntries[] = self::X;
}
}
if ($isYActive) {
for ($i = 0; $i < $YPercentage; $i++) {
$balancedEntries[] = self::Y;
}
}
if ($isZActive) {
for ($i = 0; $i < $ZPercentage; $i++) {
$balancedEntries[] = self::Z;
}
}
return $balancedEntries;
}
And then, in case you want a proportion of 1 to 100 (as in percentages):
$balancedResult = $balancedEntries[array_rand($balancedEntries, 1)];
Since array_rand will return 1 key from the original array, you use it to get it's value.

Another try, this should work for your case - But it only work if you have an adapter as a single char string, this is not visible by your question.
public function handleAdapter()
{
# a map with all adapters
$map = array(
self::W => self::LOAD_BALANCE_W,
self::X => self::LOAD_BALANCE_X,
self::Y => self::LOAD_BALANCE_Y,
self::Z => self::LOAD_BALANCE_Z
);
# generate a string map with one char per percentage point
$stringMap = "";
foreach($map as $key => $value){
# skip if disabled
if(!$this->_config[$key]) continue;
# repeat the key for each percentage point
$stringMap .= str_repeat($key, (int)$this->_config[$value]);
}
# return a random string char from the map
return $stringMap[rand(0, strlen($stringMap) - 1)];
}

Edit: I've misunderstood the question, the answer is wrong.
I understand your question so that you always want to return the adapter with the lowest load to force traffic to this adapter.
public function handleAdapter()
{
$isWActive = (boolean)$this->_config[self::W];
$isXActive = (boolean)$this->_config[self::X];
$isYActive = (boolean)$this->_config[self::Y];
$isZActive = (boolean)$this->_config[self::Z];
$WPercentage = (int)$this->_config[self::LOAD_BALANCE_W];
$XPercentage = (int)$this->_config[self::LOAD_BALANCE_X];
$YPercentage = (int)$this->_config[self::LOAD_BALANCE_Y];
$ZPercentage = (int)$this->_config[self::LOAD_BALANCE_Z];
$map = array();
if($isWActive) $map[self::W] = $WPercentage;
if($isXActive) $map[self::X] = $XPercentage;
if($isYActive) $map[self::Y] = $YPercentage;
if($isZActive) $map[self::Z] = $ZPercentage;
asort($map);
return key($map);
}
Edit: Fixed wrong sort(), you need asort() to maintain the index.

Related

Why do I get an array in response after calling an array value by key

I call a function, and I want to get a response with an array and two elements per key.
include_once($_SERVER['DOCUMENT_ROOT'].'/matsuka/_giveRandomQuestSearchPok.php');
$pokQ = QuestPoks::giveRandomQuestPok();
The function itself looks like this
public static function giveRandomQuestPok() {
$sC = \Work::$sql->prepare('SELECT region FROM users WHERE id = ?');
$sC->bind_param("i", $_SESSION['id']);
$sC->execute();
$dA = $sC->get_result();
$region = $dA->fetch_assoc();
if($region['region'] == 1){
include_once($_SERVER['DOCUMENT_ROOT'].'/matsuka/randomPoks/Kanto.php');
}elseif($region['region'] == 3){
include_once($_SERVER['DOCUMENT_ROOT'].'/matsuka/randomPoks/Hoenn.php');
}
$rarity = mt_rand(1,100);
if($rarity == 1){
$rare = 1;
$object = \matsuka\Rare[mt_rand(0, count(\matsuka\Rare) - 1)];
}elseif($rarity > 1 && $rarity <= 33){
$rare = 2;
$object = \matsuka\Uncommon[mt_rand(0, count(\matsuka\Uncommon) - 1)];
}else{
$rare = 3;
$object = \matsuka\Common[mt_rand(0, count(\matsuka\Common) - 1)];
}
$array = array();
$array['pok'] = $object;
$array['rare'] = $rare;
return $array;
}
After executing the function I want to assign two variables to control the result
$pok = $pokQ["pok"];
$rare = $pokQ["rare"];
But the handler still reads them as an array.
And when I paste it into sql I get an Array, although I was hoping to get the array data by their corresponding key.
In var_dump I get quite a strange answer. I seem to see the required value of array called by the key, but on top of that I see another array, if I understand correctly.
int(401)
{
"name":"\u0413\u0443\u0441\u0442\u0430\u0432",
"actionQuest":"<img src=\"\/img\/quests\/7.webp\" class=\"quest\"> \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0432 \u0437\u0430\u0434\u0430\u043d\u0438\u0438 \u00ab\u041f\u043e\u043c\u043e\u0449\u044c \u0441\u0442\u0430\u0440\u043e\u043c\u0443 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044e\u00bb. \u0417\u0430\u0433\u043b\u044f\u043d\u0438\u0442\u0435 \u0432 \u0410\u043a\u0432\u0430\u0431\u0443\u043a.",
"question":"\u0422\u044b \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u0441\u043f\u0440\u0430\u0432\u0438\u043b\u0441\u044f \u0441 \u043c\u043e\u0438\u043c \u043f\u0440\u043e\u0448\u043b\u044b\u043c \u0437\u0430\u0434\u0430\u043d\u0438\u0435\u043c. \u042f \u0445\u043e\u0440\u043e\u0448\u0435\u043d\u044c\u043a\u043e \u0438\u0437\u0443\u0447\u0438\u043b \u0442\u043e\u0433\u043e \u043f\u043e\u043a\u0435\u043c\u043e\u043d\u0430. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043d\u0435 \u043d\u0443\u0436\u0435\u043d: <div class=\"questPokemon\"><img src=\"\/img\/pokemons\/mini\/normal\/Array.webp\"> <div>#Array <\/div><\/div>"
}
Why does this happen and what is my mistake?
In the array I should only get 3-digit numbers under each key

How to rewrite a php script to JavaScript

I have an express server running using nodejs, and I'm using SQL syntax to query data from my MYSQL database.
The query is to get all members under the current user ID and also get members under it's children and so on, to get a genealogy tree. I'm trying to query a genealogy tree for a user.
I have a PHP script for the query, which worked fine
This is the PHP script:
$memory = $_GET['memory'];
echo '<div style="background:#ccc;display:flex;width:50px;height:50px;justify-
content:center;align-items:center;border-radius:50%;">'.$memory.'</div>';
$transend = array($memory);
$step = 1;
for ($i=0; $i < $step; $i++) {
$under = $transend[$i];
$get = $con->query("SELECT * FROM multilevel WHERE `under`='$under'");
$cnt = $get->num_rows;
if ($cnt>0) {
for ($g=0; $g < $cnt; $g++) {
$fet = $get->fetch_object();
$id = $fet->id;
$position = $fet->position;
array_push($transend, $id);
$step = $step*2;
echo '<div style="background:#ccc;display:flex;width:50px;height:50px;justify-content:center;align-items:center;border-radius:50%;">'.$id.'-'.$position.'</div>';
}
} else {
break;
}
}
I am trying to rewrite it using SQL syntax in node. This is my nodejs code:
A Tree Constructor
const Tree = function (binary) {
this.position = binary.position;
this.level = binary.level;
this.user_id = binary.user_id;
this.under_user_id = binary.under_user_id;
this.brought_by = binary.brought_by;
this.username = binary.username;
};
A method to get all binary for a user
Tree.findBinaries = async (id, result) => {
const theId = parseInt(id);
let transend = [theId];
let step = 1;
let data = [];
for (let i = 0; i < step; i++) {
const under = transend[i];
connection.query(
`SELECT * FROM multilevel WHERE under = ?`,
under,
(err, res) => {
if (err) {
result(null, err);
return;
}
if (res.length) {
for (let index = 0; index < res.length; index++) {
const { id } = res[index];
// push id
transend.push(id);
data.push(res[index]);
step = step * 2;
}
result(null, data);
} else {
result(null, "no data found");
}
}
);
}
};
The transend.push(id) and data.push(res[index]), are not been pushed to the top level, also the step is not been updated. So the loop is running just once.
The expected Result is supposed to be 16 items of children and children of children, But it is currently returning to just the first level. I don't know what I'm currently doing wrong.

MariabDB synchronous UPDATE query

I'm working with PHP and MariaDB and I run into a problem.
I update a value to multiple rows, and then SELECT there rows to make a new calculation the data for another task.
The problem here that I get the wrong number. I guess that the MariaDB has not finished the UPDATE query, but it return the finished flag to PHP and then the PHP proceeds the SELECT query. [I just guess]
I open to any idea. If I'm wrong, please correct me.
Thank you for sharing
This is my code
$modelAdminOrderBidSys = $this->load->model('Admin\Order\BidSys');
$acceptedItem = typeCast($modelAdminOrderBidSys->getItem($cartItemId));
if (!$acceptedItem) {
return array(
'result' => 'error',
'message' => 'Cannot find item #' . $cartItemId
);
}
$acceptedItem['lastOffer'] = $acceptedItem['offer'];
$acceptedItem['accepted'] = 1;
$acceptedItem['isBot'] = 0;
$modelAdminOrderBidSys->updateItem($cartItemId, array2object($acceptedItem));
$cartItems = typeCast($modelAdminOrderBidSys->getItems($acceptedItem['cartId']));
$accepted = 1;
$total = 0;
$offer = 0;
$lastOffer = 0;
foreach($cartItems as $cartItem) {
if ((int)$cartItem['accepted'] < 1) {
$accepted = 0;
}
$total += (float)$cartItem['total'];
$offer += (float)$cartItem['offer'];
$lastOffer += (float)$cartItem['lastOffer'];
}
$postField = new \stdClass();
$postField->accepted = $accepted;
$postField->total = $total;
$postField->offer = $offer;
$postField->lastOffer = $lastOffer;
$modelAdminOrderBidSys->updateCart($acceptedItem['cartId'], $postField);
It sounds like your SELECT transaction starts before the UPDATE has committed. Try changing the transaction_isolation (in config) / tx_isolation (at runtime with SET GLOBAL) to READ-COMMITTED. Default is REPEATABLE-READ.

Filing or balancing array with dynamic generated index and values

Basically I want to balance an array.
The array I want to balance is retrieved from DB and can be unknown
Here is sample array retrieved from DB, it can vary
<?php
$arr_from_DB = array(
'1'=>NULL,
'2'=>1,
'3'=>1,
);
$node_width_from_DB = 3;
$node_depth_from_DB = 2;
?>
//Max Capacity was caclulated from $node_width_from_DB, $node_depth_from_DB AND WAS ALSO SAVED in DB , simulated below for width = 3 , depth = 2
$max_cap_of_array = 13;
//With $arr_from_DB fed to the display fxn on frontend, this is the result
//What I want to achieve, I want to transform $arr_from_DB to below ARray, All Array index with negative is seen to be dynamically generated
<?php
$formated_arr = array(
'1'=>NULL,
'2'=>1,
'3'=>1,
'-1'=>1,
'-2'=>2,
'-3'=>2,
'-4'=>2,
'-5'=>3,
'-6'=>3,
'-7'=>3,
'-8'=>-1,
'-9'=>-1,
'-10'=>-1,
);
?>
//With $formated_arr fed to the display fxn on frontend, this is the result
WHAT I TRIED SO FAR
<?php
$arr_filled = RECfillMissingDownlineArr($arr_from_DB);
var_dump($arr_filled);
function RECfillMissingDownlineArr($selectedArr, $pointer=1){
$node_width_from_DB = 3;
$node_depth_from_DB = 2;
//Max Capacity was caclulated from $node_width_from_DB, $node_depth_from_DB AND WAS ALSO SAVED in DB , simulated below for width = 3 , depth = 2
$max_cap_of_array = 13;
//var_dump($Allarr);
if($pointer>= $max_cap_of_array){
return $selectedArr;
}
$array_worked = array_count_values($selectedArr);
$array_worked3 = array_keys($selectedArr);
$array_worked2 = array_values($array_worked3);
//$key_p = $array_worked3[$pointer];
foreach($array_worked as $key=>$value){
//echo 'Value nm'.$value.'<br>';
if($value<$node_width_from_DB){
$key_p = $key;
break;
}
}
$array_worked1 = array_keys($selectedArr, $key_p);
for ($i=0; $i <$width ; $i++) {
if(empty($array_worked1[$i])){
$key_pointer = $pointer * -1;
$selectedArr[$key_pointer] = $key;
$pointer++;
return RECfillMissingDownlineArr($selectedArr,$pointer);
}
}
}
OUTPUT NULL, It's not what I want, it's returning null alltogether
?>

Catch Tweets with JSON and sort by likes?

I am currently running a wordpress backend and want to display some tweets based on hastags on my website. For the general API request and database storage, I use this function:
private function parseRequest($json) {
$tmp = $json;
$result = array();
if (isset($json['statuses'])) {
$tmp = $json['statuses'];
}
if (isset($tmp) && is_array($tmp)){
foreach ($tmp as $t) {
$this->image = null;
$this->media = null;
$tc = new \stdClass();
$tc->feed_id = $this->id();
$tc->id = $t['id_str'];
$tc->type = $this->getType();
$tc->nickname = '#'.$t['user']['screen_name'];
$tc->screenname = (string)$t['user']['name'];
$tc->userpic = str_replace('.jpg', '_200x200.jpg', str_replace('_normal', '', (string)$t['user']['profile_image_url']));
$tc->system_timestamp = strtotime($t['created_at']);
$tc->text = $this->getText($t);
$tc->userlink = 'https://twitter.com/'.$t['user']['screen_name'];
$tc->permalink = $tc->userlink . '/status/' . $tc->id;
$tc->media = $this->getMedia($t);
#$tc->additional = array('shares' => (string)$t['retweet_count'], 'likes' => (string)$t['favorite_count'], 'comments' => (string)$t['reply_count']);
if ($this->isSuitablePost($tc)) $result[$tc->id] = $tc;
}
}
return $result;
}
Now I am looking for a function that counts all the variable in the "additional array together e.g. shares + likes + comments and sorts all posts based on the resulting number.
I am using the standard wordpress sql database. I cannot find a solution or I am just blind.
Thanks in regards
You could use a simple usort function:
usort($tc, function($a, $b) {
$a_sum = array_sum($a->additional);
$b_sum = array_sum($b->additional);
if ($a_sum == $b_sum) {
return 0;
}
return ($a_sum < $b_sum) ? -1 : 1;
});

Categories