| summaryrefslogtreecommitdiff | 
diff options
| author | nsensfel <SpamShield0@noot-noot.org> | 2018-09-10 17:27:16 +0200 | 
|---|---|---|
| committer | nsensfel <SpamShield0@noot-noot.org> | 2018-09-10 17:27:16 +0200 | 
| commit | ff5dd0eb5df2aa55dc5306eefbd851da8e8e6f4c (patch) | |
| tree | c7c70e24aa6b19dd12609d1a3eec1987918558cd /src/roster | |
| parent | 936f186b6b767273fdc3c01f17311981c46e102c (diff) | |
character -> roster
Diffstat (limited to 'src/roster')
| -rw-r--r-- | src/roster/query/rst_load.erl | 116 | ||||
| -rw-r--r-- | src/roster/query/rst_update.erl | 155 | ||||
| -rw-r--r-- | src/roster/reply/rst_add_char.erl | 39 | ||||
| -rw-r--r-- | src/roster/rst_handler.erl | 35 | ||||
| -rw-r--r-- | src/roster/rst_shim.erl | 25 | ||||
| -rw-r--r-- | src/roster/struct/rst_character.erl | 238 | ||||
| -rw-r--r-- | src/roster/struct/rst_roster.erl | 127 | 
7 files changed, 735 insertions, 0 deletions
| diff --git a/src/roster/query/rst_load.erl b/src/roster/query/rst_load.erl new file mode 100644 index 0000000..761d1c9 --- /dev/null +++ b/src/roster/query/rst_load.erl @@ -0,0 +1,116 @@ +-module(rst_load). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-include("../../../include/yaws_api.hrl"). + +-record +( +   input, +   { +      player_id :: binary(), +      session_token :: binary() +   } +). + +-record +( +   query_state, +   { +      player :: shr_player:type(), +      inventory :: shr_inventory:type(), +      roster :: rst_roster:type() +   } +). + +-type input() :: #input{}. +-type query_state() :: #query_state{}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export([out/1]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec parse_input (binary()) -> input(). +parse_input (Req) -> +   JSONReqMap = jiffy:decode(Req, [return_maps]), +   PlayerID = maps:get(<<"pid">>, JSONReqMap), +   SessionToken =  maps:get(<<"stk">>, JSONReqMap), + +   #input +   { +      player_id = PlayerID, +      session_token = SessionToken +   }. + +-spec authenticate_user (input()) -> ({'ok', shr_player:type()} | 'error'). +authenticate_user (Input) -> +   PlayerID = Input#input.player_id, +   SessionToken = Input#input.session_token, + +   Player = shr_timed_cache:fetch(player_db, any, PlayerID), + +   case shr_security:credentials_match(SessionToken, Player) of +      true -> {ok, Player}; +      _ -> error +   end. + +-spec fetch_data (shr_player:type(), input()) -> query_state(). +fetch_data (Player, Input) -> +   PlayerID = Input#input.player_id, +   RosterID = shr_player:get_roster_id(Player), +   InventoryID = shr_player:get_inventory_id(Player), + +   Roster = shr_timed_cache:fetch(char_roster_db, PlayerID, RosterID), +   Inventory = shr_timed_cache:fetch(char_roster_db, PlayerID, InventoryID), + +   #query_state +   { +      player = Player, +      roster = Roster, +      inventory = Inventory +   }. + +-spec generate_reply(query_state()) -> binary(). +generate_reply (QueryState) -> +   Roster = QueryState#query_state.roster, +   Inventory = QueryState#query_state.inventory, + +   RosterCharacters = rst_roster:get_characters(Roster), +   SetInventory = shr_set_inventory:generate(Inventory), +   EncodedRoster = +      array:to_list +      ( +         array:sparse_map(fun rst_add_char:generate/2, RosterCharacters) +      ), + +   Output = jiffy:encode([SetInventory|EncodedRoster]), + +   Output. + +-spec handle (binary()) -> binary(). +handle (Req) -> +   Input = parse_input(Req), +   case authenticate_user(Input) of +      {ok, Player} -> +         shr_security:lock_queries(Input#input.player_id), +         QueryState = fetch_data(Player, Input), +         shr_security:unlock_queries(Input#input.player_id), +         generate_reply(QueryState); + +      error -> jiffy:encode([shr_disconnected:generate()]) +   end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +out(A) -> +   { +      content, +      "application/json; charset=UTF-8", +      handle(A#arg.clidata) +   }. diff --git a/src/roster/query/rst_update.erl b/src/roster/query/rst_update.erl new file mode 100644 index 0000000..7e53972 --- /dev/null +++ b/src/roster/query/rst_update.erl @@ -0,0 +1,155 @@ +-module(rst_update). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-include("../../../include/yaws_api.hrl"). + +-record +( +   input, +   { +      player_id :: binary(), +      session_token :: binary(), +      character_ix :: non_neg_integer(), +      character :: rst_character:type() +   } +). + +-record +( +   query_state, +   { +      player :: shr_player:type(), +      inventory :: shr_inventory:type(), +      roster :: rst_roster:type() +   } +). + +-type input() :: #input{}. +-type query_state() :: #query_state{}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export([out/1]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec parse_input (binary()) -> input(). +parse_input (Req) -> +   JSONReqMap = jiffy:decode(Req, [return_maps]), +   PlayerID = maps:get(<<"pid">>, JSONReqMap), +   SessionToken =  maps:get(<<"stk">>, JSONReqMap), +   CharacterIX = maps:get(<<"cix">>, JSONReqMap), +   EncodedCharacter = maps:get(<<"chr">>, JSONReqMap), + +   Character = rst_character:decode(EncodedCharacter), + +   #input +   { +      player_id = PlayerID, +      session_token = SessionToken, +      character_ix = CharacterIX, +      character = Character +   }. + +-spec authenticate_user (input()) -> ({'ok', shr_player:type()} | 'error'). +authenticate_user (Input) -> +   PlayerID = Input#input.player_id, +   SessionToken = Input#input.session_token, + +   Player = shr_timed_cache:fetch(player_db, any, PlayerID), + +   case shr_security:credentials_match(SessionToken, Player) of +      true -> {ok, Player}; +      _ -> error +   end. + +-spec fetch_data (shr_player:type(), input()) -> query_state(). +fetch_data (Player, Input) -> +   PlayerID = Input#input.player_id, +   RosterID = shr_player:get_roster_id(Player), +   InventoryID = shr_player:get_inventory_id(Player), + +   Roster = shr_timed_cache:fetch(char_roster_db, PlayerID, RosterID), +   Inventory = shr_timed_cache:fetch(char_roster_db, PlayerID, InventoryID), + +   #query_state +   { +      player = Player, +      roster = Roster, +      inventory = Inventory +   }. + +-spec update_data (query_state(), input()) -> query_state(). +update_data (QueryState, Input) -> +   Inventory = QueryState#query_state.inventory, +   Character = Input#input.character, + +   rst_character:validate(Inventory, Character), + +   %% TODO [FUNCTION: chr][REQUIRED]: unimplemented. +   QueryState. + +-spec commit_update (query_state(), input()) -> 'ok'. +commit_update (QueryState, Input) -> +   PlayerID = Input#input.player_id, +   CharacterIX = Input#input.character_ix, +   Character = Input#input.character, +   Player = QueryState#query_state.player, +   Roster = QueryState#query_state.roster, + +   RosterID = shr_player:get_roster_id(Player), +   UpdatedRoster = rst_roster:set_character(CharacterIX, Character, Roster), + +   Query = +      shr_db_query:new +      ( +         char_roster_db, +         RosterID, +         {user, PlayerID}, +         [ +            shr_db_query:update_indexed +            ( +               rst_roster:get_characters_field(), +               CharacterIX, +               [shr_db_query:set_value(Character)] +            ) +         ] +      ), + +   shr_database:commit(Query), +   shr_timed_cache:update(char_roster_db, PlayerID, RosterID, UpdatedRoster), + +   'ok'. + +-spec generate_reply () -> binary(). +generate_reply () -> +   jiffy:encode([shr_okay:generate()]). + +-spec handle (binary()) -> binary(). +handle (Req) -> +   Input = parse_input(Req), +   case authenticate_user(Input) of +      {ok, Player} -> +         shr_security:lock_queries(Input#input.player_id), +         QueryState = fetch_data(Player, Input), +         Update = update_data(QueryState, Input), +         commit_update(Update, Input), +         shr_security:unlock_queries(Input#input.player_id), +         generate_reply(); + +      error -> jiffy:encode([shr_disconnected:generate()]) +   end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +out(A) -> +   { +      content, +      "application/json; charset=UTF-8", +      handle(A#arg.clidata) +   }. diff --git a/src/roster/reply/rst_add_char.erl b/src/roster/reply/rst_add_char.erl new file mode 100644 index 0000000..1e0d1da --- /dev/null +++ b/src/roster/reply/rst_add_char.erl @@ -0,0 +1,39 @@ +-module(rst_add_char). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export([generate/2]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec generate +   ( +      non_neg_integer(), +      rst_character:type() +   ) +   -> {list(any())}. +generate (IX, Character) -> +   {ActiveWeapon, SecondaryWeapon} = rst_character:get_weapon_ids(Character), + +   { +      [ +         {<<"msg">>, <<"add_char">>}, +         {<<"ix">>, IX}, +         {<<"nam">>, rst_character:get_name(Character)}, +         {<<"awp">>, ActiveWeapon}, +         {<<"swp">>, SecondaryWeapon}, +         {<<"ar">>, rst_character:get_armor_id(Character)}, +         {<<"gls">>, array:to_list(rst_character:get_glyph_ids(Character))}, +         {<<"gb">>, rst_character:get_glyph_board_id(Character)} +      ] +   }. diff --git a/src/roster/rst_handler.erl b/src/roster/rst_handler.erl new file mode 100644 index 0000000..3d6073b --- /dev/null +++ b/src/roster/rst_handler.erl @@ -0,0 +1,35 @@ +-module(rst_handler). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export([start/1]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec start (pid()) -> 'ok'. +start (TimedCachesManagerPid) -> +   case shr_database:fetch(roster_db, <<"0">>, admin) of +      {ok, _} -> ok; +      not_found -> +         shr_database:insert_at +         ( +            roster_db, +            <<"0">>, +            any, +            any, +            rst_shim:generate_random_character_roster() +         ) +   end, +   shr_timed_caches_manager:new_cache(TimedCachesManagerPid, roster_db, none), + +   ok. diff --git a/src/roster/rst_shim.erl b/src/roster/rst_shim.erl new file mode 100644 index 0000000..57a62f5 --- /dev/null +++ b/src/roster/rst_shim.erl @@ -0,0 +1,25 @@ +-module(rst_shim). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export([generate_random_character_roster/0]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec generate_random_character_roster () -> rst_roster:type(). +generate_random_character_roster () -> +   Result = rst_roster:new(<<"0">>, <<"0">>), + +   %% TODO [DEBUG][REQUIRED]: unimplemented. + +   Result. diff --git a/src/roster/struct/rst_character.erl b/src/roster/struct/rst_character.erl new file mode 100644 index 0000000..e3663cc --- /dev/null +++ b/src/roster/struct/rst_character.erl @@ -0,0 +1,238 @@ +-module(rst_character). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-record +( +   character, +   { +      name :: binary(), +      portrait :: binary(), +      weapon_ids :: {shr_weapon:id(), shr_weapon:id()}, +      armor_id :: shr_armor:id(), +      glyph_ids :: array:array(shr_glyph:id()), +      glyph_board_id :: shr_glyph_board:id() +   } +). + +-opaque type() :: #character{}. + +-export_type([type/0]). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%% Accessors +-export +( +   [ +      get_name/1, +      get_portrait/1, +      get_weapon_ids/1, +      get_armor_id/1, +      get_glyph_ids/1, +      get_glyph_board_id/1, + +      set_name/2, +      set_portrait/2, +      set_weapon_ids/2, +      set_armor_id/2, +      set_glyph_ids/2, +      set_glyph_board_id/2, + +      get_name_field/0, +      get_portrait_field/0, +      get_weapon_ids_field/0, +      get_armor_id_field/0, +      get_glyph_ids_field/0, +      get_glyph_board_id_field/0 +   ] +). + +-export +( +   [ +      decode/1, +      random/0 +   ] +). + +-export +( +   [ +      validate/2 +   ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec validate_name (binary()) -> ok. +validate_name (_Name) -> +   % TODO [SECURITY][LOW]: unimplemented +   ok. + +-spec validate_portrait (shr_inventory:type(), binary()) -> ok. +validate_portrait (_Inventory, _Portrait) -> +   % TODO [SECURITY][LOW]: unimplemented +   ok. + +-spec validate_weapons +   ( +      shr_inventory:type(), +      {shr_weapon:id(), shr_weapon:id()} +   ) +   -> ok. +validate_weapons (_Inventory, {_ActiveWeapon, _SecondaryWeapon}) -> +   % TODO [SECURITY][LOW]: unimplemented +   ok. + +-spec validate_armor (shr_inventory:type(), shr_armor:id()) -> ok. +validate_armor (_Inventory, _Armor) -> +   % TODO [SECURITY][LOW]: unimplemented +   ok. + +-spec validate_glyphs (shr_inventory:type(), array:array(shr_glyph:id())) -> ok. +validate_glyphs (_Inventory, _Glyphs) -> +   % TODO [SECURITY][LOW]: unimplemented +   ok. + +-spec validate_glyph_board (shr_inventory:type(), shr_glyph_board:id()) -> ok. +validate_glyph_board (_Inventory, _GlyphBoard) -> +   % TODO [SECURITY][LOW]: unimplemented +   ok. + +-spec validate_glyphs_on_board +   ( +      array:array(shr_glyph:id()), +      shr_glyph_board:id() +   ) +   -> ok. +validate_glyphs_on_board (_Glyphs, _GlyphBoard) -> +   % TODO [SECURITY][LOW]: unimplemented +   ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%% Accessors +-spec get_name (type()) -> binary(). +get_name (Char) -> Char#character.name. + +-spec get_portrait (type()) -> binary(). +get_portrait (Char) -> Char#character.portrait. + +-spec get_weapon_ids (type()) -> {shr_weapon:id(), shr_weapon:id()}. +get_weapon_ids (Char) -> Char#character.weapon_ids. + +-spec get_armor_id (type()) -> shr_armor:id(). +get_armor_id (Char) -> Char#character.armor_id. + +-spec get_glyph_ids (type()) -> array:array(shr_glyph:id()). +get_glyph_ids (Char) -> Char#character.glyph_ids. + +-spec get_glyph_board_id (type()) -> shr_glyph_board:id(). +get_glyph_board_id (Char) -> Char#character.glyph_board_id. + + +-spec set_name (binary(), type()) -> type(). +set_name (Name, Char) -> +   Char#character +   { +      name = Name +   }. + +-spec set_portrait (binary(), type()) -> type(). +set_portrait (PortraitID, Char) -> +   Char#character +   { +      portrait = PortraitID +   }. + +-spec set_armor_id (shr_armor:id(), type()) -> type(). +set_armor_id (ArmorID, Char) -> +   Char#character +   { +      armor_id = ArmorID +   }. + +-spec set_weapon_ids ({shr_weapon:id(), shr_weapon:id()}, type()) -> type(). +set_weapon_ids (WeaponIDs, Char) -> +   Char#character +   { +      weapon_ids = WeaponIDs +   }. + +-spec set_glyph_ids (array:array(shr_glyph:id()), type()) -> type(). +set_glyph_ids (GlyphIDs, Char) -> +   Char#character +   { +      glyph_ids = GlyphIDs +   }. + +-spec set_glyph_board_id (shr_glyph_board:id(), type()) -> type(). +set_glyph_board_id (GlyphBoardID, Char) -> +   Char#character +   { +      glyph_board_id = GlyphBoardID +   }. + +-spec random () -> type(). +random () -> +   #character +   { +      name = <<"">>, +      portrait = <<"0">>, +      weapon_ids = {0, 0}, +      armor_id = 0, +      glyph_ids = array:new(), +      glyph_board_id = <<"0">> +   }. + +-spec get_name_field () -> non_neg_integer(). +get_name_field () -> #character.name. +-spec get_portrait_field () -> non_neg_integer(). +get_portrait_field () -> #character.portrait. +-spec get_armor_id_field () -> non_neg_integer(). +get_armor_id_field () -> #character.armor_id. +-spec get_weapon_ids_field () -> non_neg_integer(). +get_weapon_ids_field () -> #character.weapon_ids. +-spec get_glyph_ids_field () -> non_neg_integer(). +get_glyph_ids_field () -> #character.glyph_ids. +-spec get_glyph_board_id_field () -> non_neg_integer(). +get_glyph_board_id_field () -> #character.glyph_board_id. + +-spec decode (map()) -> type(). +decode (JSONReqMap) -> +   Name = maps:get(<<"nam">>, JSONReqMap), +   Portrait = maps:get(<<"prt">>, JSONReqMap), +   ActiveWeapon = maps:get(<<"awp">>, JSONReqMap), +   SecondaryWeapon = maps:get(<<"swp">>, JSONReqMap), +   Armor = maps:get(<<"ar">>, JSONReqMap), +   GlyphsList = maps:get(<<"gls">>, JSONReqMap), +   GlyphBoard = maps:get(<<"gb">>, JSONReqMap), + +   #character +   { +      name = Name, +      portrait = Portrait, +      weapon_ids = {ActiveWeapon, SecondaryWeapon}, +      armor_id = Armor, +      glyph_ids = array:from_list(GlyphsList), +      glyph_board_id = GlyphBoard +   }. + +-spec validate (shr_inventory:type(), type()) -> ok. +validate (Inventory, Character) -> +   Glyphs = Character#character.glyph_ids, +   GlyphBoard = Character#character.glyph_board_id, + +   validate_name(Character#character.name), +   validate_portrait(Inventory, Character#character.portrait), +   validate_weapons(Inventory, Character#character.weapon_ids), +   validate_armor(Inventory, Character#character.armor_id), +   validate_glyphs(Inventory, Glyphs), +   validate_glyph_board(Inventory, GlyphBoard), +   validate_glyphs_on_board(Glyphs, GlyphBoard), + +   ok. diff --git a/src/roster/struct/rst_roster.erl b/src/roster/struct/rst_roster.erl new file mode 100644 index 0000000..a362619 --- /dev/null +++ b/src/roster/struct/rst_roster.erl @@ -0,0 +1,127 @@ +-module(rst_roster). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-type id() :: binary(). + +-record +( +   roster, +   { +      id :: id(), +      owner :: binary(), +      characters :: array:array(rst_character:type()) +   } +). + +-opaque type() :: #roster{}. + +-export_type([type/0, id/0]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%% Accessors +-export +( +   [ +      get_id/1, +      get_owner/1, +      get_characters/1, +      get_character/2, + +      set_characters/2, +      set_character/3, + +      add_character/2, +      remove_character/2 +   ] +). + +-export +( +   [ +      get_characters_field/0 +   ] +). + +-export +( +   [ +      new/2 +   ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%% Accessors +-spec get_id (type()) -> id(). +get_id (Roster) -> Roster#roster.id. + +-spec get_owner (type()) -> binary(). +get_owner (Roster) -> Roster#roster.owner. + +-spec get_characters (type()) -> array:array(rst_character:type()). +get_characters (Roster) -> Roster#roster.characters. + +-spec get_character (non_neg_integer(), type()) -> rst_character:type(). +get_character (IX, Roster) -> array:get(IX, Roster#roster.characters). + +-spec set_characters (array:array(rst_character:type()), type()) -> type(). +set_characters (Characters, Roster) -> Roster#roster{ characters = Characters }. + +-spec set_character +   ( +      non_neg_integer(), +      rst_character:type(), +      type() +   ) +   -> type(). +set_character (IX, Character, Roster) -> +   Roster#roster +   { +      characters = array:set(IX, Character, Roster#roster.characters) +   }. + +-spec add_character (rst_character:type(), type()) -> type(). +add_character (Character, Roster) -> +   CurrentCharacters = Roster#roster.characters, +   CurrentSize = array:size(CurrentCharacters), + +   Roster#roster +   { +      characters = array:set(CurrentSize, Character, CurrentCharacters) +   }. + +-spec remove_character (non_neg_integer(), type()) -> type(). +remove_character (IX, Roster) -> +   CurrentCharacters = Roster#roster.characters, +   CurrentSize = array:size(CurrentCharacters), +   NewSize = (CurrentSize - 1), +   LastCharacter = array:get(NewSize, CurrentCharacters), + +   S0Characters = array:set(IX, LastCharacter, CurrentCharacters), +   S1Characters = array:resize(NewSize, S0Characters), + +   Roster#roster +   { +      characters = S1Characters +   }. + +-spec get_characters_field () -> non_neg_integer(). +get_characters_field () -> #roster.characters. + +-spec new (binary(), binary()) -> type(). +new (ID, Owner) -> +   #roster +   { +      id = ID, +      owner = Owner, +      characters = array:new() +   }. | 


