/* * (c) ENSICAEN * This file is owned by ENSICAEN students. * No portion of this document may be reproduced, copied * or revised without written permission of the authors. */ import java.util.ArrayList; import java.util.List; /** * La classe de base qui contient en autre le main(). */ public final class ChaineEmbouteillage { private static final int TEMPS_FINAL = 1000; private final List _machines = new ArrayList<>(); private Depot _depot; public static void main( String[] args ) { ChaineEmbouteillage c = new ChaineEmbouteillage(); c.initialiser(); c.lancer(); c.afficherStatistiques(); } public void initialiser() { Tapis tapis1 = new TapisIntermediaire(10); Tapis tapis2 = new TapisIntermediaire(15); _machines.add(new Machine("Laveuse", new Stock(), tapis1, 3, 2, 6)); _machines.add(new Machine("Soutireuse", tapis1, tapis2, 5, 2, 6)); _depot = new Depot(); _machines.add(new Machine("Etiqueteuse", tapis2, _depot, 4, 4, 6)); } public void lancer() { for (int temps = 0; temps < TEMPS_FINAL; temps++) { for (Machine m : _machines) { m.update(temps); } } } public void afficherStatistiques() { for (Machine m : _machines) { m.afficheStatistiques(); } System.out.format("Nombre de bouteilles trait?es : %d\n", _depot.compteBouteille()); } } /** * La classe des machines d'embouteillage. */ final class Machine { private enum Etat { ATTENTE_AMONT, ATTENTE_AVAL, TRAITEMENT, PANNE }; private Etat _etat = Etat.ATTENTE_AMONT; private final String _nom; private final int _cadence; private final int _dureePanne; private final double _frequencePanne; private int _finOccupation; private int _finPanne; private final Tapis _tapisAmont; private final Tapis _tapisAval; private Bouteille _bouteille; private int _tempsInnoccupe; public Machine( String nom, Tapis amont, Tapis aval, int cadence, int dureePanne, double frequencePanne ) { _nom = nom; _frequencePanne = frequencePanne; _dureePanne = dureePanne; _cadence = cadence; _tapisAmont = amont; _tapisAval = aval; } protected void update( int temps ) { detectePanne(temps); switch (_etat) { case ATTENTE_AMONT: _bouteille = _tapisAmont.donneBouteille(); if (_bouteille != null) { _etat = Etat.TRAITEMENT; _finOccupation = temps + _cadence; } else { _tempsInnoccupe++; } break; case ATTENTE_AVAL: if (_tapisAval.prendBouteille(_bouteille)) { _bouteille = null; _etat = Etat.ATTENTE_AMONT; } else { _tempsInnoccupe++; } break; case TRAITEMENT: if (_finOccupation < temps) { _etat = Etat.ATTENTE_AVAL; } break; case PANNE: if (temps == _finPanne) { _etat = Etat.ATTENTE_AMONT; } break; } } private void detectePanne( int temps ) { boolean panne = (int) (Math.random() * _frequencePanne) == 0; if (panne) { _etat = Etat.PANNE; _finPanne = temps + _dureePanne; } } public void afficheStatistiques() { System.out.println("Machine : " + _nom); System.out.println("temps Innoccupe : " + _tempsInnoccupe); } } /* * Les tapis sont des zones de stokage et d'?change * de bouteilles entre les machines. */ abstract class Tapis { protected abstract Bouteille donneBouteille(); protected abstract boolean prendBouteille( Bouteille bouteille ); } /** * Le stock fournit les bouteilles. * Il est suppos? infini. */ final class Stock extends Tapis { @Override protected Bouteille donneBouteille() { return new Bouteille(); } @Override protected boolean prendBouteille( Bouteille bouteille ) { return false; } } /** * Le d?p?t rassemble les bouteilles usin?es. * Il est suppos? d'une capacit? infinie. */ final class Depot extends Tapis { private final List _bouteilles = new ArrayList<>(); @Override protected Bouteille donneBouteille() { return null; } @Override protected boolean prendBouteille( Bouteille bouteille ) { _bouteilles.add(bouteille); return true; } public int compteBouteille() { return _bouteilles.size(); } } /** * Un tapis interm?diaire entre deux machines est une zone * de stockage d'une capacit? d?termin?e. */ final class TapisIntermediaire extends Tapis { private final int _capacite; private final List _bouteilles = new ArrayList<>(); TapisIntermediaire( int capacite ) { _capacite = capacite; } @Override protected Bouteille donneBouteille() { if (!_bouteilles.isEmpty()) { return _bouteilles.remove(0); } return null; } @Override protected boolean prendBouteille( Bouteille bouteille ) { if (_bouteilles.size() < _capacite) { _bouteilles.add(bouteille); return true; } return false; } } /** * Une bouteille. */ final class Bouteille { }