Oblig 4 (INF1000 - H?st 2011)
Filmregister - PDF utgave[ Nye presiseringer er markert med gr?nn tekst. ]
Leveringsfrist
Fredag 11. nov kl. 16.00. Leveres i Joly. Viktig! Det blir sv?rt begrensede muligheter for ? levere nye fors?k i Oblig 4 eller ? f? mye utsetttelse. Kandidatlista til eksamen b?r v?re klar 14 dager f?r eksamen, dvs. 18. nov (bare én uke etter den vanlige fristen). Alle som skal ta eksamen b?r f? obligen sin godkjent f?r dette. Hvis det du leverer innen fristen ikke er ferdig m? du fortsette ? jobbe med obligen og levere ferdig utgave s? fort som mulig.Leveringskrav
Som for tidligere oppgaver gjelder det at Oblig 4 skal leveres individuelt - to studenter kan alts? ikke levere felles eller kopier av samme l?sning. Kravene til innleverte oppgaver ved Ifi finner du her:
Oblig4.java: Denne filen skal inneholde det ferdige Java-programmet ditt (all Java-kode skal ligge i én fil). F?r du leverer skal du lage en kommentar ?verst i .java-filen der du skriver litt info om besvarelsen din, f.eks. hvilken deloppgave du har spesielle sp?rsm?l til, eller om du fullf?rte alle deloppgaver og ekstraoppgaver. Skriv ogs? hvilken leveringsm?te du valgte for UML-klassediagrammet (se neste punkt). Husk ? kommentere koden din (se tips fra INF1100).
UML-klassediagram: Du skal levere et UML-klassediagram over systemet ditt. Diagrammet skal inneholde navnene p? klassene, og de viktigste koblingene mellom disse (s?rlig pekerne som er deklarert ?verst i klassene, f?r metodene), 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: (a) elektronisk innlevert sammen med din Oblig4.java, (b) p? papir, eller (c) via mail.
Se hint 2 nedenfor for tips om UML-klassediagrammer. For elektronisk levering (a) bruk en av disse filtypene: .pdf, .jpg, .png, .gif, (eller .txt), og pass p? ? levere den i samme levering som programfilen (.java-filen) men lagt inn som tilleggsfil rett etter at du har lagt inn .java-filen i Joly (se hint 10). For ? levere p? papir g?r du p? gruppetimen din og leverer personlig til din gruppel?rer.
Oppgave
I denne obligen skal du lage et kommandostyrt system som behandler informasjon om filmer. Programmet skal lese inn data fra f?lgende to datafiler, og gi brukeren mulighet til ? utf?re kommandoer som finner og viser frem forskjellig type informasjon om filmene. Programmet trenger ikke skrive til fil eller endre datafilene, og du skal ikke levere disse filene.NB! Datafilene skulle bli oppdatert men er ikke blitt det enda. Utgavene som er lagt ut er ok men de mangler nyere filmer.
filmdata.txt: Tekstbasert datafil med informasjon om filmer. (Filst?rrelse: ca. 950 KB)
persondata.txt: Tekstbasert datafil med informasjon om personer (regiss?rer og skuespillere). (Filst?rrelse: ca. 570 KB)
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):kode tittel ?r regiss?r skuespillere;... sjangre [evt.tillegg]...Noen filmer mangler data i felt 3-6 (regiss?r, skuespillere, eller sjangre), da st?r det "-" i feltet.
- kode er en unik kode for hver film, og best?r av tre bokstaver (én stor og to sm? bokstaver) etterfulgt av et tall (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). Noen filmer har flere regiss?rer, da st?r kodene til disse adskilt med semikolon (";").
- skuespillere er en rekke med koder som angir skuespillere, disse angis p? samme m?te som regiss?r. Oftest er det mer enn én skuespiller, og da st?r kodene til disse adskilt med semikolon (";").
- sjangre er en sammenhengende tekststreng som angir sjangre
for filmen, i form av enkelt-bokstav-koder eller enkelt-sifre.
Tallsifrene angir om filmen forekommer i forskjellige lister.
Vi skal bare bruke noen f? av disse kodene i oppgaven, men her er
alle:
a=action A=animation b=biographical c=comedy C=children d=drama D=documentary e=epic E=adventure f=fantasy F=family g=computer_animation(datagrafikk) h=horror H=superhero i=history k=crime m=musical M=music n=film_noir o=Eastern(?sten) 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 s=Serienavn i felt 7, dette st?r p? filmer som er del av en serie, f.eks. i James Bond-filmene st?r det "s=James Bond". [ De andre tilleggsfelt trengs ikke i deloppgavene, men du kan bruke de hvis du ?nsker det, de er tatt fra TMDb og kan inneholde: r=rating er en karakter for filmen, fra 0 til 10.0. i=imdb er IMDb-id til filmen. c=land1;land2;... er landene filmen kommer fra. o=original_name er navnet til filmen p? originalspr?ket. ]
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 ved hjelp av 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.
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:Eksempler p? kommandoer du kan taste inn: m = Vis denne menyen s = Vis statistikk Aaa1 = Vis info om en film Aaa = Finn film tom1 = Vis info om en person tom = Finn person 2000s = Vis info om et ti?r 2010 = [ Ekstraoppgave: Vis info om et ?r ] :a = [ Ekstraoppgave: Vis info om en sjanger ] q = Avslutt Kommando ('m' = 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 andre tegn.
Vis statistikk: Skal skrive ut totalt antall filmer, og antall filmer i hvert av ti?rene 1990-1999, 2000-2009, og 2010-2019.
Vis info om en 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. Du kan ogs? gi enda mer informasjon om filmen, f.eks. sjangre eller evt. serie som filmen tilh?rer. Til denne kommandoen skal brukeren angi film ved koden til en av filmene (f.eks. "Ava1" for Avatar).
Finn film: Skriver ut informasjon om en film p? samme m?te som kommendoen over (Vis info om en film), men lar brukeren s?ke etter en film:
- (a) s?k: Hvis bruker bare tastet inn tre bokstaver, og den f?rste er en stor bokstav, s? skal programmet skrive ut en liste med filmene hvor film-koden (og dermed ogs? tittelen) 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.
- (b) [ Ekstraoppgave: navn ]: Hvis du ?nsker det kan du ogs? implementere andre m?ter ? angi filmer p?, f.eks. med full tittel til filmen, eller med noen bokstaver fra begynnelsen av filmtittelen (f.eks. "Avat" eller "Avata" for Avatar).
Vis info om en person, og Finn person: Skal fungere omtrent som kommandoene ovenfor, med de samme m?tene ? 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, med tittel og ?r.
Vis info om et ti?r: Hvis brukeren taster inn fire tallsifre etterfulgt av bokstaven s (f.eks. 1990s), og siste tallsiffer er 0, s? skal programmet vise f?lgende: (a) ?Beste filmer?: 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. (b) [ Ekstraoppgave: ?Mest aktiv regiss?r?: ] Skriv ut regiss?ren som lagde flest filmer det ti?ret.
[ Ekstraoppgave: 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 film?: Hvilken film st?r i flest ?reslister (1-5) det ?ret; og (b) ??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?.
[ Ekstraoppgave: Vis info om en sjanger: ] Taster bruker kolon etterfulgt av 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.
[ Ekstra-ekstraoppgave: Filmliste: ] NB! Dette er en oppgave som gir deg mulighet til ? lage tilleggsfunksjonalitet som gj?r programmet mer nyttig for eget bruk - dersom du ?nsker for eksempel ? holde rede p? hvilke filmer du selv har, eller hvilke filmer du har sett, eller dine vurderinger av filmer du har sett. Legg til mulighet for brukeren til ? lage en liste av filmer. Du velger hvilke muligheter programmet gir brukeren, og hvordan du programmerer det, men legg til et menyvalg som forklarer funksjonalitet og fremgangsm?te til bruker. Listen som lages b?r lagres p? en egen datafil, f.eks. n?r programmet avsluttes, og hentes inn igjen n?r programmet starter.
Hint
Disse hint er ment for de som ?nsker litt ekstra-hjelp. Du trenger ikke lese dette avsnittet for ? l?se obligen, og det anbefales sterkt at du lager ditt eget forslag til datastruktur og gjerne skisserer dette i UML f?r du ser p? forslaget til programskall nedenfor. Da f?r du samtidig gjort deg godt kjent med oppgaveteksten. Dette vil du ha mye igjen for senere, selv om du skulle ende med ? bruke den ferdiglagede koden. Du kan ogs? sp?rre om og finne flere hint i bloggen. Det kan v?re lurt ? l?se litt enklere oppgaver f?r du g?r l?s p? deloppgavene i denne obligen, s?rlig Ukeoppgaver 9 om HashMap (som er hovedtemaet i obligen). Oppgavesettet har l?sningsforslag.Programskall: Her er et eksempel p? et mulig skall for programmet, men du vil l?re mer med obligen hvis du setter opp programstrukturen din p? egen h?nd f?r du studerer dette eksemplet!
/* Skriv en kommentar om din besvarelse her. * ... * * Leveringsm?te for UML-klassediagram: ... */ import easyIO.*; import java.util.HashMap; class Oblig4 { public static void main(String[] args) { new Filmregister().ordrelokke(); } } class Person { String kode; String navn; String filmerRegissert; // Filmkoder adskilt f.eks. med semikolon. String filmerSpilt; // Filmkoder adskilt f.eks. med semikolon. // filmerRegissert og filmerSpilt kan ogs? overf?res til arrayer av // Film[]-pekere n?r alle filmer er lagt inn; eller du kan lagre de // i sm? HashMap-er. Se hint 3 for flere tips. // Evt. metoder for ? behandle en person. } class Film { // Variabler for dataene som gjelder for en film. // ... // Evt. metoder for ? behandle en film. } class TiAar { // Variabler for dataene som gjelder for 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[] tiaar = new TiAar[14]; // [0]=1880-1889, ..., [13]=2010-2019 /** * 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(); } /** Ordrel?kke: */ void ordrelokke() { String ordre = ""; // Kommandoen som bruker taster inn. char char0 = 'm'; // F?rste tegn i kommandoen. visMeny(); while (! ordre.equals("q")) { // Skriv ut ledetekst og les inn en ordre fra tastatur. skjerm.out("Kommando ('m' = meny): "); ordre = tast.readLine(); int ordreLengde = ordre.trim().length(); if (ordreLengde > 0) { char0 = ordre.charAt(0); } if (ordreLengde == 1 && char0 == 'm') { visMeny(); } else if (ordreLengde >= 3 && char0 >= 'A' && char0 <= 'Z') { visInfoOmFilm(ordre); } // else if ...osv... // Skriv en else-if gren for hver ordretype. } } void visMeny() { // Legg til de andre linjene av menyen her. skjerm.outln("\nMeny:"); skjerm.outln("m = 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 innleveringssystemet eller mail), eller du kan scanne
inn en papir-tegning. Det er scanner ved ekspedisjonen i 4. etg. OJD og p?
Abel-stua (kjelleren i Matematikk-bygningen).
Hvis du velger elektronisk levering, skal du bruke en av disse
filtypene: .pdf, .jpg, .png, .gif, (eller .txt).
UML-klassediagrammer ble gjennomg?tt i
Ukeoppgaver 7.
- 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:
if (film.sjangre.contains("a")) { // ...
Tilsvarende kan du teste for koder p? mer enn ett tegn, men det fungerer best hvis du legger til et skilletegn p? slutten av teksten man skal lete i, f.eks. hvis du har valgt ? lagre skuespillerlista til en film i en String-variabel ?stars?, og plusset p? skilletegn bak(stars = stars + ";";) , s? kan du teste om Sandra Bullock spiller i filmen slik:if (film.stars.contains("san1;")) { // ...
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.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 105-114 om tekster; og om put, get,
keySet, values, size, og containsKey p? side 181-192 om HashMap-er.
- Store og sm? bokstaver: Det er mange m?ter ? teste om et tegn
i ordren som brukeren tastet inn er stor eller liten bokstav.
Her er tre mulige m?ter, velg en av dem:
if (tegn >= 'A' && tegn <= 'Z') { // ... if (Character.isUpperCase(tegn)) { // ... if (ordre.toLowerCase().equals(ordre)) { // ...
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 sm? bokstaver. - Tall eller bokstav: Det er ogs? mange m?ter ? finne ut om et
gitt tegn er et tallsiffer:
if (tegn >= '0' && tegn <= '9') { // ... if (Character.isDigit(tegn)) { // ... if (ordre.matches("[0-9]+")) { // ...
Siste alternativet tester om hele ordren best?r av bare tallsifre ("[0-9]" matcher et hvilket som helst tall, og "+"-tegnet betyr ?en eller flere forekomster?). Det fins ogs? Character.isLetter(tegn) for ? teste om et tegn er en bokstav. - Er ordren et ti?r? (NB: F?lgende er ikke pensum). Du kan ogs? bruke f?lgende til ? teste om bruker ga ordren om ti?r:
if (ordre.matches("[0-9][0-9][0-9]0s")) { // ...
Spesielt interesserte kan lese mer om dette i Java API-en under String.matches(regex) og regular expression (se ogs? side 114 i l?reboka). - Lesing av 6 eller flere felt:
Linjene i datafilen "filmdata.txt" kan inneholde
6 eller flere felt adskilt med tabulator-tegnet. 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 if (felt[6].startsWith("s=")).
- String til int og tilbake: Man kan konvertere fra
String til int ved hjelp av parseInt slik:
int tall = Integer.parseInt(tekstVerdi);
Her skal tekstVerdi v?re en String som bare inneholder tallsifre. Bruk tekstVerdi.substring(f_o_m, til) for ? plukke ut ?nsket del-streng hvis tallsifrene er blandet med andre tegn i tekstVerdi. Du kan lese mer om substring p? side 105-106 i l?reboka, eller i Java API-en under String.
Det omvendte, konvertering fra int til String, kan ordnes ved ? plusse p? den tomme strengen:String tekst = "" + intVerdi;
- Info om innlevering:
Joly krever at f?rste fil som legges inn i en innlevering er en .java-fil,
derfor kan du ikke levere UML-diagrammet alene i Joly. Hvis du valgte
leveringsm?te (a) for diagrammet (dvs. sammen med .java-filen),
s? legger du inn begge filene i samme levering i Joly: F?rst legger
du inn Oblig4.java, og s? legger du inn UML-diagrammet ditt som
tilleggsfil.
Du kan diskutere med andre studenter hvordan dere skal l?se oppgaven, men det er ikke lov ? kopiere noe Java-kode fra dem, selv om du endrer p? koden etterp?; og det er heller ikke lov ? hente programbiter fra andre besvarelser, for eksempel fra Internet. Hvis du diskuterer mye med en annen student skriv hvem det gjelder i kommentaren din ?verst i programmet (da unng?r du mistanke om at du pr?vde ? skjule dette, n?r vi oppdager det i likhets-kontrollen vi foretar med innleveringene).
Kilder
Alle dataene som st?r i datafilene er tatt fra Wikipedia og TMDb (disse er valgt fordi de er ?pne og krever ikke lisens for bruk). Filmlisten er tatt fra de alfabetiske listene over "filmer som har egen Wikipedia-side".Hvis du har sp?rsm?l, kommentarer, eller rettelser til obligen kan du skrive de i kurs-bloggen eller maile de til meg, josek [at] ifi.uio.no..