diff --git a/README_ru.md b/README_ru.md
index 42449f2..ccc38cd 100644
--- a/README_ru.md
+++ b/README_ru.md
@@ -118,7 +118,8 @@ AIO Launcher включает в себя интерпретатор LuaJ 3.0.1
Стандартный API Lua расширен следующими функциями:
* `string:split(delimeter)` - разделяет строку с помощью указанного разделителя и возвращает таблицу;
-* `has_value(table, value)` - проверяет есть ли в таблице указанное значение;
+* `string:replace(regexp, string)` - заменяет текст, найденный регулярным выражением, на другой текст;
+* `get_index(table, value)` - возвращает индекс элемента таблицы;
* `round(x, n)` - округляет число;
В комплект также входят:
diff --git a/bad-script2.lua b/bad-script2.lua
new file mode 100644
index 0000000..102216e
--- /dev/null
+++ b/bad-script2.lua
@@ -0,0 +1,2 @@
+ui:show_toast("Hello")
+
diff --git a/my_covid_widget.lua b/my_covid_widget.lua
new file mode 100644
index 0000000..f756317
--- /dev/null
+++ b/my_covid_widget.lua
@@ -0,0 +1,74 @@
+-- name = "Covid info #2"
+-- description = "Статистика по заболеввниям и выздоровлениям COVID-19"
+-- data_source = "https://covid19api.com/"
+-- type = "widget"
+-- author = "Evgeny Zobnin (zobnin@gmail.com)"
+-- version = "1.0"
+
+local api_url = "https://api.covid19api.com/summary"
+local ccode = "RU"
+
+local json = require "json"
+local equals = " = "
+local tab = {}
+
+function on_alarm()
+ http:get(api_url)
+end
+
+function on_network_result(result)
+ local t=json.decode(result)
+ if ccode == "" then
+ local dat = string.sub(t.Global.Date,1,10):gsub("-",".")
+ ui:set_title(ui:get_default_title().." "..dat)
+ local new = t.Global.NewConfirmed
+ local total = t.Global.TotalConfirmed
+ local newDeaths = t.Global.NewDeaths
+ local totalDeaths = t.Global.TotalDeaths
+ local newRecovered = t.Global.NewRecovered
+ local totalRecovered = t.Global.TotalRecovered
+ local newActives = new - newRecovered - newDeaths
+ local totalActives = total - totalRecovered - totalDeaths
+ tab = {
+ "Заболевшие | всего"..equals..comma_value(total).." | новые"..equals..comma_value(new),
+ "Выздоровевшие | всего"..equals..comma_value(totalRecovered).." | новые"..equals..comma_value(newRecovered),
+ "Умершие | всего"..equals..comma_value(totalDeaths).." | новые"..equals..comma_value(newDeaths),
+ "Активные | всего"..equals..comma_value(totalActives).." | новые"..equals..comma_value(newActives)
+ }
+ else
+ local i = 1
+ while 1 do
+ if t.Countries[i].CountryCode == ccode then
+ break
+ end
+ i = i + 1
+ end
+ local dat = string.sub(t.Countries[i].Date,1,10):gsub("-",".")
+ ui:set_title(ui:get_default_title().." "..ccode.." "..dat)
+ local new = t.Countries[i].NewConfirmed
+ local total = t.Countries[i].TotalConfirmed
+ local newDeaths = t.Countries[i].NewDeaths
+ local totalDeaths = t.Countries[i].TotalDeaths
+ local newRecovered = t.Countries[i].NewRecovered
+ local totalRecovered = t.Countries[i].TotalRecovered
+ local newActives = new - newRecovered - newDeaths
+ local totalActives = total - totalRecovered - totalDeaths
+ tab = {
+ "Заболевшие | всего"..equals..comma_value(total).." | новые"..equals..comma_value(new),
+ "Выздоровевшие | всего"..equals..comma_value(totalRecovered).." | новые"..equals..comma_value(newRecovered),
+ "Умершие | всего"..equals..comma_value(totalDeaths).." | новые"..equals..comma_value(newDeaths),
+ "Активные | всего"..equals..comma_value(totalActives).." | новые"..equals..comma_value(newActives)
+ }
+ end
+ ui:show_lines(tab)
+end
+
+function comma_value(n) -- credit http://richard.warburton.it
+ local left,num,right = string.match(n,'^([^%d]*%d)(%d*)(.-)$')
+ return (left..(num:reverse():gsub('(%d%d%d)','%1,'):reverse())..right):gsub(","," ")
+end
+
+function on_resume()
+ ui:set_folding_flag(true)
+ ui:show_lines(tab)
+end
diff --git a/my_currencies_widget.lua b/my_currencies_widget.lua
new file mode 100644
index 0000000..4d880b6
--- /dev/null
+++ b/my_currencies_widget.lua
@@ -0,0 +1,112 @@
+-- name = "Курсы валют #2"
+-- description = "Виджет курсов валют. Нажмите на виджет, чтобы изменить дату"
+-- data_source = "https://github.com/fawazahmed0/currency-api#readme"
+-- type = "widget"
+-- author = "Andrey Gavrilov"
+-- version = "1.0"
+
+local sx = require "pl.stringx"
+local json = require "json"
+
+local curs = {"usd:rub", "eur:rub", "eur:usd", "gbp:rub", "gbp:usd", "chf:usd", "aed:usd", "cny:rub", "inr:rub", "btc:usd"}
+
+-- constants
+local red_color = "#f44336"
+local green_color = "#48ad47"
+local text_color = ui:get_secondary_text_color()
+local equals = " = "
+
+-- global vars
+local result_curr = ""
+local tabl = {}
+
+function on_resume()
+ ui:set_folding_flag(true)
+ ui:show_lines(tabl)
+end
+
+function on_alarm()
+ get_rates("latest", "curr")
+end
+
+function get_rates(loc_date,id)
+ http:get("https://cdn.jsdelivr.net/gh/fawazahmed0/currency-api@1/"..loc_date.."/currencies/usd.json",id)
+end
+
+function on_network_result_curr(result)
+ result_curr = result
+
+ local t = json.decode(result)
+ local dat = t.date
+ local prev_date = prev_date(dat)
+
+ get_rates(prev_date, "prev")
+end
+
+function on_network_result_prev(result)
+ tabl = create_tab(result)
+ ui:show_lines(tabl)
+end
+
+function on_click(idx)
+ ui:show_edit_dialog("Введите дату курсов", "Введите дату курсов в формате 2020.12.31. Пустое значение - текущая дата.")
+end
+
+function on_dialog_action(dat)
+ if dat == "" then dat = "latest" end
+ get_rates(dat:gsub('%.', "-"), "curr")
+end
+
+function prev_date(dat)
+ local prev_date = dat:split("-")
+ local prev_time = os.time{year=prev_date[1], month=prev_date[2], day=prev_date[3]} - (60*60*24)
+ return os.date("%Y-%m-%d", prev_time)
+end
+
+function create_tab(result)
+ local tab = {}
+ local t_c = json.decode(result_curr)
+ local t_p = json.decode(result)
+
+ -- set title
+ local dat = t_c.date
+ ui:set_title(ui:get_default_title().." "..dat:gsub("-", "."))
+
+ for idx = 1, #curs, 1 do
+ local cur = curs[idx]:split(":")
+
+ local rate_curr1 = t_c.usd[cur[1]]
+ local rate_curr2 = t_c.usd[cur[2]]
+ local rate_prev1 = t_p.usd[cur[1]]
+ local rate_prev2 = t_p.usd[cur[2]]
+
+ local rate_curr = round(rate_curr2/rate_curr1, 4)
+ local rate_prev = round(rate_prev2/rate_prev1, 4)
+ local change = round((rate_curr-rate_prev)/rate_prev*100,2)
+
+ local line = "1 "..string.upper(cur[1])..equals..rate_curr.." "..string.upper(cur[2])
+ line = line..get_formatted_change_text(change)
+
+ tab[idx] = line
+ end
+ return tab
+end
+
+-- utils --
+
+function get_formatted_change_text(change)
+ if change > 0 then
+ return " +"..change.."%"
+ elseif change < 0 then
+ return " "..change.."%"
+ else
+ return " "..change.."%"
+ end
+end
+
+function round(x, n)
+ local n = math.pow(10, n or 0)
+ local x = x * n
+ if x >= 0 then x = math.floor(x + 0.5) else x = math.ceil(x - 0.5) end
+ return x / n
+end
diff --git a/utils.lua b/utils.lua
deleted file mode 100644
index e028a88..0000000
--- a/utils.lua
+++ /dev/null
@@ -1,44 +0,0 @@
-function get_args_kv()
- local keys = {}
- local values = {}
- local args = aio:get_args()
-
- for idx = 1, #args, 1 do
- local arg = sx.split(args[idx], ":")
- keys[idx] = arg[1]
- values[idx] = arg[2]
- end
-
- return { keys, values }
-end
-
-function string:split(sep)
- if sep == nil then
- sep = "%s"
- end
-
- local t={}
-
- for str in string.gmatch(self, "([^"..sep.."]+)") do
- table.insert(t, str)
- end
-
- return t
-end
-
-function round(x, n)
- local n = math.pow(10, n or 0)
- local x = x * n
- if x >= 0 then x = math.floor(x + 0.5) else x = math.ceil(x - 0.5) end
- return x / n
-end
-
-function table:get_index(val)
- for index, value in ipairs(self) do
- if value == val then
- return index
- end
- end
-
- return -1
-end