# Pricing `[Shared]`

Pricing is a shared module to normalize and manipulate prices in your scripts.

:::tip
You can use the [Price Generator](/DeveloperResources/price-generator) to build price tables and paste the generated Lua code into your config files.
:::

## Quick usage

```lua
-- Create a price with $5 and 1 acid item.
local price = jo.pricing.new({
  money = 5,
  item = "acid"
})

-- Add 1 gold to the existing price.
price:add({ gold = 1 })

-- Create a group where the player can pay either $10 or 1 gold.
local group = jo.pricing.newGroup({
  { money = 10 },
  { gold = 1 }
})
```

Prices are normalized into canonical cost tables:

```lua
log(price:getCosts())
-- Expected output:
-- {
--   { money = 5 },
--   { gold = 1 },
--   { item = "acid", quantity = 1, keep = false }
-- }

print(group.operator)
-- Expected output: "or"
```

## Mathematical Operations

### Addition

Use the `+` operator to combine two prices into a new `PriceClass`.

```lua
local priceA = jo.pricing.new({ money = 10 })
local priceB = jo.pricing.new({ money = 5, item = "water" })

local total = priceA + priceB

log(total:getCosts())
-- Expected output:
-- {
--   { money = 15 },
--   { item = "water", quantity = 1, keep = false }
-- }

log(priceA:getCosts())
-- Expected output: { { money = 10 } }
```

### Multiplication

Use the `*` operator to multiply a price into a new `PriceClass`.
Currencies keep their multiplied value, while item quantities are rounded to the nearest integer.

```lua
local price = jo.pricing.new({
  money = 10,
  item = "water",
  quantity = 3
})

local multiplied = price * 1.5

log(multiplied:getCosts())
-- Expected output:
-- {
--   { money = 15 },
--   { item = "water", quantity = 5, keep = false }
-- }

log(price:getCosts())
-- Expected output:
-- {
--   { money = 10 },
--   { item = "water", quantity = 3, keep = false }
-- }
```

The reversed order also works:

```lua
local multiplied = 2 * jo.pricing.new({ money = 5 })

log(multiplied:getCosts())
-- Expected output: { { money = 10 } }
```

#### PriceGroupClass

The `*` operator can also multiply every price in a `PriceGroupClass`.
It returns a new group, preserves the original operator and does not modify the source group.

```lua
local group = jo.pricing.newGroup({
  { money = 10 },
  { gold = 2 }
})

local multipliedGroup = group * 3

print(multipliedGroup.operator)
-- Expected output: "or"

log(multipliedGroup:get(1):getCosts())
-- Expected output: { { money = 30 } }

log(multipliedGroup:get(2):getCosts())
-- Expected output: { { gold = 6 } }

log(group:get(1):getCosts())
-- Expected output: { { money = 10 } }
```

The reversed order is supported too:

```lua
local multipliedGroup = 3 * group
```

### Division

Use the `/` operator to divide a price by a number into a new `PriceClass`.
It reuses the multiplication behavior internally, so currencies keep their divided value and item quantities are rounded to the nearest integer.

```lua
local price = jo.pricing.new({
  money = 15,
  item = "water",
  quantity = 5
})

local divided = price / 2

log(divided:getCosts())
-- Expected output:
-- {
--   { money = 7.5 },
--   { item = "water", quantity = 3, keep = false }
-- }

log(price:getCosts())
-- Expected output:
-- {
--   { money = 15 },
--   { item = "water", quantity = 5, keep = false }
-- }
```

Only `price / number` is supported. Division by zero raises an error.

### Length

Use the `#` operator to count canonical entries.
For a `PriceClass`, it returns the number of costs.
For a `PriceGroupClass`, it returns the number of prices in the group.

```lua
local price = jo.pricing.new({ money = 10, item = "water" })
local group = jo.pricing.newGroup({
  { money = 10 },
  { gold = 2 }
})

print(#price)
-- Expected output: 2

print(#group)
-- Expected output: 2
```

### Equality

Use the `==` operator to compare two prices by value. Cost order does not matter.

```lua
local priceA = jo.pricing.new({ money = 10, item = "water" })
local priceB = jo.pricing.new({
  { item = "water", quantity = 1, keep = false },
  { money = 10 }
})

print(priceA == priceB)
-- Expected output: true
```

## Constructor

### jo.pricing.new()

Creates a canonical [PriceClass](#priceclass-methods). <br>

#### Syntax

```lua
jo.pricing.new(data, reuseExisting)
```

#### Parameters

`data` : _PriceInput|[PriceClass](#priceclass-methods)_ `[Optional]`
> Price input to normalize <br> default:`nil`
>

`reuseExisting` : _boolean_ `[Optional]`
> Reuse existing [PriceClass](#priceclass-methods) if already created <br> default:`false`
>

#### Return Value

Type : _[PriceClass](#priceclass-methods)_

---

### jo.pricing.newGroup()

Creates a canonical [PriceGroupClass](#pricegroupclass-methods). <br>

#### Syntax

```lua
jo.pricing.newGroup(data, reuseExisting)
```

#### Parameters

`data` : _PriceGroupInput_ `[Optional]`
> Price group input to normalize <br> default:`nil`
>

`reuseExisting` : _boolean_ `[Optional]`
> Reuse existing [PriceGroupClass](#pricegroupclass-methods) if already created <br> default:`false`
>

#### Return Value

Type : _[PriceGroupClass](#pricegroupclass-methods)_

## JO Functions

### jo.pricing.getCosts()

Returns the canonical costs list for a price input. <br>

#### Syntax

```lua
jo.pricing.getCosts(price)
```

#### Parameters

`price` : _PriceInput_
> Price input
>

#### Return Value

Type : _Cost[]_

---

### jo.pricing.isPrice()

Returns true when a value is a [PriceClass](#priceclass-methods) instance. <br>

#### Syntax

```lua
jo.pricing.isPrice(value)
```

#### Parameters

`value` : _any_
> Value to test
>

#### Return Value

Type : _boolean_

---

### jo.pricing.isPriceGroup()

Returns true when a value is a [PriceGroupClass](#pricegroupclass-methods) instance. <br>

#### Syntax

```lua
jo.pricing.isPriceGroup(value)
```

#### Parameters

`value` : _any_
> Value to test
>

#### Return Value

Type : _boolean_

---

### jo.pricing.tax()

Returns the canonical costs list for a price input. <br>
Splits a price into tax and remaining prices. <br>

#### Syntax

```lua
jo.pricing.tax(price, percentage, roundUpItems)
```

#### Parameters

`price` : _PriceInput_
> Price input to split
>

`percentage` : _number_ `[Optional]`
> Tax multiplier applied to the input price <br> default:`0`
>

`roundUpItems` : _boolean_ `[Optional]`
> Round item quantities up instead of down <br> default:`false`
>

#### Return Value

Type : _[PriceClass](#priceclass-methods),[PriceClass](#priceclass-methods)_

## PriceClass Methods

### PriceClass:add()

Adds a price to the current [PriceClass](#priceclass-methods). <br>

#### Syntax

```lua
PriceClass:add(price)
```

#### Parameters

`price` : _PriceInput_
> Price input to add to the current price
>

#### Return Value

Type : _[PriceClass](#priceclass-methods)_

---

### PriceClass:clear()

Removes every cost from the current [PriceClass](#priceclass-methods). <br>

#### Syntax

```lua
PriceClass:clear()
```

#### Return Value

Type : _[PriceClass](#priceclass-methods)_

---

### PriceClass:copy()

Creates a new independent copy of the current [PriceClass](#priceclass-methods). <br>

#### Syntax

```lua
PriceClass:copy()
```

#### Return Value

Type : _[PriceClass](#priceclass-methods)_

---

### PriceClass:equals()

Returns true when another price has the same costs. <br>

#### Syntax

```lua
PriceClass:equals(other)
```

#### Parameters

`other` : _PriceInput_
> Price input to compare with the current price
>

#### Return Value

Type : _boolean_

---

### PriceClass:getCosts()

Returns the canonical costs list. <br>

#### Syntax

```lua
PriceClass:getCosts()
```

#### Return Value

Type : _Cost[]_

---

### PriceClass:getGold()

Returns the gold amount. <br>

#### Syntax

```lua
PriceClass:getGold()
```

#### Return Value

Type : _number|nil_

---

### PriceClass:getItem()

Returns an ItemCost by item name and keep flag. <br>

#### Syntax

```lua
PriceClass:getItem(item, keep)
```

#### Parameters

`item` : _string_
> Item name
>

`keep` : _boolean_
> Item keep flag - `false`: consumed cost, `true`: required but kept
>

#### Return Value

Type : _ItemCost|nil_

---

### PriceClass:getItems()

Returns all ItemCost entries. <br>

#### Syntax

```lua
PriceClass:getItems()
```

#### Return Value

Type : _ItemCost[]_

---

### PriceClass:getMoney()

Returns the money amount. <br>

#### Syntax

```lua
PriceClass:getMoney()
```

#### Return Value

Type : _number|nil_

---

### PriceClass:getRol()

Returns the rol amount. <br>

#### Syntax

```lua
PriceClass:getRol()
```

#### Return Value

Type : _number|nil_

---

### PriceClass:hasCurrency()

Returns true when a currency cost exists. <br>

#### Syntax

```lua
PriceClass:hasCurrency(key)
```

#### Parameters

`key` : _"money"|"gold"|"rol"_
> Currency cost key
>

#### Return Value

Type : _boolean_

---

### PriceClass:hasItem()

Returns true when an ItemCost exists for an item name and keep flag. <br>

#### Syntax

```lua
PriceClass:hasItem(item, keep)
```

#### Parameters

`item` : _string_
> Item name
>

`keep` : _boolean_
> Item keep flag - `false`: consumed cost, `true`: required but kept
>

#### Return Value

Type : _boolean_

---

### PriceClass:isCurrencyOnly()

Returns true when the [PriceClass](#priceclass-methods) contains only currency costs. <br>

#### Syntax

```lua
PriceClass:isCurrencyOnly()
```

#### Return Value

Type : _boolean_

---

### PriceClass:isFree()

Returns true when the [PriceClass](#priceclass-methods) has no payable costs. <br>

#### Syntax

```lua
PriceClass:isFree()
```

#### Return Value

Type : _boolean_

---

### PriceClass:isItemOnly()

Returns true when the [PriceClass](#priceclass-methods) contains only item costs. <br>

#### Syntax

```lua
PriceClass:isItemOnly()
```

#### Return Value

Type : _boolean_

---

### PriceClass:removeCurrency()

Removes a currency cost from the current [PriceClass](#priceclass-methods). <br>

#### Syntax

```lua
PriceClass:removeCurrency(key)
```

#### Parameters

`key` : _"money"|"gold"|"rol"_
> Currency cost key to remove
>

#### Return Value

Type : _[PriceClass](#priceclass-methods)_

---

### PriceClass:removeItem()

Removes an ItemCost from the current [PriceClass](#priceclass-methods). <br>

#### Syntax

```lua
PriceClass:removeItem(item, keep)
```

#### Parameters

`item` : _string_
> Item name
>

`keep` : _boolean_
> Item keep flag - `false`: consumed cost, `true`: required but kept
>

#### Return Value

Type : _[PriceClass](#priceclass-methods)_

## PriceGroupClass Methods

### PriceGroupClass:clear()

Removes every price from the group. <br>

#### Syntax

```lua
PriceGroupClass:clear()
```

#### Return Value

Type : _[PriceGroupClass](#pricegroupclass-methods)_

---

### PriceGroupClass:compact()

Compacts an "and" [PriceGroupClass](#pricegroupclass-methods) into a new [PriceClass](#priceclass-methods). <br>

#### Syntax

```lua
PriceGroupClass:compact()
```

#### Return Value

Type : _[PriceClass](#priceclass-methods)_

---

### PriceGroupClass:copy()

Creates a new independent copy of the current [PriceGroupClass](#pricegroupclass-methods). <br>

#### Syntax

```lua
PriceGroupClass:copy()
```

#### Return Value

Type : _[PriceGroupClass](#pricegroupclass-methods)_

---

### PriceGroupClass:count()

Returns the number of prices in the group. <br>

#### Syntax

```lua
PriceGroupClass:count()
```

#### Return Value

Type : _number_

---

### PriceGroupClass:get()

Returns a [PriceClass](#priceclass-methods) by index. <br>

#### Syntax

```lua
PriceGroupClass:get(index)
```

#### Parameters

`index` : _number_
> Price index
>

#### Return Value

Type : _[PriceClass](#priceclass-methods)|nil_

---

### PriceGroupClass:getCosts()

Returns the costs of a price by index. <br>

#### Syntax

```lua
PriceGroupClass:getCosts(index)
```

#### Parameters

`index` : _number_
> Price index
>

#### Return Value

Type : _Cost[]|nil_

---

### PriceGroupClass:insert()

Inserts a [PriceClass](#priceclass-methods) into the group. <br>

#### Syntax

```lua
PriceGroupClass:insert(price, index)
```

#### Parameters

`price` : _PriceInput_
> Price input to insert
>

`index` : _number_ `[Optional]`
> Insertion index <br> default: append at the end
>

#### Return Value

Type : _[PriceGroupClass](#pricegroupclass-methods)_

---

### PriceGroupClass:isEmpty()

Returns true when the group contains no prices. <br>

#### Syntax

```lua
PriceGroupClass:isEmpty()
```

#### Return Value

Type : _boolean_

---

### PriceGroupClass:remove()

Removes a [PriceClass](#priceclass-methods) from the group by index. <br>

#### Syntax

```lua
PriceGroupClass:remove(index)
```

#### Parameters

`index` : _number_
> Price index to remove
>

#### Return Value

Type : _[PriceClass](#priceclass-methods)|nil_

---

### PriceGroupClass:set()

Replaces an existing [PriceClass](#priceclass-methods) by index. <br>

#### Syntax

```lua
PriceGroupClass:set(index, price)
```

#### Parameters

`index` : _number_
> Existing price index to replace
>

`price` : _PriceInput_
> Replacement price input
>

#### Return Value

Type : _[PriceGroupClass](#pricegroupclass-methods)_
