-module(dummy_navigator). -behaviour(gen_server). -export([ %% api start_link/2, goto_barcode/2, teleport_butler/2, lift/2, get_location/1, get_lift_state/1, %% cb init/1, handle_call/3, handle_cast/2 ]). -record(state, { butler_id, current_location, lift_state = down, going_to_barcode, count }). %% api start_link(BId, Location) -> gen_server:start_link(?MODULE, [BId, Location], []). goto_barcode(Pid, Barcode) -> gen_server:cast(Pid, {goto_barcode, Barcode}). %% teleportation for testing teleport_butler(Pid, Barcode) -> gen_server:cast(Pid, {teleport, Barcode}). lift(Pid, Direction) -> gen_server:cast(Pid, {lift, Direction}). get_location(Pid) -> gen_server:call(Pid, get_location). get_lift_state(Pid) -> gen_server:call(Pid, get_lift_state). %% cb init([BId, Location]) -> gproc:add_local_name({?MODULE, BId}), {ok, #state{ butler_id = BId, current_location = Location, lift_state = down, count = 0 }}. handle_call(get_location, _From, State) -> {reply, State#state.current_location, State}; handle_call(get_lift_state, _From, State) -> {reply, State#state.lift_state, State}. handle_cast({goto_barcode, Barcode}, State = #state{butler_id = BId, current_location = PrevLocation, lift_state = LiftState}) -> {noreply, NewState = #state{current_location = NewLocation}} = handle_goto_barcode({goto_barcode, Barcode}, State), %% broadcast this gproc:send({p, l, {pubsub, on_butler_move}}, {self(), {pubsub, on_butler_move}, {BId, PrevLocation, NewLocation, LiftState}}), {noreply, NewState}; handle_cast({teleport, Barcode}, State) -> {noreply, State#state{count = 0, current_location = Barcode, going_to_barcode = undefined}}; handle_cast({lift, up}, State) -> {noreply, State#state{lift_state = up}}; handle_cast({lift, down}, State) -> {noreply, State#state{lift_state = down}}. %% if already at this barcode, just reset counters and do nothing handle_goto_barcode({goto_barcode, CurrentBarcode}, State = #state{current_location = CurrentBarcode}) -> {noreply, State}; %% after 5 counts of requests of going to same barcode, just go to it handle_goto_barcode({goto_barcode, GoingToBarcode}, State = #state{count = 5, going_to_barcode = GoingToBarcode}) -> {noreply, State#state{current_location = GoingToBarcode, going_to_barcode = undefined, count = 0}}; %% if its same as going_to_barcode but count is not 5 yet, then move butler to some random barcode and increase count handle_goto_barcode({goto_barcode, GoingToBarcode}, State = #state{count = Count, going_to_barcode = GoingToBarcode}) -> {noreply, State#state{count = Count + 1, current_location = butler_functions:gen_random_barcode()}}; %% if its not current barcode or going to barcode, reset counter and make it the going to barcode. also randomly move butler somewhere handle_goto_barcode({goto_barcode, Barcode}, State = #state{going_to_barcode = GoingToBarcode}) when Barcode =/= GoingToBarcode -> {noreply, State#state{count = 0, current_location = butler_functions:gen_random_barcode(), going_to_barcode = Barcode}}.