Les dette før du begynner på oppgaven.


KØSYSTEM PÅ PASSKONTOR

I denne eksamensoppgaven skal du lage et java-program som håndterer køen av kunder på et passkontor i en større by, tilsvarende det vi har på politihuset i Oslo. Passkontoret har stor pågang av kunder som trenger nytt pass, og i travle perioder kan ventetiden bli lang. En av utfordringene for de ansatte er å håndtere køen av kunder på en god måte.
Når man kommer inn på passkontoret møter man en kølappautomat med to knapper. Skal man søke om pass, trykker man på knappen for det, skal man hente pass trykker man på den andre knappen. Godt synlig i lokalet står det en opplysningstavle som viser hvilket kølappnummer som står for tur til å bli ekspedert, hvilken type kølapp det gjelder og hvilken luke kunden med kølappen skal gå til. Bildene under viser brukergrensesnittene til klassene som simulerer henholdsvis kølappautomaten (til venstre) og opplysningstavlen (til høyre).

Ekspederingen av passkundene er fordelt på 15 luker. Lukene er av to typer. 12 av dem er reservert for kunder som skal søke om pass, mens i de resterende 3 blir det kun levert ut ferdige pass. På neste side ser du to bilder av brukergrensesnittet til klassen som simulerer lukene.

       

På rammen står det enten"Søke pass" eller "Hente pass", alt etter hva slags luke det dreier seg om. Øverst på displayet står det lukens nummer, og deretter står det nummer på kølappen som skal ekspederes. Når saksbehandleren er ferdig med en kunde og klar for neste, trykker vedkommende på "Ekspeder neste"-knappen.

Programmet består av den abstrakte superklassen Kølapp, subklassene SøkeKølapp og HenteKølapp, klassen som inneholder en array med kølapper, klassen KøSystem som inneholder to køer (søke-kø og hente-kø), klassen KølappAutomat som simulerer kølappautomaten, klassen Luke som simulerer en luke der kunder blir ekspedert, klassen LukeArray som inneholder en array av luker, klassen OpplysningsTavle som simulerer opplysningstavlen og til slutt driverklassen Passkontor som inneholder main-metoden. Som du ser er det mange klasser, men til gjengjeld er det svært få metoder i hver klasse. De enkelte oppgavene inneholder nærmere informasjon.

OPPGAVE 1

Den abstrakte superklassen Kølapp har to konkrete subklasser SøkeKølapp og HenteKølapp. I denne oppgaven skal du programmere klassene Kølapp og SøkeKølapp. (Klassekroppene i de to subklassene vil bli identiske, og derfor holder det å programmere den ene her. Det er likevel nødvendig å ha begge subklassene med i det endelige programmet. )

Superklassen Kølapp skal kun ha følgende datafelt og metoder:

a) Programmer klassen Kølapp.

Subklassen SøkeKølapp skal kun ha følgende datafelt og konstruktør:

b) Programmer klassen SøkeKølapp.

OPPGAVE 2

I denne oppgaven skal du programmere metoder i klassen . Du kan forutsette at kølappene befinner seg kontinuerlig etter hverandre i arrayen. Nedenfor ser du en skisse av klassen.

public class Kø
{
  private Kølapp[] kø;
  private int antall = 0;  // antall kølapper som er satt inn i arrayen
  private int neste = 0;   // indeks for kølapp som står for tur til å
                           // bli ekspedert

  < Konstruktør som skal opprette arrayen kø.
    Lengden på arrayen skal mottas som parameter. >

  public boolean tomKø()
  {
    < Hvis køen er tom, skal metoden returnere true,
      i motsatt fall skal den returnere false. >
  }

  public boolean settIKø( Kølapp k )
  {
    < Metoden skal sette parameteren k inn i arrayen, under
      forutsetning av at det er plass. Hvis så er tilfelle,
      skal metoden returnere true, i motsatt fall skal den
      returnere false. (NB! Når en person trekker en kølapp,
      vil denne metoden bli kalt opp.) >
  }

  public int ekspeder()
  {
    < Metoden skal returnere nummeret tilhørende kølappen
      som står for tur til å bli ekspedert, under forutsetning
      av at det står noen i kø. Hvis køen er tom, skal metoden
      returnere -1. >
  }

} // end of class Kø

a) Programmer

b) Programmer metoden settIKø(Kølapp k).

c) Programmer metoden ekspeder().

OPPGAVE 3

I denne oppgaven skal du programmere metoder i klassen KøSystem. Foruten konstantene SØKE_PASS og HENTE_PASS har klassen to -objekter: et som skal håndtere køen av personer som skal søke om pass, og et annet som skal håndtere køen av personer som skal hente pass. Nedenfor ser du en skisse av klassen.

public class KøSystem
{
  public static final int SØKE_PASS = 1, HENTE_PASS = 2;

  Kø søkeKø, henteKø;

  < Konstruktør som skal opprette objektene søkeKø og henteKø.
    Lengden på arrayene i Kø-objektene skal mottas som parametre.
    Disse kan være av forskjellig lengde. >

  public boolean tomKø( int type )
  {
    < Hvis køen, av den typen som parameteren type angir, er tom,
      skal metoden returnere true. I motsatt fall skal metoden
      returnere false. >
  }

  public int trekkKølapp( int type )
  {
    < Metoden skal opprette et kølapp-objekt, av den typen som
      parameteren type angir, og så sette det inn i riktig kø, under
      forutsetning av at dette lar seg gjøre. Metoden skal deretter
      returnere kølappens nummer. Hvis det ikke lar seg gjøre å sette
      inn kølappen, skal metoden returnere -1. >
  }

  public int ekspeder( int type )
  {
    < Metoden skal returnere nummeret til kølappen som står
      for tur til å bli ekspedert i den type kø som parameteren
      type angir. Hvis denne køen er tom, skal metoden returnere -1. >
  }

}// end of class KøSystem

a) Programmer

b) Programmer metoden trekkKølapp( int type ).

c) Programmer metoden ekspeder( int type ).

OPPGAVE 4

Over ser du et bilde av brukergrensesnittet til klassen KølappAutomat,
og under finner du en skisse av klassen.

< import-setninger >

public class KølappAutomat extends JFrame
{
  private JButton søkePass, hentePass;
  private JTextField kønr;
  private KøSystem ks;

  public KølappAutomat( KøSystem k, String s )
  {
    super( s );  // Rammeteksten
    ks = k;
    < Setter opp brukergrensesnittet. >
    Knappelytter lytter = new Knappelytter();
    søkePass.addActionListener( lytter );
    hentePass.addActionListener( lytter );
  }

  public void melding( JTextField tf, Color c, int str, String tekst )
  {
    tf.setFont(new Font("Times", Font.BOLD, str));
    tf.setBackground( c );
    tf.setText(tekst);
  }

  <  Privat lytteklasse  som fanger opp klikkene på knappene
     "SØKE PASS" og "HENTE PASS". Lytteklassen skal sørge for at
     kølapp-objekt av riktig type settes inn i køsystemet. Klikkene
     tilsvarer det å trekke en kølapp, og kølappens nummer skal
     vises i tekstfeltet. >

} // end of class KølappAutomat

a) Programmer den private lytteklassen Knappelytter.

OPPGAVE 5

Over ser du et bilde av brukergrensesnittet til klassen OpplysningsTavle,
og under finner du en skisse av klassen.

< import-setninger >

public class OpplysningsTavle extends JFrame
{
  private JTextField typefelt, nrfelt, lukefelt;
  private KøSystem ks;

  public OpplysningsTavle( KøSystem k, String s )
  {
    super( s );
    ks = k;
    < Setter opp brukergrensesnittet. >
  }

  public void melding( JTextField tf, Color c, int str, String tekst )
  {
    < Som beskrevet i klassen KølappAutomat. >
  }

  public int ekspederNeste( int lukeNr, int luketype )
  {
    < Metoden blir kalt når det i en luke klikkes på "Ekspeder neste"-knappen
      (se oppgave 6). Metoden mottar lukens nummer og type som parametre, og
      skal sørge for at neste kunde med kølapp av riktig type blir ekspedert,
      under forutsetning av at det står noen i denne køen.
      Hvis dette er tilfelle skal opplysningstavlen oppdateres:
      - I det øveste tekstfeltet skal det skrives "Søke pass" eller "Hente pass",
      avhengig av parameteren luketype.
      - I det midterste tekstfeltet skal det skrives "Kølapp" etterfulgt av
      kølappens nummer.
      - I det nederste skal det skrives "Gå til luke" etterfulgt av lukens
      nummer.
      Til slutt skal metoden returnere kølappens nummer. Hvis køen
      (av den aktuelle typen) er tom, skal metoden returnere -1. >
  }

} // end of class OpplysningsTavle

a) Programmer metoden ekspederNeste( int lukeNr, int luketype ).

OPPGAVE 6

       

Over ser du to bilder av brukergrensesnittet til klassen Luke.
For hver luke skal lukens type, lukens nummer og navnet på saksbehandleren lagres. I tillegg er det et datafelt, antallKunder, som skal holde rede på hvor mange kunder saksbehandleren til enhver tid har ekspedert. Under finner du en skisse av klassen:

< import-setninger >

public class Luke extends JFrame
{
  private int lukeType;
  private int lukeNr;
  private String saksbehandler;
  private int antallKunder;

  private JButton ekspeder;
  private JTextField lukefelt, nrfelt;
  private OpplysningsTavle tavle;

  public Luke(String navn, int type, int nr, OpplysningsTavle ot )
  {
    super( ( type == KøSystem.SØKE_PASS ) ? "Søke pass" :  "Hente pass" );

    saksbehandler = navn;
    lukeType = type;
    lukeNr = nr;
    tavle = ot;

    antallKunder = 0;

    Knappelytter lytter = new Knappelytter();
    ekspeder.addActionListener( lytter );
   <  Setter opp brukergrensesnittet. >
  }

  public void melding(JTextField tf, Color c, int str, String tekst)
  {
    < Som beskrevet i klassen KølappAutomat. >
  }

  < get-metoder for saksbehandler og antallKunder >

  < toString()-metode  som skal returnere verdiene til datafeltene
    lukeNr, saksbehandler og antallKunder i form av en tekst. >

  public void ekspederNesteKunde()
  {
    < Metoden bli kalt når saksbehandleren i luka klikker på
      "Ekspeder neste"- knappen. Metoden skal sørge for at opplysningstavlen
      i lokalet blir oppdatert, slik det er beskrevet i "ekspederNeste"-metoden
      i oppgave 5. I tillegg skal lukens eget tekstfelt "lukefelt"  oppdateres
      med kølappnummeret til neste kunde som skal ekspederes. Hvis det ikke
      står noen i kø, skal dette tekstfeltet blankes ut. >
  }

  < Privat lytteklasse som kaller ekspederNesteKunde()
    når det klikkes på "Ekspeder neste"- knappen. >

} // end of class Luke

a) Programmer

b) Programmer metoden ekspederNesteKunde().

OPPGAVE 7

Som nevnt i oppgavens innledning, er det til tider stor pågang av kunder som ønsker nytt pass. Av denne grunn ønsker arbeidsgiveren å få informasjon om hvor mange passøknader som er behandlet i løpet av en dag, gjennomsnittlig antall passøknader pr luke, hvilken saksbehandler som har behandlet flest søknader, og rangering av saksbehandlerne (lukene) ut fra hvor mange søknader hver har behandlet i løpet av arbeidsdagen. Metoden skrivStatistikk() presenterer den ønskede informasjonen i et dialogvindu og blir kalt opp fra når programmet avsluttes: (se windowClosing-metoden i hovedprogrammet til slutt i oppgaven.)

Nedenfor ser du en skisse av klassen LukeArray.

< import-setninger >

public class LukeArray
{
  private Luke[] lukene;

  public LukeArray(OpplysningsTavle tavle, int type, int startnr, String[] navn)
  {
    < Konstruktøren skal opprette Luke-arrayen. Denne skal være like lang
      som lengden på String-arrayen som mottas som parameter. Deretter skal
      lukearrayen fylles med Luke-objekter. Lukene skal nummereres etter økende
      nummer, der parameteren "startnr" angir nummeret til det første
      Luke-objektet som settes inn i arrayen. >
  }

  public int totaltAntallKunder()
  {
    < Metoden skal returnere det totale antall kunder som er blitt eksedert
      i lukene tilsvarende Luke-objektene i arrayen. >
  }

  public double snittAntallKunderPrLuke()
  {
    < Metoden skal beregne og returnere gjennomsnittlig antall kunder som
      er blitt ekspedert i lukene tilsvarende Luke-objektene i arrayen. >
  }

  public Luke flestKunder()
  {
    < Metoden skal returnere det Luke-objektet som tilsvarer luken der det
      er behandlet flest kunder. >
  }

  public String dagensSaksbehandler()
  {
    < Saksbehandleren som har ekpedert flest kunder blir kåret til
      "Dagens saksbehandler". Metoden skal returnere navnet til vedkommende. >
  }

  public void sortertArray()
  {
    < Metoden skal sortere Luke-objektene i arrayen etter antall ekspederte
      kunder, slik at det Luke-objektet som tilsvarer luken der det er
      behandlet flest kunder står først. (Sorteres etter minkende antall.) >
  }

  public String toString()
  {
    < Metoden skal returnere all informasjon som er lagret i Luke-objektene
      i arrayen. Informasjonen skal skrives ut i sortert rekkefølge
      etter sorteringskriteriene som er beskrevet i sortertArray()-metoden.  >
  }

  public void skrivStatistikk()
  {
    < Viser dialogvinduet som det er bilde av på forrige side.
      Denne metoden skal du IKKE programmere. >
  }

} // end of class LukeArray

a) Programmer klassens konstruktør.

b) Programmer metodene

c) Programmer metodene

d) Programmer metoden sortertArray().

e) Programmer metoden toString().

 

SLUTT PÅ OPPGAVENE

 

Til orientering er klassen Passkontor, som inneholder main-metoden, lagt ved:

< import-setninger >

public class Passkontor
{
  public static void main( String[] args )
  {
    KøSystem køene = new KøSystem(100, 50);

    OpplysningsTavle tavle = new OpplysningsTavle(køene, "");

    String[] saksbehandlere1 =
    {"Olsen", "Hansen", "Berg","Johansen", "Lie", "Andersen", "Kielland", "Moe"};

    final LukeArray søkelukene =
       new LukeArray(tavle,  KøSystem.SØKE_PASS, 1, saksbehandlere1);

    String[] saksbehandlere2 = { "Jensen", "Furuholmen", "Harket"};

    final LukeArray hentelukene =
         new LukeArray(tavle, KøSystem.HENTE_PASS,
                       saksbehandlere1.length + 1,saksbehandlere2);

    KølappAutomat automat = new KølappAutomat(køene, "Kølappautomat");

    tavle.addWindowListener(
      new WindowAdapter() {
      public void windowClosing( WindowEvent e )
      {
        søkelukene.skrivStatistikk();
        System.exit( 0 );
      }
     } );

  } // end of main

}// end of class Passkontor