-- AUTOR: Elvira Mayordomo Cámara
-- PROYECTO: módulo de implementación del
-- TAD rvuelos solución del examen del
-- 24-1-03
-- FICHERO: rvuelos.adb
-- FECHA: 21-1-03; 9-1-04

with unchecked_deallocation;
package body rvuelos is
procedure dispose is new
unchecked_deallocation(rnombre,lista);

function h(nom:ustring;m:integer) return integer is
--hash por método de la división con módulo m
-- coste en tiempo O(longitud(nom))
res:integer;
begin
	res:=0;
	for i in 1..length(nom) loop
		res:=res+character'pos(Element(nom,i));
	end loop;
	return res mod m;	
end h;

procedure anadirE(l:in out colaEspecial; p:in ptreserva) is
-- a p sólo le falta sig y ant
-- tiempo O(1)
begin	
	p.sig:=null; p.ant:=l.ult;
	if l.ult/=null then l.ult.sig:=p; end if;
	l.ult:=p;
	if l.prim=null then l.prim:=l.ult; end if;
end anadirE;

procedure borraE(p:in ptreserva;q:in out ptResVueloCat) is
-- pre: p tiene reserva o lista de espera en q
-- tiempo O(1)
begin 
	if p.ant=null then
		if p.enListaEspera then 
			q.listaEspera.prim:=p.sig;
		else
			q.listaReservas.prim:=p.sig;
		end if;
	else
		p.ant.sig:=p.sig;
	end if;				
	if p.sig=null then
		if p.enListaEspera then 
			q.listaEspera.ult:=p.ant;
		else
			q.listaReservas.ult:=p.ant;
		end if;
	else
		p.sig.ant:=p.ant;	
	end if;						
end borraE;

procedure borraElemento(l:in out lista; n:in ustring) is
-- Pre: n está en l
aux, aux2: lista;
begin
	aux:=l;
	if l/=null and then l.elnombre=n then
		aux2:=l;
		l:=l.sig;
	else	
		while aux.sig/=null and then aux.sig.elnombre/=n loop
			aux:=aux.sig;
		end loop;
		aux2:=aux.sig;
		aux.sig:=aux.sig.sig;
	end if;
	dispose(aux);	
end borraElemento;

	procedure reservar(vuelo,pasajero,categoria: in ustring;
	todo: in out tpVuelosDiarios) is
	-- Pre: existe el vuelo y la categoría
	-- coste en tiempo O(1) en media
	p:ptreserva;
	q:ptResVueloCat;
	begin
		p:=new tpreserva'(pasajero,vuelo,categoria,true,null,null );
		q:=consultar(todo.tablaVueloCategoria,vuelo&categoria);
		if q.numplazas>q.numocupadas then
			q.numocupadas:=q.numocupadas+1;
			p.enListaEspera:=false;
			anadirE(q.listaReservas,p); 
			modificar(todo.tablaPasajero,pasajero,p);
		else 
			p.enListaEspera:=true;
			anadirE(q.listaEspera,p); 
			modificar(todo.tablaPasajero,pasajero,p);
		end if;		
	end reservar;
	
	procedure cancelar(pasajero: in ustring;
	todo: in out tpVuelosDiarios) is
	-- Pre: el pasajero está en el sistema
	-- coste en tiempo O(1) en media
	p,sustituto:ptreserva;
	q:ptResVueloCat;
	begin
	p:=consultar(todo.tablaPasajero,pasajero);
	q:=consultar(todo.tablaVueloCategoria,p.elvuelo&p.lacategoria);
	borraE(p,q);
	q.numocupadas:=q.numocupadas-1;
	sustituto:=q.listaReservas.prim;
	borraE(sustituto,q);
	borrar(todo.tablaPasajero,p.elpasajero);	
	reservar(p.elvuelo,sustituto.elpasajero,p.lacategoria,todo);	
	end cancelar;
	
	procedure cancelarVuelo(vuelo: in ustring; todo: in out tpVuelosDiarios)
	is
	-- Pre:el vuelo existe
	-- coste en tiempo:
	-- O(núm. vuelos * núm. categorías)
	l,l2:lista;cat,vol,vol2,pas:ustring;
	p:ptreserva;
	q,q2:ptResVueloCat;
	-- tiempo O(nvuelos*ncategorias+npasajeros)
	begin
	borraElemento(todo.losVuelos,vuelo);
	l:=todo.lasCategorias;
	while l/=null loop
		cat:=l.elnombre;
		l:=l.sig;
		q:=consultar(todo.tablaVueloCategoria,vuelo&cat);
		l2:=todo.losVuelos;
		while q.listaReservas.prim/=null and
		l2/=null loop
			vol:=l2.elnombre;
			l2:=l2.sig;
			q2:=consultar(todo.tablaVueloCategoria,vol&cat);
			while q2.numplazas>q2.numocupadas loop
				pas:=q.listaReservas.prim.elpasajero;
				cancelar(pas,todo);
				reservar(vol,cat,pas,todo);
			end loop;
		end loop;
		while q.listaReservas.prim/=null loop
			pas:=q.listaReservas.prim.elpasajero;
			cancelar(pas,todo);
			reservar(vol,cat,pas,todo);	
		end loop;	
		while q.listaEspera.prim/=null loop
			pas:=q.listaEspera.prim.elpasajero;
			cancelar(pas,todo);
			reservar(vol,cat,pas,todo);	
		end loop;
	end loop;	
	end cancelarVuelo;
	
end rvuelos;			
		


syntax highlighted by Code2HTML, v. 0.9.1