Ingeniería de Requisitos Ejercicios de restricciones en OCL: Fútbol noviembre 2012 Enunciado Teniendo en cuenta el siguiente modelo estático: Exprese en OCL las restricciones que corresponden con las siguientes reglas de negocio: 1. Durante una misma temporada, no pueden existir entradas para asientos que estén abonados. 2. Asistir a los partidos mediante un abono debe ser más económico que hacerlo comprando entradas para cada partido, asumiendo la misma zona del campo y asumiendo también que dada una temporada t, t.partido es el conjunto de todos los partidos que se han disputado o se van a disputar durante dicha temporada. 3. Un asiento no puede tener más de un abono por temporada. 4. Especifique la postcondición de la consulta Partido::Espectadores() : Integer, que devuelve el número de espectadores a un partido. Asuma que los abonados asisten siempre a los partidos y que toda persona que compra una entrada también asiste siempre. Página 1 de 3 Ingeniería de Requisitos Ejercicios de restricciones en OCL: Fútbol noviembre 2012 Soluciones 1. Durante una misma temporada, no pueden existir entradas para asientos que estén abonados. context Temporada inv noEntradaAsientoAbonado: ( abono.asiento->asSet )->intersection( ( partido.entrada.asiento->asSet ) )->isEmpty El conjunto de asientos abonados debe ser disjunto con el conjunto de asientos con entrada en una misma temporada. En este caso concreto, se podría también haber aplicado la intersección entre multiconjuntos, sin necesidad de convertir a conjunto, es decir, también es válida la siguiente solución: context Temporada inv noEntradaAsientoAbonado: abono.asiento->intersection( partido.entrada.asiento )->isEmpty Usando let para mayor claridad: context Temporada inv noEntradaAsientoAbonado: let asientosAbonados : Set( Asiento ) = abono.asiento->asSet in let asientosConEntrada : Set( Asiente ) = partido.entrada.asiento->asSet in asientosAbonados->intersection( asientosConEntrada )->isEmpty Otra solución alternativa es: context Entrada inv noEntradaAsientoAbonado: partido.temporada.abono.asiento->excludes( asiento ) El asiento de una entrada no es uno de los asientos abonados en la temporada del partido de la entrada. Página 2 de 3 Ingeniería de Requisitos Ejercicios de restricciones en OCL: Fútbol noviembre 2012 2. Asistir a los partidos mediante un abono debe ser más económico que hacerlo comprando entradas para cada partido, asumiendo la misma zona del campo y asumiendo también que dada una temporada t, t.partido es el conjunto de todos los partidos que se han disputado o se van a disputar durante dicha temporada. context Precio inv abonoMásBaratoEntradas: let precioTodasLasEntradas : Integer = temporada.partido->size() * precioEntrada in precioAbono < precioTodasLasEntradas Para todos los precios establecidos en una temporada para en una zona concreta del campo, el precio del abono debe ser menor que el precio de la entrada en dicha zona multiplicado por el número de partidos en dicha temporada. 3. Un asiento no puede tener más de un abono por temporada. context Asiento inv soloUnAbonoPorTemporada: abono->forAll( a1, a2 | ( a1 <> a2 ) = ( a1.temporada <> a2.temporada ) ) Otra alternativa es: context Asiento inv soloUnAbonoPorTemporada: abono.temporada->isUnique( añoComienzo ) 4. Especifique la postcondición de la operación Partido::Espectadores() : Integer, que devuelve el número de espectadores a un partido. Asuma que los abonados asisten siempre a los partidos y que toda persona que compra una entrada también asiste siempre. context Partido::Espectadores() : Integer body: self.temporada.abono->size + self.entrada->size El número de espectadores que asiste a un partido es el número de abonados en la temporada del partido más el número de entradas vendidas para dicho partido. Página 3 de 3