Skip to main content
Glama
utils.erl4.14 kB
%% Utility functions module -module(utils). -include("../include/types.hrl"). %% String utilities -export([ capitalize/1, trim/1, split_string/2, format_currency/1, validate_input/2 ]). %% List utilities -export([ find_by_id/2, group_by/2, partition_by/2, safe_nth/2 ]). %% Math utilities -export([ calculate_discount/2, round_to_decimal/2, percentage/2 ]). %% Date/Time utilities -export([ timestamp/0, format_datetime/1, days_between/2 ]). %%%=================================================================== %%% String utilities %%%=================================================================== -spec capitalize(string()) -> string(). capitalize([]) -> []; capitalize([H|T]) -> [string:to_upper(H) | T]. -spec trim(string()) -> string(). trim(String) -> string:strip(string:strip(String, right), left). -spec split_string(string(), string()) -> [string()]. split_string(String, Delimiter) -> string:tokens(String, Delimiter). -spec format_currency(float()) -> string(). format_currency(Amount) -> lists:flatten(io_lib:format("$~.2f", [Amount])). -spec validate_input(atom(), term()) -> boolean(). validate_input(email, Email) when is_list(Email) -> models:validate_email(Email); validate_input(age, Age) when is_integer(Age) -> Age >= 0 andalso Age =< 150; validate_input(name, Name) when is_list(Name) -> length(Name) > 0 andalso length(Name) =< 100; validate_input(_, _) -> false. %%%=================================================================== %%% List utilities %%%=================================================================== -spec find_by_id(integer(), [tuple()]) -> {ok, tuple()} | {error, not_found}. find_by_id(_Id, []) -> {error, not_found}; find_by_id(Id, [H|T]) when element(2, H) =:= Id -> {ok, H}; find_by_id(Id, [_|T]) -> find_by_id(Id, T). -spec group_by(fun((term()) -> term()), [term()]) -> [{term(), [term()]}]. group_by(Fun, List) -> Dict = lists:foldl(fun(Item, Acc) -> Key = Fun(Item), case lists:keyfind(Key, 1, Acc) of {Key, Values} -> lists:keyreplace(Key, 1, Acc, {Key, [Item|Values]}); false -> [{Key, [Item]}|Acc] end end, [], List), [{K, lists:reverse(V)} || {K, V} <- Dict]. -spec partition_by(fun((term()) -> boolean()), [term()]) -> {[term()], [term()]}. partition_by(Predicate, List) -> lists:partition(Predicate, List). -spec safe_nth(integer(), [term()]) -> {ok, term()} | {error, out_of_bounds}. safe_nth(N, List) when N > 0 andalso N =< length(List) -> {ok, lists:nth(N, List)}; safe_nth(_, _) -> {error, out_of_bounds}. %%%=================================================================== %%% Math utilities %%%=================================================================== -spec calculate_discount(float(), float()) -> float(). calculate_discount(Price, DiscountPercent) when DiscountPercent >= 0 andalso DiscountPercent =< 100 -> Price * (100 - DiscountPercent) / 100. -spec round_to_decimal(float(), integer()) -> float(). round_to_decimal(Number, Decimals) -> Factor = math:pow(10, Decimals), round(Number * Factor) / Factor. -spec percentage(number(), number()) -> float(). percentage(Part, Total) when Total =/= 0 -> (Part / Total) * 100; percentage(_, 0) -> 0.0. %%%=================================================================== %%% Date/Time utilities %%%=================================================================== -spec timestamp() -> integer(). timestamp() -> {MegaSecs, Secs, _MicroSecs} = os:timestamp(), MegaSecs * 1000000 + Secs. -spec format_datetime(integer()) -> string(). format_datetime(Timestamp) -> {{Year, Month, Day}, {Hour, Minute, Second}} = calendar:gregorian_seconds_to_datetime(Timestamp + 62167219200), lists:flatten(io_lib:format("~4..0w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w", [Year, Month, Day, Hour, Minute, Second])). -spec days_between(integer(), integer()) -> integer(). days_between(Timestamp1, Timestamp2) -> abs(Timestamp2 - Timestamp1) div (24 * 3600).

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ryota-murakami/serena'

If you have feedback or need assistance with the MCP directory API, please join our Discord server