Programaci´
on 2
Curso 2017/2018
Pr´
actica 3
Evacuaci´
on del planeta helado Hoth (orientado a objetos)
Esta pr´actica consiste en implementar, utilizando programaci´on orientada a
ob-jetos, la pr´actica 1, con algunos cambios en el comportamiento que se explican
m´as adelante.
1.
Normas generales
1.1.
Entrega
1. El ´ultimo d´ıa para entregar esta pr´actica es el mi´ercoles 23 de mayo,
hasta las 23:59. No se admitir´an entregas fuera de plazo.
2. La pr´actica debe tener varios ficheros: “Coordinate.cc” y “Coordinate.h”,
“Base.cc” y “Base.h”, “Ship.cc” y “Ship.h”, “Planet.cc” y “Planet.h”,
“Util.cc” y “Util.h”. Todos ellos se entregar´an a trav´es del servidor de
pr´acticas, en un archivo comprimido llamado “prog2p3.tgz”; no se debe
entregar el Makefile ni el evacuationOfHoth.cc. Para crear el fichero comprimido sigue estas instrucciones:
a) Crea un directorio nuevo
b) Copia la ´ultima versi´on de los ficheros de la pr´actica en dicho
direc-torio (comprueba siempre que es la versi´on que quieres entregar); no
copies el evacuationOfHoth.cc
c) Ejecuta la siguiente orden desde ese directorio, pero no olvides poner el nombre prog2p3.tgz:
tar cvfz prog2p3.tgz *.h *.cc
En la web de la asignatura se publicar´a un fichero “evacuationOfHoth-p3.cc”,
que no deber´ıa ser modificado y que no es necesario entregar (pero s´ı debe
renombrarse a “evacuationOfHoth.cc” para compilar y probar la pr´
acti-ca con el autocorrector). Para corregir la pr´actica se utilizar´a ese fichero exactamente.
1.2.
Detecci´
on de plagios/copias
En el Grado en Ingenier´ıa Inform´atica, la Programaci´on es una materia
fun-damental, que se aprende programando y haciendo las pr´acticas de las diferentes
asignaturas (y otros programas, por supuesto). Si alguien pretende aprobar las
asignaturas de programaci´on sin programar (copiando), obviamente tendr´a
se-rios problemas para aprobar y para seguir otras asignaturas, y cuando intente
trabajar. Concretamente, en Programaci´on 2 es muy dif´ıcil que alguien que no
ha hecho las pr´acticas supere el examen de teor´ıa, por lo que copiar una pr´actica es una de las peores decisiones que se puede tomar.
La pr´actica debe ser un trabajo original de la persona que la entrega; en
caso de detectarse indicios de copia de una o m´as pr´acticas se tomar´an las
medidas disciplinarias correspondientes, informando a la direcci´on de la EPS
por si hubiera lugar a otras medidas disciplinarias adicionales.
1.3.
Otras normas
1. La pr´actica se debe entregar exclusivamente a trav´es del servidor de pr´
acti-cas del departamento de Lenguajes y Sistemas Inform´aticos, al que se
pue-de accepue-der pue-despue-de la p´agina principal del departamento ( www.dlsi.ua.es,
“Entrega de pr´acticas”) o directamente en la url https://pracdlsi.
dlsi.ua.es.
No se admitir´an entregas por otros medios (correo electr´onico,
UA-Cloud, etc.).
El usuario y contrase˜na para entregar pr´acticas es el mismo que se
utiliza en el UACloud.
La pr´actica se puede entregar varias veces, pero s´olo se corregir´a la ´
ultima entrega (las anteriores entregas no se borran).
2. El programa debe poder ser compilado sin errores con el compilador de C++ existente en la distribuci´on de Linux de los laboratorios de pr´acticas; si la pr´actica no se puede compilar su calificaci´on ser´a 0. Se recomienda
compilar y probar la pr´actica con el autocorrector inmediatamente antes
de entregarla.
3. La correcci´on de la pr´actica se har´a de forma autom´atica, por lo que es imprescindible respetar estrictamente los textos y los formatos de salida que se indican en este enunciado.
4. Al principio de todos los ficheros fuente entregados se debe incluir un comentario con el nombre y el NIF (o equivalente) de la persona que entrega la pr´actica, como en el siguiente ejemplo:
// NIF 12345678X GARCIA GARCIA, JUAN MANUEL
5. El c´alculo de la nota de la pr´actica y su influencia en la nota final de
la asignatura se detallan en las transparencias de la presentaci´on de la
asignatura.
2.
Introducci´
on
En esta pr´actica se implementar´a con programaci´on orientada a objetos la
pr´actica 1, es decir, no se utilizar´an ficheros ni argumentos.
En la siguiente p´agina tienes un diagrama UML con las clases que es
3 CLASES Y M ´ETODOS 3
+ Coordinate()
+ Coordinate(x: double, y: double) + <<const>> getX() : double + <<const>> getY() : double
+ <<const>> distance(c : const Coordinate &): double <<friend>> operator<< : ostream &
<<friend>> operator>>: istream & - x : double
- y : double
Coordinate
+ Ship(name : string, maxPeople : int, maxEquipment : int) + <<const>> getName() : string
+ <<const>> getMaxPeople() : int + <<const>> getMaxEquipment() : int + <<const>> getCurPeople() : int + <<const>> getCurEquipment() : int + setMaxPeople(maxPeople : int) : void + setMaxEquipment(maxEquipment : int) : void + <<const>> hasBases() : bool
+ <<const>> numBases() : unsigned + <<const>> getBase(pos : unsigned) : Base * + <<const>> admitsBase(base : const Base &) : bool + addBase(pbase : Base * ) : void
+ <<const>> centroid() : Coordinate + detachBases() : void
<<friend>> operator<< : ostream & - name : string - maxPeople : int - maxEquipment : int - MinShipPeople : unsigned = 100 - curPeople : int - curEquipment : int Ship
+ Base(name : string, position : const Coordinate&, people: int, equipment : int)
+ <<const>> getName() : string + <<const>> getPosition() : Coordinate + <<const>> getPeople() : int + <<const>> getEquipment() : int + <<const>> isAssigned() : bool
+ setPosition(position : const Coordinate &) : void + setPeople(people : int) : void
+ setEquipment(equipment : int) : void + setAssigned(assigned: bool): void <<friend>> operator<< : ostream & - name : string - people : int - equipment : int - MinBasePeople : unsigned = 50 - assigned : bool Base
+ error(n : Error) : void
Util
-position 1
-bases
* + Planet(name : string) + <<const>> getName() : string + <<const>> getNumBases() : unsigned + <<const>> getBase(pos : unsigned) : Base + <<const>> getNumShips() : unsigned + <<const>> getShip(pos : unsigned) : Ship - <<const>> searchBase(name : string) : int - <<const>> searchShip(name : string) : int + createBase(name : string='''') : void + createShip() : void
+ deleteBase(name : string=''''): void + deleteShip(name : string=''''): void + evacuationPlan() : void <<friend>> operator<< : ostream & - name : string Planet -bases * -ships *
3.
Clases y m´
etodos
En el diagrama UML se muestran las clases que se deben implementar, con sus atributos y m´etodos. Adem´as, tendr´as que utilizar m´as m´etodos (privados
siempre) y quiz´a atributos (tambi´en privados), seg´un sea necesario para
im-plementar la pr´actica. Ten en cuenta que algunos atributos aparecen en las
relaciones de agregaci´on y composici´on.
A continuaci´on se describen los m´etodos m´as importantes de cada clase;
los constructores y getters/setters no se explican, salvo que lo que tengan que hacer no sea evidente. Algunos de ellos no es necesario utilizarlos en la pr´actica, pero se utilizar´an en las pruebas unitarias para la correcci´on de la pr´actica. Se recomienda implementar las clases en el orden en que aparecen en el enunciado.
3.1.
Util
error : se usa para emitir mensajes de error. El tipo enumerado con los posibles errores debe estar en el fichero Util.h, pero fuera de la clase Util.
3.2.
Coordinate
Esta clase se utiliza para gestionar las coordenadas de las bases. Tiene dos constructores, uno sin par´ametros que debe poner los dos atributos, x e y, a cero,
y un constructor con par´ametros que debe asignar a los atributos los valores de
los par´ametros.
Adem´as de los getters, hay un par de m´etodos m´as:
distance : devuelve la distancia eucl´ıdea entre las dos coordenadas (la que
recibe la llamada del m´etodo, y la que aparece como argumento).
operator<< : operador de salida, debe mostrar las dos componentes de la
coordenada entre par´entesis y separadas por una coma, como por ejemplo:
(12.3,-4.56)
operator>> : operador de entrada, debe leer las dos componentes de la
coor-denada con el formato x y (separadas por blancos).
3.3.
Base
Esta clase se utiliza para almacenar los datos de una base. Con respecto a la pr´actica anterior, se ha a˜nadido un atributo m´as, assigned, que indica si la base est´a asignada a una nave o no (est´a en el planeta). En esta pr´actica, las bases nunca se borran del vector de bases del planeta, lo que se almacena en la
nave es una referencia (puntero) a la base, y la forma de saber si la base est´a
en una nave o en el planeta es mediante este atributo. Para acceder y modificar
este atributo se usar´an los m´etodos isAssigned y setAssigned.
Los m´etodos m´as relevantes de esta clase son:
Base : constructor para crear una base con los datos indicados en los
argumen-tos. Por defecto, las bases no est´an asignadas a ninguna nave.
Si el n´umero de personas que se pasa como par´ametro no es positivo, debe
lanzar una excepci´on utilizando como valor de la excepci´on el ERR_WRONG_NUMBER;
si es positivo pero menor que 50, la excepci´on debe lanzarse con ERR_LOW_PEOPLE.
Si la cantidad de material pasada como par´ametro no es positiva debe
lan-zarse la excepci´on con ERR_WRONG_NUMBER. Las excepciones deben lanzarse
en el orden en que se describen aqu´ı.
En el m´etodo createBase de la clase Planet se tendr´an que capturar estas
excepciones y emitir el mensaje de error correspondiente al valor lanzado por la excepci´on.
setPeople : modifica el valor del atributo people, pero tiene que hacer las mismas comprobaciones que el constructor, y lanzar las excepciones co-rrespondientes.
setEquipment : como setPeople, modifica el valor del atributo equipment,
pero tiene que hacer la misma comprobaci´on que el constructor, y lanzar
3 CLASES Y M ´ETODOS 5
operator<< : operador de salida, imprimir´a los datos de la base como la
fun-ci´on printBase de las pr´acticas anteriores, pero a˜nadiendo el atributo
assigned, como en este ejemplo: [(main base) 1251 12345 (12.34,-7.89) 0]
El ´ultimo valor antes del “]” ser´a un 0 o un 1 seg´un si el valor del atributo assigned es false o true (cuando se imprime un valor booleano con el operador << se imprime un 0 o un 1).
3.4.
Ship
Esta clase implementa las naves que se van a utilizar para la evacuaci´on
del planeta. Como en las pr´acticas anteriores, debe almacenar las bases que se
le asignen utilizando un vector. Sin embargo, al tratarse de una relaci´on de
agregaci´on, el vector almacenar´a punteros a Base (que se corresponder´an con
objetos almacenados en el vector de bases del planeta), en vez de objetos de la clase Base.
Los m´etodos m´as importantes son los siguientes (alguno no es necesario
utilizarlo para hacer la pr´actica, se incluye solamente para las pruebas unitarias):
Ship : constructor que inicializa nombre, cantidad m´axima de personas y
canti-dad m´axima de material. Los atributos curPeople y curEquipment deben
inicializarse a 0. Como en el constructor de la clase Base, este tambi´en de-be comprobar que los valores de maxPeople y maxEquipment son correctos
(con las mismas restricciones que en las pr´acticas anteriores) y lanzar las
excepciones correspondientes, que tendr´an que ser capturadas en el m´
eto-do createShip de la clase Planet.
setMaxPeople : modifica el valor del atributo maxPeople, pero tiene que hacer las mismas comprobaciones que el constructor, y lanzar las excepciones correspondientes.
setMaxEquipment : como setMaxPeople, modifica el valor del atributo maxEquipment,
pero tiene que hacer la misma comprobaci´on que el constructor, y lanzar
la excepci´on correspondiente.
hasBases : devuelve true si la nave tiene alguna base asignada (es decir, si tiene alguna base en su vector de bases), y false en caso contrario.
numBases : devuelve el n´umero de bases, es decir, el n´umero de elementos del
vector de bases.
getBase : devuelve el puntero a la base situado en la posici´on pos del vector,
o bien NULL si pos no est´a dentro del vector.
admitsBase : devuelve true si la base pasada como par´ametro puede ser
eva-cuada por la nave, es decir, si la cantidad de personas y material de la base se podr´ıan almacenar en la nave.
addBase : a˜nade el puntero a la base pasado como par´ametro al vector de bases
centroid : calcula el centroide o punto medio de las posiciones de las bases
de la nave (como en las pr´acticas anteriores), y devuelve una coordenada
nueva con el centroide. Si no hay ninguna base en la nave, debe devolver la coordenada (0,0).
detachBases : devuelve las bases de la nave al planeta (no hay que almacenar las bases en el vector del planeta, simplemente hay que desasignarlas), limpia el vector y actualiza los atributos curPeople y curEquipment. operator<< : muestra los datos de la nave siguiendo el mismo formato que en
las pr´acticas anteriores (similar a la funci´on printShip). Tambi´en como
en las pr´acticas anteriores, si la nave tiene bases asociadas debe mostrar
dichas bases (usando el operador correspondiente de la clase Base).
3.5.
Planet
En esta clase se implementan los m´etodos relacionados con el planeta. Como
se ha explicado anteriormente, las bases no se mueven del vector del planeta, simplemente se asignan a las naves, que almacenan un puntero a la base en su vector de bases (que ser´ıa un vector<Base *>).
Planet : crea un planeta con su nombre.
getBase y getShip : en estos getters, que se utilizar´an para las pruebas
unita-rias, se asume que el argumento pos es correcto, es decir, est´a dentro del
rango de posiciones v´alidas del vector.
searchBase y searchShip : estos m´etodos privados buscan una base o nave en
el vector correspondiente a partir de su nombre, y devuelven la posici´on
en el vector de la base o nave, o bien -1 si no la encuentran.
createBase : se debe comprobar si el par´ametro name es una cadena vac´ıa, en
cuyo caso debe pedir por pantalla el nombre de la base; si no es la cadena
vac´ıa, se toma ese par´ametro como nombre de la base.
Si ya existe una base con ese nombre, se pedir´a al usuario qu´e dato desea modificar (como en las pr´acticas anteriores), y se actualizar´a la base. Si
no existe, se pedir´an todos los datos de la base (personas, material y
coordenadas) sin hacer ninguna comprobaci´on,1y se crear´a una base nueva
con esos datos; si la base puede crearse (es decir, si no se genera ninguna excepci´on), la base se a˜nadir´a al final del vector de bases del planeta. Este
m´etodo (o bien los m´etodos privados en los que delegue) debe capturar
las excepciones que lanzan el constructor y los setters de la clase Base. Para leer las coordenadas de la base se debe utilizar el operador de entrada de dicha clase, que lee ambas coordenadas a la vez, por lo que es necesario
adaptar el mensaje de petici´on, que debe ser el siguiente:
Enter base coordinate:
Este mensaje debe emitirse en la clase Planet, no en la clase Coordenada. 1Las comprobaciones ya se hacen en el constructor de la base.
4 PROGRAMA PRINCIPAL 7
createShip : como en la funci´on con el mismo nombre de las pr´acticas
ante-riores, se pedir´a al usuario el nombre de la nave y, si no est´a repetido se
solicitar´an el resto de datos de la nave (como en el m´etodo createBase,
sin hacer comprobaciones porque ya las hace el constructor de la nave), se crear´a la nave y se a˜nadir´a al vector. Si ya existe una nave con ese nombre
se emitir´a el error ERR_WRONG_SHIP_NAME, como en las pr´acticas
anterio-res. Este m´etodo debe capturar las excepciones lanzadas por el constructor
de la clase Ship.
deleteBase : se debe comprobar si el par´ametro name es una cadena vac´ıa, en
cuyo caso se pedir´a al usuario el nombre de la base y se borrar´a, como en
las pr´acticas anteriores.
deleteShip : como en deleteBase, se debe comprobar si el par´ametro name es
una cadena vac´ıa, en cuyo caso se pedir´a al usuario el nombre de la nave
y se borrar´a, como en las pr´acticas anteriores.
evacuationPlan : como en la pr´actica 1, simula el plan de evacuaci´on del
planeta.
operator<< : operador de salida, muestra los datos del planeta siguiendo el mis-mo formato que en la pr´actica anterior (similar a la funci´on printPlanet).
4.
Programa principal
El programa principal estar´a en el fichero “evacuationOfHoth-p3.cc” que
se publicar´a en la web de la asignatura. Este fichero no debe modificarse y no
puede entregarse con la pr´actica (la pr´actica se compilar´a con la versi´on publica-da en la web antes de corregirla), pero s´ı debe renombrarse a “evacuationOfHoth.cc”
para compilar y probar la pr´actica.
5.
Implementaci´
on
Para implementar la pr´actica debes tener en cuenta, adem´as de todo lo
comentado anteriormente:
1. Es probable que puedas aprovechar c´odigo de la pr´actica 1, y es buena idea que lo hagas, pero tampoco intentes aprovecharlo todo; a veces se tarda
menos en escribir el c´odigo de nuevo que en intentar adaptar un c´odigo ya
existente.
2. Como en las pr´acticas anteriores, el resto de decisiones en la