Simple requests: Under Calculate a Value what would you think of adding the operator: % (Modulus).

Also, instead of simply having 'round half up' and 'round half down' would it be possible to add the options of 'floor' and 'ceil'.

I had the use case for all three today and the work around was doable, but required adding extra steps.

I'm not the most proficient (aka: I can copy and paste) php, but if there is something I can help with I would love to.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mitchell’s picture

Project: Rules » Rules Data Transforms
Version: 7.x-2.x-dev » 7.x-1.x-dev
Component: Rules Engine » Code
Priority: Normal » Major

Hi, timodwhit.
Moving to the other project b/c it should provide good examples if you want to try to code this. Hopefully all this code will come back shortly.

mitchell’s picture

Marked #1371492: Rounding as duplicate.

mitchell’s picture

Project: Rules Data Transforms » Rules
Component: Code » Rules Engine
Issue tags: +data transforms

Moving back to Rules.
Tagging.

timodwhit’s picture

Mitchell,

Thanks for looking at this. If I knew how to patch, I would. I think it is fairly simple code because the PHP is fairly simple also.

$value = ceil()
$value = floor()
$value = x % y; where x is the value to take the modulus of and y is the mod. It would read x mod y.

thanks for the help. Also, nice meeting you in Denver.

mitchell’s picture

I think it is fairly simple code because the PHP is fairly simple also.

Yep, it is! See: rules_data_transforms.rules.inc for code that works exactly as you describe it, (without the ceil, floor, and mod). I'm not sure yet if that's the coding style that will get committed, but watch/contribute to #745314: Action: transform text to see/make what happens.

Also, nice meeting you in Denver.

Pleasure meeting you too!

timodwhit’s picture

function custom_rules_rules_action_info(){
  $actions = array(
        //Ceiling Action: ceil()
        'ceiling'=>array(
          'label' => t('Set ceiling of a number'),
          'group' => t('Custom Actions'),
          'parameter' => array(
            'input_a' => array( 
              'type'=> 'decimal',
              'label' => t('Variable to be ceil()')
              ),
          ),
          'provides' => array(
            'ceiling_result' => array(
              'type' => 'integer',
              'label' => t('Integer Result from ceil'),
            ),
          ),
         ),
        
        //Floor Action: floor()
         'flooring'=>array(
          'label' => t('Set floor of a number'),
          'group' => t('Custom Actions'),
          'parameter' => array(
            'input_b' => array(
              'type' => 'decimal',
              'label' => t('Variable to be floor()'),
            ),
          ),
          'provides' => array(
            'flooring_result' => array(
              'type' => 'integer',
              'label' => t('Integer Result from floor'),
            ),
          ),
      ),
        //Modulus: %
        'modulus' => array(
          'label' => t('Modulus'),
          'group' => t('Custom Actions'),
          'parameter' => array(
            'input c' => array(
              'type' =>'integer',
              'label' => t('First input value: c mod d.'),
            ),
            'input d' => array(
              'type' => 'integer',
              'label' => t('Second input value: c mod d'),
            ),
          ),
          'provides' => array(
            'modulus_result'=> array(
              'type' => 'integer',
              'label' => t('Modulus results'),
            ),
          ),
          
        ),
   );
return $actions;
}

function ceiling($input_a){
  $vars = ceil($input_a);
  return array('ceiling_result' => $vars);
} 

function flooring($input_b){
  $vars = floor($input_b);
  return array('flooring_result' => $vars);
} 

function modulus($input_c,$input_d){
  $vars = $input_c % $input_d;
  return array('modulus_result' => $vars);
}

wrote this last night. Feel free to use. Sorry if it isn't proper. Seemed to work for me.

mitchell’s picture

Good job, and congrats on producing code that works for you.... but this is, after all, the Rules issue queue.

Your code belongs in the project, at least that's what everyone looking at it will think, and what better way than to create a patch.

timodwhit’s picture

I'll try to create a patch in a couple weeks, unless someone wants to beat me to it! ;-)

geek-merlin’s picture

Status: Active » Closed (duplicate)

think it's good to extend the patch at #1301022: Action: type conversion for numbers, integers, and strings
so marking this as dup

occucopy’s picture

Hi timodwhit, is there a patch of this rolling around somewhere? Would love to be able to patch it in!

timodwhit’s picture

Hey Occucopy, I ended up making a custom module for actions. I don't know how to make patches, it is on my list of things to learn, I was also worried about making a patch and then having to recommit it every update.

Feel free and turn the above code into a patch if you're up to it...

occucopy’s picture

Hey timodwhit, I tried copy-and-pasting your code into my own custom module, but the options weren't showing up in the drop-down list. Is there any way you could post the one you made? Thanks a bunch!

timodwhit’s picture

FileSize
1.58 KB

Here you are. I think there are some custom commerce ones in there too, feel free to delete those.

occucopy’s picture

Great, thanks!

dbkern’s picture

This module appeared in the nick of time. Unfortunately, I can't find the options in any select lists either. I've cleared cache numerous time to no avail.

Am I correct that these additional options should be available in calculating a value? I very much need the ability to round a fraction down to the integer.

Can't make it work with custom php code either. I tried $my_variable=floor($my_variable); but the next action wouldn't take the value of this resulting variable, only the non-rounded prior variable. Any suggestions?

timodwhit’s picture

@dbKern The actions are under actions-> custom actions -> Set Floor...

dbkern’s picture

Aaaahhhhh.... Many thanks!! Should do the trick.

timodwhit’s picture

FileSize
1.32 KB

Reposting the module because it had specific commerce rules that would only work for my set up. Sorry about that.

Also, if anyone is super proficient at making patches. Please feel free to take and make this a patch, I'm pretty swamped and haven't had time to learn it...

dbkern’s picture

Thanks for the more specific module. I've got it enabled and it's working well.

timodwhit’s picture

Good to hear! :-)

mitchell’s picture

Title: Modulus, Ceiling, and Floor, Calculation » Action: modulus, ceiling, floor (rounding)
Status: Closed (duplicate) » Active

This issue is not a duplicate of #1301022: Action: type conversion for numbers, integers, and strings. More on that in my comment there, #15.
I have a couple comments about the original post and a small code review.

>> Under Calculate a Value what would you think of adding the operator: % (Modulus)
I might be missing something, but your code doesn't do that. What should the scope of this issue be? Please update the issue summary with this info.

>> Also, instead of simply having 'round half up' and 'round half down' would it be possible to add the options of 'floor' and 'ceil'.
This is an obscure reference to #1301022: Action: type conversion for numbers, integers, and strings, that I tried to clear up in #15.

On that note, how can decimal rounding be worked into this code? Should it be, should it not be?

Code review:
The function descriptions are currently use-case specific. It would help me very much to understand more use cases by explaining the concepts more generally, and if need be, with some examples. We'll still have the handbook too!

I'm going to ask fago in #745314: Action: transform text where all the new patches similarly tagged, 'data transforms', will go and if/how to make it easier to do. The patch in #1301022: Action: type conversion for numbers, integers, and strings fits with the current code layout.

timodwhit’s picture

Hey Mitchell,

WRT to use cases:

Modulus is a form of division. Where the number is divided and only produces the remainder. For example:
4 mod 2 = 0
5 mod 2 = 1
6 mod 2 = 0
6 mod 4 = 2 6/4 = 1 with a remainder of 2.

Ceiling: Rounds the number up to the integer regardless of the what side of the half it is on. 5.01 = 6

Floor: Rounds down to the integer regardless of what side of the half it is on. 5.99 = 5

Use Case for me was Shipping.
I have 4 box sizes that need to be accommodated for.

1 that holds 1 item = $12,
1 that holds 2 items = $15
1 that holds 3 items = $18
1 that holds 4 items = $20

The equation that you end up with is this: 12x + 8y + z = shipping cost

x = ceiling(total items/4)
y = floor(total items/4)
z = if (total items mod 4 = 1) = $3
else( total items mod 4= 2) = $5
else = 0

Hope this helps.

Mitchell, looked briefly at the post. I personally haven't looked into decimal rounding, so I cannot comment but I'm sure PHP would handle it appropriately and the rules framework seems like it would allow for anything PHP can do. I'll look at this over the weekend.

dbkern’s picture

My use case:

I needed to add $3 to shipping for every additional 10 pieces of merchandise ordered.

qty / 10 = y
y rounded down (floor)
y x 3 = amt
amt + base = total shipping

Hope this helps.

timodwhit’s picture

Component: Rules Engine » Rules Core

More math to insert:

       'max_number' => array(
          'label' => t('Max Number'),
          'group' => t('Custom Actions'),
          'parameter' => array(
            'input_a' => array(
              'type' =>'integer',
              'label' => t('Value 1'),
            ),
            'input_b' => array(
              'type' =>'integer',
              'label' => t('Value 2'),
            ),
          ),
          'provides' => array(
            'max_result'=> array(
              'type' => 'integer',
              'label' => t('Value results'),
            ),
          ),
        ),
        'min_number' => array(
          'label' => t('Min Number'),
          'group' => t('Custom Actions'),
          'parameter' => array(
            'input_a' => array(
              'type' =>'integer',
              'label' => t('Value 1'),
            ),
            'input_b' => array(
              'type' =>'integer',
              'label' => t('Value 2'),
            ),
          ),
          'provides' => array(
            'min_result'=> array(
              'type' => 'integer',
              'label' => t('Value results'),
            ),
          ),
        ),
     'abs_number' => array(
          'label' => t('Max Number'),
          'group' => t('Custom Actions'),
          'parameter' => array(
            'input_a' => array(
              'type' =>'integer',
              'label' => t('Value 1'),
            ),
            'input_b' => array(
              'type' =>'integer',
              'label' => t('Value 2'),
            ),
          ),
          'provides' => array(
            'abs_result'=> array(
              'type' => 'integer',
              'label' => t('Value results'),
            ),
          ),
        ),
function max_number($input_a,$input_b){
  $vars = max($input_a, $input_b);
  return array('max_result' => $vars);
}

function min_number($input_a,$input_b){
  $vars = min($input_a, $input_b);
  return array('min_result' => $vars);
}
function abs_number($input_a,$input_b){
  $vars = abs($input_a, $input_b);
  return array('abs_result' => $vars);
}

This provides the maximum number between two values, the minimum and the absolute value of a number. Simple PHP really, but should help with calculations.

admin@online’s picture

Hi

I have uploaded your module as I need to have different wholesale and retails pricing. I am using Drupal 7.

I cannot find where to 'activate' the rule? I have enabled it in the modules list, but how do I change the ADD OFFSET value to a percentage(%)?

Please assist. I see a lot of code above and am not very well learned in php.

admin@online’s picture

Version: 7.x-1.x-dev » 7.x-2.1
Priority: Major » Critical

Hi

I have uploaded your module as I need to have different wholesale and retails pricing. I am using Drupal 7.

I cannot find where to 'activate' the rule? I have enabled it in the modules list, but how do I change the ADD OFFSET value to a percentage(%)?

This is 1 of the major things holding me back from launching our site :(

Please assist. I see a lot of code above and am not very well learned in php.

Thanks in advance!!

admin@online’s picture

Version: 7.x-2.1 » 7.x-2.2
Category: feature » support

Hi

I have uploaded your module as I need to have different wholesale and retails pricing. I am using Drupal 7.

I cannot find where to 'activate' the rule? I have enabled it in the modules list, but how do I change the ADD OFFSET value to a percentage(%)?

This is 1 of the major things holding me back from launching our site :(

Please assist. I see a lot of code above and am not very well learned in php.

Thanks in advance!!

(Sorry for the multiple posts, it's just quite urgent)

geek-merlin’s picture

Category: support » feature
Priority: Critical » Normal

#25-#27:
@ismail: hijacking issues is NOT the way to win friends or get free support.
please go to forums or open a support issue. you might want to add steps to reproduce the issue there.

admin@online’s picture

Category: feature » support

Hi Axel, sorry about that. I am new to this whole issues, forum thingy. Did not mean to 'hijack' anything. Thought everything was open to everyone.. guess the 'community' and 'open source' threw me. lol. I did open an issue, but no responses :[...
What do you mean add steps?

geek-merlin’s picture

Version: 7.x-2.2 » 7.x-1.x-dev
Category: support » feature

you might want to leave this issue focused to erm, the original issue.

and you might want to read this for some key to better karma and positive relations to other developers.
Making an issue report | drupal.org
Getting an issue addressed sooner | drupal.org

timodwhit’s picture

Version: 7.x-1.x-dev » 7.x-2.2

Please link to your new issue, so that can be solved and put to rest.

Once you have enabled the module, all you need to do is add an action and the rules will be listed. If you don't see them, flush all caches, if that fails something went wrong somewhere.

To add an offset before the calculation is done, go into data selection, select your variable and then add offset. To add it after, select an appropriate action to perform on the variable output.

admin@online’s picture

I have created a wholesale authenticated user and a retail authenticated user. I want to assign a custom rule for anonymous and retail users to see different (retail) pricing. How do I change the Offset value from an integer to a percentage(%)? Rule listed below: Event: Calculating the sell price of a product Condition: User has roles... Actions: Add an amount to the price Is there anyway to change the ADD OFFSETvalue to a percentage(%)?

Hope i linked that correctly..
@ timodwhit
I have the custom rule module enabled.
I have attached the screenshot of my rule. I am sorry, but I am finding it tough to find the option to change that offset to a percentage :(. This is basically the only thing preventing the site from going live :[
Step by step assistance would greatly help if I am doing something wrong..

Thanks for your advice thus far

timodwhit’s picture

Two things:
1) see your issue I have responded there.
2) From below: "Project issue numbers (ex. [#12345]) turn into links automatically."

Horroshow’s picture

I'm trying to use modulus on a variable from a previous Calculate a value action. But the variable (result) is not available in the data selector drop down list.

KarlShea’s picture

Version: 7.x-2.2 » 7.x-2.x-dev
Issue summary: View changes
Status: Active » Needs review
FileSize
827 bytes

Attached is a patch to perform modulus during a data calculation. The rounding code already uses floor() and ceil() so it doesn't look like that is needed anymore.

Status: Needs review » Needs work

The last submitted patch, 35: rules-add-modulus-1479526-35.patch, failed testing. View results

TR’s picture

Status: Needs work » Needs review
FileSize
817 bytes

Rerolled patch #35 against current HEAD.

TR’s picture

Still need some reviews.

The data_calc action isn't explicitly tested in rules.test, although it is used indirectly a few tests (with the '*' and '+' operators) so there is at least some coverage.

At this point in the D7 Rules lifecycle we really ought to be adding a new test for each new feature, to ensure that the feature works and doesn't break Rules for our rather large user base. And since we have to write a test for the new '%' operation let's also take this opportunity to explicitly test the other operations - that will require almost no extra code.

Anyone need this feature? Interested in helping out here?

firfin’s picture

Works fine for me. Been using it on one environment for over a year.
Just re-applied it (manually, git didn't approve, so needs a re-roll) on another project and seems to do the trick there too.

Unfortunately I am not not capable of writing tests yet, but when I have some spare time I'll try and dive into it. Absolutely no promises there BTW ...
Should it start with D8 then? Of just D7 first?