Ruby Case statement


MarkMc
 Share

Recommended Posts

I finally got this to work thanks to Michael,(and a quick skype from Michael Big thanks :) and Joe (Notepad++ helped :) and assorted posts from the macro gang.

Questions-

is there a way to shorten what I have (EVO label almost) using  blocks, arrays, or hashes? I still have to add several categories to this and then I have to redo some of it for 4 other brands of cabinet so simplifying it would be nice. Since I just got out of one rabbit hole thought I ask if or which one I should go down next.

 

Second- I had a heck of a time with the case statement. I tried defining it  a lot of ways such as

cabtype=owner.description

case cabtype

when cabtype=="base cabinet"----

result "xyz"

when cabtype=="utility cabinet"...

result "abc"

Finally got this to work with an undefined case statement.

I used case because I may have ranges in there and it looked easier to me. I did try "IF" statements with about he same amount of errors, this is just what I finally got to work.

 

Attached the label macro as it stands (Evo label almost) and the dimension macros that are in it.

 

Edited out an oops_mia culpa-deleted macros for now, did not realize until I saw BT's note.

BTW there was an oops in the utility cabinet section

 

 

 

Link to comment
Share on other sites

1 hour ago, BrownTiger said:

There are many ways to code the same thing...

Thanks. Alas it only works on base and utility cabinets AND only if they are 24" deep. Errors on wall cabinets and any other depth. Still will be a good learning experience :)

 

I see you defined the dimensions within the macro itself. (this is a question..)

One reason I used %xyz dims% instead of writing it in directly was I want to write this for several other brands of cabinets. Those brands allow smaller dimensional changes and use different nomenclature. I was thinking that it would be easier to find and replace %xyz dims% with %zzz dims%  (say to 16ths, or 1/8ths instead of half or 1inch)  and then just change some of the "TEXT" in the results to match the brands nomenclature. ??

Link to comment
Share on other sites

5 hours ago, MarkMc said:

Thanks. Alas it only works on base and utility cabinets AND only if they are 24" deep.

 

I do NOT have X9, did not have ChiefArchitect. Just used JavaDeveloper to type it. If something works - it is a miracle.

 

5 hours ago, MarkMc said:

One reason I used %xyz dims% instead of writing it in directly was I want to write this for several other brands of cabinets.

 

OOP has three principals. I followed Encapsulation rule and got rid of OWNER notation (choosing NONE instead), using global functions (macro) never a good excuse in my book.  

 

My $.02

Link to comment
Share on other sites

I think your macro could be greatly simplified and made easier to read/understand but i also think you now have several potential conflicts now-- hard to tell what you intend.

 

If you could  define what codes are to be used for each type/condition and under what conditions/dims dims are to be added and which? Would help greatly.

The secret to a good code snippet is not to just start writing but have a clear spec of what you want to accomplish first.

What I got:

 

1. B = Base Cabinet

2. W = Wall Cabinet

3. Sink = SR

4, Tall = U

5. 2 = width > 24

6. depth of 13 == Wall Base

7. Other dim criteria which is not clear and seems to overlap others?

8. dims on end of label string are dependent on what criteria to be shown?

 

 

Link to comment
Share on other sites

10 hours ago, BrownTiger said:

If something works - it is a miracle.

That's how I feel once past 4 or 5 lines.

Looked up 3 principals (will have to read that a few more times)-Encapsulation is why you placed the dimension code in the beginning instead of using %xyx%? The purpose being that the macro won't be broken if the %xyz% changes in the future?.

I thought that when you folks said to stay away from "global" it was referring to $xyz ?

 

I'd written lots of versions and parts of this. Copied, edited, tried with NONE, with "referenced ? obj = referenced : obj = owner", with and without "owner." "obj." (and my cousin Vinny), Case, If/elsif....

Until I got a bit to work, would then try adding a piece of the next section, when that failed would try again until I got a few pieces strung together. Then built it all, which didn't work, fixed that.

Bottom line is I did not always know what was wrong but I did try lots of things.

 

5 hours ago, GerryT said:

I think your macro could be greatly simplified and made easier to read/understand but i also think you now have several potential conflicts now-- hard to tell what you intend.

I was hoping there was a simpler way.

NOTE There is a mistake in what I posted originally in the third section #Tall. Several lines read "wall cabinet" should read "utility cabinet" Is that the conflicts you are referring to?

 

This is intended as label for the cabinets that I can insert with a hotkey for one brand. Few things change with other brands once it is done. Cabinets that require face configuration, hence other nomenclature are kept in the user library and brought in with "replace from.."

 

List you have accurate except

3) Sink= SRB (I see that could just be adding SR-I just don't know how yet)

5) 2 = width >=24 (chief doesn't offer "number of doors"-24 comes both ways so decided on "2" at 24 since rarely use that size.

6) depth of 13 == Wall Base (BW) or Utility Base (UW)

8) end of string is  depth of cabinet (2B27-18) When not 13 or 24

8) you're questions got me thinking that it might be simpler to make the depth as a separate macro added into the label box. Or added to all as an option (don't know how to do that  yet)

 

Since first posting I discovered that I will also need to have something for fillers since Chief uses the default cabinet label for fillers and we place those with hotkeys.

9) three more- Filler Utility, filler wall, filler base. We don't use the size drawn in the model for those, instead the size ordered.

In this brand they all read F (3, 6, 9) height except for base fillers which need to read F 3,6, or 9 with height less toe kick (4.5 in this case)

In other brands they will read BF (1.5, 3, 6);   WF or TF 1.5,3,6 height

 

10) thinking of adding for corner cabinets both wall and base with variable diagonal face true or false. But may just replace from library for those. So may have that throw an "oops"

11) While right now "number of drawers" is handled using "Replace from..."  I've considered using "num drawers" to throw an error as a red flag in case someone altered the face of a cabinet.

 

A)Things I was thinking I might investigate- using some collection then comparing to collection? Or using some collection and returning the result ?

B) Using "until"? then something for fillers?

 

I got this to work with brute force and duct tape, (most of) Ruby has not "clicked in".

I don't know if I will need enough macros to make learning it worth the effort, but I'm going to hack at it till it clicks, no longer capable of giving up.

I'd like to be pointed to what road(s) to go down so I don't end up in the swamp.

Link to comment
Share on other sites

11 hours ago, GerryT said:

I think your macro could be greatly simplified and made easier

Gerry-the way you posed the questions got me thinking.

Define each element once-

Prefixes-2, SR, 2SR, W, 2W, R (#forgot refrigerator wall at 24 d)  

Type-B, W, U, F, "replace from library" (corner cabinets, num drawers >1)

Dimensions-width (9...43), depth (nil for 13 and not 24 Unless wall), height, filler width, filler height defined.

Then  put them all together  -prefix, type, width, height, depth- in something (hash, array, block? have to read all that yet again) return as string-

Unless "filler"

then something for fillers.

Something like that? ...need more duct tape, not sure I know how to assemble it yet.

 

 

Link to comment
Share on other sites

21 hours ago, GerryT said:

Consider a left to right label build based on your criteria.

I finally got that from your questions.

I saw you posted this on my phone yesterday (at the Methodist Church serving another Thanksgiving dinner that can't be beat.) Felt like a kid on Christmas eve last night.

Just got to look at it. This will be a great learning excercise!  Thanks so much.

I'm going to spend some time understanding what you did. There are some things that need changing but I want to try those on my own (sans duct tape) before coming back for more advice. May take me a while rereading the books. Think that I can learn more that way. Again thanks so much.

 

 

Link to comment
Share on other sites

5 minutes ago, BrownTiger said:

Does owner.automatic_label[0] works anymore in X.?

 

 

Why wouldn't it?  That should work in a user Text Macro regardless of the Chief Version. 

  • owner.automatic_label is a string.
  • owner.automatic_label[n] simply returns the character at that location.
Link to comment
Share on other sites

I was questioning this 

type = {"base cabinet" => 'B' , "wall cabinet" => 'W', "utility cabinet" => 'U'}

cab = type[automatic_description]

=

In theory

cab = automatic_description[0].upcase

 

But I am not sure how  automatic_label  and automatic_description related... And if automatic_label  is still present in X9.

Link to comment
Share on other sites

3 hours ago, BrownTiger said:

In theory

cab = automatic_description[0].upcase

I need to be able to change the values for different brands "T" for "U" and for other cabinet types; vanity (Vxxx; VTxxx, etc) closet (DCT...); desk (DDB; etc)

I suppose a bunch of substitutions could be written but out of my league, thinking it is easier for me to adjust per brand and to get a few cabinets in the library for each brand of other types (V, DC, DD..) which also vary by brand.

I used what I did after looking at the listing for object properties, selected based on how I understood I could create logic to get where I needed.

Link to comment
Share on other sites

On 12/31/2016 at 2:23 PM, GerryT said:

Let me know if you need to rework anything??

Getting closer than I hoped, found a few things to change as I double checked the catalog-got there ...eventually. Learned a good bit I think.

left to do

  • filler labels to read only F3xx, F6xx, F9xx

  • need to read diagonal doors on corner cabinets

  • may have it throw an error if base width >36

But I think I'm going to look into cleaning up what I added first which may give me a better idea how to do those few things. For any other cabinets I'll use replace from library since those all need face configuration.

 

A few question if I may-

Do I understand correctly what you did?

  • a method that defines in_conv

  • using a case statement (which is why there are two “end”

  • a hash that defines type

  • a ternary statement that defines tdr

  • a ternary for SR

  • cab is an array that matches value from the hash type to get a result?

  • An empty string lbl

  • that string is then filled by concatenating parts some of which rely on simple conditional statements (if , unless)

  • resulting in the final string lbl

Correct?

 

dimensions-

Got incorrect result when width<9' and included 3/4” (1.75 read F3xx; 3.75 read F5xx; until 9”)

Tried a bunch of stuff, read about rational, value.ceil, value.floor (have to re-read all that a few times, don't get it exactly but finally figured out they did not refer to the default room :)

Eventually changed (value.ceil +1) to (value.floor +1) and everything works fine. I don't understand ?

 

Along the way I discovered that precision=2 doesn't have an effect when deleted (precision was spelled as precesion which gave me a hint) Is it not needed?

 

Next-added corner wall cabinet and corner base cabinet to the hash (type)

then I tried to get label for those to NOT include: tdr (2) or depth for either AND also not include height for base. (NOTE -changed db to tdr)

 

I was able to eliminate depth and height with:

lbl.concat ("-" )+( (in_conv(depth)).to_s ) if depth.to_i !=13 && depth.to_i !=24 && depth.to_i !=36

I expected that would be || (or) instead of && -it reads to me as if all those conditions are required but it works-don't understand?

 

Getting rid of '2' on corner cabinets and a few other places-I had a heck of a time with this- think there may be an easier or at least cleaner way. Going to play with that.

 

It appears that I can't add condition OR (||) within the ternary statements, correct? Actually have not been able to nest much of anything there-guessing I have to define it first instead of trying to use a statement?

 

Wondering if I misunderstand what lbl= “ ” is? I've tried inserting if then, and case statements before, after, in it to eliminate the “2” with no success.

 

I had unreliable results using =cab 'B' or than I did using !=cab 'W' && !='U' Don't think it was pilot error, several places and variations ??

 

Odd thing?- I tried to make a shorter macro, that did not output as much, while checking corner cabinets. For that I deleted most of the lbl.concat but the evaluation error listed expecting all of the original lbl.concat statements. Is that some sort of global so long as the original lbl statement is in a macro that is listed in the plan? Or just pilot error?

Fixed it by changing lbl to something different.

 Here's what I have so far, have about 18 in various stages that didn't work saved  (threw out a bunch too) for reference.

 

 

 

Link to comment
Share on other sites

I'm not sure I really follow with a lot of what you said Mark, but regarding this statement...

 

"Got incorrect result when width<9' and included 3/4” (1.75 read F3xx; 3.75 read F5xx; until 9”)

Tried a bunch of stuff, read about rational, value.ceil, value.floor (have to re-read all that a few times, don't get it exactly but finally figured out they did not refer to the default room :)

Eventually changed (value.ceil +1) to (value.floor +1) and everything works fine. I don't understand ?"

 

value.ceil is simply rounding your value up to the nearest whole number and converting it to an integer.

 

value.floor is simply rounding your value down to the nearest whole number and converting it to an integer.

Link to comment
Share on other sites

36 minutes ago, Joe_Carrick said:

 

Change it to width<(9*12) and until 9 and it should work

I'll try changing that. It works as is though? Have a plan with all possible cabinets in it. 

Michael, that was a great explanation, I've read 4 or 5 explanations several times. Now I get it.  

Link to comment
Share on other sites

My comments:

1. you are correct in your understanding

2. the problem with weights of ?.75 is that you are using a precision of 2 which will usually round up/down on .75. Try a higher precision (4)? Also the in_conv method should take two arguments, the last one being the precision. Change the 2 in the formula to the precision input and you can quickly set the precision for anything you want. --- My mistake for not catching this.

3. lbl  = ' ' in simply an initializer which is necessary to tell Ruby that it is a string. needed to use the concat method. space is not needed. lbl = '' (two single quotes)

 

Not sure I answered all your questions. A phone call or a goto might help if you need?

 

EDIT:

     For your conditional try -- depth.to_i != (13 && 24 && 36)  -- is that clearer? Be careful of precedence - use parentheses for grouping conditions

     As to the error messages -- Ruby is acknowledged to have the worst error messages. It often gets confused and does not drop previous error messages. Generally look at those near the bottom of the list. if it get really bad, just save, close and reopen

 

Link to comment
Share on other sites

1-YIPPPEEE :D

2- need to read more about numbers etc-have it working as I noted- didn't work when put back value.ceil and made those changes (possible pilot error)

3-that's what I thought, it was the error messages that got me confused about it.

 

On 1/5/2017 at 8:23 PM, GerryT said:

For your conditional try -- depth.to_i != (13 && 24 && 36)  -- is that clearer? Be careful of precedence - use parentheses for grouping conditions

Tried this-got curiously unexpected results elsewhere, likely pilot error, will be trying again.

What I did not understand was that I could not get "OR" (||) to work as I expected. Found something on the web that explained it. I thought "and" "or" and variants were Boolean, this say not.

Gerry sent you a PM thanks.

I have something that works for almost everything in this brand, attached. It really needs cleaning up and simplifying (noted in code) but what I've tried so far has not worked (going back to the books). May change it by splitting for cabinet types (think one of you told me to do that at some point somewhere)

 

Link to comment
Share on other sites

Gerry,

I am looking at the possibility of creating a Struct:

  • Struct.new("Cabinets", :brand_series, :door_style, :overlay,....)  must have the max number of members defined
  • Struct::Cabinets.new(<string read from a csv>)   ie: ["Conestoga Premium", "TW-10", "0.5"]
  • Struct::Cabinets.new(<string read from a csv>)   ie: ["Conestoga Economy", "TW-10", "0.5"]

I would envision setting this up to fill the contents of the "Comments" by inserting a macro into that OIP field for a Cabinet.  The "Manufacturer" field might have "Conestoga Premium" as it's contents - thus triggering the retrieval of the correct :brand_series data. 

 

This could expand the data available available to include such things as Door Style, Overlay, Hinge type, etc.  All of these could be listed in the Comments column of the Schedule.  It would even be possible to have extend this to use the "Description" to subclass within a given :brand/series.  All the data would be in a csv exported from an Excel file.  Empty columns would simply be ignored.

 

Does this make sense to you?

 

OTOH, it would be much better if CA simply provided access to all the other attributes ;)

 

Link to comment
Share on other sites

2 hours ago, Joe_Carrick said:

Gerry,

I am looking at the possibility of creating a Struct:

  • Struct.new("Cabinets", :brand_series, :door_style, :overlay,....)  must have the max number of members defined
  • Struct::Cabinets.new(<string read from a csv>)   ie: ["Conestoga Premium", "TW-10", "0.5"]
  • Struct::Cabinets.new(<string read from a csv>)   ie: ["Conestoga Economy", "TW-10", "0.5"]

I would envision setting this up to fill the contents of the "Comments" by inserting a macro into that OIP field for a Cabinet.  The "Manufacturer" field might have "Conestoga Premium" as it's contents - thus triggering the retrieval of the correct :brand_series data. 

 

This could expand the data available available to include such things as Door Style, Overlay, Hinge type, etc.  All of these could be listed in the Comments column of the Schedule.  It would even be possible to have extend this to use the "Description" to subclass within a given :brand/series.  All the data would be in a csv exported from an Excel file.  Empty columns would simply be ignored.

 

Does this make sense to you?

 

OTOH, it would be much better if CA simply provided access to all the other attributes ;)

 

yes , a good idea. I personally just use a hash and Marshal to get/save. I believe you can use Marshal to also save structs -- so somewhat the same.

BTW, Ruby has a excellent CSV module that would handle your csv files automatically. Unfortunately, Chief has chosen to not include it. i have requested that it be included together with the XML module -- no luck maybe you can do better?

Link to comment
Share on other sites

23 hours ago, GerryT said:

BTW, Ruby has a excellent CSV module that would handle your csv files automatically. Unfortunately, Chief has chosen to not include it. i have requested that it be included together with the XML module -- no luck maybe you can do better?

What would Ruby's CSV module do that couldn't be done with a defined method to read and build a "struct" or "hash" from the csv contents?

Link to comment
Share on other sites

The Ruby CSV class has all the methods necessary to handle CSV files and data -- Why reinvent the wheel?? Check out Ruby class CSV  on Ruby Docs. Plus by using the same methods -- everyone is on the same page and can easily understand and use common public macros?

Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share