Last active
August 29, 2015 14:04
-
-
Save roowe/140bbe75d77a53aa2620 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%% 本数据结构大概目的,维护大规模数据选取小范围来随机,并定长维护,剔除老数据 | |
-module(lists_rand). | |
-export([new/0, cur/1, in/2]). | |
-define(SIZE, 10000). | |
-define(CHOOSE_COUNT, 5). | |
-record(list_rand,{ | |
max_size = ?SIZE, | |
size = 0, | |
every_count = ?CHOOSE_COUNT, | |
all_list = queue:new(), | |
rest_list = [] | |
}). | |
new() -> | |
#list_rand{}. | |
cur(#list_rand{ | |
all_list = Q, | |
rest_list = [] | |
} = ListRand) -> | |
cur(ListRand#list_rand{ | |
rest_list = queue:to_list(Q) | |
}); | |
cur(#list_rand{ | |
every_count = EveryCount, | |
rest_list = RestList | |
} = ListRand) -> | |
{OutList, NewRestList} = ds_misc:split(EveryCount, RestList), | |
{OutList, ListRand#list_rand{ | |
rest_list = NewRestList | |
}}. | |
in(X, #list_rand{ | |
size = Size, | |
all_list = Q | |
} = ListRand) -> | |
out(ListRand#list_rand{ | |
size = Size + 1, | |
all_list = queue:in(X, Q) | |
}). | |
out(#list_rand{ | |
max_size = MaxSize, | |
size = Size, | |
all_list = Q | |
} = ListRand) | |
when Size > MaxSize -> | |
out(ListRand#list_rand{ | |
size = Size - 1, | |
all_list = element(2, queue:out(Q)) | |
}); | |
out(ListRand) -> | |
ListRand. | |
test() -> | |
ListRand = #list_rand{ | |
max_size = 50, | |
every_count = 10 | |
}, | |
ListRand1 = lists:foldl(fun(N, AccListRand) -> | |
in(N, AccListRand) | |
end, ListRand, lists:seq(1,50)), | |
ListRand2 = lists:foldl(fun(N, AccListRand) -> | |
{OutList, NewListRand} = cur(AccListRand), | |
io:format("~p ~w~n", [N, OutList]), | |
NewListRand | |
end, ListRand1, lists:seq(1,6)), | |
ListRand3 = lists:foldl(fun(N, AccListRand) -> | |
in(N, AccListRand) | |
end, ListRand2, lists:seq(100,150)), | |
ListRand4 = lists:foldl(fun(N, AccListRand) -> | |
{OutList, NewListRand} = cur(AccListRand), | |
io:format("~p ~w~n", [N, OutList]), | |
NewListRand | |
end, ListRand3, lists:seq(1,6)), | |
ok. | |
%% (roowe@127.0.0.1)26> lists_rand:test(). | |
%% 1 [10,9,8,7,6,5,4,3,2,1] | |
%% 2 [20,19,18,17,16,15,14,13,12,11] | |
%% 3 [30,29,28,27,26,25,24,23,22,21] | |
%% 4 [40,39,38,37,36,35,34,33,32,31] | |
%% 5 [50,49,48,47,46,45,44,43,42,41] | |
%% 6 [10,9,8,7,6,5,4,3,2,1] | |
%% 1 [20,19,18,17,16,15,14,13,12,11] | |
%% 2 [30,29,28,27,26,25,24,23,22,21] | |
%% 3 [40,39,38,37,36,35,34,33,32,31] | |
%% 4 [50,49,48,47,46,45,44,43,42,41] | |
%% 5 [110,109,108,107,106,105,104,103,102,101] | |
%% 6 [120,119,118,117,116,115,114,113,112,111] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%%%------------------------------------------------------------------- | |
%%% @author Roowe <bestluoliwe@gmail.com> | |
%%% @copyright (C) 2014, Roowe | |
%%% @doc | |
%%% | |
%%% @end | |
%%% Created : 23 Jul 2014 by Roowe <bestluoliwe@gmail.com> | |
%%%------------------------------------------------------------------- | |
-module(mod_match_league_recommened). | |
-behaviour(gen_server). | |
%% API | |
-export([start_link/0]). | |
-export([sign_up/2, recommended/2]). | |
%% gen_server callbacks | |
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, | |
terminate/2, code_change/3]). | |
-include("common.hrl"). | |
-include("define_mnesia.hrl"). | |
-define(SERVER, ?MODULE). | |
-record(state, {}). | |
%%%=================================================================== | |
%%% API | |
%%%=================================================================== | |
sign_up(Ability, PlayerId) -> | |
gen_server:cast(?MODULE, {sign_up, Ability, PlayerId}). | |
recommended(Ability, PlayerId) -> | |
gen_server:call(?MODULE, {recommended, Ability, PlayerId}). | |
test() -> | |
Fun = | |
fun() -> | |
mod_match_league_recommened:recommended(rand_misc:rand(100), 0), | |
ok | |
%% [mod_match_league_recommened:recommended(Ability, 0) || Ability <- lists:seq(1,100)], | |
%% ok | |
end, | |
Before = os:timestamp(), | |
PidMRefs = [spawn_monitor(Fun) || _ <- lists:seq(1,3000)], | |
[receive | |
{'DOWN', MRef, process, _, normal} -> ok; | |
{'DOWN', MRef, process, _, Reason} -> exit(Reason) | |
end || {_Pid, MRef} <- PidMRefs], | |
After = os:timestamp(), | |
Times = timer:now_diff(After, Before), | |
io:format("~p: ~p microseconds~n", [?MODULE, Times]), | |
ok. | |
test2() -> | |
Data = lists:foldl(fun(N, Acc) -> | |
case ets_cache:get(key(N)) of | |
[] -> | |
Acc; | |
ListRand -> | |
[{N, ListRand}|Acc] | |
end | |
end, [], lists:seq(1,100)), | |
?DEBUG("Data ~p~n", [length(Data)]). | |
%%-------------------------------------------------------------------- | |
%% @doc | |
%% Starts the server | |
%% | |
%% @spec start_link() -> {ok, Pid} | ignore | {error, Error} | |
%% @end | |
%%-------------------------------------------------------------------- | |
start_link() -> | |
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). | |
%%%=================================================================== | |
%%% gen_server callbacks | |
%%%=================================================================== | |
%%-------------------------------------------------------------------- | |
%% @private | |
%% @doc | |
%% Initializes the server | |
%% | |
%% @spec init(Args) -> {ok, State} | | |
%% {ok, State, Timeout} | | |
%% ignore | | |
%% {stop, Reason} | |
%% @end | |
%%-------------------------------------------------------------------- | |
init([]) -> | |
process_flag(trap_exit, true), | |
case hdb:dirty_read(server_data, {?MODULE, node()}) of | |
[] -> | |
ignore; | |
#server_data{ | |
v = Data | |
} -> | |
?DEBUG("Data ~p~n", [length(Data)]), | |
[ets_cache:set(key(Ability), ListRand) || {Ability, ListRand} <- Data] | |
end, | |
{ok, #state{}}. | |
%%-------------------------------------------------------------------- | |
%% @private | |
%% @doc | |
%% Handling call messages | |
%% | |
%% @spec handle_call(Request, From, State) -> | |
%% {reply, Reply, State} | | |
%% {reply, Reply, State, Timeout} | | |
%% {noreply, State} | | |
%% {noreply, State, Timeout} | | |
%% {stop, Reason, Reply, State} | | |
%% {stop, Reason, State} | |
%% @end | |
%%-------------------------------------------------------------------- | |
handle_call({recommended, Ability, PlayerId}, _From, State) -> | |
MinAbility = erlang:max(1, Ability-10), | |
MaxAbility = erlang:min(100, Ability+10), | |
RandList = | |
lists:foldl(fun(N, Acc) -> | |
Key = key(N), | |
case ets_cache:get(Key) of | |
[] -> | |
Acc; | |
ListRand -> | |
{OutList, NewListRand} = lists_rand:cur(ListRand), | |
ets_cache:set(Key, NewListRand), | |
OutList ++ Acc | |
end | |
end, [], lists:seq(MinAbility, MaxAbility)), | |
List = rand_misc:rand_n(5, lists:delete(PlayerId, RandList)), | |
{reply, List, State}; | |
handle_call(_Request, _From, State) -> | |
?WARNING_MSG("unknow request ~p~n", [_Request]), | |
Reply = ok, | |
{reply, Reply, State}. | |
%%-------------------------------------------------------------------- | |
%% @private | |
%% @doc | |
%% Handling cast messages | |
%% | |
%% @spec handle_cast(Msg, State) -> {noreply, State} | | |
%% {noreply, State, Timeout} | | |
%% {stop, Reason, State} | |
%% @end | |
%%-------------------------------------------------------------------- | |
handle_cast({sign_up, Ability, PlayerId}, State) -> | |
Key = key(Ability), | |
case ets_cache:get(Key) of | |
[] -> | |
ListRand = lists_rand:new(); | |
ListRand -> | |
ignore | |
end, | |
NewListRand = lists_rand:in(PlayerId, ListRand), | |
ets_cache:set(Key, NewListRand), | |
{noreply, State}; | |
handle_cast(_Msg, State) -> | |
?WARNING_MSG("unknow msg ~p~n", [_Msg]), | |
{noreply, State}. | |
%%-------------------------------------------------------------------- | |
%% @private | |
%% @doc | |
%% Handling all non call/cast messages | |
%% | |
%% @spec handle_info(Info, State) -> {noreply, State} | | |
%% {noreply, State, Timeout} | | |
%% {stop, Reason, State} | |
%% @end | |
%%-------------------------------------------------------------------- | |
handle_info({'EXIT', Pid, Reason}, State) -> | |
?DEBUG("Pid ~p, Reason ~p~n", [Pid, Reason]), | |
{stop, Reason, State}; | |
handle_info(_Info, State) -> | |
?WARNING_MSG("unknow info ~p~n", [_Info]), | |
{noreply, State}. | |
%%-------------------------------------------------------------------- | |
%% @private | |
%% @doc | |
%% This function is called by a gen_server when it is about to | |
%% terminate. It should be the opposite of Module:init/1 and do any | |
%% necessary cleaning up. When it returns, the gen_server terminates | |
%% with Reason. The return value is ignored. | |
%% | |
%% @spec terminate(Reason, State) -> void() | |
%% @end | |
%%-------------------------------------------------------------------- | |
terminate(Reason, _State) -> | |
?DEBUG("Reason ~p~n", [Reason]), | |
Data = lists:foldl(fun(N, Acc) -> | |
case ets_cache:get(key(N)) of | |
[] -> | |
Acc; | |
ListRand -> | |
[{N, ListRand}|Acc] | |
end | |
end, [], lists:seq(1,100)), | |
?DEBUG("Data ~p~n", [length(Data)]), | |
hdb:dirty_write(server_data, #server_data{ | |
k = {?MODULE, node()}, | |
v = Data | |
}), | |
ok. | |
%%-------------------------------------------------------------------- | |
%% @private | |
%% @doc | |
%% Convert process state when code is changed | |
%% | |
%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState} | |
%% @end | |
%%-------------------------------------------------------------------- | |
code_change(_OldVsn, State, _Extra) -> | |
{ok, State}. | |
%%%=================================================================== | |
%%% Internal functions | |
%%%=================================================================== | |
key(Ability) -> | |
{?MODULE, Ability}. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment