Vous êtes sur la page 1sur 18

Etude de cas “simulation de banque” UML/C++

Philippe Laroque
$Id: simuBanque.lyx 1665 2009-03-05 16:02:45Z phil $
laroque@u-cergy.fr

mars 2009

Abstract
Ce petit document résume, à travers une étude de cas simple, le principe du passage d’un
modèle UML à un codage C++. L’exemple utilise la STL. Il est donné comme corrigé indicatif
lors de la formation continue “SAGEM” en avril 2009.

1 Rappel du sujet
Il s’agit de simuler le fonctionnement d’une banque contenant un nombre fixé de caissiers, et
recevant des clients qui arrivent de manière pseudo-aléatoire. Lorsqu’un client arrive, si un caissier
est libre il prend en charge le client, sinon le client prend place dans une file d’attente (supposée
commune à tous les caissiers, représentée par exemple par un système de tickets numérotés en
ordre croissant).
Le but de la simulation est de fournir des résultats statistiques sur les différents acteurs de la
simulation. Pour cela, on donne en entrée de la simulation:
• La durée estimée de la simulation : c’est la durée au bout de laquelle la banque n’accepte
plus de nouveaux clients. Bien entendu, ceux qui se trouvent déjà dans la file seront servis...

• Le nombre de caissiers.
• Le temps moyen de service de chaque caissier (on suppose donc qu’ils ne sont pas tous
également performants ...).
• Le temps moyen entre deux arrivées successives de clients.

On souhaite obtenir, à la fin de la simulation, les résultats suivants :


• La durée réelle de la simulation (c’est-à-dire la durée au bout de laquelle tous les clients qui
se trouvaient encore dans la file ont été servis).
• Les longueurs maximale et moyenne de la file d’attente.

• Le nombre de clients servis (au total, et par caissier).


• Le taux d’occupation de chque caissier.
• Le temps moyen d’attente d’un client dans la file.

1
Hypothèses de fonctionnement
Pour réaliser cette simulation, on adopte un certain nombre d’hypothèses simplificatrices :
• Les clients sont honnêtes (ils ne cherchent pas à passer devant ceux qui étaient là avant eux).
• Les clients sont patients (quelle que soit la longueur de la file, ils attendent leur tour et ne
quittent pas la banque avant d’avoir été servis).

• Les clients sont  paresseux  (si plusieurs caissiers sont libres lors de l’arrivée d’un client,
ce dernier se fera servir par le caissier de plus faible numéro, celui situé le plus près de la
porte d’entrée).
• Les caissiers ne sont jamais fatigués : dès la fin de traitement d’un client, le caissier en
reprend un si la file n’est pas vide.
• On dispose d’un générateur aléatoire permettant de déterminer les arrivées de clients et les
temps de service effectifs des caissiers.
• La simulation repose sur la succession d’événements discrets: on suppose qu’entre deux
événements consécutifs il ne se passe rien de marquant dans le système, donc le temps varie
de manière discrète.

2 Modèle UML initial


Quelques remarques sur le modèle ci-dessous:

• les attributs ne figurent pas, ils sont à la charge du développeur de chaque classe;
• les passages d’objets se font tous par adresse, même si le modèle UML ne permet pas de le
représenter (même chose en ce qui concerne les objets retournés par une méthode);
• les associations sont traversables par une méthode (accesseur) du même nom que le rôle. Par
exemple, pour accéder à la file d’attente depuis la banque b, on écrit en C++ b->fileAttente();
Ces méthodes ne sont pas représentées dans le modèle de conception ci-dessous (mais doivent
bien sûr être définies!):

2
Poisson DiscreteSimulation Event
0..*
init() DiscreteSimulation() Event(h : double,s : DiscreteSimulation)
next(moy : double = 1) : double add(e : Event) time() : double
run() fire(
time() : double

Client
Client(ha : double) Depart Arrivee
heureArrivee() : double
Depart(h : double,s : DiscreteSimulation,c : Caissier) Arrivee(h : double,s : DiscreteSimulation)
fire( fire(
0..*

FileAttente
Banque Caissier
FileAttente(bq : Banque)
Banque() Caissier(tms : double,bq : Banque)
estVide() : bool
unCaissierLibre() : Caissier N nbClientsServis() : int
longueurMax() : int
nbClientsServis() : int estLibre() : bool
longueurMoyenne() : double
dureePrevue() : double liberer()
tempsMoyenAttente() : double
dureeReelle() : double tauxOccupation() : double
ajouter(c : Client)
tempsMoyenEntreArrivees() : double servir(c : Client)
retirer() : Client

Constructeur: les paramètres de la simulation


(dureePrevue, nbCaissiers, tService, tEntreArriv ees)

3 Le code source de l’application


Il est à noter que la version de code source présentée ici ne gère pas proprement les problèmes de
mémoire (les classes ne sont pas mises sous forme canonique, les variables allouées dynamiquement
ne sont donc pas toutes récupérées).

3.1 Le pattern “simulation discrete”


Les deux classes Event et DiscreteSimulation ont été définies de telle façon qu’elles ne dépendent
pas de l’application, et sont donc entièrement réutilisables (notion de “pattern”).

3.1.1 La classe Event


/****************************************************************************
*
* $Id: Event.h 1667 2009-03-10 14:09:08Z phil $
*
****************************************************************************/

#ifndef __Event_h
#define __Event_h

#include <iostream>
#include <string>
using namespace std;

class DiscreteSimulation;

/*******************************

3
* Event is the abstract root for all event types.
* It only publishes the time at which it is to fired, and the
* fire() method (abstract).
*******************************/

class Event {
protected:
const double _time;
DiscreteSimulation *ds;
public:
Event(double h, DiscreteSimulation *s) : _time(h) { ds = s; }
double time() { return _time; }
virtual void fire() = 0;
virtual string type() = 0;
friend ostream& operator << (ostream& o, Event& e) {
return o << e.type() << "@" << e.time();
}
};

#endif

/****************************************************************************/

3.1.2 La classe DiscreteSimulation


L’interface

/****************************************************************************
*
* $Id: DiscreteSimulation.C 1667 2009-03-10 14:09:08Z phil $
*
****************************************************************************/

static char rcsId[] = "@(#) $Id: DiscreteSimulation.C 1667 2009-03-10 14:09:08Z phil $";

#include "DiscreteSimulation.h"

/***************************************************************************
* Implementation of the DiscreteSimulation class.
* The insertion of an Event
* is extremely simple, since the map used to store the events is
* "naturally" sorted !
* The run() method iteratively removes the first (that is, "chronologically"
* next) event from the map, fires it and deletes it. It stops when the
* map is empty.
***************************************************************************/
void DiscreteSimulation :: add (Event *e) {
events.insert(e);
}

void DiscreteSimulation :: run() {


while (events.size()) {

4
Event *e = (*(events.begin()));
events.erase(events.begin());
_time = e->time();
e->fire();
// cout << *e << endl; // uncomment to debug
delete e;
}
}

/***************************************************************************/

L’implémentation
/****************************************************************************
*
* $Id: DiscreteSimulation.C 1667 2009-03-10 14:09:08Z phil $
*
****************************************************************************/

static char rcsId[] = "@(#) $Id: DiscreteSimulation.C 1667 2009-03-10 14:09:08Z phil $";

#include "DiscreteSimulation.h"

/***************************************************************************
* Implementation of the DiscreteSimulation class.
* The insertion of an Event
* is extremely simple, since the map used to store the events is
* "naturally" sorted !
* The run() method iteratively removes the first (that is, "chronologically"
* next) event from the map, fires it and deletes it. It stops when the
* map is empty.
***************************************************************************/
void DiscreteSimulation :: add (Event *e) {
events.insert(e);
}

void DiscreteSimulation :: run() {


while (events.size()) {
Event *e = (*(events.begin()));
events.erase(events.begin());
_time = e->time();
e->fire();
// cout << *e << endl; // uncomment to debug
delete e;
}
}

/***************************************************************************/

5
3.2 La classe Arrivee
L’interface
/****************************************************************************
*
* $Id: Arrivee.C 1664 2009-03-05 14:52:22Z phil $
*
****************************************************************************/

static char rcsId[] = "@(#) $Id: Arrivee.C 1664 2009-03-05 14:52:22Z phil $";

#include <iostream>
#include "Arrivee.h"
#include "Client.h"
#include "Caissier.h"
#include "FileAttente.h"
#include "Poisson.h"
#include "Banque.h"
using namespace std;

/***************************************************************************
* lors d’une arrivee :
* - on cree le client
* - on calcule l’heure de la prochaine arrivee
* - si cette heure est < duree prevue, on cree la prochaine arrivee
* et on l’ajoute a l’echeancier
* - si un caissier est libre, il sert le client
* - sinon, le client fait la queue dans la file d’attente
***************************************************************************/
void Arrivee :: fire() {
// cerr << "Il est " << _time << " : arrivee\n";
Banque * s = (Banque*) ds;
Client * c = new Client(_time,s);
double next = _time + Poisson::next(s->tempsMoyenEntreArrivees());
if (next < s->dureePrevue())
s->add(new Arrivee(next,s));
Caissier * cs = s->unCaissierLibre();
if (cs)
cs->servir(c);
else
s->fileAttente()->ajouter(c);
}

/***************************************************************************/

L’implémentation
/****************************************************************************
*
* $Id: Arrivee.C 1664 2009-03-05 14:52:22Z phil $
*
****************************************************************************/

6
static char rcsId[] = "@(#) $Id: Arrivee.C 1664 2009-03-05 14:52:22Z phil $";

#include <iostream>
#include "Arrivee.h"
#include "Client.h"
#include "Caissier.h"
#include "FileAttente.h"
#include "Poisson.h"
#include "Banque.h"
using namespace std;

/***************************************************************************
* lors d’une arrivee :
* - on cree le client
* - on calcule l’heure de la prochaine arrivee
* - si cette heure est < duree prevue, on cree la prochaine arrivee
* et on l’ajoute a l’echeancier
* - si un caissier est libre, il sert le client
* - sinon, le client fait la queue dans la file d’attente
***************************************************************************/
void Arrivee :: fire() {
// cerr << "Il est " << _time << " : arrivee\n";
Banque * s = (Banque*) ds;
Client * c = new Client(_time,s);
double next = _time + Poisson::next(s->tempsMoyenEntreArrivees());
if (next < s->dureePrevue())
s->add(new Arrivee(next,s));
Caissier * cs = s->unCaissierLibre();
if (cs)
cs->servir(c);
else
s->fileAttente()->ajouter(c);
}

/***************************************************************************/

3.3 La classe Banque


L’interface

/****************************************************************************
*
* $Id: Banque.C 1664 2009-03-05 14:52:22Z phil $
*
****************************************************************************/

static char rcsId[] = "@(#) $Id: Banque.C 1664 2009-03-05 14:52:22Z phil $";

#include "Banque.h"
#include "FileAttente.h"
#include "Caissier.h"
#include "Poisson.h"
#include "Arrivee.h"

7
/***************************************************************************
* La banque est responsable de la creation des caissiers et de la file.
* dans cette version, pas de mise sous forme canonique
***************************************************************************/
Banque :: Banque(double dp, int nbC, double *tms, double tma) {
_file = new FileAttente(this);
_caissiers = new Caissier*[nbC];
_nbCaissiers = nbC;
_dureePrevue = dp;
_tempsMoyenEntreArrivees = tma;
add(new Arrivee(Poisson::next(tma),this));
Poisson::init(); // initialisation generateur aleatoire
for (int i=0; i<nbC;i++)
_caissiers[i] = new Caissier(tms[i],this);
}

/***************************************************************************
* retourne le premier caissier disponible, ou 0 si tous pris
* (implemente donc l’hypothese du client paresseux)
***************************************************************************/
Caissier * Banque :: unCaissierLibre() {
for (int i = 0; i < _nbCaissiers; i++)
if (_caissiers[i]->estLibre()) return _caissiers[i];
return 0;
}

/***************************************************************************
* somme des clients servis par les differents caissiers
***************************************************************************/
int Banque :: nbClientsServis() {
int res = 0;
for (int i = 0; i< _nbCaissiers; i++) {
res += _caissiers[i]->nbClientsServis();
}
return res;
}

/***************************************************************************/

L’implémentation
/****************************************************************************
*
* $Id: Banque.C 1664 2009-03-05 14:52:22Z phil $
*
****************************************************************************/

static char rcsId[] = "@(#) $Id: Banque.C 1664 2009-03-05 14:52:22Z phil $";

#include "Banque.h"
#include "FileAttente.h"
#include "Caissier.h"

8
#include "Poisson.h"
#include "Arrivee.h"

/***************************************************************************
* La banque est responsable de la creation des caissiers et de la file.
* dans cette version, pas de mise sous forme canonique
***************************************************************************/
Banque :: Banque(double dp, int nbC, double *tms, double tma) {
_file = new FileAttente(this);
_caissiers = new Caissier*[nbC];
_nbCaissiers = nbC;
_dureePrevue = dp;
_tempsMoyenEntreArrivees = tma;
add(new Arrivee(Poisson::next(tma),this));
Poisson::init(); // initialisation generateur aleatoire
for (int i=0; i<nbC;i++)
_caissiers[i] = new Caissier(tms[i],this);
}

/***************************************************************************
* retourne le premier caissier disponible, ou 0 si tous pris
* (implemente donc l’hypothese du client paresseux)
***************************************************************************/
Caissier * Banque :: unCaissierLibre() {
for (int i = 0; i < _nbCaissiers; i++)
if (_caissiers[i]->estLibre()) return _caissiers[i];
return 0;
}

/***************************************************************************
* somme des clients servis par les differents caissiers
***************************************************************************/
int Banque :: nbClientsServis() {
int res = 0;
for (int i = 0; i< _nbCaissiers; i++) {
res += _caissiers[i]->nbClientsServis();
}
return res;
}

/***************************************************************************/

3.4 La classe Depart


L’interface

/****************************************************************************
*
* $Id: Depart.C 1665 2009-03-05 16:02:45Z phil $
*
****************************************************************************/

static char rcsId[] = "@(#) $Id: Depart.C 1665 2009-03-05 16:02:45Z phil $";

9
#include <iostream>
#include "Depart.h"
#include "Banque.h"
#include "Client.h"
#include "Caissier.h"
#include "FileAttente.h"
using namespace std;

/***************************************************************************
* lors de la fin du service d’un caissier,
* - si la file est vide, le caissier attend
* - sinon,
* - le premier client quitte la file
* - le caissier le sert
***************************************************************************/
void Depart :: fire() {
// cerr << "Il est " << _time << " : depart\n";
Banque * s = (Banque*) ds;
if (s->fileAttente()->estVide()) _caissier->liberer();
else {
Client * c = s->fileAttente()->retirer();
_caissier->servir(c);
delete c;
}
}

/***************************************************************************/

L’implémentation
/****************************************************************************
*
* $Id: Depart.C 1665 2009-03-05 16:02:45Z phil $
*
****************************************************************************/

static char rcsId[] = "@(#) $Id: Depart.C 1665 2009-03-05 16:02:45Z phil $";

#include <iostream>
#include "Depart.h"
#include "Banque.h"
#include "Client.h"
#include "Caissier.h"
#include "FileAttente.h"
using namespace std;

/***************************************************************************
* lors de la fin du service d’un caissier,
* - si la file est vide, le caissier attend
* - sinon,
* - le premier client quitte la file
* - le caissier le sert

10
***************************************************************************/
void Depart :: fire() {
// cerr << "Il est " << _time << " : depart\n";
Banque * s = (Banque*) ds;
if (s->fileAttente()->estVide()) _caissier->liberer();
else {
Client * c = s->fileAttente()->retirer();
_caissier->servir(c);
delete c;
}
}

/***************************************************************************/

3.5 La classe FileAttente


L’interface

/****************************************************************************
*
* $Id: FileAttente.C 1664 2009-03-05 14:52:22Z phil $
*
****************************************************************************/

static char rcsId[] = "@(#) $Id: FileAttente.C 1664 2009-03-05 14:52:22Z phil $";

#include "FileAttente.h"
#include "Banque.h"
#include "Client.h"
#include "Caissier.h"

/***************************************************************************
* constructeur:
* mise a zero des parametres internes, memorisation du lien retour
* vers la banque
***************************************************************************/
FileAttente :: FileAttente(Banque* b) {
_banque = b;
_lMax = 0;
_surface = _lMoy = _sommeTempsAttente = _precedent = 0.0;
}

/***************************************************************************
* valeur moyenne : l’integrale temporelle de la longueur sur la duree reelle
***************************************************************************/
double FileAttente :: longueurMoyenne() {
return _surface / _banque->dureeReelle();
}

/***************************************************************************
* l’ajout physique du client dans la file s’accompagne:

11
* - d’une MAJ de la longueur max le cas echeant
* - de l’ajout d’une portion de surface a la valeur de l’integrale
***************************************************************************/
void FileAttente :: ajouter(Client* c) {
int s = _clients.size();
double h = _banque->time();
_surface += s * (h - _precedent); // valeur du rectangle a ajouter
_precedent = h; // memorisation du dernier evt file
_clients.push_back(c);
if (s >= _lMax) _lMax++;
}

/***************************************************************************
* le retrait physique du client de tete s’accompagne:
* - de l’ajout d’une portion de surface a la valeur de l’integrale
***************************************************************************/
Client * FileAttente :: retirer() {
int s = _clients.size();
double h = _banque->time();
Client * res = _clients.front();
_surface += s * (h - _precedent); // valeur du rectangle a ajouter
_sommeTempsAttente += (h - res->heureArrivee());
_precedent = h; // memorisation du dernier evt file
_clients.pop_front(); // N.B. : retourne void !!
return res;
}

/***************************************************************************
***************************************************************************/
double FileAttente :: tempsMoyenAttente() {
return _sommeTempsAttente / _banque->nbClientsServis();
}

/***************************************************************************/

L’implémentation
/****************************************************************************
*
* $Id: FileAttente.C 1664 2009-03-05 14:52:22Z phil $
*
****************************************************************************/

static char rcsId[] = "@(#) $Id: FileAttente.C 1664 2009-03-05 14:52:22Z phil $";

#include "FileAttente.h"
#include "Banque.h"
#include "Client.h"
#include "Caissier.h"

/***************************************************************************
* constructeur:

12
* mise a zero des parametres internes, memorisation du lien retour
* vers la banque
***************************************************************************/
FileAttente :: FileAttente(Banque* b) {
_banque = b;
_lMax = 0;
_surface = _lMoy = _sommeTempsAttente = _precedent = 0.0;
}

/***************************************************************************
* valeur moyenne : l’integrale temporelle de la longueur sur la duree reelle
***************************************************************************/
double FileAttente :: longueurMoyenne() {
return _surface / _banque->dureeReelle();
}

/***************************************************************************
* l’ajout physique du client dans la file s’accompagne:
* - d’une MAJ de la longueur max le cas echeant
* - de l’ajout d’une portion de surface a la valeur de l’integrale
***************************************************************************/
void FileAttente :: ajouter(Client* c) {
int s = _clients.size();
double h = _banque->time();
_surface += s * (h - _precedent); // valeur du rectangle a ajouter
_precedent = h; // memorisation du dernier evt file
_clients.push_back(c);
if (s >= _lMax) _lMax++;
}

/***************************************************************************
* le retrait physique du client de tete s’accompagne:
* - de l’ajout d’une portion de surface a la valeur de l’integrale
***************************************************************************/
Client * FileAttente :: retirer() {
int s = _clients.size();
double h = _banque->time();
Client * res = _clients.front();
_surface += s * (h - _precedent); // valeur du rectangle a ajouter
_sommeTempsAttente += (h - res->heureArrivee());
_precedent = h; // memorisation du dernier evt file
_clients.pop_front(); // N.B. : retourne void !!
return res;
}

/***************************************************************************
***************************************************************************/
double FileAttente :: tempsMoyenAttente() {
return _sommeTempsAttente / _banque->nbClientsServis();
}

/***************************************************************************/

13
3.6 La classe Poisson
/****************************************************************************
*
* $Id: Poisson.h 975 2007-01-10 11:09:59Z phil $
*
****************************************************************************/

#ifndef __Poisson_h
#define __Poisson_h

/*******************************
* Generateur aleatoire de nombre reels positifs suivant une loi de Poisson.
* la loyenne est fixee par le parametre de la methode de classe next().
* par defaut, la moyenne est 1.0
*******************************/

#include <math.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

class Poisson {

public:
// permet d’avoir des resultats differents a chaque fois
// ou de forcer une meme serie aleatoire (param. seed)
static void init(int seed = 0) {
srandom(seed ? seed : getpid());
}
static double next(double moy = 1.0) {
return -log(((double)random()/RAND_MAX))*moy;
}
};

#endif

/****************************************************************************/

3.7 Le programme de test


/****************************************************************************
*
* $Id: tBanque.C 1664 2009-03-05 14:52:22Z phil $
*
****************************************************************************/

static char rcsId[] = "@(#) $Id: tBanque.C 1664 2009-03-05 14:52:22Z phil $";

#include <iostream>
#include <stdio.h>
#include "Banque.h"
#include "Caissier.h"
#include "FileAttente.h"

14
#include <string.h>
#include <stdlib.h>
using namespace std;

/***************************************************************************
* les valeurs par defaut de la simulation :
* - 2 caissiers (temps de service 1 et 1)
* - duree de 10
* - les clients arrivent tous les 0.6
*
* Ces valeurs peuvent etre modifiees sur la ligne de commande :
* $ banque [ -dp duree ] [[ -nc nbCaissiers ] -ts temps1...tempsN ] [ -ta tempsArrivees ]
* avec
* - -dp pour modifier la duree prevue
* - -nc pour modifier le nombre de caissiers (il faut alors donner les temps
* de service de tous les caissiers)
* - -ts pour modifier les temps moyens de service des caissiers
* - -ta pour modifier le temps moyen entre deux arrivees successives
***************************************************************************/

int main(int argc, char ** argv) {

// etablissement des valeurs par defaut de la simulation


int nbCaissiers = 2;
double * temps = new double[2];
double tempsArrivees = 0.6;
double duree = 10.0;

// boucle de lecture des parametres de la ligne de commande


int i = 1;
temps[0] = temps[1] = 1.0;
while (argv[i]) {
if (!strcmp(argv[i], "-dp")) sscanf(argv[i+1],"%lf",&duree);
else if (!strcmp(argv[i], "-nc")) {
sscanf(argv[i+1],"%d",&nbCaissiers);
delete [] temps;
temps = new double[nbCaissiers];
for (int i = 0; i < nbCaissiers; i++)
temps[i] = 1.0;
}
else if (!strcmp(argv[i], "-ta")) sscanf(argv[i+1],"%lf",&tempsArrivees);
else if (!strcmp(argv[i], "-ts")) {
temps = new double[nbCaissiers];
for (int j =0; j < nbCaissiers; j++)
sscanf(argv[i+1+j],"%lf",&temps[j]);
i += nbCaissiers-1;
}
else {
cerr << "usage: banque [ -dp duree ] [[ -nc nbCaissiers ] -ts temps1...tempsN ] [ -ta tempsArr
exit(1);
}
i += 2;
}

15
// affichage des valeurs des parametres de la simulation
cout << "duree : " << duree
<< "\nnbc : " << nbCaissiers
<< "\nta : " << tempsArrivees
<< "\ntps : ";
for (int i = 0; i < nbCaissiers ; i++)
cout << temps[i] << ’ ’;
cout << endl;

//////////////////////////////////////////////////////////////////////

// creation et lancement de la simulation


Banque s(duree,nbCaissiers,temps,tempsArrivees);
s.run();

// affichage des resultats


FileAttente * f = s.fileAttente();
cout << "duree Reelle : " << s.dureeReelle() << endl;
cout << "nb clients : " << s.nbClientsServis() << endl;
cout << "lg max file : " << f->longueurMax() << endl;
cout << "lg moy file : " << f->longueurMoyenne() << endl;
for (int i = 1; i <= nbCaissiers ; i++) {
cout << "caissier " << i << " : ";
Caissier * c = s.caissiers(i);
cout << c->tauxOccupation() << "%, "
<< c->nbClientsServis() << " clients\n";
}
return 0;
}

/***************************************************************************/

3.8 Le makefile
Seul le début est intéressant, les dépendances générées représentent 10 pages et ne sont pas repro-
duites:

# Makefile pour l’application ‘‘simulation banque’’


# $Id: simuBanque.lyx 1665 2009-03-05 16:02:45Z phil $
#
############################################################

.C.o :
c++ -c $<
.o:
c++ -o $@ $<

ALL = banque
all : $(ALL)

clean :
touch clean simuBanque

16
rm -f clean *.o *.aux *.log *.dvi *.toc *.tex *.tmp *~ 2> /dev/null
rm -rf $(ALL) simuBanque 2>/dev/null

OBJS = Arrivee.o Banque.o DiscreteSimulation.o Caissier.o \


Depart.o FileAttente.o tBanque.o

banque : $(OBJS)
c++ -o $@ $(OBJS) && clear && ./banque

############################################################
# gestion des dependances C++
############################################################
depend:
sed ’/^#DEP/q’ < Makefile > mk.tmp
c++ -M *.C >> mk.tmp
mv mk.tmp Makefile

#DEPENDANCES : NE PAS DETRUIRE


Arrivee.o: Arrivee.C /usr/include/c++/4.3/iostream \
/usr/include/c++/4.3/i486-linux-gnu/bits/c++config.h \
/usr/include/c++/4.3/i486-linux-gnu/bits/os defines.h \
[...]

4 Une sortie du programme réalisé


bash-2.04$ banque
duree : 10
nbc : 2
ta : 0.6
tps : 1 1
duree Reelle : 11.2335
nb clients : 21
lg max file : 4
lg moy file : 1.12115
caissier 1 : 92.0221%, 11 clients
caissier 2 : 83.6479%, 10 clients
bash-2.04$ banque -dp 100 -nc 3 -ts 2 2 2
duree : 100
nbc : 3
ta : 0.6
tps : 2 2 2
duree Reelle : 113.113
nb clients : 184
lg max file : 25
lg moy file : 12.9794
caissier 1 : 99.0303%, 67 clients
caissier 2 : 99.0375%, 62 clients
caissier 3 : 98.1438%, 55 clients
bash-2.04$

17
Contents
1 Rappel du sujet 1

2 Modèle UML initial 2

3 Le code source de l’application 3


3.1 Le pattern “simulation discrete” . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
3.1.1 La classe Event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
3.1.2 La classe DiscreteSimulation . . . . . . . . . . . . . . . . . . . . . . . . . 4
3.2 La classe Arrivee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.3 La classe Banque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.4 La classe Depart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.5 La classe FileAttente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.6 La classe Poisson . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.7 Le programme de test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.8 Le makefile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

4 Une sortie du programme réalisé 17

18

Vous aimerez peut-être aussi