# Roomle Content Naming Conventions

This is a recommendation to prevent unnecessary errors and mental efforts to figure out what is happening in your content. Content creators should avoid using grammar errors in the ids or keys and should follow their common sense to write a clear and understandable code. There is nothing more annoying in coding than to having to follow that in one component you use `width` and in another component, someone uses `Widht`, so that everyone needs to remember a case difference and that they should use a typo to write a correct code.

## Choosing a Good ID

All IDs should be lower case and should only contain letters, digits and underscores. If the situation requires (due to some matching of imported/exported data), you can also use capital letters, dashes and periods.

### `catalogId`

Always include manufacturer / seller / designer / producer or tenant name of the configured product. If you need to use more than one catalog for that client, use the string as a prefix followed by underscore and then a clear description of the catalogue content.

Example:

* If you want to create one catalog with all products:
  * `furnishmyhome` - Single catalog of the client company `Furnish My Home Ltd.`
* If there are more distinctive and little related categories of the products:
  * `furnishmyhome_sofas`
  * `furnishmyhome_shelfsystems`

### `componentId`

The external identifier part of the componentId should contain a project, configurator or product name and then a distinguishable identifier, so that it can be guessed easily which part of the configurator the component represents.

Do not include word you have already used in the catalogId.

Use `root`, `main` or `master` for the entry component for the configurator, so that you know which component you need to run. The other components are subComponents

Good examples for a sofa called Celeste

* `furnishmyhome:celeste_main`
* `furnishmyhome:celeste_pillows`
* `furnishmyhome:celeste_legs`
* `furnishmyhome:celeste_longchair`
* `furnishmyhome:celeste_1seater`

Bad exmaple:

* `furnishmyhome:Base_Celeste`
* `furnishmyhome:Longchair`
* `furnishmyhome:Pillow`
* `furnishmyhome:Leg_Celeste`

Usage of capital letters, can not keep convention if another sofa gets added to the catalog. Not clear what the root component is. Also, the product name is not the first word, which makes the file sorting to be of no use.

If you intend to use one component in more projects, you can use `common` or a pluralized category name to distinguish it belongs

* `furnishmyhome:common_calculations` for a function library component
* `furnishmyhome:sofas_dockingrules` for a data component that defines docking rules for all sofas in general

### itemId

ItemIds should carry information on which componentId they lead to. It does not have to be equal, but the content creator should understand this from reading the itemId already. Pattern for selecting itemId:

`catalogueId:projectname_partname_[distinctiveParameterValue]`

Examples:

`abcdesign:celeste_longchair_left`, `abcdesign:celeste_longchair_right` (longchair\_left and longchair\_right are elementType values, we omit the `main` in itemId)

`abcdesign:celeste_1seater_1200` - single seater of width 1200 (you expect that this is width in sofa elements)

`shelfmasters:supershelf_frame_800_400` leads to a frame of size 800x400 (probably width x height) -} If there are more dimensions in the itemId, follow the natural width x depth x height order.

### materialId

There are two main groups of materials, the ones with an article number, or affecting the article number, and the other ones that don't. Typically, upholstered products or products with a big selection of plain colors, can have a wide selection of such materials.

If the materials are relevant for a single configurator, use the product name prefix in the same way as you would use it for the item or component ids. If they are materials for a whole product range (typically: upholstery and sofa producers have a M:N relation between the sofas and used materials), do not use any prefix.

If the material affects the article number directly (with a suffix, for example), or is even its own part list entry, and this article number is same across a big product range, you can use this code as the external id of the material directly - unless it contains special characters (like space, ä, ö, ü, etc.).

Hint: For storing article number together with the materialId, you can use additional [data subcomponent](https://docs.roomle.com/rubens/roomlescript-reference/roomlescript-built-in-functions#getsubcomponentdata) or [material properties](https://docs.roomle.com/rubens/roomlescript-reference/roomlescript-built-in-functions#getmaterialproperty).

For the non-article number relevant materials, use a clear description of the physical material type, color, or other distinctive property, like `plastic_black_rough`, `bronze_polished`, `wood_oak_oiled` etc. If they are relevant for a single configurator, you can add a product name prefix.

### meshId

The Roomle Blender addon will export the meshes with the prefixes matching the `txt` file and therefore will create the meshIds for you. However, care should be taken if meshes are updated, so that meshes are not overwritten in an unintended way.

### tagId

The tagId doesn't add the catalogId. If the tag should be relevant for a single catalog or tenant only, we recommend adding the `catatalogId:` to the tagId manually, so that no mix of inter-catalog tags can occur.

Otherwise, the same logical rules for tags apply. For product tags, use plural of the product category, like `mycatalog:chairs`, or `sofas`. For material tags, you can use the price group or material line group name, like `mycatalog:fabric_pg1`.

## Patterns for Naming Parameters and Variables in Given Situations

| Situation                                                                              | Prefix / Suffix / Rule                           | Example                                                                      | Typical type and values                             |
| -------------------------------------------------------------------------------------- | ------------------------------------------------ | ---------------------------------------------------------------------------- | --------------------------------------------------- |
| Can change element type to                                                             | `canBe-`                                         | `canBeFootstool`                                                             | `Boolean`                                           |
| Can change to a situation                                                              | `can(Be)-`                                       | `canBeFreestanding`                                                          | `Boolean`                                           |
| Can have accessory or neighbor of type docked                                          | `canHave-`                                       | `canHaveFootstool`                                                           | `Boolean`                                           |
| Has accessory or neighbor of type docked                                               | `has-`                                           | `hasFootstool`, `hasLegs`                                                    | `Boolean`                                           |
| Has child behind a dock mask                                                           | `has{Mask}Child`                                 | `hasLeftChild`, `hasTopChild`                                                | `Boolean`                                           |
| Has accessory of type                                                                  | `{accessory}Type`                                | `legsType`, `handleType`                                                     | `String` / matching with that accessory's parameter |
| The main type of this component                                                        | `elementType`                                    | `elementType`                                                                | `String`                                            |
| Is child behind parent's mask                                                          | `is{Parent's Mask}Child`                         | `isLeftChild`, `isTopChild`                                                  | `Boolean`                                           |
| Is in a situation                                                                      | `is-`                                            | `isFreestanding`, `isOnFloor`, `isRoot`, `isCorner`                          | `Boolean`                                           |
| Is of type                                                                             | `is-`                                            | `isFootstool`                                                                | `Boolean`                                           |
| Situation of a \[neighbor/child] behind a connection mask                              | `{mask}[Neighbor/Child/][Is/Has/CanBe]`          | `leftNeighborElementType`, `topChildHasBottomShelf`, `rightNeighborIsCorner` | Depends on the situation                            |
| Docking mask should be allowed {=} can dock with that mask                             | `allow{mask}Dock`                                | `allowLeftDock`                                                              | `Boolean`                                           |
| Count of accessories docked                                                            | `count${accessoryName}(docked)`                  | `countFootstools(Docked)`, `countPillows`                                    | `Integer`                                           |
| Main component's material                                                              | `material`                                       | `material`                                                                   | `Material`                                          |
| Distinguish between main component's materials if we can't say one of them is the main | `{part}Material`                                 | `countertopMaterial`, `sidesMaterial`, `frontsMaterial`                      | `Material`                                          |
| Material of some accessory                                                             | `{accessory}Material`                            | `legsMaterial`, `handleMaterial`                                             | `Material`                                          |
| Dimensions                                                                             | `width`, `depth`, `height`, `diameter`, `radius` | `width`, `depth`, `height`, `diameter`, `radius`, `sizeX`                    | `Decimal` (!)                                       |
| Position of docking points or accessories                                              | `{situation}Pos[X/Y/Z]`                          | `leftDockPosX`, `topDockPosZ`                                                | `Decimal` (!)                                       |
| Base dimensions for accessories or dock placement                                      | `{situation}[Width/Depth/Height/Length]`         | `legsBaseWidth`, `dockDepth`                                                 | `Decimal` (!)                                       |
| Sizes of construction elements                                                         | `{part}[Width/Depth/Height/Length/Thickness]`    | `woodThickness`                                                              | `Decimal` (!)                                       |
| Gaps or distance between, offset of first                                              | `{situation}[GapOffset]`                         | `freestandingDockGap`, `holesOffset`, `holesDistance`                        | `Decimal` (!)                                       |
| Any arrays                                                                             | pluralized form of the elements' meaning         | `neighbourRuntimeIds`, `legPositions`                                        |                                                     |

Always **use camelCase to separate words** in variable and parameter names instead of using underscores\_to\_separate\_words. If the identifier has an abbreviation, let only the first character of the abbreviation be uppercase, like weHave**Abc**Abbreviation or **abc**Abbreviation instead of weHave**ABC**Abbreviation or **aBC**Abbreviation.

## Language Specific Characters for Identifiers

First of all, the recommendation is to always code in English. Do not use words from other languages for parameter and value keys, unless it is a direct technical requirement from the client or to match some other data set in case of imports, etc. If the naming is up to you, always use the English equivalent of the word. If, for any reason, you need to write them in any different language, handle the language-specific characters in a way that is common to that given language, for example:

* German
  * ä, ö, ü -} replace with ae, oe, ue
  * ß -} replace with ss
* Czech
  * ignore diacritic marks ě, š, ž, ý, á, ů -} e, s, z, y, a, u etc.

This is of course not relevant for labels or string content, where you should display the texts correctly.

## Naming Docking Masks

The docking masks should contain information about what can be docked behind them. Imagine it as a connector, where you specify the standard you need for the other part to connect. There can be several situations:

* You dock a part of a modular product (sofa, shelf frame) - use the same prefix of the product as you use for the componentId.
* You can dock one concrete part - use a docking mask describing the part.
* You can dock a type of accessories - use an umbrella term of matching accessories.

Use the masks as they are described above in cases where there is only one child docking point on the child side - that means that the child has only one connector and the position of the docking does not influence the child further. However, if you need to distinguish this (generally if the child is not smaller than the parent or is not lower in the product hierarchy), use words like: left, right, bottom, top, back, forward, etc. from the perspective of the parent. Example: sofamoduleLeft, where the parent docking point is on the left in the parent component and on the right in the child component. Be aware that this takes some time to get used to when you work from the child's perspective.

**New:** Docking masks should be unique, otherwise unrelated components could be docked together in the Rubens Room Planner. You can include your catalogId and product prefix to have a high change of making the mask unique.

Warning: Because dock masks are scripts, a constant docking mask name should be enclosed in apostrophes:

```json
    "mask": "'furnishmyhome:celeste:LEFT'"
```
