|
| 1 | +% Room Decoder Server |
| 2 | + |
| 3 | +-module(decoder). |
| 4 | +-behavior(gen_server). |
| 5 | +-export([start_link/0,stop/1,add_room/2]). |
| 6 | +-export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3]). |
| 7 | + |
| 8 | +start_link() -> gen_server:start_link(?MODULE, [], []). |
| 9 | + |
| 10 | +%% Calls |
| 11 | +add_room(Pid, Room) -> gen_server:cast(Pid, {add_room, Room}). |
| 12 | +stop(Pid) -> gen_server:call(Pid, stop). |
| 13 | + |
| 14 | +%%% Server Functions |
| 15 | +init([]) -> {ok, []}. |
| 16 | + |
| 17 | +handle_call(stop, _From, State) -> {stop, normal, ok, State}; |
| 18 | +handle_call(Msg, _From, State) -> io:format("Unknown Message: ~p", [Msg]), {stop, unknown_message, State}. |
| 19 | + |
| 20 | +handle_cast({add_room, Room}, State) -> |
| 21 | + % Determine if the room is a decoy |
| 22 | + {ActualChecksum, IsDecoy} = check_is_decoy(Room), |
| 23 | + RoomEntry = {Room, ActualChecksum, IsDecoy}, |
| 24 | + io:format("Adding room to DB: ~p~n", [RoomEntry]), |
| 25 | + |
| 26 | + % Store the room in the database |
| 27 | + {noreply, [ RoomEntry | State ]}; |
| 28 | +handle_cast(Msg, State) -> io:format("Unknown Message: ~p", [Msg]), {stop, unknown_message, State}. |
| 29 | + |
| 30 | +handle_info(Msg, State) -> io:format("Unknown Message: ~p", [Msg]), {stop, unknown_message, State}. |
| 31 | + |
| 32 | +terminate(Reason, _State) -> |
| 33 | + io:format("Terminating ~p process because: ~p", ?MODULE, Reason), |
| 34 | + ok. |
| 35 | + |
| 36 | +% We don't have any state migration. |
| 37 | +code_change(_OldVsn, State, _Extra) -> {ok, State}. |
| 38 | + |
| 39 | +%% Private |
| 40 | +check_is_decoy({Segments, _, Checksum}) -> |
| 41 | + Letters = lists:sort(lists:flatten(Segments)), |
| 42 | + Groups = lists:foldr(fun(Elem, AccIn) -> |
| 43 | + case lists:keysearch(Elem, 1, AccIn) of |
| 44 | + false -> |
| 45 | + [ {Elem, 1} | AccIn]; |
| 46 | + {value, {Letter, Count}} -> |
| 47 | + lists:keyreplace(Elem, 1, AccIn, {Letter, Count + 1}) |
| 48 | + end |
| 49 | + end, |
| 50 | + [], |
| 51 | + Letters), |
| 52 | + Sorted = lists:reverse(lists:keysort(2, Groups)), |
| 53 | + Top5 = lists:sublist(Sorted, 1, 5), |
| 54 | + ActualChecksum = [ X || {X, _} <- Top5 ], |
| 55 | + {ActualChecksum, Checksum =/= ActualChecksum}. |
0 commit comments