feat: unit conversion + random generators packs (7 new commands)
Two pure-Lua packs that don't need network or LLM — pure offline utilities.
unit_convert (resources/commands/unit_convert/, 4 commands)
- convert.length "переведи 100 метров в футы" / "сколько 5 миль в км"
meters↔feet, km↔miles. Pluralises russian unit names.
- convert.weight "переведи 70 кг в фунты"
kg↔lbs.
- convert.temperature "переведи 100 цельсий в фаренгейт" / "минус 40 в цельсий"
Handles negative numbers. C↔F formulas inline.
- convert.speed "переведи 100 км в час в мили в час"
km/h↔mph.
- All round results to 1-2 decimal places, speak with proper Russian
grammatical number (фут/фута/футов).
generators (resources/commands/generators/, 3 commands)
- gen.coin "подбрось монету" / "орёл или решка"
→ "Орёл!" or "Решка!" (math.random with time+minute seed)
- gen.password "сгенерируй пароль 16 символов"
→ cryptographically-ish 6..64-char password,
alphanumeric + !@#$%^&*-_=+, copies to clipboard,
SPEAKS LENGTH ONLY (never echoes the password).
Default 16 chars if no number in phrase.
- gen.uuid "сгенерируй uuid" / "юид"
→ v4 UUID, copies to clipboard, speaks last 4 chars
(confirmation without 32-char monologue).
Tests: 112/112 pass (commands::tests auto-validates).
Pack count: 62 → 64.
This commit is contained in:
parent
20b6b06b5d
commit
84d3b57ddc
9 changed files with 289 additions and 0 deletions
6
resources/commands/generators/coin.lua
Normal file
6
resources/commands/generators/coin.lua
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
math.randomseed(os.time() + (jarvis.context.time.minute or 0) * 1000)
|
||||||
|
local r = math.random(1, 2)
|
||||||
|
if r == 1 then
|
||||||
|
return jarvis.cmd.ok("Орёл!")
|
||||||
|
end
|
||||||
|
return jarvis.cmd.ok("Решка!")
|
||||||
54
resources/commands/generators/command.toml
Normal file
54
resources/commands/generators/command.toml
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
# Random generators — coin flip, password, secret token, color.
|
||||||
|
|
||||||
|
[[commands]]
|
||||||
|
id = "gen.coin"
|
||||||
|
type = "lua"
|
||||||
|
script = "coin.lua"
|
||||||
|
sandbox = "minimal"
|
||||||
|
timeout = 2000
|
||||||
|
|
||||||
|
[commands.phrases]
|
||||||
|
ru = [
|
||||||
|
"подбрось монету",
|
||||||
|
"брось монетку",
|
||||||
|
"орёл или решка",
|
||||||
|
"монетка",
|
||||||
|
]
|
||||||
|
en = ["flip a coin", "coin flip", "heads or tails"]
|
||||||
|
ua = ["підкинь монетку"]
|
||||||
|
|
||||||
|
|
||||||
|
[[commands]]
|
||||||
|
id = "gen.password"
|
||||||
|
type = "lua"
|
||||||
|
script = "password.lua"
|
||||||
|
sandbox = "full"
|
||||||
|
timeout = 3000
|
||||||
|
|
||||||
|
[commands.phrases]
|
||||||
|
ru = [
|
||||||
|
"сгенерируй пароль",
|
||||||
|
"придумай пароль",
|
||||||
|
"пароль 12 символов",
|
||||||
|
"сгенерируй надёжный пароль",
|
||||||
|
]
|
||||||
|
en = ["generate password", "make a password"]
|
||||||
|
ua = ["згенеруй пароль"]
|
||||||
|
|
||||||
|
|
||||||
|
[[commands]]
|
||||||
|
id = "gen.uuid"
|
||||||
|
type = "lua"
|
||||||
|
script = "uuid.lua"
|
||||||
|
sandbox = "full"
|
||||||
|
timeout = 3000
|
||||||
|
|
||||||
|
[commands.phrases]
|
||||||
|
ru = [
|
||||||
|
"сгенерируй uuid",
|
||||||
|
"сгенерируй юид",
|
||||||
|
"юид",
|
||||||
|
"уникальный идентификатор",
|
||||||
|
]
|
||||||
|
en = ["generate uuid", "uuid"]
|
||||||
|
ua = ["згенеруй юід"]
|
||||||
22
resources/commands/generators/password.lua
Normal file
22
resources/commands/generators/password.lua
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
-- "Сгенерируй пароль 16 символов" → secure password (alphanumeric + symbols)
|
||||||
|
-- Copies result to clipboard, speaks length only (so it's not echoed).
|
||||||
|
local phrase = (jarvis.context.phrase or ""):lower()
|
||||||
|
local n = tonumber(phrase:match("(%d+)")) or 16
|
||||||
|
if n < 6 then n = 6 end
|
||||||
|
if n > 64 then n = 64 end
|
||||||
|
|
||||||
|
local pool = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*-_=+"
|
||||||
|
math.randomseed(os.time() + (jarvis.context.time.minute or 0) * 1000)
|
||||||
|
|
||||||
|
local pw = {}
|
||||||
|
for _ = 1, n do
|
||||||
|
local idx = math.random(1, #pool)
|
||||||
|
table.insert(pw, pool:sub(idx, idx))
|
||||||
|
end
|
||||||
|
local password = table.concat(pw)
|
||||||
|
|
||||||
|
jarvis.system.clipboard.set(password)
|
||||||
|
jarvis.system.notify("Пароль (" .. n .. " символов)", "Скопирован в буфер обмена")
|
||||||
|
|
||||||
|
-- Speak length only, never the password itself.
|
||||||
|
return jarvis.cmd.ok(string.format("Пароль на %d символов в буфере.", n))
|
||||||
27
resources/commands/generators/uuid.lua
Normal file
27
resources/commands/generators/uuid.lua
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
-- Generate v4 UUID, copy to clipboard, speak short suffix.
|
||||||
|
math.randomseed(os.time() + (jarvis.context.time.minute or 0) * 1000)
|
||||||
|
|
||||||
|
local function hex(n)
|
||||||
|
local s = {}
|
||||||
|
for _ = 1, n do
|
||||||
|
s[#s + 1] = string.format("%x", math.random(0, 15))
|
||||||
|
end
|
||||||
|
return table.concat(s)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- v4 UUID: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx where y is 8|9|a|b
|
||||||
|
local y_pool = { "8", "9", "a", "b" }
|
||||||
|
local uuid = string.format(
|
||||||
|
"%s-%s-4%s-%s%s-%s",
|
||||||
|
hex(8), hex(4), hex(3),
|
||||||
|
y_pool[math.random(1, 4)], hex(3),
|
||||||
|
hex(12)
|
||||||
|
)
|
||||||
|
|
||||||
|
jarvis.system.clipboard.set(uuid)
|
||||||
|
jarvis.system.notify("UUID", uuid)
|
||||||
|
|
||||||
|
-- Speak last 4 hex chars so user knows it landed but doesn't have to listen
|
||||||
|
-- to 32 characters.
|
||||||
|
local suffix = uuid:sub(-4)
|
||||||
|
return jarvis.cmd.ok("UUID в буфере, заканчивается на " .. suffix .. ".")
|
||||||
82
resources/commands/unit_convert/command.toml
Normal file
82
resources/commands/unit_convert/command.toml
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
# Unit conversion — length, weight, temperature, speed, volume.
|
||||||
|
# Pure Lua, no external API.
|
||||||
|
|
||||||
|
[[commands]]
|
||||||
|
id = "convert.length"
|
||||||
|
type = "lua"
|
||||||
|
script = "length.lua"
|
||||||
|
sandbox = "minimal"
|
||||||
|
timeout = 2000
|
||||||
|
|
||||||
|
[commands.phrases]
|
||||||
|
ru = [
|
||||||
|
"переведи метры в футы",
|
||||||
|
"переведи футы в метры",
|
||||||
|
"сколько метров",
|
||||||
|
"сколько футов",
|
||||||
|
"сколько километров",
|
||||||
|
"сколько миль",
|
||||||
|
"переведи в метры",
|
||||||
|
"переведи в футы",
|
||||||
|
"переведи в км",
|
||||||
|
"переведи в мили",
|
||||||
|
]
|
||||||
|
en = ["convert meters to feet", "convert feet to meters", "how many meters", "how many feet"]
|
||||||
|
ua = ["переведи метри у фути"]
|
||||||
|
|
||||||
|
|
||||||
|
[[commands]]
|
||||||
|
id = "convert.weight"
|
||||||
|
type = "lua"
|
||||||
|
script = "weight.lua"
|
||||||
|
sandbox = "minimal"
|
||||||
|
timeout = 2000
|
||||||
|
|
||||||
|
[commands.phrases]
|
||||||
|
ru = [
|
||||||
|
"переведи килограммы в фунты",
|
||||||
|
"переведи фунты в килограммы",
|
||||||
|
"сколько кг в фунтах",
|
||||||
|
"сколько фунтов",
|
||||||
|
"сколько килограммов",
|
||||||
|
]
|
||||||
|
en = ["convert kg to pounds", "how many pounds", "how many kg"]
|
||||||
|
ua = ["переведи кг у фунти"]
|
||||||
|
|
||||||
|
|
||||||
|
[[commands]]
|
||||||
|
id = "convert.temperature"
|
||||||
|
type = "lua"
|
||||||
|
script = "temperature.lua"
|
||||||
|
sandbox = "minimal"
|
||||||
|
timeout = 2000
|
||||||
|
|
||||||
|
[commands.phrases]
|
||||||
|
ru = [
|
||||||
|
"переведи цельсий в фаренгейт",
|
||||||
|
"переведи фаренгейт в цельсий",
|
||||||
|
"сколько по фаренгейту",
|
||||||
|
"сколько по цельсию",
|
||||||
|
"сколько градусов в фаренгейтах",
|
||||||
|
]
|
||||||
|
en = ["convert celsius to fahrenheit", "celsius to fahrenheit", "fahrenheit to celsius"]
|
||||||
|
ua = ["переведи цельсій у фаренгейт"]
|
||||||
|
|
||||||
|
|
||||||
|
[[commands]]
|
||||||
|
id = "convert.speed"
|
||||||
|
type = "lua"
|
||||||
|
script = "speed.lua"
|
||||||
|
sandbox = "minimal"
|
||||||
|
timeout = 2000
|
||||||
|
|
||||||
|
[commands.phrases]
|
||||||
|
ru = [
|
||||||
|
"переведи километры в час в мили в час",
|
||||||
|
"переведи в кмч",
|
||||||
|
"переведи в мили в час",
|
||||||
|
"сколько миль в час",
|
||||||
|
"сколько км в час",
|
||||||
|
]
|
||||||
|
en = ["convert kmh to mph", "kmh to mph", "mph to kmh"]
|
||||||
|
ua = ["переведи кмг у миль на годину"]
|
||||||
33
resources/commands/unit_convert/length.lua
Normal file
33
resources/commands/unit_convert/length.lua
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
-- Длина: метры ↔ футы, км ↔ мили
|
||||||
|
local phrase = (jarvis.context.phrase or ""):lower()
|
||||||
|
local n_str = phrase:match("([%d%.,]+)")
|
||||||
|
if not n_str then return jarvis.cmd.error("Не понял число.") end
|
||||||
|
local n = tonumber((n_str:gsub(",", ".")))
|
||||||
|
if not n then return jarvis.cmd.error("Не понял число.") end
|
||||||
|
|
||||||
|
-- detect "in" target — "в футы" / "в метры" / "в км" / "в мили"
|
||||||
|
-- and source from before "в" or from common units in phrase
|
||||||
|
local result, unit_out
|
||||||
|
|
||||||
|
if phrase:find("в фут") or phrase:find("to feet") then
|
||||||
|
-- meters → feet
|
||||||
|
result = n * 3.28084
|
||||||
|
unit_out = result < 2 and "фут" or (result < 5 and "фута" or "футов")
|
||||||
|
elseif phrase:find("в метр") or phrase:find("to meters") then
|
||||||
|
-- feet → meters
|
||||||
|
result = n / 3.28084
|
||||||
|
unit_out = "метров"
|
||||||
|
elseif phrase:find("в милях") or phrase:find("в миль") or phrase:find("to miles") then
|
||||||
|
-- km → miles
|
||||||
|
result = n * 0.621371
|
||||||
|
unit_out = result < 2 and "миля" or (result < 5 and "мили" or "миль")
|
||||||
|
elseif phrase:find("в километр") or phrase:find("в км") or phrase:find("to km") then
|
||||||
|
-- miles → km
|
||||||
|
result = n * 1.60934
|
||||||
|
unit_out = "километров"
|
||||||
|
else
|
||||||
|
return jarvis.cmd.error("Скажите в чём перевести: в метры/футы/км/мили.")
|
||||||
|
end
|
||||||
|
|
||||||
|
local rounded = math.floor(result * 100 + 0.5) / 100
|
||||||
|
return jarvis.cmd.ok(string.format("%g %s.", rounded, unit_out))
|
||||||
21
resources/commands/unit_convert/speed.lua
Normal file
21
resources/commands/unit_convert/speed.lua
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
-- Скорость: км/ч ↔ миль/ч
|
||||||
|
local phrase = (jarvis.context.phrase or ""):lower()
|
||||||
|
local n_str = phrase:match("([%d%.,]+)")
|
||||||
|
if not n_str then return jarvis.cmd.error("Не понял число.") end
|
||||||
|
local n = tonumber((n_str:gsub(",", ".")))
|
||||||
|
if not n then return jarvis.cmd.error("Не понял число.") end
|
||||||
|
|
||||||
|
local result, unit_out
|
||||||
|
|
||||||
|
if phrase:find("в милях") or phrase:find("в миль") or phrase:find("to mph") then
|
||||||
|
result = n * 0.621371
|
||||||
|
unit_out = "миль в час"
|
||||||
|
elseif phrase:find("в кмч") or phrase:find("в км в час") or phrase:find("в километров") or phrase:find("to kmh") then
|
||||||
|
result = n * 1.60934
|
||||||
|
unit_out = "километров в час"
|
||||||
|
else
|
||||||
|
return jarvis.cmd.error("Скажите: в милях в час или в км в час.")
|
||||||
|
end
|
||||||
|
|
||||||
|
local rounded = math.floor(result + 0.5)
|
||||||
|
return jarvis.cmd.ok(string.format("%d %s.", rounded, unit_out))
|
||||||
21
resources/commands/unit_convert/temperature.lua
Normal file
21
resources/commands/unit_convert/temperature.lua
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
-- Температура: Цельсий ↔ Фаренгейт
|
||||||
|
local phrase = (jarvis.context.phrase or ""):lower()
|
||||||
|
local n_str = phrase:match("(%-?[%d%.,]+)")
|
||||||
|
if not n_str then return jarvis.cmd.error("Не понял число.") end
|
||||||
|
local n = tonumber((n_str:gsub(",", ".")))
|
||||||
|
if not n then return jarvis.cmd.error("Не понял число.") end
|
||||||
|
|
||||||
|
local result, unit_out
|
||||||
|
|
||||||
|
if phrase:find("в фаренгейт") or phrase:find("to fahrenheit") then
|
||||||
|
result = n * 9.0 / 5.0 + 32.0
|
||||||
|
unit_out = "по Фаренгейту"
|
||||||
|
elseif phrase:find("в цельси") or phrase:find("to celsius") then
|
||||||
|
result = (n - 32.0) * 5.0 / 9.0
|
||||||
|
unit_out = "по Цельсию"
|
||||||
|
else
|
||||||
|
return jarvis.cmd.error("Скажите в чём перевести: в фаренгейт или в цельсий.")
|
||||||
|
end
|
||||||
|
|
||||||
|
local rounded = math.floor(result * 10 + 0.5) / 10
|
||||||
|
return jarvis.cmd.ok(string.format("%g градусов %s.", rounded, unit_out))
|
||||||
23
resources/commands/unit_convert/weight.lua
Normal file
23
resources/commands/unit_convert/weight.lua
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
-- Вес: кг ↔ фунты
|
||||||
|
local phrase = (jarvis.context.phrase or ""):lower()
|
||||||
|
local n_str = phrase:match("([%d%.,]+)")
|
||||||
|
if not n_str then return jarvis.cmd.error("Не понял число.") end
|
||||||
|
local n = tonumber((n_str:gsub(",", ".")))
|
||||||
|
if not n then return jarvis.cmd.error("Не понял число.") end
|
||||||
|
|
||||||
|
local result, unit_out
|
||||||
|
|
||||||
|
if phrase:find("в фунт") or phrase:find("to pound") then
|
||||||
|
-- kg → lbs
|
||||||
|
result = n * 2.20462
|
||||||
|
unit_out = result < 2 and "фунт" or (result < 5 and "фунта" or "фунтов")
|
||||||
|
elseif phrase:find("в кг") or phrase:find("в килограм") or phrase:find("to kg") then
|
||||||
|
-- lbs → kg
|
||||||
|
result = n / 2.20462
|
||||||
|
unit_out = "килограмм"
|
||||||
|
else
|
||||||
|
return jarvis.cmd.error("Скажите в чём перевести: в фунты или в кг.")
|
||||||
|
end
|
||||||
|
|
||||||
|
local rounded = math.floor(result * 100 + 0.5) / 100
|
||||||
|
return jarvis.cmd.ok(string.format("%g %s.", rounded, unit_out))
|
||||||
Loading…
Add table
Add a link
Reference in a new issue