Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 

176 linhas
5.3 KiB

-module(rankWork).
-behavior(gen_srv).
-include("ranks.hrl").
-export([
start_link/1
, mUpdateScore/3
, mUpdateInfo/2
, mGetRankInfo/5
]).
-export([
init/1
, handleCall/3
, handleCast/2
, handleInfo/2
, terminate/2
, code_change/3
]).
-record(state, {}).
%% ******************************************** API *******************************************************************
start_link(SrvName) ->
gen_srv:start_link({local, SrvName}, ?MODULE, [], []).
%% ******************************************** callback **************************************************************
init(_Args) ->
{ok, #state{}}.
handleCall(_Msg, _State, _FROM) ->
{reply, ok}.
handleCast(_Msg, _State) ->
kpS.
handleInfo(_Msg, _State) ->
kpS.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%% ****************************************************** logic ********************************************************
mUpdateScore(Key, RankType, Score) ->
{_RankLimit, RankMax} = ?ranksLimit:getV(RankType),
RankPos = ?ranksCfg:getV(RankType),
case ets:lookup(etsRankInfo, Key) of
[RankRecord] ->
OldScore = element(RankPos, RankRecord),
ets:delete(RankType, OldScore),
RankSize = ets:info(RankType, size),
case RankSize >= RankMax of
true ->
FirstKey = ets:first(RankType),
case Score > FirstKey of
true ->
ets:insert(RankType, Score),
ets:delete(RankType, FirstKey);
_ ->
ignore
end;
_ ->
ets:insert(RankType, Score)
end,
ets:update_element(etsRankInfo, Key, {RankPos, Score});
_ ->
%% 插入新的数据
RankSize = ets:info(RankType, size),
case RankSize >= RankMax of
true ->
FirstKey = ets:first(RankType),
case Score > FirstKey of
true ->
ets:insert(RankType, Score),
ets:delete(RankType, FirstKey),
NewRecord = #etsRankRecord{key = Key},
RankRecord = setelement(RankPos, NewRecord, Score),
ets:insert(etsRankInfo, RankRecord);
_ ->
ignore
end;
_ ->
ets:insert(RankType, Score),
NewRecord = #etsRankRecord{key = Key},
RankRecord = setelement(RankPos, NewRecord, Score),
ets:insert(etsRankInfo, RankRecord)
end
end,
{mayReply, ok}.
mUpdateInfo(Key, RecordKvs) ->
ets:update_element(etsRankInfo, Key, RecordKvs),
{mayReply, ok}.
mGetRankInfo(RankType, MyKey, Cnt, Page, PageInfo) ->
{RankLimit, _RankMax} = ?ranksLimit:getV(RankType),
%% 请求第一页的时候 附加上自己的排名
SelfRank =
case Page of
0 ->
case ets:lookup_element(etsRankInfo, MyKey) of
[RankRecord] ->
RankPos = ?ranksCfg:getV(RankType),
CurScore = element(RankPos, RankRecord),
MyIndex = ets:select_count(RankType, [{{'$1', '$2'}, [{'>=', '$1', CurScore}], [true]}]),
max(RankLimit, MyIndex);
_ ->
-1
end;
_ ->
0
end,
MS =
case PageInfo == 0 orelse PageInfo of
true ->
[{'$1', [], ['$1']}];
<<"">> ->
[{'$1', [], ['$1']}];
_ ->
try binary_to_term(PageInfo) of
KeyTerm when KeyTerm == <<"">>; KeyTerm == "" ->
[{'$1', [], ['$1']}];
KeyTerm ->
% ets:fun2ms(fun({K, _V} = T) when K < KeyTerm -> T end)
[{{'$1', '$2'}, [{'<', '$1', KeyTerm}], ['$_']}]
catch _C:_R ->
[{'$1', [], ['$1']}]
end
end,
case ets:select_reverse(RankType, MS, Cnt) of
'$end_of_table' ->
{true, {<<"">>, []}};
{KeyIds, '$end_of_table'} ->
{true, SelfRank, makeRankData(KeyIds, Cnt * Page + 1)};
{KeyIds, _NextKey} ->
Length = length(KeyIds),
if
Length < Cnt ->
{true, SelfRank, makeRankData(KeyIds, Cnt * Page + 1)};
true ->
NewCurCnt = Page * Cnt + Length,
case NewCurCnt >= RankLimit of
true ->
{true, SelfRank, makeRankData(KeyIds, Cnt * Page + 1)};
_ ->
{false, SelfRank, makeRankData(KeyIds, Cnt * Page + 1)}
end
end
end.
makeRankData(KeyIds, Idx) ->
makeRankData(KeyIds, Idx, <<"">>, []).
makeRankData([], _Idx, LastKey, Acc) ->
case LastKey of
<<"">> ->
{LastKey, lists:reverse(Acc)};
_ ->
{erlang:term_to_binary(LastKey), lists:reverse(Acc)}
end;
makeRankData([{CurKey, Score} | KeyIds], Idx, LastKey, Acc) ->
case ets:lookup(ets_pub_rank_info, CurKey) of
[OneData] ->
makeRankData(KeyIds, Idx + 1, CurKey, [#rankInfo{rank = Idx, key = CurKey, publicInfo = element(?publicInfoPos, OneData), rankTypeScore = Score} | Acc]);
_ ->
makeRankData(KeyIds, Idx, LastKey, Acc)
end.