1

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

Markomafs
  • 546
  • 4
  • 19
  • This will help you make a question that gets effective answer: http://stackoverflow.com/help/mcve – Topological Sort Nov 18 '15 at 18:23
  • sorry, but according to this link, my question is Minimal, Complete and Verifiable. Can you help me and send a edit suggestion? – Markomafs Nov 19 '15 at 11:38
  • I just checked the link. According to it, a Complete example is one such that has "all parts needed to reproduce the problem." An MCE is something I can _run_. I can't run your function as is. It doesn't even have the tags. When I provide it tags and load it, I get the error that "public" is unexpected here. To run it, I have to fix the tags, create your object, set up some code that calls this function, and print the results. Don't know how. Why not tell us? – Topological Sort Nov 19 '15 at 16:44
  • MCE its about to reproduce, not exactly run and jsfiddle is about JS/HTML/CSS not php. but i create a which you could reproduce : https://gist.github.com/markomafs/5d892d06d6670909f9b4 – Markomafs Nov 19 '15 at 18:06
  • OK, I ran it. It produced a lot of W's. I have no way of knowing if this is correct output. So I'll give up. – Topological Sort Nov 19 '15 at 18:15
  • the expeted output is fews "W", Some "X", More Some "Y" and many "Z" – Markomafs Nov 19 '15 at 19:08

3 Answers3

2

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.

1

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)];
}
Brain Foo Long
  • 2,057
  • 23
  • 28
0

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.

Brain Foo Long
  • 2,057
  • 23
  • 28