-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.
|