您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

175 行
5.3 KiB

3 年前
3 年前
3 年前
3 年前
3 年前
  1. -module(rankWork).
  2. -behavior(gen_srv).
  3. -include("ranks.hrl").
  4. -export([
  5. start_link/1
  6. , mUpdateScore/3
  7. , mUpdateInfo/2
  8. , mGetRankInfo/5
  9. ]).
  10. -export([
  11. init/1
  12. , handleCall/3
  13. , handleCast/2
  14. , handleInfo/2
  15. , terminate/2
  16. , code_change/3
  17. ]).
  18. -record(state, {}).
  19. %% ******************************************** API *******************************************************************
  20. start_link(SrvName) ->
  21. gen_srv:start_link({local, SrvName}, ?MODULE, [], []).
  22. %% ******************************************** callback **************************************************************
  23. init(_Args) ->
  24. {ok, #state{}}.
  25. handleCall(_Msg, _State, _FROM) ->
  26. {reply, ok}.
  27. handleCast(_Msg, _State) ->
  28. kpS.
  29. handleInfo(_Msg, _State) ->
  30. kpS.
  31. terminate(_Reason, _State) ->
  32. ok.
  33. code_change(_OldVsn, State, _Extra) ->
  34. {ok, State}.
  35. %% ****************************************************** logic ********************************************************
  36. mUpdateScore(Key, RankType, Score) ->
  37. {_RankLimit, RankMax} = ?ranksLimit:getV(RankType),
  38. RankPos = ?ranksCfg:getV(RankType),
  39. case ets:lookup(etsRankInfo, Key) of
  40. [RankRecord] ->
  41. OldScore = element(RankPos, RankRecord),
  42. ets:delete(RankType, OldScore),
  43. RankSize = ets:info(RankType, size),
  44. case RankSize >= RankMax of
  45. true ->
  46. FirstKey = ets:first(RankType),
  47. case Score > FirstKey of
  48. true ->
  49. ets:insert(RankType, Score),
  50. ets:delete(RankType, FirstKey);
  51. _ ->
  52. ignore
  53. end;
  54. _ ->
  55. ets:insert(RankType, Score)
  56. end,
  57. ets:update_element(etsRankInfo, Key, {RankPos, Score});
  58. _ ->
  59. %% 插入新的数据
  60. RankSize = ets:info(RankType, size),
  61. case RankSize >= RankMax of
  62. true ->
  63. FirstKey = ets:first(RankType),
  64. case Score > FirstKey of
  65. true ->
  66. ets:insert(RankType, Score),
  67. ets:delete(RankType, FirstKey),
  68. NewRecord = #etsRankRecord{key = Key},
  69. RankRecord = setelement(RankPos, NewRecord, Score),
  70. ets:insert(etsRankInfo, RankRecord);
  71. _ ->
  72. ignore
  73. end;
  74. _ ->
  75. ets:insert(RankType, Score),
  76. NewRecord = #etsRankRecord{key = Key},
  77. RankRecord = setelement(RankPos, NewRecord, Score),
  78. ets:insert(etsRankInfo, RankRecord)
  79. end
  80. end,
  81. {mayReply, ok}.
  82. mUpdateInfo(Key, RecordKvs) ->
  83. ets:update_element(etsRankInfo, Key, RecordKvs),
  84. {mayReply, ok}.
  85. mGetRankInfo(RankType, MyKey, Cnt, Page, PageInfo) ->
  86. {RankLimit, _RankMax} = ?ranksLimit:getV(RankType),
  87. %% 请求第一页的时候 附加上自己的排名
  88. SelfRank =
  89. case Page of
  90. 0 ->
  91. case ets:lookup_element(etsRankInfo, MyKey) of
  92. [RankRecord] ->
  93. RankPos = ?ranksCfg:getV(RankType),
  94. CurScore = element(RankPos, RankRecord),
  95. MyIndex = ets:select_count(RankType, [{{'$1', '$2'}, [{'>=', '$1', CurScore}], [true]}]),
  96. max(RankLimit, MyIndex);
  97. _ ->
  98. -1
  99. end;
  100. _ ->
  101. 0
  102. end,
  103. MS =
  104. case PageInfo == 0 orelse PageInfo of
  105. true ->
  106. [{'$1', [], ['$1']}];
  107. <<"">> ->
  108. [{'$1', [], ['$1']}];
  109. _ ->
  110. try binary_to_term(PageInfo) of
  111. KeyTerm when KeyTerm == <<"">>; KeyTerm == "" ->
  112. [{'$1', [], ['$1']}];
  113. KeyTerm ->
  114. % ets:fun2ms(fun({K, _V} = T) when K < KeyTerm -> T end)
  115. [{{'$1', '$2'}, [{'<', '$1', KeyTerm}], ['$_']}]
  116. catch _C:_R ->
  117. [{'$1', [], ['$1']}]
  118. end
  119. end,
  120. case ets:select_reverse(RankType, MS, Cnt) of
  121. '$end_of_table' ->
  122. {true, {<<"">>, []}};
  123. {KeyIds, '$end_of_table'} ->
  124. {true, SelfRank, makeRankData(KeyIds, Cnt * Page + 1)};
  125. {KeyIds, _NextKey} ->
  126. Length = length(KeyIds),
  127. if
  128. Length < Cnt ->
  129. {true, SelfRank, makeRankData(KeyIds, Cnt * Page + 1)};
  130. true ->
  131. NewCurCnt = Page * Cnt + Length,
  132. case NewCurCnt >= RankLimit of
  133. true ->
  134. {true, SelfRank, makeRankData(KeyIds, Cnt * Page + 1)};
  135. _ ->
  136. {false, SelfRank, makeRankData(KeyIds, Cnt * Page + 1)}
  137. end
  138. end
  139. end.
  140. makeRankData(KeyIds, Idx) ->
  141. makeRankData(KeyIds, Idx, <<"">>, []).
  142. makeRankData([], _Idx, LastKey, Acc) ->
  143. case LastKey of
  144. <<"">> ->
  145. {LastKey, lists:reverse(Acc)};
  146. _ ->
  147. {erlang:term_to_binary(LastKey), lists:reverse(Acc)}
  148. end;
  149. makeRankData([{CurKey, Score} | KeyIds], Idx, LastKey, Acc) ->
  150. case ets:lookup(ets_pub_rank_info, CurKey) of
  151. [OneData] ->
  152. makeRankData(KeyIds, Idx + 1, CurKey, [#rankInfo{rank = Idx, key = CurKey, publicInfo = element(?publicInfoPos, OneData), rankTypeScore = Score} | Acc]);
  153. _ ->
  154. makeRankData(KeyIds, Idx, LastKey, Acc)
  155. end.