Oblig 4 (INF1000 - V?r 2010)
FilmregisterM?l: I denne oppgaven vil du l?re hvordan man kan behandle en st?rre mengde data p? en objektorientert m?te, og f? trening i hele pensum. Oppgaven kombinerer alle programmerings-elementer vi har sett tidligere i kurset, og innf?rer datastrukturen "HashMap".
Leveringsfrist
Fredag 7. mai kl. 16.00. Leveres via Joly-systemet. (Joly kan brukes hjemmefra vha. VPN eller lignende.)Leveringskrav
L?sningen du lager skal v?re objektorientert. Det betyr at programmet skal bruke objekter av klasser du selv definerer, og interaksjon mellom disse for ? l?se de forskjellige deloppgavene. Besvarelsen m? bruke minst 3 klasser og 2 HashMap-er, men du kan godt utvide dette med flere klasser, HashMap-er, og andre datastrukturer etter ?nske.- Oblig4.java:
Denne filen skal inneholde det ferdige Java-programmet ditt (all Java-kode
skal ligge i én fil). F?r du leverer lag en kommentar ?verst
i Oblig4.java der du skriver noe om besvarelsen din generelt,
f.eks. om du ikke klarte ? bli ferdig med en deloppgave, eller at
du fullf?rte alle deloppgavene. Skriv ogs? hvilken leveringsm?te du
valgte for UML-klassediagrammet (se neste punkt).
- UML-klassediagram: Du skal levere et UML-klassediagram over systemet ditt. Diagrammet skal inneholde navnene p? klassene, og de viktigste koblingene mellom disse, illustrert som forhold (linjer) mellom klassene. Gi navn p? forholdene, og angi antall p? begge sider av disse. Du skal velge en av f?lgende 3 m?ter ? levere diagrammet p?. Skriv hvilken du valgte ?verst i Oblig4.java: p? papir, elektronisk via Joly, eller via mail. Se hint 2 nedenfor for tips om UML-klassediagrammer. For elektronisk levering bruk en av disse filtypene: .pdf, .png, .gif, .jpg, .txt. For ? levere p? papir g? p? gruppetimen.
- filmdata.txt:
Tekstbasert datafil med informasjon om filmer. Filen er lagt
ut i to forskjellige tegnsett, velg et av dem:
- filmdata.txt: (ASCII-enkoding, passer alle plattformer men tar ikke vare p? aksenter).
- filmdata.utf8.txt: (UTF-8, tar vare p? utenlandske bokstaver og lignende).
- persondata.txt: (ASCII).
- persondata.utf8.txt: (UTF-8).
Oppgaven skal l?ses individuelt. Det forutsettes at du har lest
og forst?tt kravene til innleverte oppgaver ved Ifi:
Oppgave
I denne obligen skal du lage et kommandostyrt system som behandler informasjon om filmer. Programmet ditt skal lese inn to datafiler, og gi mulighet til brukeren for ? utf?re kommandoer som finner og viser frem forskjellig type informasjon om filmdataene som ble lest inn. Programmet ditt trenger ikke skrive til fil eller endre datafilene.Filen filmdata.txt
Denne filen inneholder informasjon om filmer, med én linje for hver film. Hver linje har 6 eller flere felt, som er adskilt vha. et tabulator-tegn (dette skilletegnet angis som "\t" i Java):Noen av de siste feltene kan mangle data, og da st?r det "-" i feltet.kode tittel ?r regiss?r skuespillere;... sjangre [evt.tillegg]...
- kode er en unik kode for hver film, og best?r av tre store bokstaver etterfulgt av et tall (som g?r fra 1 og oppover).
- tittel og ?r er navn p? filmen og ?ret den kom.
- regiss?r er en kode som angir regiss?ren til filmen, og best?r av tre sm? bokstaver etterfulgt av et tall (som g?r fra 1 og oppover).
- skuespillere er en rekke med koder som angir skuespillere, disse angis p? samme m?te som regiss?r, men kan v?re flere og er da adskilt med semikolon (";").
- sjangre er en sammenhengende tekststreng som angir sjangre
for filmen, i form av enkelt-bokstav-koder og enkelt-sifre.
Tallsifrene angir om filmen forekommer i forskjellige lister.
Vi skal bare bruke noen f? av disse kodene i oppgaven, men her er
hele listen:
a=action A=animation b=biographical c=comedy C=children D=documentary d=drama e=epic E=adventure f=fantasy g=computer_animation(datagrafikk) h=horror H=superhero k=crime m=musical n=film_noir r=romantic_comedy R=romance s=science_fiction S=sports t=thriller w=war W=western x=disaster
1=St?r i listen Films considered the greatest ever fra Wikipedia
2=St?r i listen List of Academy Award-winning films (filmer som fikk Oscar)
3=St?r i listen Palme d'Or (filmer som vant i Cannes)
4=St?r i listen Sight & Sound (liste omtalt i link 1= ovenfor).
5=St?r i listen AFI's 100 Years... 100 Movies (10th Anniversary Edition) - [evt.tillegg]: For noen av filmene er det mer enn 6 felt i linjen. Vi skal bare bruke felt 7, som heter s=Serienavn, dette st?r p? filmer som er del av en serie, f.eks. i James Bond-filmene st?r det "s=James Bond".
Filen persondata.txt
Denne filen har data p? to felt, adskilt med tabulator-tegn: kode, og fullt navn til en person. Her st?r navnene til alle regiss?rer og skuespillere som var angitt i den andre datafilen med bare kode. Tips: Disse kodene hopper ikke over noen tall, f.eks. hvis det finnes ole9, s? vil ogs? ole1 til ole8 finnes. Dette kan du bruke til ? kunne s?ke raskere etter personer (eller filmkoder, som f?lger samme prinsipp) n?r bruker taster 3 bokstaver og ?nsker en liste over matchende personer eller filmer.P.S. Det er litt feil og mangler i datafilene, men disse p?virker ikke en l?sning av obligen. Du trenger alts? ikke laste ned evt. senere utgaver av datafilene for ? l?se obligen (men spesielt interesserte kan se om rettelser er lagt ut ved ? se p? fildatoene).
Kommandoene
Oppgaven din blir ? lage et program som kan lese inn disse to filene, og svare p? f?lgende typer kommandoer som bruker kan gi. Du kan velge hvordan du vil sette opp menyen, men det anbefales f?lgende meny:(*): Kommandoene markert med stjerne er valgfrie ekstra-oppgaver, men det anbefales ? l?se disse ogs?.Eksempler p? kommandoer du kan taste inn: . = Vis statistikk AAA1 = Vis info om en film AAA = Finn film tom1 = Vis info om en person tom = Finn person 90 = Vis info om et ti?r 2009 = Vis info om et ?r (*) a = Vis info om en sjanger (*) ? = Vis meny q = Avslutt Kommando ('?' = meny): _
Idéen her er at bruker kan taste inn en hvilken som helst av disse typer kommandoer, og programmet finner hva slags kommando ble gitt ut fra antall tegn i kommandoen og om disse tegn er sifre, bokstaver, eller punktum. Men hvis du foretrekker det kan du ogs? bruke to-stegs kommandoer som i oblig 2 og 3 (menyvalg etterfulgt av sp?rsm?l til bruker).
- Vis statistikk: Skal skrive ut totalt antall filmer,
og antall filmer i hvert av ti?rene 1980-1989, 1990-1999, og 2000-2009.
- Vis info om en film, og Finn film: Skal la brukeren
angi en film, og skriver deretter ut f?lgende informasjon om filmen:
tittel, ?r, fullt navn til regiss?r, og fullt navn til skuespillerne.
Brukeren skal kunne angi film p? minst 2 forskjellige m?ter:
- kode: Hvis det som brukeren tastet inn var koden til en av filmene (f.eks. "AVA1" for Avatar), skal info om den filmen skrives ut.
- s?k: Hvis bruker bare tastet inn tre bokstaver, og det f?rste (eller flere) er store bokstaver, s? skal programmet skrive ut en liste med filmene hvor tittelen (film-koden) begynner med disse bokstavene, og brukeren skal kunne velge ?nsket film fra listen. Du kan bruke de unike film-kodene i datafilen til dette, disse ser bort fra "The " og "A " i begynnelsen av filmnavn.
- navn (valgfri ekstra-oppgave) (*): Hvis du ?nsker det kan du ogs? implementere andre m?ter ? angi filmer p?, f.eks. med full tittel til filmen eller full tittel etterfulgt av ?r. Du kan ogs? gi enda mer informasjon om filmen, f.eks. sjangre eller evt. serie som filmen tilh?rer.
- Vis info om en person, og Finn person: Skal fungere
omtrent som kommandoen ovenfor, med de samme 2 eller 3 m?ter ? angi ?nsket
person p? (men med sm? bokstaver i stedet). Informasjonen
som vises skal inneholde filmene som personen regisserte, og de som
hun spilte i.
- Vis info om et ti?r: Hvis brukeren taster inn to tallsifre,
og det siste er 0, skal programmet vise f?lgende to ting:
(a) ?Mest aktiv regiss?r?: Regiss?ren som lagde flest filmer det ti?ret, og
(b) Filmene som
st?r i 2 eller flere av filmlistene 1-5 i det ti?ret. Filmlistene
er angitt med kodene 1-5 i felt
nr. 6 for hver film, f.eks. kode ?2? st?r p? filmer som har f?tt Oscar.
- Vis info om et ?r (*): Hvis brukeren taster inn et ?rstall
mellom 1900 og 2010 s? skal programmet vise f?lgende to ting om det ?ret:
(a) ??rets sjanger? blant comedy, fantasy, horror, eller
science-fiction: her skal programmet finne
hvilken av disse 4 sjangrene forekommer i flest filmer det ?ret, basert p?
sjanger-kodene c, f, h, s. Skriv ogs? ut antall
filmer resultatet er baserert p?; og (b) Hvilken film st?r i flest
?reslister (1-5) det ?ret (uten hensyn til sjanger).
- Vis info om en sjanger (*): Taster bruker bare en av bokstavene a, E, H, x (som st?r for a=action, E=eventyrfilm, H=superhero, x=disaster), s? skal programmet vise f?lgende to ting om valgt sjanger: (a) Skuespilleren som spilte i flest filmer i sjangeren; og (b) Navnene p? filmseriene som har minst en film innen sjangeren.
Hint
Disse hint er bare for de som ?nsker litt ekstra-hjelp. Det kan ogs? bli lagt ut flere ekstra-hint senere, men obligen kan alts? godt l?ses uten ? lese noen av hintene.-
Programskall: Her er et eksempel p? et mulig skall for programmet,
men du kan l?re mer med obligen hvis du setter opp programstrukturen din
p? egen h?nd f?r du ser p? dette eksemplet!
/* Skriv en kommentar om din besvarelse her. * ... * * Leveringsm?te for UML-diagram: ... */ import easyIO.*; import java.util.HashMap; class Oblig4 { public static void main(String[] args) { new Filmregister().ordrel?kke(); } } class Person { String kode; String navn; boolean erRegiss?r; boolean erSkuespiller; String filmerRegissert; // Filmkoder adskilt f.eks. med semikolon. String filmerSpilt; // Filmkoder adskilt f.eks. med semikolon. // filmerRegissert og filmerSpilt kan ogs? deklareres som HashMap-er // eller f.eks. overf?res til arrayer av Film[]-pekere n?r alle filmer // er lagt inn. Se hint 3 for flere tips. // Evt. metoder for ? behandle en person. } class Film { // Variabler for dataene som gjelder en film. // ... // Evt. metoder for ? behandle en film. } class TiAar { // Variabler for dataene som gjelder et ti?r. // ... // Evt. metoder for ? behandle et ti?r. } class Filmregister { In tast = new In(); Out skjerm = new Out(); HashMap<String, Person> personer = new HashMap<String, Person>(); HashMap<String, Film> filmer = new HashMap<String, Film>(); TiAar[] ti?r = new TiAar[11]; // [0]=1900-1909, ..., [10]=2000-2009 /** * Konstrukt?r: Leser datafilene, lagrer innholdet i objekter av * klassene Person, Film, (og evt. TiAar), og putter Person- og * Film-objektene i HashMap-ene ?personer? og ?filmer?. */ Filmregister() { // Leser datafilen "persondata.txt": In fil = new In("persondata.txt"); fil.inLine(); // Hopp over f?rste linje, som ikke har data. while (! fil.endOfFile()) { // Les en linje fra datafilen: String kode = fil.inWord(); String navn = fil.inLine(); // Opprett Person-objekt, og lagre det i HashMap-en ?personer?. // ... skjerm.out(kode.charAt(0)); // Testutskrift. } fil.close(); // Leser datafilen "filmdata.txt": fil = new In("filmdata.txt"); fil.inLine(); // Hopp over f?rste linje, som ikke har data. while (! fil.endOfFile()) { // F?lgende setning leser inn en hel linje fra datafilen og // oppretter en array med de forskjellige feltene i linjen. // felt[0] vil da inneholde filmkoden, felt[1] tittel, osv. String linje = fil.inLine(); String[] felt = linje.split("\t"); // Opprett Film-objekt med de innleste felt-datane, og evt. // TiAar-objekt hvis det ikke finnes allerede, og lagre // filmobjektet i HashMap-en ?filmer?. // ... // For ? teste om det var flere enn 6 felt i linjen kan // du bruke if-setningen: if (felt.length > 6). skjerm.out(felt[0].charAt(0)); // Testutskrift. } fil.close(); } void ordrel?kke() { String ordre = ""; // Kommandoen som bruker taster inn. char char0 = '?'; // F?rste tegn i kommandoen. visMeny(); while (! ordre.equals("q")) { // Skriv ut ledetekst og les inn en ordre fra tastatur. skjerm.out("Kommando ('?' = meny): "); ordre = tast.readLine(); int ordreLengde = ordre.trim().length(); if (ordreLengde > 0) { char0 = ordre.charAt(0); } if (ordreLengde == 1 && char0 == '?') { visMeny(); } else if (ordreLengde >= 3 && char0 >= 'A' && char0 <= 'Z') { visInfoOmFilm(ordre); } // else if ...osv... // Skriv en else-if gren for hver ordretype. } } void visMeny() { // Skriv ut meny her. skjerm.outln("..."); skjerm.outln("? = Vis meny"); skjerm.outln("q = Avslutt"); } void visInfoOmFilm(String kode) { // Vis info om filmen som har angitt kode (inn-parameter). } // Lag en metode for hver ordre her. Disse metodene kan // kalle p? metoder i de andre klassene. }
- UML-klassediagram: Se eksempel p? side 236 i l?reboka. Du kan bruke nesten et hvilket som helst tegneprogram for ? lage diagrammet p? datamaskin (hvis du vil levere det via Joly eller mail), eller du kan scanne inn en papir-tegning. Det er scanner p? Abel- og VB-termstuen. Hvis du velger elektronisk levering, skal du bruke en av disse filtypene: .pdf, .png, .gif, .jpg, .txt.
-
String contains og split: For ? teste om en film tilh?rer en sjanger kan du
bruke den forh?ndsdefinerte metoden ?contains? for tekster, f.eks.
hvis ?sjangre? er en String-variabel med det som sto i
felt 6 for filmen ?film?, s? vil f?lgende if-setning teste om filmen
er en action-film:
Tilsvarende kan du teste for koder p? mer enn ett tegn, men det fungerer best hvis teksten man skal lete inn i har et skilletegn p? slutten av koden man ser etter (eller b?de foran og bak), f.eks. hvis du har valgt ? lagre skuespillerlista til en film i en String-variabel ?stars?, og plusset p? skilletegn bakif (film.sjangre.contains("a")) { // ...
(stars = stars + ";";) , s? kan du teste om Sandra Bullock spiller i filmen slik:
Dette gjelder hvis du lagrer skuespillerlisten til en film i en String-variabel. To andre m?ter ? lagre slike sm? lister p? er som en array (som kan opprettes vha. stars.if (film.stars.contains("san1;")) { // ...
split(";") ) eller i en liten HashMap. Du kan se et eksempel p? split i koden ovenfor. NB! Tekst-verdien du bruker split p? skal ikke inneholde skilletegnet helt foran, s? hvis teksten har ";" som f?rste tegn b?r dette fjernes (f.eks. vha. substring) f?r man utf?rersplit(";") , hvis ikke kan man f? en tom streng som f?rste resultat av split. - keySet og substring: Du vil f? bruk for metodene for manipulasjon av HashMap-er og String-er, disse kan du lese mer om i kapittel 6 og 9 i l?reboka, les bl.a. om substring, indexOf, startsWith, parseInt, og split p? side 104-111 om tekster; og om put, get, keySet, values, size, og containsKey p? side 180-189 om HashMap-er.
-
Store og sm? bokstaver: Du kan teste om et tegn i ordren
som brukeren tastet inn er stor eller liten bokstav p? mange
m?ter, her er tre alternative m?ter, velg en av dem:
Den f?rste m?ten er ogs? vist i siste else-if i koden ovenfor og g?r ut p? ? teste om et gitt tegn er mellom 'A' og 'Z', i s? fall vet vi at det er en stor bokstav. Bruk 'a' og 'z' for ? teste for sm? bokstaver. Neste if-setning viser bruk av den forh?ndsdefinerte metoden isUpperCase(tegn) til klassen Character, denne klassen er alltid tilgjengelig i Java, p? samme m?te som String. Bruk isLowerCase(tegn) for ? teste for sm? bokstaver. Siste alternativ viser hvordan du kan teste om alle bokstaver i en ordre er store bokstaver.if (tegn >= 'A' && tegn <= 'Z') { // ... if (Character.isUpperCase(tegn)) { // ... if (ordre.toUpperCase().equals(ordre)) { // ...
- Lesing av 6 - 7 felt: Linjene i datafilen "filmdata.txt" kan inneholde 6 eller flere felt. En enkel m?te ? lese datafilen p? som tar h?yde for dette er vist i koden ovenfor der det st?r split("\t"). Og for ? sjekke om 7. felt er serienavn kan du bruke startsWith("s="). Det g?r ogs? an ? lese datafilen vha. fil.inWord("\t") og lignende. Dette leser inn felt som har mellomrom inni seg riktig, men da trenger du ogs? en smart m?te ? skille mellom evt. 7. felt og begynnelsen av neste linje.
Kilder
All data som st?r i datafilene kommer fra Wikipedia. Film-listen er tatt fra disse alfabetiske listene.Kommentarer og rettelser til denne obligen kan sendes til josek [at] ifi.uio.no (Jose Luis Rojas K.)