---
description: You can access the setup information you need about this product
---

# Wert Vending Machines

## <mark style="background-color:orange;">INSTALLATION</mark>



1 - Upload the script folder to the location of your resources

2 - Check config and editable file settings. If you are using different systems, you can make the necessary adjustments in these files, such as for , `ox_lib`, etc.

3 - Load vending.sql file in ur database.

4 - Load item settings in ur item list

5 - **Installation successful, have a good funs**



## <mark style="background-color:purple;">OX LIB OPTION</mark>

There are many ox settings available in the files, if you want, you can configure them.

<figure><img src="https://344044646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FAjk6DeXMrr9YWGvceJWb%2Fuploads%2FHUPT9WuDi4M2GlA9FD5H%2Fimage.png?alt=media&#x26;token=2fcda6ea-c14c-477a-8e47-7e587e58187d" alt=""><figcaption></figcaption></figure>

<figure><img src="https://344044646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FAjk6DeXMrr9YWGvceJWb%2Fuploads%2FhxYd3bMF2yFuCQcIkMLu%2Fimage.png?alt=media&#x26;token=3c5a29be-bf60-4d0b-bc8c-d949c3a009fb" alt=""><figcaption><p>If you want to use ox_lib, please check if this link is enabled on fxmanifest.check it out from inside lua. this must be turned on before you can use ox_lib. After opening it, it will be enough to use the refresh and ensure commands.</p></figcaption></figure>



## <mark style="background-color:blue;">INFORMATION</mark>

{% hint style="info" %}
The script comes with default settings. There are many settings in the configuration file, and you can customize all of them to your personal preferences. Below are the configuration files, feel free to check them out.
{% endhint %}



## <mark style="color:green;background-color:yellow;">OX INVENTORY</mark>

If you are using the ox inventory and you have turned on the configure setting, please add these codes to the ox\_inventory/modules/items/client location.

```lua
-- U Can add like this more items ...
Item('vending_machine_1', function(data, slot)
	TriggerEvent('wert-vending:client:place-vending-machine', slot)
end)
```



## <mark style="background-color:yellow;">ITEM SETTINGS</mark>

{% file src="https://344044646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FAjk6DeXMrr9YWGvceJWb%2Fuploads%2FvNHy3IMnc7rrBf9EvPKy%2Finventoryimages.zip?alt=media&token=e0bd24d3-bf00-4236-8bf3-90e4a2759383" %}

```lua
["vending_machine_1"] = {
		["name"] = "vending_machine_1",
		["label"] = "Kurkakola Vending Machine",
		["weight"] = 100,
		["type"] = "item",
		["image"] = "vending_machine_1.png",
		["unique"] = true,
		["useable"] = true,
		["expire"] = nil,
		["shouldClose"] = true,
		["combinable"] = nil,
		["description"] = "A Vending Machine ..."
	},
	["vending_machine_2"] = {
		["name"] = "vending_machine_2",
		["label"] = "Soda Vending Machine",
		["weight"] = 100,
		["type"] = "item",
		["image"] = "vending_machine_2.png",
		["unique"] = true,
		["useable"] = true,
		["expire"] = nil,
		["shouldClose"] = true,
		["combinable"] = nil,
		["description"] = "A Vending Machine ..."
	},
	["vending_machine_3"] = {
		["name"] = "vending_machine_3",
		["label"] = "Coffe Vending Machine",
		["weight"] = 100,
		["type"] = "item",
		["image"] = "vending_machine_3.png",
		["unique"] = true,
		["useable"] = true,
		["expire"] = nil,
		["shouldClose"] = true,
		["combinable"] = nil,
		["description"] = "A Vending Machine ..."
	},
	["vending_machine_4"] = {
		["name"] = "vending_machine_4",
		["label"] = "Candybox Vending Machine",
		["weight"] = 100,
		["type"] = "item",
		["image"] = "vending_machine_4.png",
		["unique"] = true,
		["useable"] = true,
		["expire"] = nil,
		["shouldClose"] = true,
		["combinable"] = nil,
		["description"] = "A Vending Machine ..."
	},
```



## <mark style="background-color:red;">OPEN FILES</mark>

```lua
Config = {}

Config.DebugPoly = false
Config.UseTarget = true
Config.TargetSystem = 'qb-target' -- 'qb-target' | 'ox_target' | # U can check editable_client.lua for codes ...
Config.OxLib = true
Config.OxInventory = false -- # If u use ox inventory u can set true

Config.BuyItemAccount = 'cash' -- 'cash' or 'bank' | Player use which money type (account) for buy items from vending

Config.NoTargetInteractionDistance = 1.5 -- # No Target Interaction distance size
Config.NoTargetInteractionKeys = { -- # https://docs.fivem.net/docs/game-references/controls/
    openVending = 38,
    openBossmenu = 29,
    changeModel = 26,
    removeVending = 45,
    buyVending = 38
}

Config.WendingMachineItems = {
    vending_machine_1 = {
        model = `prop_vend_soda_01`,
        useJob = nil, -- # If u want only use x job this vending machine item set job name here like "police"
    },
    vending_machine_2 = {
        model = `prop_vend_soda_02`,
        useJob = nil, -- # If u want only use x job this vending machine item set job name here like "police"
    },
    vending_machine_3 = {
        model = `prop_vend_coffe_01`,
        useJob = nil, -- # If u want only use x job this vending machine item set job name here like "police"
    },
    vending_machine_4 = {
        model = `prop_vend_snak_01`,
        useJob = nil, -- # If u want only use x job this vending machine item set job name here like "police"
    },
    -- # If u want add more vending and item here
}

Config.EnableChangeModel = false -- # After place vending machine player can change vending model ?
Config.AllowRemoveVendingMachine = true -- # Remove machine option ?
Config.RemoveVendingMachineAddItem = true -- # When player remove machine should add item again his inventory ?

Config.ValidVendingModels = { -- # Models that may be allowed when you try to change the model
    "prop_vend_soda_01", -- Only string please not use joat or hash or number
    "prop_vend_soda_02", -- Only string please not use joat or hash or number
    "prop_vend_coffe_01", -- Only string please not use joat or hash or number
    "prop_vend_snak_01", -- Only string please not use joat or hash or number
}

Config.UseWhitelistItems = true -- # If you activate this, you can only add the items you specify below
Config.WhitelistItems = { -- # Select items for vending if active white system
    {
        model = `prop_vend_soda_01`,
        items = {
            -- Item list
            'kurkakola',
            'water_bottle',
        },
    },
    {
        model = `prop_vend_soda_02`,
        items = {
            -- Item list
            'sprunk',
            'water_bottle',
        },
    },
    {
        model = `prop_vend_coffe_01`,
        items = {
            -- Item list
            'coffee',
            'water_bottle',
        },
    },
    {
        model = `prop_vend_snak_01`,
        items = {
            -- Item list
            'twerks_candy',
            'snikkel_candy',
            'sandwich',
        },
    },
}

Config.EnableDefaultVendings = true -- # Should the other vending machines in the game be put up for sale?
Config.DefaultVendingModels = { -- # Models for default vendings

}
Config.DefaultVendingMachinePrice = { -- # Prices for vending machine models
    [`prop_vend_soda_01`] = 100, -- Model and price
    [`prop_vend_soda_02`] = 100, -- Model and price
    [`prop_vend_coffe_01`] = 100, -- Model and price
    [`prop_vend_snak_01`] = 100, -- Model and price
}
Config.BuyVendingMachineAccount = 'cash' -- 'cash' or 'bank' | Player use which money type (account) for buy vending machine
```

```lua
local ESX = exports["es_extended"]:getSharedObject()
currentMoney = 0 -- Please don't touch this!

local function GetPlayerMoney()
    ESX.TriggerServerCallback('wert-vending:server:get-start-money-amount', function(myMoney)
        while myMoney == nil do Wait(10) end
        currentMoney = myMoney
    end)
end

function CustomNotifVariation(text, style, time)
    ESX.ShowNotification(text or '', style or info, time or 3000)
end

function ShowTextUI(text)
    if Config.OxLib then
        lib.showTextUI(text, {position = 'left-center'})
    else
        -- If u want customize
    end
end

function HideTextUI()
    if Config.OxLib then
        lib.hideTextUI()
    else
        -- If u want customize
    end
end

function AddVendingTarget(entity, data)
    if Config.TargetSystem == 'qb-target' then
        exports["qb-target"]:AddTargetEntity(entity, data)
    elseif Config.TargetSystem == 'ox_target' then
        exports.ox_target:addLocalEntity(entity, data.options)
    end
end

function AddVendingModelTarget(entities, data)
    if Config.TargetSystem == 'qb-target' then
        exports["qb-target"]:AddTargetModel(entities, data)
    elseif Config.TargetSystem == 'ox_target' then
        exports.ox_target:addModel(entities, data.options)
    end
end

-- # Events

RegisterNetEvent('wert-vending:client:custom-notif', function(text, style, time)
    CustomNotifVariation(text, style, time)
end)

RegisterNetEvent('esx:setAccountMoney', function(account)
    if not account then return end
    local moneyType = account.name
    if moneyType == 'money' then moneyType = 'cash' end
    if not moneyType then return end
    if not amount then return end
    if moneyType ~= Config.BuyItemAccount then return end
    local update = true
    currentMoney = account.money and tonumber(account.money) or nil
    if not currentMoney then update = false end
    if not update then return end
    if not exports['wert-vending']:VendingUIActive() then return end
    TriggerEvent('wert-vending:client:update-wallet-interface')
end)

RegisterNetEvent('esx:playerLoaded', function()
    Wait(1000)
    GetPlayerMoney()
end)

AddEventHandler('onResourceStart', function(resource)
    if resource == GetCurrentResourceName() then
        Wait(1000)
        GetPlayerMoney()
    end
end)
```

```lua
local ESX = exports["es_extended"]:getSharedObject()
Webhooks = {
    additem = '',
    removeitem = '',
    withdraw = '',
    deposit = '',
    setprice = '',
    checkout = '',
    createvending = '',
    removevending = '',
}

myItemLabels = {}
if Config.OxInventory then
    for item, data in pairs(exports.ox_inventory:Items()) do myItemLabels[item] = data.label end
end

function GetPlayerFullName(src)
    local ply = ESX.GetPlayerFromId(src)
    if not ply then return 'Unkown' end
    return ply.getName()
end

function GetPlayerDirectLicense(src)
    local ply = ESX.GetPlayerFromId(src)
    if not ply then return 'Unkown' end
    return ply.getIdentifier()
end

function WithdrawComplete(src, amount, identifier)
    local ply = ESX.GetPlayerFromId(src)
    if not ply then return end
    amount = tonumber(amount)
    ply.addMoney(amount)
    local fullName = ply.getName()
    local myLicense = ply.getIdentifier()
    local logMessage = 'Player Name : ' .. fullName ..
    '\n Player ID : ' .. src ..
    '\n Player License : ' .. myLicense ..
    '\n Amount : ' .. amount ..
    '\n Vending Identifier : ' .. identifier
    exports['wert-vending']:CreateDiscordLog({
        webhook = 'withdraw',
        title = 'Withdraw Complete (' .. identifier .. ')',
        message = logMessage,
    })
end

function CheckDeposit(src, amount)
    local ply = ESX.GetPlayerFromId(src)
    if not ply then return false end
    amount = tonumber(amount)
    local money = ply.getMoney()
    if (money - amount) >= 0 then
        return true
    else
        return false
    end
end

function DepositComplete(src, amount, identifier)
    local ply = ESX.GetPlayerFromId(src)
    if not ply then return end
    amount = tonumber(amount)
    ply.removeMoney(amount)
    local fullName = ply.getName()
    local myLicense = ply.getIdentifier()
    local logMessage = 'Player Name : ' .. fullName ..
    '\n Player ID : ' .. src ..
    '\n Player License : ' .. myLicense ..
    '\n Amount : ' .. amount ..
    '\n Vending Identifier : ' .. identifier
    exports['wert-vending']:CreateDiscordLog({
        webhook = 'deposit',
        title = 'Deposit Complete (' .. identifier .. ')',
        message = logMessage,
    })
end

function GetBackVendingItem(src, item, amount)
    local ply = ESX.GetPlayerFromId(src)
    if not ply then return end
    if Config.OxInventory then
        exports.ox_inventory:AddItem(src, item, amount)
    else
        ply.addInventoryItem(item, amount)
    end
end

function CheckAddItem(src, targetItem, targetAmount, identifier)
    local ply = ESX.GetPlayerFromId(src)
    if not ply then return false end
    local fullName = ply.getName()
    local myLicense = ply.getIdentifier()
    if Config.OxInventory then
        local success = exports.ox_inventory:RemoveItem(src, targetItem, targetAmount)
        if success then
            local logMessage = 'Player Name : ' .. fullName ..
            '\n Player ID : ' .. src ..
            '\n Player License : ' .. myLicense ..
            '\n Item Name : ' .. targetItem ..
            '\n Amount : ' .. targetAmount ..
            '\n Vending Identifier : ' .. identifier
            exports['wert-vending']:CreateDiscordLog({
                webhook = 'additem',
                title = 'Item Added Into Vending (' .. identifier .. ')',
                message = logMessage,
            })
            return true
        else
            return false
        end
    else
        if ply.removeInventoryItem(targetItem, targetAmount) then
            local logMessage = 'Player Name : ' .. fullName ..
            '\n Player ID : ' .. src ..
            '\n Player License : ' .. myLicense ..
            '\n Item Name : ' .. targetItem ..
            '\n Amount : ' .. targetAmount ..
            '\n Vending Identifier : ' .. identifier
            exports['wert-vending']:CreateDiscordLog({
                webhook = 'additem',
                title = 'Item Added Into Vending (' .. identifier .. ')',
                message = logMessage,
            })
            return true
        else
            return false
        end
    end
end

function GetAvailableAddItems(src, checkTable)
    local data = {}
    local ply = ESX.GetPlayerFromId(src)
    if not ply then return data end
    if Config.OxInventory then
        local items = exports.ox_inventory:GetInventoryItems(src)
        for slot, itemData in pairs(items) do
            if itemData and (not checkTable or checkTable[itemData.name]) then
                local originalExt = itemData.name .. '.png'
                local image = 'nui://ox_inventory/web/images/' .. imgExt
                data[#data+1] = {
                    image = image,
                    label = itemData.label or itemData.name:upper(),
                    amount = itemData.count,
                    item = itemData.name,
                }
            end
        end
        return data
    else
        local items = ply.getInventory()
        for slot, itemData in pairs(items) do
            if itemData and (not checkTable or checkTable[itemData.name]) then
                local itemInfo = myItemLabels[itemData.name]
                local originalExt = itemData.name .. '.png'
                local imgExt = originalExt
                local image = 'nui://qb-inventory/html/images/' .. imgExt
                data[#data+1] = {
                    image = image,
                    label = itemInfo or itemData.name:upper(),
                    amount = itemData.count,
                    item = itemData.name,
                }
            end
        end
        return data
    end
end

function CheckBuyVendingPayment(src, price)
    local ply = ESX.GetPlayerFromId(src)
    if not ply then return false end
    local money = ply.getMoney()
    if Config.BuyVendingMachineAccount == 'bank' then
        money = ply.getAccount('bank').money
    end
    if not money then money = 0 end
    money = tonumber(money)
    if money - price >= 0 then
        if Config.BuyVendingMachineAccount == 'cash' then
            ply.removeMoney(price)
        else
            ply.removeAccountMoney(Config.BuyVendingMachineAccount, price)
        end
        return true
    end
    return false
end

-- # Items

if not Config.OxInventory then
    for itemname, data in pairs(Config.WendingMachineItems) do
        ESX.RegisterUsableItem(itemname, function(source)
            local src = source
            local ply = ESX.GetPlayerFromId(src)
            if not ply then return end
            if data.useJob and ply.job.name ~= data.useJob then
                TriggerClientEvent('wert-vending:client:custom-notif', src, LANG.error.permission, 'error')
                return
            end
            TriggerClientEvent('wert-vending:client:place-vending-machine', src, {name = itemname})
        end)
    end
end
```

```lua
LANG = {
    error = {
        permission = 'You are not have permission for this vending place!',
        busy = 'You are busy!',
        vending_not_found = 'This vending machine not found!',
        vending_busy = 'This vending already using by someone!',
        modelchange = 'Cancelled! Because u dont select new model',
        modelnotfound = 'Invalid model please set a valid model!',
        witdraw_money_header = 'Withdraw Failed!',
        witdraw_money_description = 'Vending machine not enough this money! U can try after again!',
        item_not_found_try_removeitem_Header = 'Remove action failed!',
        item_not_found_try_removeitem_Description = 'Vending machine not have this item try again after please!',
        checkout_error_header = 'Checkout Failed!',
        checkout_error_vendingnotfound = 'Vending not found!',
        checkout_error_itemoramount = 'Item or enough stock not found! Please check another amounts!',
        checkout_error_money = 'Not enough money, please try again after!',
        vending_not_available = 'This vending machine is not available!',

        removeItem_SomeProblemFound_Header = 'Failed!',
        removeItem_SomeProblemFound_Description = "Couldn't get the data, please try again later!",

        removeItem_Busy_Header = 'Vending Is Busy!',
        removeItem_Busy_Description = "You can't do this operation right now because the vending machine is being used by someone!",

        deposit_money_header = 'Deposit Failed!',
        deposit_money_description = 'U are not have enough money from ur wallet!',

        addItem_SomeProblemFound_Header = 'Failed!',
        addItem_SomeProblemFound_Description = "Couldn't get the data, please try again later!",

        addItem_Busy_Header = 'Vending Is Busy!',
        addItem_Busy_Description = "You can't do this operation right now because the vending machine is being used by someone!",

        addItem_TargetItem_Error_Header = 'Item Not Found!',
        addItem_TargetItem_Error_Description = 'The item you are trying to add is not in your inventory',

        setPrice_Busy_Header = 'Vending Is Busy!',
        setPrice_Busy_Description = "You can't do this operation right now because the vending machine is being used by someone!",

        setPrice_SomeProblemFound_Header = 'Failed!',
        setPrice_SomeProblemFound_Description = "Couldn't get the data, please try again later!",

        setPrice_TargetItem_Error_Header = 'Item Not Found!',
        setPrice_TargetItem_Error_Description = 'The item you choose to change the price is not in the vending machine!',
    },

    success = {
        vending_removed = 'Machine successfuly removed!',
        model_changed = 'Model successfuly changed!',
        witdraw_money = 'Succesfully! U are withdraw %S$ From Vending Machine!',
        cartClearTitle = 'Cart has ben cleared!',
        cartClearText = 'The items in your cart have been returned. You can start shopping again',
    },

    place = {
        space = 'SPACE',
        space_desc = 'Fix it to the ground',
        z = 'Z',
        z_desc = 'Reduce the height',
        arrow = 'ARROW KEYS',
        arrow_desc = 'Change it location',
        qe = 'Q-E',
        qe_desc = 'Rotate',
        enter = 'ENTER',
        enter_desc = 'Finish',
        backspace = 'BACKSPACE',
        backspace_desc = 'Cancel'
    },
    
    informations = {
        emptyBasketTitle = 'Your cart is empty!',
        emptyBasketText = 'You can complete your shopping by adding items to your cart.',
        cartAlreadyClearTitle = 'Cart is already empty!',
        cartAlreadyClearText = 'There are no items to clear in your cart',
    },

    vending_target_interaction = 'Vending Machine',
    vending_target_bossmenu = 'Boss Action',
    vending_target_remove = 'Remove Vending Machine',
    vending_target_change_model = 'Change Model',
    vending_target_buyVending = 'Buy Vending Machine',

    vending_noTarget_interaction = '[E] Vending Machine',
    vending_noTarget_bossmenu = '[B] Boss Action',
    vending_noTarget_remove = '[R] Remove Vending Machine',
    vending_noTarget_change_model = '[C] Change Model',    
    vending_noTarget_buyVending = '[E] Buy Vending Machine',
    
    vendingui = {
        header = 'VENDING MACHINE',
        basket = 'Basket',
        clearall = 'Clear All',
        confirm = 'Confirm',
        totalPrice = 'Total : %s$',
        wallet = '(Wallet : %s$)',
    },

    labelinput = {
        header = 'Vending Machine Label',
        label = 'Select Label',
        description = 'Text',
        confirm = 'Confirm'
    },

    changemodelinput = {
        header = 'New Vending Machine Model',
        label = 'Select Model String',
        description = 'Text',
        confirm = 'Confirm'
    },

    removevending = {
        label = 'Remove Vending Machine',
        text = 'Do u confirm remove this vending machine ?',
        cancel = 'Cancelled!',
        
        menu_remove_header = 'Remove Vending Machine',
        menu_remove_description = 'Click for remove machine!',

        menu_close_header = 'Close Menu',
        menu_close_description = 'Click for close menu!',
    },

    bossmenuinterface = {
        mainMenu = 'MAIN MENU',
        label = '%s BOSS MENU',
        welcome = 'Welcome, %s',
        informationText = 'You can access the actions related to the vending machine through this menu. You can do the actions you want from the buttons below.',
        currentSafe = 'Case : %s$',
        currentSafeDescription = 'Current Safe Amount',
        withdrawButton = 'Withdraw',
        withdrawButtonDescription = 'Click For Withdraw Money',
        depositButton = 'Deposit',
        depositButtonDescription = 'Click For Deposit Money',
        additemButton = 'Add Item',
        additemButtonDescription = 'Click For Add Item To Vending',
        removeitemButton = 'Remove Item From Vending',
        removeitemButtonDescription = '[%s] Item Available In Vending',
        setpriceButton = 'Set Item Prices',
        setpriceButtonDescription = '[%s] Item Available In Vending',
        addItemComplete_header = 'Item Added!',
        addItemComplete_description = 'The item was successfully added to the vending machine!',
        removeItemComplete_header = 'Item Removed!',
        removeItemComplete_description = 'The item has been removed from the vending machine and added to your inventory!',
        withdrawComplete_header = 'Withdrawed!',
        withdrawComplete_description = '%s$ Successfully completed! Thanks for action ...',
        depositComplete_header = 'Deposited!',
        depositComplete_description = '%s$ Successfully completed! Thanks for action ...',
        itemPriceChanged_header = 'Price Updated!',
        itemPriceChanged_description = 'The price of the item has been successfully changed!',
        withdrawPopuiHeader = 'WITHDRAW MONEY FROM VENDING CASE',
        withdrawPopuiAvailable = 'Available balance',
        withdrawPopuiInputLabel = 'The Amount to Be Withdraw - $',
        withdrawPopuiInputPlaceholder = 'Value ($)',
        withdrawPopuiConfirm = 'CONFIRM',
        withdrawPopuiCancel = 'CANCEL',
        depositPopuiHeader = 'DEPOSIT MONEY FROM VENDING CASE',
        depositPopuiAvailable = 'Available balance',
        depositPopuiInputLabel = 'The Amount to Be Deposit - $',
        depositPopuiInputPlaceholder = 'Value ($)',
        depositPopuiConfirm = 'CONFIRM',
        depositPopuiCancel = 'CANCEL',
        setItemPricesHeader = 'SET ITEM PRICES',
        editItem = 'Edit',
        removeItemHeader = 'REMOVE ITEM FROM VENDING',
        removeItem = 'Remove',
        addItemHeader = 'ADD ITEM VENDING FROM INVENTORY',
        addItem = 'Add',
        addItemPopuiHeader = 'ADD ITEM TO VENDING (%s)',
        addItemPopuiDesc = 'Maximum Count',
        addItemPopuiInputLabel = 'The Amount to Be Add',
        addItemPopuiInputPlaceholder = 'Value (x)',
        addItemPopuiAdd = 'ADD',
        addItemPopuiCancel = 'CANCEL',
        setPriceItemPopuiHeader = 'SET ITEM PRICE (%s)',
        setPriceItemPopuiDesc = 'Current Price',
        setPriceItemPopuiInputLabel = 'New Item Price',
        setPriceItemPopuiInputPlaceholder = 'Price ($)',
        setPriceItemPopuiAdd = 'SET',
        setPriceItemPopuiCancel = 'CANCEL',
    },

    buyVendingMachine = {
        label = 'Vending Machine (%s$)',
        description = 'Confirm the transaction to purchase this vending machine',
        cancel = 'Cancelled!',
        buyButtonMenu = 'Buy',
        buyButtonMenuDescription = 'Click for buy this machine!',
        closeMenu = 'Close Menu',
        closeMenuDescription = 'Click for close menu!',
        moneyError = 'You dont have enough money for this vending machine!',
    },

    defaultVendingLabel = 'Vending Machine',
}

function ChangeLangText(text, ...)
    return string.format(text, ...)
end
```
