|
|
@ -0,0 +1,123 @@ |
|
|
|
-module(player_manager). |
|
|
|
-behaviour(gen_server). |
|
|
|
|
|
|
|
-export([start_link/0, init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). |
|
|
|
-export([create_player/1, delete_player/1, get_player/1, list_players/0]). |
|
|
|
|
|
|
|
-record(state, { |
|
|
|
players = #{} % Map: PlayerId -> PlayerInfo |
|
|
|
}). |
|
|
|
|
|
|
|
-record(player_info, { |
|
|
|
id, |
|
|
|
name, |
|
|
|
score = 0, |
|
|
|
games_played = 0, |
|
|
|
wins = 0, |
|
|
|
losses = 0, |
|
|
|
status = offline % offline | online | in_game |
|
|
|
}). |
|
|
|
|
|
|
|
%% API |
|
|
|
start_link() -> |
|
|
|
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). |
|
|
|
|
|
|
|
create_player(Name) -> |
|
|
|
gen_server:call(?MODULE, {create_player, Name}). |
|
|
|
|
|
|
|
delete_player(PlayerId) -> |
|
|
|
gen_server:call(?MODULE, {delete_player, PlayerId}). |
|
|
|
|
|
|
|
get_player(PlayerId) -> |
|
|
|
gen_server:call(?MODULE, {get_player, PlayerId}). |
|
|
|
|
|
|
|
list_players() -> |
|
|
|
gen_server:call(?MODULE, list_players). |
|
|
|
|
|
|
|
%% Callbacks |
|
|
|
init([]) -> |
|
|
|
{ok, #state{}}. |
|
|
|
|
|
|
|
handle_call({create_player, Name}, _From, State = #state{players = Players}) -> |
|
|
|
PlayerId = generate_player_id(), |
|
|
|
PlayerInfo = #player_info{ |
|
|
|
id = PlayerId, |
|
|
|
name = Name, |
|
|
|
status = online |
|
|
|
}, |
|
|
|
NewPlayers = maps:put(PlayerId, PlayerInfo, Players), |
|
|
|
{reply, {ok, PlayerId}, State#state{players = NewPlayers}}; |
|
|
|
|
|
|
|
handle_call({delete_player, PlayerId}, _From, State = #state{players = Players}) -> |
|
|
|
case maps:is_key(PlayerId, Players) of |
|
|
|
true -> |
|
|
|
NewPlayers = maps:remove(PlayerId, Players), |
|
|
|
{reply, ok, State#state{players = NewPlayers}}; |
|
|
|
false -> |
|
|
|
{reply, {error, player_not_found}, State} |
|
|
|
end; |
|
|
|
|
|
|
|
handle_call({get_player, PlayerId}, _From, State = #state{players = Players}) -> |
|
|
|
case maps:find(PlayerId, Players) of |
|
|
|
{ok, PlayerInfo} -> |
|
|
|
{reply, {ok, PlayerInfo}, State}; |
|
|
|
error -> |
|
|
|
{reply, {error, player_not_found}, State} |
|
|
|
end; |
|
|
|
|
|
|
|
handle_call(list_players, _From, State = #state{players = Players}) -> |
|
|
|
PlayerList = maps:values(Players), |
|
|
|
{reply, {ok, PlayerList}, State}; |
|
|
|
|
|
|
|
handle_call(_Request, _From, State) -> |
|
|
|
{reply, {error, unknown_call}, State}. |
|
|
|
|
|
|
|
handle_cast({update_player_status, PlayerId, Status}, State = #state{players = Players}) -> |
|
|
|
NewPlayers = case maps:find(PlayerId, Players) of |
|
|
|
{ok, PlayerInfo} -> |
|
|
|
maps:put(PlayerId, PlayerInfo#player_info{status = Status}, Players); |
|
|
|
error -> |
|
|
|
Players |
|
|
|
end, |
|
|
|
{noreply, State#state{players = NewPlayers}}; |
|
|
|
|
|
|
|
handle_cast({update_player_stats, PlayerId, GameResult}, State = #state{players = Players}) -> |
|
|
|
NewPlayers = case maps:find(PlayerId, Players) of |
|
|
|
{ok, PlayerInfo = #player_info{games_played = GamesPlayed, wins = Wins, score = Score}} -> |
|
|
|
NewGamesPlayed = GamesPlayed + 1, |
|
|
|
{NewWins, NewScore} = case GameResult of |
|
|
|
win -> {Wins + 1, Score + 10}; |
|
|
|
loss -> {Wins, Score - 5}; |
|
|
|
draw -> {Wins, Score + 2} |
|
|
|
end, |
|
|
|
maps:put(PlayerId, PlayerInfo#player_info{ |
|
|
|
games_played = NewGamesPlayed, |
|
|
|
wins = NewWins, |
|
|
|
score = NewScore |
|
|
|
}, Players); |
|
|
|
error -> |
|
|
|
Players |
|
|
|
end, |
|
|
|
{noreply, State#state{players = NewPlayers}}; |
|
|
|
|
|
|
|
handle_cast(_Msg, State) -> |
|
|
|
{noreply, State}. |
|
|
|
|
|
|
|
handle_info(_Info, State) -> |
|
|
|
{noreply, State}. |
|
|
|
|
|
|
|
terminate(_Reason, _State) -> |
|
|
|
ok. |
|
|
|
|
|
|
|
code_change(_OldVsn, State, _Extra) -> |
|
|
|
{ok, State}. |
|
|
|
|
|
|
|
%% 内部函数 |
|
|
|
|
|
|
|
%% 生成玩家ID |
|
|
|
generate_player_id() -> |
|
|
|
% 使用时间戳和随机数生成唯一ID |
|
|
|
{{Year, Month, Day}, {Hour, Minute, Second}} = calendar:local_time(), |
|
|
|
Random = rand:uniform(1000), |
|
|
|
list_to_binary(io_lib:format("player_~4..0B~2..0B~2..0B~2..0B~2..0B~2..0B~4..0B", |
|
|
|
[Year, Month, Day, Hour, Minute, Second, Random])). |