Echo server v3
Muuda echo serverit, et see vastaks echo asemel kliendi küsitud faili sisuga.
- client võtab käsurea parameetri kaudu 0..N failinime. client saadab serverile kõik failinimed ja hakkab vastu võtma serveri saadetud faile. client salvestatab vastuvõetud failid kettale, samasse kausta, kus ta käivitati.
- server saadab clientile küsitud failid. kui mõnda küsitud faili ei leiata, tuleb sellest clientile viisakalt teada anda (client peab aru saama, mis fail puudu oli) ja ülejäänud failid ikka kõik välja saata.
- server otsib faile ainult oma classpathist.
- server peab suutma korraga teenindada mitut clienti.
Täpsustused:
- programm peab kasutama maveni projektistruktuuri
- server ja client võivad peale failinimede ja sisude omavahel täiendavaid koordineerimist võimaldavaid andmeid vahetada.
- client loob serverisse ainult ühe ühenduse, mida ta kasutab kõigi failide vastu võtmiseks.
- võib eeldada, et failid mahuvad mälusse ja nende suurus on väiksem, kui Integer.MAX_VALUE. On soovitatav fail üleni mälusse lugeda ja siis sellega edasi toimetada.
Abiks on:
- classpathist failide lugemiseks ClassLoader#getResourceAsStream
vt https://github.com/mbakhoff/class-generator (viimane osa) - faili sisse lugemise jaoks ByteArrayOutputStream
- streamist täpse arvu baitide lugemiseks DataInputStream#readFully
Kuidas me testime?
- tõstame mõned suvalised failid serveri src/main/resources alla.
- käivitame käsurealt projekti kaustas
mvn package
ja tõstame loodud jar faili suvalisse tühja kausta. seejärel kävitame serveri käsurealt, nii et ainult serveri jar on classpathis. - downloadime clientiga mitu faili korraga ja võrdleme salvestatud faile algsetega.
JavaFX valuutakalkulaator
Valuutakalkulaator on JavaFX kasutades kirjutatud graafiline programm, mis oskab teisendada EUR kolmeks teiseks (omal valikul) valuutaks.
- programm loeb vahetuskursid tekstifailist
- kasutajaliideses on kaks tekstivälja - üks EUR summa jaoks ja teine võõrvaluuta summa jaoks. EUR tekstivälja summa sisestamisel peab automaatselt kohe teise tekstivälja konverteeritud summa ilmuma (property listener).
- võõrvaluuta summa tekstivälja ei tohi kasutaja saada muuta
- kasutajaliideses on drop-down menüü, kust saab võõrvaluuta valida
- kasutajaliideses on nupp, mis mõlemad tekstiväljad tühjendab
- kasutajaliides sisaldab programmi "logo". logo on mingi
javafx.scene.canvas.Canvas
abil koostatud pilt, mis sisaldab vähemalt kolme erinevat kujundit ja kahte eri värvi. - kasutajaliidese elemendid on paigutatud kasutades sobilikke layout klasse (BorderPane, HBox, VBox, GridPane jms; ära kasuta setLayoutXY ja hardcoded koordinaate)
Equals, hashcode
Analüüsi, kas objekte klassidest Company, Person ja Newspaper saaks töökindlalt ja korrektselt kasutada HashMap kollektsioonis võtmetena. Paranda klassid nii, et neile vastavad testid toimiksid (jookseks ilma crashimata lõpuni).
Klassid: https://github.com/mbakhoff/hashmap-template
Paralleelarvutused
Koosta paralleelarvutusprogramm, mis loeb ja töötleb paralleelselt mitut tekstifaili, millest igaüks sisaldab väga väga palju tühikutega eraldatud elemente.
Programmil peab olema üks käsureaparameeter - kausta path, kus andmefailid asuvad. Andmefailid on faililaiendiga .txt
. Teisi faile ei tohi programm avada. Andmefaile võib kaustas olla palju - üle 50 000. Võib eeldada, et alamkaustu ei ole.
Failid võivad sisaldada positiivseid ja negatiivseid arve. Arvud ei pruugi long tüüpi muutujasse ära mahtuda. Seetõttu peaksid kasutama BigInteger
klassi, mis võimaldab lõpmatult suurte arvudega töötamist.
Mõned failid võivad mitte ühtegi arvu sisaldada (sisaldavad ainult tekstielemente). Elementide puhul, mida ei õnnestu täisarvuks teisendada, peab programm väljastama veateate koos elemendi väärtuse ja faili nimega, kuid programm peab tööga siiski edasi minema (samast failist arvude otsimist tuleb jätkata).
Failid võivad olla nii suured, et need ei mahu korraga mälusse ära. Failides võivad kõik elemendid olla ühel real, aga võivad ka olla ridade vahele jaotatud.
Programmi lõppedes peab see ekraanile väljastama:
- Kõikide leitud arvude kogusumma
- Kõige suurema leitud üksiku arvu väärtuse
- Kõige väiksema leitud üksiku arvu väärtuse
- Kõige suurema arvude summaga faili nime
- Kõige väiksema arvude summaga faili nime
Programm peab failide töötlemiseks looma nii mitu threadi, kui masinas protsessoreid on (Runtime#availableProcessors()
). Programm peab kasutama threadide vahel andmete vahetamiseks ainult BlockingQueue objekte. Väldi threadide vahel objektide jagamist. Disaini kood nii, et synchronized plokke vaja ei lähe. Main thread peaks BlockingQueue abil worker threadidele failnimed andma. Worker threadid peaks BlockingQueue abil main threadile iga faili kohta järgneva komplekti saatma: töödeldud faili nimi, arvude min, max ja summa. Kõigi failide min, max ja kogusumma arvutab välja main thread.
NB! Vaata Practice12 PahupidiPööraja koodi.
Vihje: Faili lugemiseks üks mugavamaid variante on Scanner.
Echo server v2
Täienda echo serverit.
- Server peab suutma paralleelselt teenindada mitut ühendust (üks thread per ühendus).
- Server loeb ja echob igal vastuvõetud ühendusel piiramatult stringe.
- Client saadab iga käsurea parameetriga antud stringi eraldi serverile ja prindib iga vastuse välja.
- Clientis saadetakse kõik sõnumid ühe socketi kaudu.
Vihje: Client ja server võivad lisaks stringidele ka muud vajalikku infot vahetada, aga peavad kasutama DataOutputStream/DataInputStream. Hea mõte on näiteks kohe alguses serverile teada anda, mitu stringi selle konkreetse ühenduse peal oodata on.
Echo server
- Kirjuta server, mis võtab pordil 1337 ühendusi vastu. Vastuvõetud ühenduse peal tuleb üks string vastu võtta ja see kohe saatjale tagasi saata. Seejärel tuleb ühendus sulgeda, järgmine sissetulev ühendus vastu võtta ja seda teenindama hakata jne. Server ei pea suutma paralleelselt mitut klienti teenindada.
- Kirjuta client, mis saab käsurea parameetriga stringi ja saadab selle samas masinas jooksvale serverile. Prindi tagasi tulev echo välja.
- Stringide saatmiseks tuleb kasutada DataOutputStream/DataInputStream.
NB! Server ja client on kaks eri programmi. Mõlemal on oma main meetod.
Dungeons & Dudes
Selles ülesandes ehitame väga lihtsustatud lahingusimulaatori. Loome erinevad tegelased, kes suudavad omavahel lahingut pidada. Mängu võtame rusikad, külmrelvad ja maagia. Võidab see, kes ellu jääb!
Tegelased peavad duelle. Duell kestab, kuni üks tegelastest langeb. Tegelased käivad kordamööda ja saavad enda korra ajal teha erinevad tegevusi. Erinevad tegevused kulutavad erineva hulga action pointe, mis taastuvad käigu lõpus. Tegevustel võivad olla erinevad efektid, mis võivad rakenduda kohe või kesta mitu käiku ja mõjuda vastase käikude alguses ja/või lõpus. Mõned tegevused toimivad alati, aga mõned tegevused võivad ebaõnnestuda (vastasest mööda minna). Pihta/mööda minemise tuvastamiseks kasutatakse valemit "d20 + ründaja täpsus >= vastase kaitse", kus d20 on juhuslik arv [1..20].
- Loo abstraktne klass Dude, kes on kõigi tegelaste aluseks. Tal on muuhulgas järgnevad fieldid: accuracy, armor, health ja actionPoints. Lisaks on tal meetod
void takeTurn(Dude attackTarget)
jaboolean isAlive()
. - Loo interface Effect, milles on järgnevad meetodid:
void onHit(Dude effectTarget);
, mis käivitatakse, kui vastane esimest korda efektiga pihta saabvoid beforeTurn(Dude effectTarget);
, mis käivitatakse vastase käigu algusesvoid afterTurn(Dude effectTarget);
, mis käivitatakse vastase käigu lõpusint requiredActionPoints();
boolean isExpired();
- Loo Dude alamklassid Fighter ja Wizard. Neil on erinevad accuracy, armor, health ja actionPoints taastumise kiirus. Fighter ja Wizard kasutavad ründamiseks erinevaid tegevusi.
- Loo järgnevad Effect klassi implementatsioonid (võid ise täiendavaid välja mõelda):
WeaponAttack
- vähendab pihta minemise hetkel vastase healthKnockdown
- vähendab pihta minemise hetkel vastase actionPoints 0 pealeFirebolt
- vähendab vastase käigu lõpus vastase health. efekt lõppeb pärast health vähendamist.Spiderweb
- vähendab vastase iga käigu alguses vähendatab tema actionPoints. efekt lõpeb, kui vastast on kahe tema käigu jooksul mõjutatud.
- Ühele tegelasele saab korraga rakenduda mitu sama tüüpi effekti.
- Mõtle välja puudu olevad muutujad ja meetodid, nii et mäng toimiks. Tekita peameetod, mis tegelasi võitlema paneb ja tulemused välja kuulutab. Ette antud klasse ja meetodeid võib vajadusel muuta.
Dude objektid peavad ise suutma välja mõelda, mida nad oma käigu ajal teevad. Main meetod võib alguses lasta tegelasi valida (aga ei pea). Pärast seda kutsutakse kordamööda dude objektidel takeTurn meetodit, kuni võitja on selgunud. Võitluse ajal interaktiivselt sisendit ei küsita.
Vihje: takeTurn
meetod võiks olla Dude
klassis, subclassid ei pea seda override'ma. Dude
klassi võib lisada täiendavaid abstract meetodeid, mida takeTurn
kasutab ja mille subclassid implementivad.
Telekanalid
Põhja-Korea juhid tahavad oma 60-tollistest 3D telekatest uudiseid vaadata. Riigis levib ametlikult ainult maailma parim kanal "Põhja-Korea rahvuslikud uudised". Lisaks levitavad mässulised piraat-telejaama "Põhja-Korea maailmauudised", mis edastab Fox News uudiseid, kuhu vahele pistetakse ka mässuliste teateid. Riigipea saab Fox Newsi ka otse oma satelliidi-vastuvõtjast vaadata.
- Loo interface BroadcastListener, kus on meetod
void listen(String)
- Loo class Broadcaster. Tekita private isendiväli subscribers (List<BroadcastListener>), mis väärtustatakse konstruktoris uue tühja listiga. Lisa meetod
void subscribe(BroadcastListener)
, mis lisatab ette antud vastuvõtja subscriberite listi. Lisa meetodvoid broadcast(String)
, mille kutsumise peale saadetakse kõigile kuulajatele ette antud saade. - Loo class PropagandaStation, mis extendib Broadcasterit. Lisa meetod
void broadcastNow()
, mis saadab kõigile kuulajatele julgustavaid teateid riigi ettevõtmistest (midagi lihtsat, võib ka alati sama teadet saata). Kasuta saatmiseks broadcast meetodit. - Loo PropagandaStation alamklass TVStation. Loo konstruktor, mis võtab parameetriks listi uudistest ja salvestab selle vastavasse isendivälja. Override broadcastNow ja hakka propaganda asemel "korralikke" uudised saatma - vali saadetav uudis suvaliselt uudiste listist.
- Loo TVStation alamklass PirateStation, mis lisaks realiseerib BroadcastListener. PirateStation võtab teiste jaamade saateid vastu ja saadab (broadcast meetodiga) need kõigile oma kuulajatele edasi. Enne vastu võetud saadete edastamist saadetakse välja ka täiendavaid mässuliste teateid.
- Loo klass TV, mis realiseerib BroadcastListener. TV küljes on isendiväli, mis hoiab omaniku nime. Kõik kohale jõudvad saated prindi koos TV omaniku nimega System.out-i.
- Loo klass DigiTV, mis extendib TV aga salvestab kõik näidatud saated list tüüpi isendivälja. Lisa meetod
replayAll()
, mis kõik salvestatud saated uuesti ette mängib (System.out).
Loo testklass, mis funktsionaalsust testib. Tekita kaks DigiTV objekti (omanikud Kim Jong-un ja Kim Yong-nam) ja üks tavaline TV (omanik Pak Pong-ju). Loo propagandakanal nkNationalNews, telekanal foxNews ja piraatkanal nkWorldNews, mis edastab foxNews sisu. Pane riigijuhid erinevaid kanaleid kuulama. Kasuta kanalite broadcastNow ja DigiTV replayAll võimalusi.
Subscribe/broadcast, addEventListener/fireEvent, addObserver/notify - need kõik on erinevad kujud Observer patternist. See on väga levinud ja kasulik tehnika, mis aitab koodi modulaarsemaks ja taaskasutatavamaks muuta. Mõned näited, kus seda veel kasutatakse:
- Kasutaja klõpsab nupu peale - nupp teeb fireEvent ja kõik EventListenerid saavad reageerida.
- Programm alustab taustaprotsessina faili allalaadimist. Selle lõppedes saavad kõik DownloadObserverid teate, et fail on kasutamiseks valmis.
- Koodikomponent ootab võrgust tulevaid teateid. Vastuvõtja teavitab teda sobiva teate saabumisest.
Tabelid
Klassihierarhia ülesanne, kus on andmetabel, mis oma elemente Stringiks ühendab.
- Loo klass
Table
.Table
sees onList<String>
tüüpi isendivälidata
, mis väärtustatakse konstruktori parameetri kaudu. Lisaks on olemas meetodList<String> getElements()
ja final meetodString linesToString()
, mis returnib ühe stringina kõik tabeli elemendid, nii et nad on reavahetustega eraldatud. MeetoditlinesToString
alamklassides overrideda ei tohi. - Loo
Table
alamklassAggregatingTable
, mille sees onList<String>
tüüpi isendiväliextraData
, mis konstruktori parameetri kaudu väärtustatakse.AggregatingTable
linesToString
tulemus peab sisaldama kaextraData
elemente. - Loo
AggregatingTable
alamklassSortedAggregatingTable
. Selle klassilinesToString
peab sisaldamadata
jaextraData
elemente tähestiku järjekorras. Muutujatedata
jaextraData
sisu ei tohi muuta (vajadusel tee koopia ja muuda seda). - Loo
SortedAggregatingTable
alamklassReverseSortedAggregatingTable
, mis käitub naguSortedAggregatingTable
, aga järjekord on vastupidine. - Loo testklass, mis erinevate tabelite
linesToString
välja prindib.
NB! Vajadusel võib Table
klassi lisada uusi meetodeid ja neid alamklassides override'da. Samas koodi ei tohiks copy-pasteda.
Nimede lühendamine
Failis nimed.txt on inimeste nimed, näiteks
Aadu Suur Mari Sale Blond Mari-Liis Maasikas Timothy Henry Charles Tamm
Eeldame, et iga nimi koosneb eesnimedest (neid võib olla mitu) ja perekonnanimest (viimane sõna). Eesnimi võib sisaldada ka sidekriipsu.
Kirjutada programm, mis sisaldab järgnevaid kahte meetodi:
readPersons
, mis võtab parameetriks failinime ja tagastab ArrayList<String> tüüpi objekti, mis elementidena sisaldab kõiki nimesid, mis sealt failist õnnestus lugeda. Kui antud faili pole olemas, siis tagastab null objekti.printPersons
, mis võtab parameetriks sellesama ArrayList<String> objekti ning väljastab ekraanile kõigi inimeste nimed kujul perekonnanimi ja eesnimede esimesed tähed koos punktiga ja tühikuga. Kui eesnimes on sidekriips, säilib see ka eesnimelühendis ja punkt sel juhul ainult teise eesnime tähe järel.main
, mis eelnevaid kasutab
Näiteks ülaltoodud faili puhul ilmub ekraanile
Suur A. Blond M. S. Maasikas M-L. Tamm T. H. C.
NB! Siin antud näidisandmetes algavad read tühikuga. See on courses wiki piirang. Päris sisendfailide ridade alguses tühikuid ei ole.
Et kompilaator ei hakkaks exceptionite teemal virisema ("unhandled exception .."), lisa iga oma meetodi päisesse deklaratsioon throws Exception
. (Kui su IDE soovitab selle asemel try-catch plokke kasutada, siis ära teda kuula.)
public static void main(String[] args) throws Exception { }
SortedUniquePersonList
Loo klassid Person, mis sisaldab inimese isikuandmeid, ja SortedUniquePersonList, mis on kollektsioon Person objektide hoidmiseks. Klassid Person kui SortedUniquePersonList peavad olema defineeritud erinevates failides.
Lisaks peavad SortedUniquePersonList objektid garanteerima järgmist:
- Hoitavate Person elementide isikukood on selle listi jaoks unikaalne - ei tohi olla võimalik, et kahel samas järjendis oleval Person objektil on sama ID kood.
- Elemendid on kasvavalt järjestatud isikukoodi väärtuse alusel - Person objekt isikukoodiga "1" peab olema väiksema indeksiga kui Person objekt isikukoodiga "2"
- Sisemiselt hoitakse Person objekte Person[] tüüpi massiivis - aga see massiiv ei tohi olla väljastpoolt objekti kättesaadav!
- Sisemise massiivi suurus ei tohi olla rohkem kui 2 korda suurem parasjagu hoitavate elementide arvust. See tähendab, et vastavalt vajadusele peab mõnikord uue suurema või väiksema suurusega massiivi looma ning kõik viited sinna üle kopeerima.
- Elementide lisamisel ja eemaldamisel peavad kõik järgnevad elemendid vastavalt nihkuma.
Nii Person kui SortedUniquePersonList klasside põhjad leiad siit: https://gist.github.com/anonymous/883e2ac30ef9478e34d4 Lugege hoolikalt klassi ja meetodite kommentaare ning veenduge, et teie poolt implementeeritav funktsionaalsus vastab kommentaarides väljalubatud nõuetele.
Kuigi see pole kohustuslik, siis soovitame meetodite funktsionaalsuse kontrolli "autotestida". Tõenäoliselt teeb see arendamise lihtsamaks ja aitab vigasid paremini leida. Näiteks saaks main meetodisse kirja panna tegevuste järjestuse, mille käigus elemente lisatakse ja eemaldatakse. Pärast iga tegevust tuleks siis kontrollida, et tagastatav väärtus vastab eeldatavale.
NB! Siin ülesandes tuleb sisemiselt kasutada just Person[], mitte ArrayList<Person> vms sisseehitatud resizable andmestruktuure. Ülesande eesmärk ongi ehitada ise midagi ArrayList sarnast.
NB! Sisemise Person[] peal ei peaks olema vaja kutsuda sorteerimisalgoritme. Lisa uued elemendid kohe õigesse kohta ja vajadusel tõsta olemasolevaid elemete edasi.
Tantsupaarid v2
Koosta meetod combine
, mis võtab parameetriteks kaks täisarvumassiivi — poiste pikkuste massiiv ja tüdrukute pikkuste massiiv (pikkused on antud sentimeetrites). Kumbki massiiv ei pruugi olla pikkuste järgi järjestatud. Koostada programm, mis moodustab tantsupaarid (poiss ja tüdruk) järgmise eeskirja kohaselt.
- Kui poisse ja tüdrukuid on võrdselt, siis moodustatakse paarid nii, et kõige pikem poiss tantsib kõige pikema tüdrukuga, pikkuselt järgmised on omavahel paaris jne.
- Kui ühe soo esindajaid on rohkem kui teise soo esindajaid, siis jäetakse sellest soost sobiv arv kõige pikemaid ilma paariliseta.
Meetod peab tagastama kahemõõtmelise massiivi, kus on nii mitu elementi, kui tantsupaare koostati. Iga massiivi element on kahe elemendiga massiiv, kus esimene element on poisi pikkus ja teine tüdruku pikkus.
Koosta main
meetod, mis saab käsurealt parameetriteks poiste ja tüdrukute pikkused, koostab combine
meetodi abil tantsupaarid ja prindib need ilusti välja. Käsurida on järgnevas formaadis: poiste arv, iga poisi pikkus tühikutega eraldatud, tüdrukute arv, iga tüdruku pikkus tühikutega eraldatud.
Näide
Sisend:
3 176 179 169 2 172 167
Väljund:
176 ja 172 169 ja 167
NB! Käsurida (main
meetodi parameeter) mitte segi ajada interaktiivse sisendiga System.in
.
Vihje: Massiivi võib sorteerida kasutades meetodit java.util.Arrays.sort(int[])
.