import java.io.*;
import java.util.LinkedList;

abstract class Ereignis implements Comparable
{
    float z;
    String name;

    abstract void bearbeite();

    Ereignis(float zeitpunkt) {z = zeitpunkt; }

    public int compareTo(Object o)
    {	float zdif = z - ((Ereignis)o).z;
        if (zdif>0) return +1;
        if (zdif<0) return -1;
	return 0;
    }

    void print_trace() { System.out.println(z + " "+ name); }
}


class SchiliftSimulation
{
    LiftSchlange TalSchlange;
    PWSchlange ereignisse;
    Schifahrer s[];
    boolean einganggeschlossen;
    boolean LiftInBetrieb;

    static int AnzSchifahrer = 50;
    final boolean trace = true;

SchiliftSimulation()
{
    // Initialisierung:
    ereignisse = new Halde(1000);
    TalSchlange = new LiftSchlange();
    s = new Schifahrer[AnzSchifahrer];
    for (int i=0; i<AnzSchifahrer; i++)
	{
	    s[i] = new Schifahrer(i+1);
	    TalSchlange.anstellen(s[i]);
	}

    // Anfangsereignisse erzeugen:
    // Liftbetrieb von 9 bis 16 Uhr
    LiftInBetrieb = true;
    ereignisse.einfügen(new SesselBeiTalstation((float) (9.0*3600.0)));
    ereignisse.einfügen(new LiftStopp((float) (16.1*3600.0)));

    einganggeschlossen = false;
    ereignisse.einfügen(new Betriebsschluss((float) (16*3600.0)));


    // Hauptschleife:
    while (!ereignisse.istleer())
	{
	    Ereignis e = (Ereignis) (ereignisse.entferneMin());
	    e.bearbeite();
	}

    // Ausgabe Statistik, usw.
    // ...
}

class SesselBeiTalstation extends Ereignis
{
    
    SesselBeiTalstation(float zeitpunkt)  {
	super(zeitpunkt);
	name = "Sessel bei Talstation.";
    }
    void bearbeite()
    {
	if (!LiftInBetrieb)  { return; }
	if(trace) print_trace();
	if (!TalSchlange.istleer()) {
	    Schifahrer f= TalSchlange.entferneErstes();
	    if(trace)
               System.out.println("         nimmt Schifahrer " + f.name + " mit.");
	    ereignisse.einfügen( new AnkunftAmBerg(f, z+300));
	    // Fahrzeit 5 Minuten
	}
	ereignisse.einfügen(new SesselBeiTalstation(z+10));
    }
}

class AnkunftAmBerg extends Ereignis
{
    Schifahrer f;
    AnkunftAmBerg(Schifahrer f1, float zeitpunkt)
    {
	super(zeitpunkt); f = f1;
	name = "Schifahrer " + f.name + " kommt am Berg an.";
    }
    void bearbeite()
    {
	if(trace) print_trace();
	float DauerDerTalfahrt = (float) (60.0*(5 + 9*Math.random()));
	// zufällige Dauer der Abfahrt:
	// gleichverteilt im Intervall zwischen 5 und 14 Minuten
	ereignisse.einfügen( new AnkunftImTal(f, z+ DauerDerTalfahrt));
    }
}

class AnkunftImTal extends Ereignis
{
    Schifahrer f;

    void bearbeite()
    {
	if (trace) print_trace();
	if (!einganggeschlossen) TalSchlange.anstellen(f);
	// else go home.
    }

    AnkunftImTal(Schifahrer f1, float zeitpunkt)
    {
	super(zeitpunkt); f = f1;
	name = "Schifahrer " + f.name + " kommt bei der Talstation an.";
    }
}

class Betriebsschluss extends Ereignis
{
    Betriebsschluss(float zeitpunkt) {
        super(zeitpunkt);
	name = "======== Betriebsschluss ========";
    }
    void bearbeite()
    {   if(trace) print_trace();
	einganggeschlossen = true; 
    }
}

class LiftStopp extends Ereignis
{
    LiftStopp(float zeitpunkt) {
        super(zeitpunkt);
	name = "======== Liftstopp ========";
    }
    void bearbeite()
    {   if(trace) print_trace();
	LiftInBetrieb = false; 
    }
}

class LiftSchlange
{
    LinkedList l;
    LiftSchlange()    { l = new LinkedList();  }

    void anstellen(Schifahrer f) { l.addLast(f); }

    boolean istleer()   { return l.isEmpty(); }

    Schifahrer entferneErstes()
    {  return (Schifahrer) (l.removeFirst());  }
}
       
class Schifahrer
{
    int name;
    Schifahrer(int n) {name=n; }
}


public static void main(String[] args)
{  new SchiliftSimulation(); }

}
