|
|
@ -1,496 +0,0 @@ |
|
|
|
-module(util). |
|
|
|
|
|
|
|
-export([ |
|
|
|
string_width/1, |
|
|
|
rand_list/1, |
|
|
|
rm_str_space/1, |
|
|
|
rm_str_lr_space/1, |
|
|
|
check_sen_keyword/2 |
|
|
|
]). |
|
|
|
|
|
|
|
-export([ |
|
|
|
upset_list/1 |
|
|
|
, insert_last/2 |
|
|
|
]). |
|
|
|
|
|
|
|
|
|
|
|
%% @doc 去除字符串左右空格 |
|
|
|
rm_str_lr_space(String) -> |
|
|
|
String1 = rm_str_lr_space1(String), |
|
|
|
String2 = lists:reverse(String1), |
|
|
|
String3 = rm_str_lr_space1(String2), |
|
|
|
lists:reverse(String3). |
|
|
|
|
|
|
|
rm_str_lr_space1([32 | T]) -> |
|
|
|
rm_str_lr_space1(T); |
|
|
|
rm_str_lr_space1(T) -> |
|
|
|
T. |
|
|
|
|
|
|
|
%% @doc 去除字符串所有空格 |
|
|
|
rm_str_space(String) -> |
|
|
|
rm_str_space(String, []). |
|
|
|
|
|
|
|
rm_str_space([32 | T], L) -> |
|
|
|
rm_str_space(T, L); |
|
|
|
rm_str_space([H | T], L) -> |
|
|
|
rm_str_space(T, [H | L]); |
|
|
|
rm_str_space([], L) -> |
|
|
|
lists:reverse(L). |
|
|
|
|
|
|
|
%% @doc 随机列表 |
|
|
|
rand_list([Obj]) -> |
|
|
|
Obj; |
|
|
|
rand_list(L) -> |
|
|
|
Len = length(L), |
|
|
|
case Len > 0 of |
|
|
|
true -> |
|
|
|
Index = rand:uniform(Len), |
|
|
|
lists:nth(Index, L); |
|
|
|
_ -> |
|
|
|
false |
|
|
|
end. |
|
|
|
|
|
|
|
%% 随机取出list元素 |
|
|
|
list_rand([]) -> null; |
|
|
|
list_rand(List) -> |
|
|
|
Len = length(List), |
|
|
|
Index = rand:uniform(Len), |
|
|
|
lists:nth(Index, List). |
|
|
|
|
|
|
|
%% 随机从列表中选n个元素 |
|
|
|
%% @return:: null | List |
|
|
|
list_rand_n([], _PickNum) -> null; |
|
|
|
list_rand_n(List, PickNum) -> |
|
|
|
list_rand_n(List, PickNum, []). |
|
|
|
|
|
|
|
list_rand_n([], _PickNum, AccList) -> AccList; |
|
|
|
list_rand_n(_List, 0, AccList) -> AccList; |
|
|
|
list_rand_n(List, PickNum, AccList) -> |
|
|
|
PickOne = list_rand(List), |
|
|
|
LeftList = List -- [PickOne], |
|
|
|
list_rand_n(LeftList, PickNum - 1, [PickOne | AccList]). |
|
|
|
|
|
|
|
%% 依据权重,从元组列表中随机挑选N个元素,返回被抽中的元组列表 |
|
|
|
%% @args:: |
|
|
|
%% Tuples:: 元组列表 |
|
|
|
%% Index:: 是权重所在的位置 |
|
|
|
%% PickNum:: 随机出的数量 |
|
|
|
rand_by_weight(Tuples, Index, PickNum) when PickNum >= 0 -> |
|
|
|
rand_N_by_weight__(Tuples, Index, PickNum, []). |
|
|
|
|
|
|
|
rand_N_by_weight__(_Tuples, _Index, 0, Ret) -> Ret; |
|
|
|
rand_N_by_weight__([], _Index, _PickNum, Ret) -> Ret; |
|
|
|
rand_N_by_weight__(Tuples, Index, PickNum, Ret) -> |
|
|
|
PickOne = rand_by_weight(Tuples, Index), |
|
|
|
LeftTuples = lists:delete(PickOne, Tuples), |
|
|
|
rand_N_by_weight__(LeftTuples, Index, PickNum - 1, [PickOne | Ret]). |
|
|
|
|
|
|
|
|
|
|
|
%% 依据权重,从元组列表中随机挑选一个元素,返回被抽中的元组, |
|
|
|
%% 如果没有对应的元素,则抛出异常 |
|
|
|
%% Index是权重所在的位置 |
|
|
|
%% @return: Tuple |
|
|
|
rand_by_weight([], _Index) -> |
|
|
|
error(badargs); |
|
|
|
rand_by_weight(Tuples, Index) -> |
|
|
|
Sum = lists:sum([element(Index, Tuple) || Tuple <- Tuples]), |
|
|
|
P = rand:uniform(Sum), |
|
|
|
rand_one_by_weight__(Tuples, Index, P). |
|
|
|
|
|
|
|
rand_one_by_weight__([Tuple], _, _) -> |
|
|
|
Tuple; |
|
|
|
rand_one_by_weight__([Tuple | T], Index, P) -> |
|
|
|
case element(Index, Tuple) of |
|
|
|
Weight when P =< Weight -> |
|
|
|
Tuple; |
|
|
|
Weight -> |
|
|
|
rand_one_by_weight__(T, Index, P - Weight) |
|
|
|
end. |
|
|
|
|
|
|
|
%% 过滤掉元组列表中某个元素相同的列表 |
|
|
|
%% eg:L=[{1,2},{2,2},{3,1}]. list_filter(L, 2) -> [{1,2},{3,1}] |
|
|
|
list_filter(List, N) -> |
|
|
|
list_filter_helper(List, N, [], []). |
|
|
|
|
|
|
|
list_filter_helper([H | T], N, ResultList, KeyList) -> |
|
|
|
Key = element(N, H), |
|
|
|
case lists:member(Key, KeyList) of |
|
|
|
true -> list_filter_helper(T, N, ResultList, KeyList); |
|
|
|
false -> list_filter_helper(T, N, [H | ResultList], [Key | KeyList]) |
|
|
|
end; |
|
|
|
list_filter_helper([], _, ResultList, _) -> ResultList. |
|
|
|
|
|
|
|
%% 随机打乱list元素顺序 |
|
|
|
list_shuffle(List) -> |
|
|
|
Len = length(List), |
|
|
|
List1 = [{rand:uniform(Len + 10000), X} || X <- List], |
|
|
|
List2 = lists:sort(List1), |
|
|
|
[E || {_, E} <- List2]. |
|
|
|
|
|
|
|
%% 根据下标替换list元素值 |
|
|
|
list_replace(Index, NewElem, List) -> |
|
|
|
list_replace_helper(List, Index, NewElem, 1, []). |
|
|
|
list_replace_helper([], _Index, _NewElem, _CurIndex, NewList) -> |
|
|
|
NewList; |
|
|
|
list_replace_helper([H | T], Index, NewElem, CurIndex, NewList) -> |
|
|
|
if Index =:= CurIndex -> |
|
|
|
list_replace_helper(T, Index, NewElem, CurIndex + 1, NewList ++ [NewElem]); |
|
|
|
true -> |
|
|
|
list_replace_helper(T, Index, NewElem, CurIndex + 1, NewList ++ [H]) |
|
|
|
end. |
|
|
|
|
|
|
|
%% 根据list的元素值获得下标 |
|
|
|
list_get_index(Elem, List) -> |
|
|
|
list_get_index_helper(List, Elem, 0). |
|
|
|
list_get_index_helper([], _Elem, _Index) -> |
|
|
|
0; |
|
|
|
list_get_index_helper([H | T], Elem, Index) -> |
|
|
|
if H =:= Elem -> |
|
|
|
Index + 1; |
|
|
|
true -> |
|
|
|
list_get_index_helper(T, Elem, Index + 1) |
|
|
|
end. |
|
|
|
|
|
|
|
%% 根据list的元素值获得下标(加强版) |
|
|
|
%% @param: (Elem, N, List), List为元组列表,N为元组中第N个元素等于Elem |
|
|
|
%% @return {0,null} | {Index, H} |
|
|
|
list_get_index_ex(Elem, N, List) when is_list(List), is_integer(N) -> |
|
|
|
list_get_index_ex(Elem, N, List, 0); |
|
|
|
list_get_index_ex(_, _, _) -> {0, null}. |
|
|
|
list_get_index_ex(_Elem, _N, [], _) -> {0, null}; |
|
|
|
list_get_index_ex(Elem, N, [H | _], Index) when element(N, H) =:= Elem -> {Index + 1, H}; |
|
|
|
list_get_index_ex(Elem, N, [_ | L], Index) -> list_get_index_ex(Elem, N, L, Index + 1). |
|
|
|
|
|
|
|
|
|
|
|
%% 多个列表数值相加,结果以第一个列表的长度为准 |
|
|
|
lists_add([ResultList]) -> ResultList; |
|
|
|
lists_add([List1, List2 | T]) -> |
|
|
|
ResultList = lists_add_helper(List1, List2, []), |
|
|
|
lists_add([ResultList | T]). |
|
|
|
|
|
|
|
lists_add_helper([], _List2, ResultList) -> |
|
|
|
lists:reverse(ResultList); |
|
|
|
lists_add_helper(List1, [], ResultList) -> |
|
|
|
lists:reverse(ResultList) ++ List1; |
|
|
|
lists_add_helper([H1 | T1], [H2 | T2], ResultList) -> |
|
|
|
lists_add_helper(T1, T2, [H1 + H2 | ResultList]). |
|
|
|
|
|
|
|
%% 扩展版lists:min/1 |
|
|
|
%% @param: (List, N), List为元组列表,N为元组中第N个元素 |
|
|
|
min_ex([H | T], N) -> min_ex(T, H, N). |
|
|
|
min_ex([H | T], Min, N) when element(N, H) < element(N, Min) -> min_ex(T, H, N); |
|
|
|
min_ex([_ | T], Min, N) -> min_ex(T, Min, N); |
|
|
|
min_ex([], Min, _) -> Min. |
|
|
|
|
|
|
|
%% 扩展版lists:max/1 |
|
|
|
%% @param: (List, N), List为元组列表,N为元组中第N个元素 |
|
|
|
max_ex([H | T], N) -> max_ex(T, H, N); |
|
|
|
max_ex([], _N) -> 0. |
|
|
|
|
|
|
|
max_ex([H | T], Max, N) when element(N, H) > element(N, Max) -> max_ex(T, H, N); |
|
|
|
max_ex([_ | T], Max, N) -> max_ex(T, Max, N); |
|
|
|
max_ex([], Max, _) -> Max. |
|
|
|
|
|
|
|
%% 扩展版lists:max/1 |
|
|
|
%% @param: (List, N), List为元组列表,N为元组中第N个元素, Record为列表为空时调用者预期返回的内容 |
|
|
|
keymax([H | T], N, Record) -> keymax(T, H, N, Record); |
|
|
|
keymax([], _N, Record) -> Record. |
|
|
|
|
|
|
|
keymax([H | T], Max, N, Record) when element(N, H) > element(N, Max) -> keymax(T, H, N, Record); |
|
|
|
keymax([_ | T], Max, N, Record) -> keymax(T, Max, N, Record); |
|
|
|
keymax([], Max, _, _) -> Max. |
|
|
|
|
|
|
|
%% 列表中的元素是否全部相同 |
|
|
|
%% @param: (List, N), List为元组列表,N为元组中第N个元素 |
|
|
|
is_all_same([H | T], N) -> is_all_same(T, H, N). |
|
|
|
|
|
|
|
is_all_same([H | T], Min, N) when element(N, H) =:= element(N, Min) -> is_all_same(T, H, N); |
|
|
|
is_all_same(L, _, _) when L =/= [] -> false; |
|
|
|
is_all_same([], _, _) -> true. |
|
|
|
|
|
|
|
%% 列表中某元素的总和 |
|
|
|
sum_ex(L, N) -> sum_ex(L, 0, N). |
|
|
|
sum_ex([H | T], Sum, N) -> sum_ex(T, Sum + element(N, H), N); |
|
|
|
sum_ex([], Sum, _) -> Sum. |
|
|
|
|
|
|
|
%% for循环 |
|
|
|
for(Max, Max, F) -> |
|
|
|
F(Max); |
|
|
|
for(I, Max, F) -> |
|
|
|
F(I), |
|
|
|
for(I + 1, Max, F). |
|
|
|
|
|
|
|
%% 带返回状态的for循环 |
|
|
|
%% @return {ok, State} |
|
|
|
for(Max, Min, _F, State) when Min < Max -> {ok, State}; |
|
|
|
for(Max, Max, F, State) -> F(Max, State); |
|
|
|
for(I, Max, F, State) -> {ok, NewState} = F(I, State), for(I + 1, Max, F, NewState). |
|
|
|
|
|
|
|
%% 在List中的每两个元素之间插入一个分隔符 |
|
|
|
implode(_S, []) -> |
|
|
|
[<<>>]; |
|
|
|
implode(S, L) when is_list(L) -> |
|
|
|
implode(S, L, []). |
|
|
|
implode(_S, [H], NList) -> |
|
|
|
lists:reverse([type:object_to_list(H) | NList]); |
|
|
|
implode(S, [H | T], NList) -> |
|
|
|
L = [type:object_to_list(H) | NList], |
|
|
|
implode(S, T, [S | L]). |
|
|
|
|
|
|
|
%% 字符->列 |
|
|
|
explode(S, B) -> |
|
|
|
re:split(B, S, [{return, list}]). |
|
|
|
explode(S, B, int) -> |
|
|
|
[list_to_integer(Str) || Str <- explode(S, B), length(Str) > 0]. |
|
|
|
|
|
|
|
%% 扩展的map函数 |
|
|
|
map_ex(_Fun, [], _Arg) -> |
|
|
|
[]; |
|
|
|
map_ex(Fun, [H | T], Arg) -> |
|
|
|
[Fun(H, Arg) | map_ex(Fun, T, Arg)]. |
|
|
|
|
|
|
|
%% 截取列表的第Begin个到第End个 |
|
|
|
sublist(L, Begin, End) -> |
|
|
|
sublist(L, Begin, End, {1, []}). |
|
|
|
sublist([], _Begin, _End, {_NowNth, RetL}) -> |
|
|
|
lists:reverse(RetL); |
|
|
|
sublist([_ | _L], _Bigen, End, {NowNth, RetL}) when NowNth > End -> |
|
|
|
lists:reverse(RetL); |
|
|
|
sublist([Item | L], Begin, End, {NowNth, RetL}) when Begin =< NowNth andalso NowNth =< End -> |
|
|
|
sublist(L, Begin, End, {NowNth + 1, [Item | RetL]}); |
|
|
|
sublist([_ | L], Begin, End, {NowNth, RetL}) -> |
|
|
|
sublist(L, Begin, End, {NowNth + 1, RetL}). |
|
|
|
|
|
|
|
|
|
|
|
%%========================================================================= |
|
|
|
%% 字符文本操作 |
|
|
|
%%========================================================================= |
|
|
|
|
|
|
|
%% 字符加密 |
|
|
|
check_char_encrypt(Id, Time, TK) -> |
|
|
|
TICKET = "7YnELt8MmA4jVED7", |
|
|
|
Hex = md5(lists:concat([Time, Id, TICKET])), |
|
|
|
%NowTime = time:unixtime(), |
|
|
|
%Hex =:= TK andalso NowTime - Time >= -10 andalso NowTime - Time < 300. |
|
|
|
Hex =:= TK. |
|
|
|
|
|
|
|
%% 转换成HEX格式的md5 |
|
|
|
md5(S) -> |
|
|
|
lists:flatten([io_lib:format("~2.16.0b", [N]) || N <- binary_to_list(erlang:md5(S))]). |
|
|
|
|
|
|
|
%% Function: 检查客户端发过来的内容,false为不合法,true为合法 |
|
|
|
%% @param: String: 客户端发来的字符串 |
|
|
|
%% @param: Length: 服务端限制的字符串长度 |
|
|
|
check_string(String, Length) -> |
|
|
|
case check_length(String, Length) of |
|
|
|
true -> |
|
|
|
case check_keyword(String, ["'", "/", "\"", "_", "<", ">"]) of |
|
|
|
false -> |
|
|
|
case check_keyword(String) of |
|
|
|
false -> true; |
|
|
|
true -> false |
|
|
|
end; |
|
|
|
true -> |
|
|
|
false |
|
|
|
end; |
|
|
|
false -> |
|
|
|
false |
|
|
|
end. |
|
|
|
|
|
|
|
%% 检查关键字,存在非法字符返回true,否则false |
|
|
|
%% @spec check_keyword(Text, Words) -> false | true |
|
|
|
%% @param Text : 需要检查的字符串(或字符串的二进制形式) |
|
|
|
%% @param Words: 非法字符列表 |
|
|
|
check_keyword(_, []) -> |
|
|
|
false; |
|
|
|
check_keyword(Text, [Word | Words]) -> |
|
|
|
case re:run(Text, Word, [{capture, none}]) of |
|
|
|
match -> |
|
|
|
true; |
|
|
|
nomatch -> |
|
|
|
check_keyword(Text, Words) |
|
|
|
end. |
|
|
|
|
|
|
|
filter_text_gm(Text) when is_bitstring(Text) -> |
|
|
|
Text; |
|
|
|
filter_text_gm(Text) when is_list(Text) -> |
|
|
|
list_to_bitstring(Text). |
|
|
|
|
|
|
|
%% 敏感词检测 |
|
|
|
%% @return true 存在关键词 |
|
|
|
%% false 不存在关键词 |
|
|
|
%% @var Text:字符串 |
|
|
|
check_keyword(Text) -> |
|
|
|
if |
|
|
|
is_list(Text) -> |
|
|
|
svr_chat:word_base_other(Text); |
|
|
|
true -> |
|
|
|
true |
|
|
|
end. |
|
|
|
|
|
|
|
%% 长度合法性检查 |
|
|
|
check_length(Item, LenLimit) -> |
|
|
|
check_length(Item, 1, LenLimit). |
|
|
|
|
|
|
|
check_length(Item, MinLen, MaxLen) -> |
|
|
|
% case asn1rt:utf8_binary_to_list(list_to_binary(Item)) of |
|
|
|
% {ok, UnicodeList} -> |
|
|
|
% Len = string_width(UnicodeList), |
|
|
|
% Len =< MaxLen andalso Len >= MinLen; |
|
|
|
% {error, _Reason} -> |
|
|
|
% false |
|
|
|
% end. |
|
|
|
case unicode:characters_to_list(list_to_binary(Item)) of |
|
|
|
UnicodeList when is_list(UnicodeList) -> |
|
|
|
Len = string_width(UnicodeList), |
|
|
|
Len =< MaxLen andalso Len >= MinLen; |
|
|
|
_ -> |
|
|
|
false |
|
|
|
end. |
|
|
|
|
|
|
|
%% 字符宽度,1汉字=2单位长度,1数字字母=1单位长度 |
|
|
|
string_width(String) -> |
|
|
|
string_width(String, 0). |
|
|
|
string_width([], Len) -> |
|
|
|
Len; |
|
|
|
string_width([H | T], Len) -> |
|
|
|
case H > 255 of |
|
|
|
true -> |
|
|
|
string_width(T, Len + 2); |
|
|
|
false -> |
|
|
|
string_width(T, Len + 1) |
|
|
|
end. |
|
|
|
|
|
|
|
%% IP元组转字符 |
|
|
|
ip2bin({A, B, C, D}) -> |
|
|
|
[integer_to_list(A), ".", integer_to_list(B), ".", integer_to_list(C), ".", integer_to_list(D)]. |
|
|
|
|
|
|
|
%% 过滤掉字符串中的特殊字符 |
|
|
|
filter_string(String, CharList) -> |
|
|
|
case is_list(String) of |
|
|
|
true -> |
|
|
|
filter_string_helper(String, CharList, []); |
|
|
|
false when is_binary(String) -> |
|
|
|
ResultString = filter_string_helper(binary_to_list(String), CharList, []), |
|
|
|
list_to_binary(ResultString); |
|
|
|
false -> |
|
|
|
String |
|
|
|
end. |
|
|
|
|
|
|
|
filter_string_helper([], _CharList, ResultString) -> |
|
|
|
ResultString; |
|
|
|
filter_string_helper([H | T], CharList, ResultString) -> |
|
|
|
case lists:member(H, CharList) of |
|
|
|
true -> filter_string_helper(T, CharList, ResultString); |
|
|
|
false -> filter_string_helper(T, CharList, ResultString ++ [H]) |
|
|
|
end. |
|
|
|
|
|
|
|
|
|
|
|
%% 显示record |
|
|
|
%% 用法 : r2p(#ets_online{...}, record_info(fields, ets_online)) |
|
|
|
r2p(A, B) -> record_to_proplist(A, B). |
|
|
|
record_to_proplist(Record, Fields) -> |
|
|
|
record_to_proplist(Record, Fields, record__). |
|
|
|
|
|
|
|
record_to_proplist(Record, Fields, TypeKey) |
|
|
|
when tuple_size(Record) - 1 =:= length(Fields) -> |
|
|
|
lists:zip([TypeKey | Fields], tuple_to_list(Record)). |
|
|
|
|
|
|
|
%% 角度和cos的转换,cos(60') = 0.5 |
|
|
|
angle_to_float(Angle) -> |
|
|
|
math:cos(math:pi() * Angle / 180). |
|
|
|
|
|
|
|
%% 分页取数据 |
|
|
|
% @param Data 所有数据(列表) |
|
|
|
% @param Page 第几页数据(大于总页数则默认最后页) |
|
|
|
% @param PageNum 每一页数量 |
|
|
|
% @return {总页数, 当前页, 当前页数据} |
|
|
|
page_data(Data, Page, PageNum) -> |
|
|
|
Len = length(Data), |
|
|
|
PageTotal = ceil(Len / PageNum), |
|
|
|
PageNow = case Page > PageTotal of true -> max(1, PageTotal); false -> Page end, |
|
|
|
StartIndex = (PageNow - 1) * PageNum + 1, |
|
|
|
PickData = lists:sublist(Data, StartIndex, PageNum), |
|
|
|
{PageTotal, PageNow, PickData}. |
|
|
|
|
|
|
|
|
|
|
|
%% -------------------------- |
|
|
|
%% 计算字符串的相似度 |
|
|
|
%% -------------------------- |
|
|
|
% 用于聊天检测 |
|
|
|
calc_string_compare(A, B) -> |
|
|
|
AWordDict = word_dict(unicode:characters_to_list(type:object_to_binary(A))), |
|
|
|
BWordDict = word_dict(unicode:characters_to_list(type:object_to_binary(B))), |
|
|
|
Dict = merge_dict(AWordDict, BWordDict), |
|
|
|
F = fun(_K, {V1, V2}, {DenominatorAcc, Sqdoc1Acc, Sqdoc2Acc}) -> |
|
|
|
{DenominatorAcc + V1 * V2 |
|
|
|
, Sqdoc1Acc + V1 * V1 |
|
|
|
, Sqdoc2Acc + V2 * V2 |
|
|
|
} |
|
|
|
end, |
|
|
|
{Denominator, Sqdoc1, Sqdoc2} = dict:fold(F, {0, 0, 0}, Dict), |
|
|
|
case Sqdoc1 =:= 0 orelse Sqdoc2 =:= 0 of |
|
|
|
true -> 0; |
|
|
|
false -> Denominator / math:sqrt(Sqdoc1 * Sqdoc2) |
|
|
|
end. |
|
|
|
|
|
|
|
merge_dict(D1, D2) -> |
|
|
|
F1 = fun(_K, V) -> {V, 0} end, |
|
|
|
D1_ = dict:map(F1, D1), |
|
|
|
F2 = fun(K, V, Dict) -> |
|
|
|
case dict:find(K, D1_) of |
|
|
|
error -> dict:store(K, {0, V}, Dict); |
|
|
|
{ok, {V1, 0}} -> dict:store(K, {V1, V}, Dict); |
|
|
|
_ -> Dict |
|
|
|
end |
|
|
|
end, |
|
|
|
D2_ = dict:fold(F2, D1_, D2), |
|
|
|
D2_. |
|
|
|
% % 过滤常用词 |
|
|
|
% F3 = fun(K, _V) -> not lists:member(K, ?GENERAL_WORD) end, |
|
|
|
% D3_ = dict:filter(F3, D2_), |
|
|
|
% D3_. |
|
|
|
|
|
|
|
% 取字(连续数字、连续字符当作一个字) |
|
|
|
word_dict(L) -> word__(L, [], dict:new()). |
|
|
|
% A-Z 65-90 |
|
|
|
% a-z 97-122 |
|
|
|
% 0-9 48-57 |
|
|
|
word__([A | L], Word, WordDict) when (A >= 65 andalso A =< 90) orelse |
|
|
|
(A >= 97 andalso A =< 122) orelse |
|
|
|
(A >= 48 andalso A =< 57) -> |
|
|
|
word__(L, [A | Word], WordDict); |
|
|
|
word__([I | L], [], WordDict) -> |
|
|
|
word__(L, [], dict:update_counter([I], 1, WordDict)); |
|
|
|
word__([I | L], Word, WordDict) -> |
|
|
|
WordDict1 = dict:update_counter(Word, 1, WordDict), |
|
|
|
WordDict2 = dict:update_counter([I], 1, WordDict1), |
|
|
|
word__(L, [], WordDict2); |
|
|
|
word__([], [], WordList) -> |
|
|
|
WordList; |
|
|
|
word__([], Word, WordDict) -> |
|
|
|
dict:update_counter(Word, 1, WordDict). |
|
|
|
|
|
|
|
%% @doc 打印进程信息 |
|
|
|
process_infos() -> |
|
|
|
filelib:ensure_dir("../logs/"), |
|
|
|
File = "../logs/processes_infos.log", |
|
|
|
{ok, Fd} = file:open(File, [write, raw, binary, append]), |
|
|
|
Fun = fun(Pi) -> |
|
|
|
Info = io_lib:format("=>~p \n\n", [Pi]), |
|
|
|
case filelib:is_file(File) of |
|
|
|
true -> file:write(Fd, Info); |
|
|
|
false -> |
|
|
|
file:close(Fd), |
|
|
|
{ok, NewFd} = file:open(File, [write, raw, binary, append]), |
|
|
|
file:write(NewFd, Info) |
|
|
|
end, |
|
|
|
timer:sleep(20) |
|
|
|
end, |
|
|
|
[Fun(erlang:process_info(P)) || P <- erlang:processes()]. |
|
|
|
|
|
|
|
%% @doc 检测是否在范围内 |
|
|
|
check_range(X, Y, TarX, TarY, Range) -> |
|
|
|
X1 = abs(X - TarX), |
|
|
|
Y1 = abs(Y - TarY), |
|
|
|
math:sqrt(X1 * X1 + Y1 * Y1) =< Range. |