Les gjennom hele oppgavesettet før du begynner å besvare deloppgavene.
Som student bruker du sikkert kollektive transportmidler i Oslo og er kjent med Ruters billettsystem for kollektivtrafikken. Ruter har, etter mange år, omsider fått sitt nye billettsystem til å virke. Du får nå i oppgave å lage et tilsvarende billettsystem, som vi her kan kalle Ruter#PLUSS. Systemet skal lages i java og ha tilsvarende funksjonalitet. For at oppgaven ikke skal bli alt for stor (du har jo bare 5 timer, mens Ruter brukte mange år!) skal vi holde oss til Ruters sone 1, dvs. lage et system som gjelder for reiser innenfor Oslos grenser. Videre skal vi begrense oss til tre typer reisekort (billetter) som vi gir nye navn: Det som Ruter kaller for smartbillett heter her Klippekort, det som Ruter kaller for 24-timersbillett heter her Dagskort og det som Ruter kaller for 30-dagersbillett heter her Månedskort. Ruter#PLUSS skal imidlertid bygges opp på en slik måte at det lett vil kunne utvides med både flere billettyper og soner.
Programmet består av et klassehierarki med superklassenReisekort, og subklassene
Klippekort, Dagskort og Månedskort.
Klassen ReisekortSystem utgjør, sammen med klassehierarkiet, programmets datastruktur.
Programmet skal ha tre vinduer, et for salg av reisekort, et som simulerer billettkontrollen der kortene valideres,
og et vindu beregnet på administrasjonen. De tre vindusklassene er Reisekortsalg, Kontrollvindu og Administrasjonsvindu.
Klassen RuterPluss er programmets driverklasse og inneholder main-metoden.
Den administrative delen i programmet skal lagre opplysninger om hvor
mange kort som er solgt av de forskjellige korttypene, hvor mye det er solgt for (i antall kroner)
av de forskjellige korttypene, og hvor mye det er solgt reisekort for totalt.Klippekort, et Dagskort eller et Månedskort.
Du skal i denne deloppgaven fullføre definisjonen av den abstrakte superklassen ReiseKort,
klassen som skal være superklassen for de forskjellige korttypene.
Nedenfor ser du en skisse av klassen:
import java.util.Calendar;
import java.text.DateFormat;
public abstract class Reisekort
{
private Calendar utløpstidspunkt; // Blir tildelt verdi når kortet valideres
< kortNr - et unikt nummer som identifiserer hvert enkelt reisekort >
< pris - hva kortet koster i hele kroner >
< hjelpevariabel for å generere et unikt kortNr >
< konstruktør som mottar prisen som parameter og som
tildeler reisekortet et unikt kortNr >
< set-metode for utløpstidspunkt >
< get-metoder for kortNr, pris og utløpstidspunkt >
public String gyldigTil()
{
if ( utløpstidspunkt == null )
return null;
DateFormat tf = DateFormat.getDateTimeInstance
( DateFormat.LONG, DateFormat.MEDIUM );
return tf.format(utløpstidspunkt.getTime());
}
public boolean gyldig() // Metoden vil bli redefinert av subklassene
{
Calendar nå = Calendar.getInstance();
return nå.before( utløpstidspunkt );
}
} // end of class Reisekort
a)
Fullfør definisjonen av Reisekort ved å erstatte all pseudo-kode med java-instruksjoner.
De neste to deloppgavene går ut på å programmere metoder i klassen
Klippekort. Et Klippekort er et verdikort der man setter inn penger.
Hver gang man foretar en reise, skal kortet valideres i billettkontrollen. Hvis det er nok
penger på klippekortet, er kortet gyldig som billett i en time.
Et reisekort kan "lades opp" ved at man setter inn penger på kortet.
I den neste oppgaven vil du få bruk for å kunne lagre et tidspunkt.
Til dette kan du bruke et Calendar-objekt som du oppretter ved å skrive:
Calendar dato = Calendar.getInstance();Hvis du ønsker å øke tidspunktet
dato med en time, skriver du:
dato.add( Calendar.HOUR_OF_DAY, 1 );
Nedenfor ser du en skisse av denne klassen:
import java.util.Calendar;
public class Klippekort extends Reisekort
{
public static final int PRIS_PER_REISE = 28;
private int saldo; // beløpet som til enhver tid er igjen på klippekortet
private static int antallSolgte = 0; // Det totale antall solgte klippekort
private static int sumAlleKlippekort = 0; // Den totale summen som er satt inn
// på alle klippekortene til sammen.
< Konstruktør som mottar det beløpet som skal settes inn på kortet
ved opprettelsen av det. Foruten å sørge for å initialisere klassens
datafelt, skal den også sørge for å oppdatere antall solgte klippekort
og ikke minst summen det er solgt klippekort for så langt. >
< get-metoder for saldo, sumAlleKlippekort og antallSolgte >
public boolean gyldig() // Blir redefinert her!
{
< Metoden kalles hver gang man skal foreta en reise med klippekortet.
Kortet er gyldig hvis det brukes innen utløpstidspunktet. (Det er gyldig
i en time etter at man har betalt.) Hvis kortet brukes etter
utløpstidspunktet, skal metoden sjekke om det er nok penger på kortet
til å foreta reisen. I så fall er kortet også gyldig og nytt
utløpstidspunkt må settes i tillegg til at saldoen reduserer.
Returverdien skal angi utfallet av valideringen. >
}
public void ladOpp( int beløp )
{
< Metoden over skal øke saldoen på kortet med det beløpet som
parameteren angir og oppdatere datafeltet sumAlleKlippekort. >
}
} // end of class Klippekort
b) Programmer klassens konstruktør og alle get-metodene.
c) Programmer metodene public boolean gyldig() og public void ladOpp( int beløp ).
Klassene Dagskort og Månedskort skal ikke programmeres, men
du vil få bruk for dem senere i oppgaven. Et dagskort er gyldig som billett i 24 timer etter at
det er opprettet, mens et månedskort er gyldig i 30 dager etter opprettelsen.
Du trenger ikke å vite noe om hvordan klassene
er implementert, men du må vite hva metodene gjør, hvilke parametere de har og hva de returnerer.
Nedenfor ser du skisser av klassene, med deres public datafelt og metoder.
public class Dagskort < arver Reisekort >
{
public final static int DAGSPRIS = 75;
< private datafelt >
public Dagskort() { ... }
public static int getSumAlleDagskort() { ... }
public static int getAntallSolgte() { ... }
public boolean gyldig() { ... } // redefinert
} // end of class Dagskort
public class Månedskort < arver Reisekort >
{
public final static int MÅNEDSPRIS = 1040;
< private datafelt >
public Månedskort() { ... }
public static int getSumAlleMånedskort() { ... }
public static int getAntallSolgte() { ... }
public boolean gyldig() { ... } // redefinert
} // end of class Månedskort
ReisekortSystem, som er skissert nedenfor, lagrer alle reisekortene i en array.
I utgangspunktet er det plass til 100 reisekort. Arrayens størrelse skal imidlertid
kunne økes etter behov slik at salget av reisekort ikke begrenses. Nedenfor ser du en
skisse av klassen:
public class ReisekortSystem
{
public static final int = ANTALL 100;
public static final int UTVIDELSE = 10;
private Reisekort[] reisekortene;
public ReisekortSystem()
{
< Oppretter arrayen med lengde lik ANTALL. >
}
public Reisekort finnReisekort(int nr)
{
< Metoden skal returnere (en referanse/peker til) det reisekortet
i arrayen som har kortNr lik den innkomne parameteren nr.
Hvis kortet ikke finnes i arrayen, skal metoden returnere null.>
}
public void utvidArray()
{
< Metoden skal utvide arrayen med så mange elementer som konstanten
UTVIDELSE angir. Metoden vil bli kalt når det er behov for å utvide
arrayen i forbindelse med innsetting av et nytt reisekort. >
}
public void settInnReisekort(Reisekort k)
{
< Metoden mottar et nytt reisekort som parameter og skal sette dette
inn på første ledige plass i arrayen, under forutsetning av at det
ikke finnes et reisekort med samme nr i arrayen fra før.
Hvis arrayen er full, skal den først utvides med så mange
elementer som konstanten UTVIDELSE angir, og deretter skal kortet
settes inn. >
}
public Klippekort ladOppKlippekort( int nr, int beløp )
{
< Hvis det finnes et klippekort med kortNr lik den innkomne parameteren nr,
skal metoden øke saldoen på dette kortet med så mye som parameteren
beløp angir, og deretter returnere (en referanse/peker til) klippekortet.
Hvis det ikke finnes et slikt klippekort, skal metoden returnere null. >
}
public static String inntjeningsInfo()
{
< Metoden skal returnere en tekst som inneholder informasjon om hvor mange
reisekort det er solgt av de forskjellige typene, hvor mye som er tjent inn
på hver type, og hvor mye som er tjent inn totalt. >
}
} // end of class ReisekortSystem
a) Programmer klassens konstruktør og metoden public Reisekort finnReisekort(int nr).
b) Programmer metoden public void utvidArray().
c) Programmer metoden public void settInnReisekort(Reisekort k).
d) Programmer metoden public Klippekort ladOppKlippekort( int nr, int beløp ).
e) Programmer metoden public static String inntjeningsInfo().
a) Programmer vindusklassen Administrasjonsvindu, slik at vinduet
blir seende ut som på bildet. Klassen skal være sin egen lytteklasse og programmeres slik
at når du klikker på knappen "Salgsinformasjon" blir den informasjonen som returneres fra
inntjeningsInfo()-metoden i klassen ReisekortSystem vist i tekstområdet.
Nedenfor ser du en skisse av klassen Kontrollvindu:
< import-setninger >
public class Kontrollvindu < ... >
{
private JTextField kortIdFelt;
private JTextArea display;
private JButton kontroll;
private ReisekortSystem kortsystem;
public Kontrollvindu(ReisekortSystem r)
{
< kaller superklassens konstruktør >
kortsystem = r;
< oppretter lytteobjekt og knytter knappen til det. >
< setter opp brukergrensesnittet >
}
public void kontrollerReisekort()
{
< Metoden må lese inn kortets nummer og sjekke om det finnes
blandt de registrerte kortene. Hvis det finnes og det er gyldig,
skal følgende gjøre:
- Hvis det er et klippekort, skal prisen for en reise trekkes fra
saldoen på kortet. Deretter skal det skrives ut i tekstområde hva
reisen koster, hva som er saldoen etter at reisen er betalt og hvor
lenge billetten varer.
- Hvis det er et dagskort eller et månedskort skal det kun skrives ut
hvor lenge billetten varer.
Hvis kortet er ugyldig, skal dette skrives i tekstområdet.
For klippekort skal i tillegg saldoen skrives ut.
Hvis kortet er ukjent, skal dette skrives i tekstområdet.>
}
< privat lytteklasse >
} // end of class Kontrollvindu
a) Programmer metoden public void kontrollerReisekort()
Reisekortsalg.
Denne klassen brukes til salg av reisekort og opplading av klippekort.
Nedenfor ser du en skisse av klassen:
< import-setninger >
public class Reisekortsalg < ... >
{
private static final int KLIPP = 1, DAG = 2, MÅNED = 3;
private JTextField kortNrFelt, betalingsFelt, beløpsFelt;
private JButton klipp, dag, mnd, ladeknapp;
private JTextArea info;
private Lytter lytter;
private ReisekortSystem kortsystem;
public Reisekortsalg(ReisekortSystem k)
{
super("KORTSALG");
kortsystem = k;
lytter = new Lytter();
< oppretter skjermkomponenene >
klipp.addActionListener(lytter);
dag.addActionListener(lytter);
mnd.addActionListener(lytter);
ladeknapp.addActionListener( lytter );
< setter opp brukergrensesnittet. >
}
public void nyttReisekort(int type)
{
< Metoden skal foreta et salg av et reisekort av typen parameteren type angir.
(Se konstantene i skissen av klassen over.) Når kortet er opprettet og satt
inn i datasystemet, skal metoden skrive ut kortets nummer i tekstfeltet
kortNrFelt og prisen som skal betales i tekstfeltet betalingsFelt. >
}
public void ladOppKlippekort()
{
< Metoden skal lade opp klippekortet med det beløpet som brukeren skriver
inn, under forutsetning av at kortnummerer som oppgis tilhører et
klippekort i datasystemet. I så fall skal den nye saldoen skrives ut
i et dialogvindu (JOptionPane.showMessageDialog(..)), og prisen som skal
betales skrives i betalingsfeltet. Hvis kortnummeret er feil skal det
skrives "error" i betalingsfeltet. >
}
< privat lytteklasse >
} // end of class Reisekortsalg
a) Programmer metoden public void nyttReisekort(int type).
b) Programmer metoden public void ladOppKlippekort().
c) Programmer den private lytteklassen slik at den fanger opp klikkene på knappene
og sørger at riktig oppgave blir utført.
RuterPluss. Klassen skal inneholde main-metoden,
der programutførelsen starter.