viernes, 9 de diciembre de 2016

Una empresa de limpieza en Erlang

%Un pequeño programa con concurrencia real, pero a la vez simulando
%una empresa que presta un servicio de limpieza. Ejecutar los siguientes
%comandos para darse una idea de qué hace:
%> c(lt1).
%> lt1:start().
%> Ls=lt1:pisoBasico(), gestor ! Ls.

%Metodología:
% Diseño multiagente con elementos clasificados en gestores y trabajadores.
% Módulos para cada agente: para un gestor y un trabajador.
% Identificación de capacidades de cada agente.
% Creación o diseño de protocolos de comunicación...
% Identificación de restricciones físicas para la simulación.


-module(lt1).
-export([start/0,start1/1,start2/1,gestionar/2,pisoBasico/0,es_piso/1, limpiar/3,
                             tomar/2,omitir/2,
                             dividir/1,sleep/1,retardar/1,
                             caso/2]).

es_parOrdenado({A,B}) when
          is_integer(A) and
          is_integer(B) -> true.

es_piso([]) -> true;
es_piso([P|Ls]) -> es_parOrdenado(P), es_piso(Ls).

start() ->
    register(gestor,spawn(lt1,gestionar,[0,0])),
    start1(gestor),
    start2(gestor).
%recibeRapido(trabajador1), recibeRapido(trabajador2)
%{trabajador1:6,trabajador2:3}

%gestionar(0,0) %servidor???
start1(Gestor) -> register(trabajador1,spawn(lt1,limpiar,[Gestor,trabajo1,6])).
start2(Gestor) -> register(trabajador2,spawn(lt1,limpiar,[Gestor,trabajo2,3])).

caso(N,M) ->
      if
         N>M -> io:format("hola",[]);
         N==M -> io:format("hollaaa",[]);
         N<M -> io:format("adios",[])
      end.

sleep(T) ->
     receive
     after T -> true
     end.

%AreaAsignada es la capacidad que un robot puede limpiar en términos de área.
%Por agregar, Id del trabajador
retardar([]) -> true;
retardar([_|Ls]) ->
         sleep(5000),
         retardar(Ls).

limpiar(Gestor,A,AreaAsignada) ->
              receive
                  {segmento,Segmento,ProcesoSolicitante} ->
                                   es_piso(Segmento),
                           retardar(Segmento),
io:format("~n Segmento de piso correcto y terminado~n~p~n",
                                          [Segmento]),                       
                             Gestor ! {terminado,A,self()}, %Palabras o msg a trab.
                             limpiar(Gestor,A,AreaAsignada);
                        {verificar, AreaALimpiar,ProcesoSolicitante} when
                                            (AreaALimpiar =< AreaAsignada) ->
                             ProcesoSolicitante ! {si,self()},
                             io:format("si~n",[]),
                             limpiar(Gestor,A,AreaAsignada);
                  {verificar, AreaALimpiar,ProcesoSolicitante} when
                                (AreaALimpiar > AreaAsignada)
                             ->
                             ProcesoSolicitante ! {no,self()},
                             io:format("no~n",[]),
                             limpiar(Gestor,A,AreaAsignada);
                 {limpiar, AreaALimpiar,ProcesoSolicitante} when
                                            (AreaALimpiar =< AreaAsignada) ->
                             ProcesoSolicitante ! {siPuedoLimpiar,self()},
                             io:format("sí puedo~n",[]),
                             AreaAsignadaNueva = AreaAsignada-AreaALimpiar,
                             limpiar(Gestor,A,AreaAsignadaNueva);
                {limpiar, AreaALimpiar,ProcesoSolicitante} when
                                (AreaALimpiar > AreaAsignada)
                             ->
                             ProcesoSolicitante ! {noPuedoLimpiar,self()},
                             io:format("no puedo~n",[]),
                             limpiar(Gestor,A,AreaAsignada);
               {alto,ProcesoSolicitante} -> io:format("Hasta luego, fue un placer",[])
     end.
                            

pisoBasico() -> [{X,Y} || X <-lists:seq(1,3),Y <-lists:seq(1,3)].

%tomar(N,Ls)

tomar(0,_) -> [];
tomar(N,[A|Ls]) -> [A|tomar(N-1,Ls)].
omitir(0,Ls) -> Ls;
omitir(N,[_|Ls]) -> omitir(N-1,Ls).

dividir(Ls) ->
        L=length(Ls),
        Mitad=L div 2,
        {tomar(Mitad,Ls),omitir(Mitad,Ls)}.


%Es una función asociada únicamente al gestor
gestionar(K1,K2) ->
%        link(trabajador1),
        if
           (K1==0) and (K2==0) -> true;
           (K1==0) and (K2==1) -> true;
           (K1==1) and (K2==0) -> true;
           (K1==1) and (K2==1) -> self() ! "TERMINADO!!!!~n"
        end,
        receive
           {reporte,terminado,IdProceso} ->
                                io:format("Listo~n~p",[IdProceso]),
                         gestionar(K1,K2);
           {Piso,IdProceso} ->
                            es_piso(Piso),
                       io:format("Piso a limpiar~n~p~n",[Piso]),
                {A,B}=dividir(Piso),
%                falta...
%                verificar si lo puede hacer...
%                             si lo puede hacer se prodece con segmento...
                trabajador1 ! {segmento, A, self()},
                trabajador2 ! {segmento, B, self()},
%    osito1@RieGau ! {segmento, A, self()},
%    osito2@RieGau ! {segmento, B, self()},
           
                gestionar(K1,K2);
        {terminado,trabajo1,Id1} ->
                    NK1=1,
                    gestionar(NK1,K2);
        {terminado,trabajo2,Id2} ->
                    NK2=1,
                    gestionar(K1,NK2);
        listo -> io:format("Sí~n",[]),
                  gestionar(K1,K2);
            alto -> io:format("Proceso gestor terminado~n",[])
        end.

%Por hacer o concluir:
% a) La idea de separar este archivo en varios otros, cada uno abarcando la
% funcionalidad de un agente específico.
% b) La posibilidad de que los archivos separados sean trabajados por programadores
% diferentes, cada programador concentrándose en elaborar o un agente o inclusive
% partes de un agente (comunicación, --infrarrojo [código de barras], actuadores, etc.).
% jabber
% c) La conceptualización de que toda comunicación entre agentes remotamente ubicados
% entre sí es mediante paso de mensajes (incluso cuando es un mismo robot interno).
%
%Falta una función de parte de los trabajadores para darse conocer con id.


1 comentario:

  1. Compilé y corrí el código según las instrucciones de los comentarios, sin embargo al momento de correr el tercer comando (Ls=pisoBasico(), gestor ! Ls.) me marca el error: exception error: undefined sell command pisoBasico/0. ¿A alguno de ustedes ya le corrió el código?

    ResponderEliminar