Erinevus lehekülje "ITI0011:Säuts" redaktsioonide vahel

Allikas: Kursused
Mine navigeerimisribale Mine otsikasti
 
(ei näidata sama kasutaja 9 vahepealset redaktsiooni)
1. rida: 1. rida:
 
[[ITI0011|Tagasi kursuse lehele]]
 
[[ITI0011|Tagasi kursuse lehele]]
  
<div style="color: #F00">Ülesande tekst täieneb!</div>
+
<div style="color: #F00">Lisaülesannete osa täieneb.</div>
  
Ülesande tähtaeg on '''26. - 27. märts'''.
+
Ülesande tähtaeg on '''7. - 8. aprill'''.
 +
 
 +
Lisapunkti ennetähtaegse esitamise eest saab siis, kui kood on gitis üleval '''3. aprilli''' seisuga. Kaitsmine toimub ikka 7. - 8. aprillil.
 +
 
 +
Loe täpsemat juhendit, kuidas seda ülesannet peaks lahendama: [[ITI0011:Säuts - koodijuhend]].
 +
 
 +
Testid tulevad alates esmaspäevast (30. märts) jooksvalt.
  
 
== Ülesande kirjeldus ==
 
== Ülesande kirjeldus ==
101. rida: 107. rida:
  
 
Kui teil on Twitteri konto olemas, saate olemasoleva konto alla luua rakenduse. Kuigi üldiselt on ülesande eesmärk pärida avalikke säutse, võite teha rakenduse, mis pärib teie kasutajaga seotud säutse (ehk siis nende omasid, keda jälgite ja/või kes on sõbrad). Jällegi, üldjuhul see lisapunkte ei anna. Tähelepanu, kui teete päringuid oma sõbrade kohta, on teil lisaks rakenduse võtmele lisada juurde ka teie enda võtmed. Selle kohta leiate näiteid siit: http://twitter4j.org/en/configuration.html . Kõik sealsed näited käivadki selle olukorra kohta, kus on vaja teha päringuid konkreetselt teie kasutaja alt. Kui te oma kasutaja infot ei lisa, saab teostada vaid avalikke päringuid.
 
Kui teil on Twitteri konto olemas, saate olemasoleva konto alla luua rakenduse. Kuigi üldiselt on ülesande eesmärk pärida avalikke säutse, võite teha rakenduse, mis pärib teie kasutajaga seotud säutse (ehk siis nende omasid, keda jälgite ja/või kes on sõbrad). Jällegi, üldjuhul see lisapunkte ei anna. Tähelepanu, kui teete päringuid oma sõbrade kohta, on teil lisaks rakenduse võtmele lisada juurde ka teie enda võtmed. Selle kohta leiate näiteid siit: http://twitter4j.org/en/configuration.html . Kõik sealsed näited käivadki selle olukorra kohta, kus on vaja teha päringuid konkreetselt teie kasutaja alt. Kui te oma kasutaja infot ei lisa, saab teostada vaid avalikke päringuid.
 +
 +
 +
== Põhiosa (5p) ==
 +
 +
Põhiosa võtab käsurealt asukoha (ja säutsude koguse, kui see on määratud), otsib vastavalt asukohale üles selle koordinaadid. Leitud koordinaatidega ja arvutatud raadiusega tehakse Twitteri päring. Tulemused kuvatakse kasutajale välja.
 +
 +
Kogu ülesanne peab olema realiseeritud ilma graafilise kasutajaliidese komponentideta. Kui kasutad mõnda komponenti nii, et teste see ei sega (kõik interface'ides etteantud meetodid töötavad otse käivitades ja teevad seda, mida on nõutud), siis otseselt punkte alla ei võeta. Aga soovitatav ei ole selliseid komponente kasutada (selle jaoks on järgmine ülesanne).
 +
 +
'''Põhiosa peaks töötama nii, et kasutajalt mingit sisendit programmi töö jooksul ei oodata''' (a la "siseta linn" või "tahad veel?"). Samuti ei tohiks ühtegi graafilise kasutajaliidese akent/dialoogi avaneda (mille puhul selle akna sulgemine oleks juba kasutaja sisend).
 +
 +
Interaktiivse kasutajaliidese lisaosas on kasutaja sisendi ootamine kohustuslik (et punktid kätte saada).
 +
 +
== Põhiosa: käsurealt juhtimine ==
 +
 +
Programm peab olema juhitav käsurealt, näiteks (juhul, kui teil on vastavad lisaosad tehtud):
 +
 +
  java Twitter Tallinn -count 50 -sort date desc -search tere
 +
 +
Minimaalne käivitamine (põhiosa) toimub näiteks selliselt:
 +
 +
  java Twitter Tallinn
 +
 +
kus
 +
* <code>java</code> on java programm ise, mis hakkab teie programmi jooksutama.
 +
* <code>Twitter</code> on klassi nimi, mida käivitatakse
 +
* <code>Tallinn</code> on asukoht, mida otsitakse.
 +
 +
Seega sellise käivitamise puhul antakse teie programmi ette üks argument: "Tallinn"
 +
 +
Teine variant põhiosa jaoks (päritakse 40 säutsu):
 +
 +
  java Twitter Tallinn -count 40
 +
 +
Kui programm pannakse käima ilma argumentideta, tuleb kasutajale kuvada juhised, kuidas programmi käima panna.
 +
 +
Argumendid, mida programm peab ära tundma:
 +
* <code>-help</code> (põhiosa) - kuvab kasutajale juhise, kuidas programmi käima panna. Peale juhiste kuvamist pannakse programm kinni, väljumiskood (exit code) peaks olema 1. Samad juhised näidatakse (ja sama väljumiskood tagastatakse) siis, kui:
 +
** programm pannakse ilma argumentideta käima või
 +
** sisestatud argumendid on valed
 +
* <code>-count ''num''</code> (põhiosa) - määrab ära, mitu säutsu välja näidatakse. Kui see puudub, siis peab programmis olema määratud vaikimisi päritav säutsude kogus 15.
 +
* <code>-sort ''field'' [asc|desc]</code> (lisaosa) - määrab ära, kuidas säutsud järjestatakse väljaprintimiseks. Väli võib olla kas: <code>author</code>, <code>date</code> või <code>tweet</code>. Valikuliselt võib kaasa panna kas <code>asc</code> või <code>desc</code>. Esimesel juhul toimub järjestamine kasvavalt, teisel juhul kahanevalt. Kui pole määratud, siis vaikimisi järjestatakse kasvavalt. Vaata ka vastavat lisaosa kirjeldust. Näide: <code>-sort author asc</code> ja <code>-sort author</code> annavad sama tulemuse.
 +
* <code>-search ''keyword''</code> (lisaosa) - kuvatakse vaid säutsud, milles esineb etteantud otsisõna.
 +
* ...
 +
 +
Argumendid võivad tulla suvalises järjekorras. '''Esimene argument on alati asukoht'''. Ehk siis kaks järgnevat käivitamist peaks andma sama tulemuse:
 +
 +
 +
  java Twitter Tallinn -count 50 -sort date desc -search tere
 +
 +
  java Twitter Tallinn -search tere -sort date desc -count 50
 +
 +
== Lisaosa: Kohanimede puhverdamine faili (2p) ==
 +
 +
Kuna linnade/asukohtade koordinaadid ei ole ajas muutuvad, siis ei ole mõtet igal korral, kui kasutaja otsib "Tallinna" kohta säutse, uut koordinaatide päringut teha. Tulemus on väga suure tõenäosusega täpselt sama, mis eelmisel korral. Seoses sellega oleks mõistlik salvestada tulemused kuskile puhvrisse (faili) ning neid hiljem sealt lugeda.
 +
 +
Selle lisaosa funktsionaalsus on:
 +
* asukoha koordinaatide päringu tulemused salvestatakse faili, et järgmisel korral ei peaks neid uuesti küsima (kohalik ''cache'')
 +
* nimetatud faili saab lisada alternatiivseid kohanimesid (näiteks "kodu", "TTÜ" jne)
 +
 +
Puhverdamiseks kasuta vaikimisi faili "kohad.csv", mis peab olema sinu programmile kättesaadav (soovitavalt paikneb samas kataloogis käivitatava klassiga) ja peab koosnema CSV kujul ridadest:
 +
 +
    ametlik_nimi,latitude,longitude,raadius_km,alternatiivnenimi_1,..,alternatiivnenimi_N
 +
 +
või ridadest, kus koordinaadid ja raadius on puudu:
 +
 +
    ametlik_nimi,,,,alternatiivnenimi_1,...,alternatiivnenimi_N
 +
 +
kus
 +
* ametlik_nimi on kohanimi, mida otsitakse API-st (näiteks <code>tallinn</code>)
 +
* alternatiivnimi_1, ..., alternatiivnimi_N on nimed, mida kasutaja saab sisestada. Näiteks saab kasutaja siin määrata "kodu". Kui vastav päring tehakse, otsitakse tegelikult ametlik_nimi asukohta (või kasutatakse juba olemasoelvaid koordinaate ja raadiust, kui need on olemas) (näiteks <code>kodu,elupaik</code>)
 +
* latitude, longitude ja raadius_km on standardse tähendusega. Need võivad puududa. (näiteks: <code>59.4,24.5,10</code>)
 +
 +
Sinu programm kasutab puhvrifaili järgmiselt:
 +
* Enne asukoha API poole pöördumist vaatab programm, kas vastav kohanimi on selles failis olemas
 +
** Kui jah, ja koordinaadid-raadius on antud, kasutab ta koordinaate ja raadiust Twitteri päringu tegemiseks. Asukoha päringut ei tehta
 +
** Kui jah, aga koordinaadid on puudu, siis
 +
*** teeb uue asukoha API päringu ametliku kohanime järgi, leiab koordinaadid ja arvutab raadiuse
 +
*** kirjutab saadud koordinaadid ja raadiuse vastava rea juurde. Järgmisel korral sama päringu puhul pole vaja asukoha API-t enam kasutada.
 +
** Kui ei, siis tehakse uus päring ning puhverdatakse tulemused faili (kirjutatakse uus rida, kus on ametlik_nimi, koordinaadid ja raadius: <code>pärnu,58.3800572,24.5200466,5)</code>.
 +
 +
Näited:
 +
 +
1) kohad.csv:
 +
 +
    tallinn,59.4,24.5,10,kodu,ttü
 +
 +
Kui tehakse otsing "tallinn", siis kasutatakse koordinaate 59.4 ja 24.5, raadius = 10km. Sama juhtub, kui teha päring "ttü", "kodu". kohad.csv fail ei muutu.
 +
 +
 +
2) kohad.csv:
 +
 +
    pärnu,,,,vanaema,suvila
 +
 +
Kui tehakse otsing "pärnu" või "vanaema" või "suvila", siis otsitakse asukoha API-ga üles "pärnu", loetakse välja koordinaadid ja arvutatakse välja raadius. Tulemuseks on sama rida failis:
 +
 +
    pärnu,58.3,24.5,5,vanaema,suvila
 +
 +
3) kohad.csv:
 +
 +
    tallinn,59.4,24.5,10,kodu,ttü
 +
 +
Kui tehakse otsing "pärnu", siis tehakse asukoha otsing "pärnu" ja salvestatakse koordinaadid ja raadius faili. Tulemuseks on fail:
 +
 +
    tallinn,59.4,24.5,10,kodu,ttü
 +
    pärnu,58.3,24.5,5
 +
 +
4) kohad.csv
 +
 +
    tallinn,59.4,24.5,10,kodu,pärnu
 +
    pärnu,58.3,24.5,5
 +
 +
Kui tehakse otsing "pärnu", siis kasutatakse infot teiselt realt. Ehk siis ametlik nimi on prioriteetsem kui alternatiivsed nimed. Kui sellist ametlikku nime ei leidu, otsitakse alternatiivsete nimede seast.
 +
 +
Faili sisu ei tohi olla tõstutundlik, ehk siis otsingud jm toimub ''case-insensitive'' printsiibil, kus suur- ja väiketäht on võrdsed ("Pärnu", "pärnu" ja "PÄRNU" on kõik samad).
 +
 +
Teie programmis mingeid muid operatsioone ei pea failiga tegema (näiteks kustuta rida või muuda vms). Faili muutmine toimub käsitsi. Samuti ei pea te otseselt tegelema valesti formaaditud failiga. Samas, kui tekib viga andmete lugemisel, ei tohiks see programmi kinni panna. Pigem kui ''cache'''i ei suudega lugeda, siis arvestada olukorraga nagu ''cache'' puudub (kõik päringud tehakse veebist).
 +
 +
See lisaosa täielikult realiseerituna annab 2 punkti.
 +
 +
 +
== Lisaosa: sortimine ja filtreerimine(otsimine) (1p) ==
 +
 +
Võimaldab säutse sorteerida vastavalt etteantud väljale. Sorteerida saab järgmiste väljade järgi:
 +
* autor
 +
* postituse kuupäev
 +
* postitus (ehk siis säutsu tekst)
 +
 +
Sorteerida saab nii kasvavas (väiksemad ees, näiteks: <code>a, b, c, ...</code> või <code>1, 3, 5, ...</code>) kui kahanevas (suuremad ees, näiteks: <code>ü, ö, ä, ...</code> või <code>9, 8, 4, ...</code>) järjekorras.
 +
 +
Samuti on võimalik anda ette otsisõna. Näidatakse välja vaid neid säutse, kus otsisõna esineb. Vihjeks: teie kasutada olev teek võimaldab otsingut suhteliselt lihtsalt teha.
 +
 +
Selle lisaosa täielik realiseerimine annab 1 punkti.
 +
 +
== Lisaosa: interaktiivne juhtimine (1-2p) ==
 +
 +
Põhiosa nõue oli, et programm oleks juhitav käsurea argumentidega:
 +
 +
  java Twitter Tallinn -count 50 -sort date desc -search tere
 +
 +
Selle lisaosa eesmärk on luua interaktiivne keskkond, mille kaudu saab programmi juhtida. Põhiosas pandi programm käima ning see lõpetas töö ilma, et oleks kasutajalt mingit sisendit oodanud. Interaktiivne keskkond tähendab seda, et programm ootab kasutajalt sisendit ja täidab etteantud käsud. Peale käsu täitmist ootab programm järgmist käsku jne (nagu command prompt või terminal). Näiteks:
 +
 +
<pre>
 +
> setcount 50
 +
> query Tallinn
 +
> print
 +
> query Pärnu 10
 +
> sort date desc
 +
> print
 +
> search tere
 +
> print
 +
> exit
 +
</pre>
 +
 +
Programm peab tundma järgmisi käske:
 +
* <code>query ''location'' [''count'']</code> (põhiosa) - tehakse uus päring vastavalt etteantud asukohaga ''location''. Päringuga on võimalik kohe kaasa anda ka tulemuste kogus. Päring ei kuva automaatselt säutse välja (vt. <code>print</code>. Näiteks <code>query Tallinn</code> teeb päringu "Tallinn", säutsude kogus on see, mis viimati programmis määratud või vaikimisi 15. <code>query Pärnu 10</code> teeb päringu "Pärnu" ja kasutab säutuse kogusena 10. See päring ei muuda mälus hoitavat säutsude kogust (vt <code>setcount</code>)
 +
* <code>print [''count'']</code> (põhiosa) - prindib viimase päringu tulemuse välja. <code>print</code> prindib kõik säutsud, mis viimase päringuga on saadud. <code>print 10</code> prindib viimasest päringust 10 esimest säutsu (sorteeritud tulemuse puhul on oluline, et määratud kogus võetakse algusest järjest). Kui säutse tuli viimase päringuga vähem, siis tuleb kõik tulemused printida.
 +
* <code>setcount ''num''</code> (põhiosa) - määrab päritavate säutsude arvu. Määratud arv jääb meelde ja kasutatakse kõikide järgmiste päringute korral (kui päringus eraldi kogust ei määrata, vt. <code>query</code>). Näiteks: <code>setcount 30</code> - edaspidi <code>query</code> päringus küsitakse ja <code>print</code> käsuga kuvatakse vaikimisi 30 säutsu.
 +
* <code>sort ''field'' [asc|desc]</code> (lisaosa) - tulemuste sorteerimine. Käsku rakendatakse viimase päringu kohta. Kui peale sorteerimist tehakse uus päring, siis uue päringu puhul enam seda sama järjestamist rakendama ei pea. Seega selle käsu tulemusel järjestatakse viimane tulemus. Väli (''field'') võib olla kas <code>author</code>, <code>date</code> või <code>tweet</code>. Lisaks võib juurde määrata järjestamise suuna: <code>asc</code> - kasvav, <code>desc</code> - kahanev. Vt rohkem [[#Lisaosa: sortimine ja filtreerimine(otsimine) (1p)]].
 +
* <code>search ''keyword''</code> (lisaosa) - teostatakse viimane päring uuesti (ehk siis kõik see, mis viimase <code>query</code> käsuga tehti), seekord kasutatakse määratud märksõna ''keyword''. Seega, kui eelnevalt otsiti "Tallinn" ja nüüd tuleb käsk <code>search kevad</code>, tehakse uus päring Tallinna kohta, kus otsisõnaks on "kevad". Kui seejärel käivitatakse käsk <code>search suvi</code>, tehakse uus päring Tallina kohta, seekord otsitakse märksõna "suvi" jne.
 +
* <code>exit</code> (põhiosa) - väljub programmist.
 +
 +
Eelnevate käskude korrektne realiseerimine annab 1p.
 +
 +
Täiendava punkti saab siis, kui nii käsurealt saadavad argumendid kui ka siin määratud käsud käivitatakse täpselt sama loogikaga. Mõlemast kohast saadud käsud teisendatakse samale kujule ning seejärel need käivitatakse. Programmi jaoks ei ole vahet, kas käsk tuli käsurealt või kasutaja poolt standardsisendist (või failist - pole antud ülesandes vajalik). Kui kunagi on teil soov täiendada programmi sedasi, et rakendust saab juhtida ka näiteks väljaspoolt üle veebi, siis piisab sellest, kui realiseerite selle osa, mis käsud vastu võtab ja tõlgendab nad juba siin mainitud ühtsele kujule. Käskude täitmise osa on teil juba realiseeritud.
 +
 +
<strike>Kui nii käsurealt kui interaktiivsest keskkonnast saadud käsud protsessitakse täpselt samamoodi, saab lisaosa eest täiendava 1p (ehk siis kokku 2p).</strike> Kui lahendate ülesande vastavalt etteantud mallile (interface'idele), siis toimub käskude parsimine ühtselt niiehknaa. Ehk siis käsud tõlgitakse Action objektideks ja need käivitatakse juba ühtemoodi. Seega kui see lisaosa on realiseeritud, saab selle eest 2p.
 +
 +
== Lisaosa (keerulisem): trendid (2p) ==
 +
 +
Lisaosa eesmärk on vastavalt määratud asukohale leida selle piirkonna trendid (ehk siis populaarsed märksõnad, teemad, ''hastag''id). Seejärel kuvatakse välja vaid need säutsud, mis kuuluvad trendide hulka (sisaldavad mõnda märksõna, ''hashtag''i vms).
 +
 +
Realiseerimise kirjeldus ilmub lähiajal. Kuigi kui te lahendate selle mingil muul kujul, siis saate ka punktid kätte.
 +
 +
Üks võimalik lahendus:
 +
* kasutada sellist API-d nagu: https://dev.twitter.com/rest/reference/get/trends/place
 +
* twitter4j puhul tasub vaadata järgmist interface'i: TrendsResources (http://twitter4j.org/javadoc/twitter4j/api/TrendsResources.html)
 +
 +
Lisaosa jaoks tuleb täiendav muudatus malli, mis võimaldaks lisaosa funktsionaalsust testida.
 +
 +
== Lisaosa (keerulisem): streaming (2p) ==
 +
 +
Lisaosa eesmärk on kuulata Twitteri voogu (''stream'') ning salvestada saadud säutsud faili. Hiljem on võimalik salvestatud failiga opereerida: vaadata kõiki säutse, vaadata statistikat (mitu säutsu, mitme erineva kasutaja poolt, kõige rohkem säutse teinud kasutaja), otsing.
 +
 +
Võimalik lahendus:
 +
* http://twitter4j.org/en/code-examples.html#streaming
 +
* http://twitter4j.org/javadoc/twitter4j/TwitterStream.html
 +
 +
Lisaosa jaoks tuleb täiendav muudatus malli, mis võimaldaks lisaosa funktsionaalsust testida.
 +
 +
 +
== Mall ==
 +
 +
Lae alla interface'ide failid: [[Meedia:ITI0011-Twitter_interfaces_v0.2.zip]] (v0.2, 25. märts).
 +
Muudatused võrreldes v0.1-ga:
 +
* FilterAction jagunes kaheks eraldi Actioniks: SortAction ja SearchAction.
 +
* Lisandus PrintAction (interaktiivses keskkonnas on vaja print käsu jaoks ka Action objekti)
 +
* Säutsude nimekiri oli enne keerulise tüübiga <code>List<? extends Tweet></code>, nüüd muudetud lihtsalt <code>List<Tweet></code>. Sinna listi saate lisada loomulikult ka <code>Tweet</code> alamtüüpi objekte (näiteks <code>MyTweet</code>).
 +
* Action interface'i sai lisatud meetod <code>execute</code>, mis vaikimisi on tühi (default implementatsioon on tühi, ehk siis see meetod ei tee midagi. Soovi korral võib kasutada iga Action'i juures seda meetodit, et vastav tegevus reaalselt "ära teha". Muidu on ülesandes eraldi TwitterApplication.executeAction() meetod, mis peaks iga erinevat tüüpi Actioni käivitamise ära tegema. Selle asemel võite teha nii, et iga Action teab ise, kuidas teda käima pannakse.
 +
 +
Paar märkust koodi kohta:
 +
* Klass, mis implementeerib TwitterApplication interface'i, peaks sisaldama main-meetodit (ehk siis sealt pannakse programm käima).
 +
* Kõik failid peavad olema ühe package (ehk kausta) sees.
 +
* Kõik projektis kasutatavad jar-failid tuleb panna lib kausta alla (HW2/lib/twitter4j.jar näiteks). Peale twitter4j teegi võite kasutada ka mõnda muud teeki.
 +
* Keerulisemate lisaosade kohta praegune mall ei vasta.
 +
 +
TwitterApplication.java:
 +
<source lang="java">
 +
 +
 +
import java.util.List;
 +
 +
/**
 +
* The core interface for your application.
 +
* <p>
 +
* The setup of this class is the following:
 +
* <ul>
 +
* <li>in the constructor (not described here)
 +
* all the different service objects should be set.
 +
* E.g. setLocationSearch(), setTwitterSearch(), setCache() etc.
 +
* <li>the actual start of the application is done with:
 +
* <code>application.run(args);</code>
 +
* </ul>
 +
* <p>
 +
* The constructor of the class which implements TwitterApplication
 +
* could be the following:
 +
* <pre>
 +
* public AwesomeTwitterApplication() {
 +
*    LocationSearch locSearch = new AwesomeLocationSearch();
 +
*    this.setLocationSearch(locSearch);
 +
*    Cache cache = new AwesomeCache();
 +
*    this.setCache(cache);
 +
*    TwitterSearch twitterSearch = new AwesomeTwitterSearch();
 +
*    this.setTwitterSearch(twitterSearch);
 +
* }
 +
* </pre>
 +
*
 +
* Constructor should not do anything else. The actual execution
 +
* of the program starts with run(args).
 +
* <p>
 +
* Setting all your implementations of the services in the constructor
 +
* gives the test system opportunity to test each one of those.
 +
* @author Ago
 +
* @see TwitterApplication#run(String[])
 +
*
 +
*/
 +
public interface TwitterApplication {
 +
/**
 +
* The application will be run using arguments
 +
* from the command line (should be passed here
 +
* directly from the main method).
 +
* runWithArgs() method will be called.
 +
* <p>
 +
* If the arguments are empty, runInteractive() is run.
 +
*
 +
* @param args Arguments from command line (the same
 +
* which are passed to the main method).
 +
* @see TwitterApplication#runWithArgs(String[])
 +
* @see TwitterApplication#runInteractive()
 +
*/
 +
default public void run(String[] args) {
 +
if (args.length == 0) {
 +
runInteractive();
 +
} else {
 +
runWithArgs(args);
 +
}
 +
}
 +
 +
/**
 +
* Tries to run the program with command line
 +
* arguments.
 +
* <p>
 +
* If command line arguments are not correct,
 +
* the program can exit with an error code.
 +
* @param args Arguments from command line.
 +
*/
 +
public void runWithArgs(String[] args);
 +
 +
/**
 +
* The application will be run in an interactive mode
 +
* where the user can enter different statements
 +
* to control the program.
 +
*/
 +
public void runInteractive();
 +
 +
/**
 +
* Given a command as a String (in interactive mode),
 +
* this method should parse the input and return
 +
* a list of Action instances.
 +
* Usually one command should create one action, this
 +
* method gives the opportunity to have combined actions
 +
* for one command line ("query tallinn 30" - query + count).
 +
* If you don't use combined actions, just return a list
 +
* with one element in it - the Action instance to be
 +
* executed.
 +
* @param action Command string from interactive mode
 +
* @return List of actions to be executed
 +
*/
 +
public List<Action> getActionsFromInput(String action);
 +
 +
/**
 +
* Given command line arguments this method parses
 +
* the arguments and returns a list of Action instances.
 +
* As the command line can accept several different actions
 +
* (for example query, sort and search), this method
 +
* return a list of all the actions.
 +
* @param args Command line arguments (from main method)
 +
* @return List of actions to be executed
 +
*/
 +
public List<Action> getActionsFromArguments(String[] args);
 +
 +
/**
 +
* Given an instance of Action, it will be executed.
 +
* If you choose to implement Action.execute()
 +
* for every action, then the body of this method can just be:
 +
* action.execute()
 +
* @param action Action to be executed
 +
*/
 +
public void executeAction(Action action);
 +
 +
/**
 +
* Executes all the actions given as a list.
 +
* The default implementation just iterates over
 +
* all the actions and calls executeAction.
 +
* @param actions A list of actions
 +
*/
 +
default public void executeActions(List<Action> actions) {
 +
for (Action action : actions) {
 +
executeAction(action);
 +
}
 +
}
 +
 +
/**
 +
* Executes a location search using location search set with
 +
* setLocationSearch().
 +
* Returns a query object which holds all the values for Twitter search.
 +
* Note that this method has a default implementation which
 +
* just executes a method from local location search and
 +
* returns its return value.
 +
* Use this default implementation if you don't have caching implemented.
 +
* If you need caching, you need to override this method.
 +
* @param location The location which is to be searched for
 +
* @return Query object which holds all the necessary information
 +
* about Twitter query
 +
* @see TwitterApplication#setLocationSearch(LocationSearch)
 +
*/
 +
default public TwitterQuery getQueryFromLocation(String location) {
 +
LocationSearch locationSearch = getLocationSearch();
 +
return locationSearch.getQueryFromLocation(location);
 +
}
 +
 +
/**
 +
* Executes a search of tweets on TwitterSearch object which
 +
* is stored via setTwitterSearch().
 +
* Returns a list of received tweets.
 +
* @param query Query object which holds all the necessary values
 +
* @return List of Tweet objects received from Twitter search.
 +
* <code>null</code> if nothing received.
 +
* @see TwitterApplication#setTwitterSearch(TwitterSearch)
 +
*/
 +
default public List<Tweet> getTweets(TwitterQuery query) {
 +
TwitterSearch twitterSearch = getTwitterSearch();
 +
return twitterSearch.getTweets(query);
 +
}
 +
 +
/**
 +
* Stores location search object which will
 +
* be used to make queries to location search API.
 +
* This should be called from the constructor.
 +
* @param locationSearch Implementation of LocationSearch, which
 +
* can find information about location (city, country etc.).
 +
*/
 +
public void setLocationSearch(LocationSearch locationSearch);
 +
 +
/**
 +
* Returns currently stored location search object.
 +
* @return Implementation of LocationSeach
 +
* which will be used for location search.
 +
*/
 +
public LocationSearch getLocationSearch();
 +
 +
/**
 +
* Stores Twitter search object which will be used
 +
* to query tweets from Twitter API.
 +
* Should be called from the constructor.
 +
* @param twitterSearch Implementation of TwitterSearch
 +
*/
 +
public void setTwitterSearch(TwitterSearch twitterSearch);
 +
 +
/**
 +
* Returns currently stored Twitter search object.
 +
* @return Implementation of TwitterSearch
 +
* which will be used for queries.
 +
*/
 +
public TwitterSearch getTwitterSearch();
 +
 +
/**
 +
* Stores cache object which will be used
 +
* to cache locations in the file.
 +
* Should be called from the constructor.
 +
* @param cache Implementation of Cache
 +
*/
 +
public void setCache(Cache cache);
 +
 +
/**
 +
* Returns currently stored cache object.
 +
* @return Implementation of Cache
 +
* which will be used for location caching.
 +
*/
 +
 +
public Cache getCache();
 +
 +
/**
 +
* Stores the latest state of tweets list.
 +
* You should store your tweets using this
 +
* method after querying, sorting, searching.
 +
* @param tweets A list of tweets
 +
*/
 +
public void setTweets(List<Tweet> tweets);
 +
 +
/**
 +
* Get the latest state of tweets list.
 +
* This method should be used for printing
 +
* and when applying sorting.
 +
* @return A list of tweets
 +
*/
 +
public List<Tweet> getTweets();
 +
 +
}
 +
 +
</source>

Viimane redaktsioon: 5. aprill 2015, kell 05:56

Tagasi kursuse lehele

Lisaülesannete osa täieneb.

Ülesande tähtaeg on 7. - 8. aprill.

Lisapunkti ennetähtaegse esitamise eest saab siis, kui kood on gitis üleval 3. aprilli seisuga. Kaitsmine toimub ikka 7. - 8. aprillil.

Loe täpsemat juhendit, kuidas seda ülesannet peaks lahendama: ITI0011:Säuts - koodijuhend.

Testid tulevad alates esmaspäevast (30. märts) jooksvalt.

Ülesande kirjeldus

Teie programm teeb päringu sotsiaalvõrgustiku Twitter avalike säutsude (tweet) seast. Päritakse viimased avalikud säutsud vastavalt etteantud kohanimele ja kuvatakse need kasutajale.

Funktsionaalsus:

  • loetakse etteantud kohanimi (nt Tallinn)
  • kohanime kohta päritakse tema geograafilised koordinaadid (latitude, longitude)
  • saadud geograafilisi koordinaate kasutatakse, et arvutada välja säutsude kogumise keskpunkt ja otsitava ala raadius
  • Twitteri API-sse saadetakse päring vastavalt määratud keskpunkti ja raadiusega
  • Twitteri API vastusest loetakse välja vajalikud andmed ja kuvatakse ekraanile.
  • programmile saab kohanime ette anda käsurealt

Lisaosad:

  • Kohanimede puhverdamine faili (et ei pea pidevalt otsima näiteks Tallinna koordinaate, mis ei muutu).
  • Säutsude sorteerimine
  • Interaktiivne programmi juhtimine
  • Testitav kood (programmi koostamine vastavalt etteantud mallile)

Täiendavat infot

Kohanimele vastavad koordinaadid

Kasutame OpenStreetMap kommuuni tööriista Nominatim (Nominatim wiki leht). Te saadate sellele tööriistale päringu soovitud kohanimega ja vastusest loete välja kohanimele vastavad koordinaadid (latitude ja longitude) ning ümbritseva ala piirmised punktid (bounding box).

Näitepäring: http://nominatim.openstreetmap.org/search?q=Tallinn&format=xml

Sealt saate tulemuse (kompaktsuse mõttes on näidatud vaid olulisem osa tulemusest):

<searchresults timestamp="Sat, 13 Sep 14 21:47:21 +0000" 
attribution="Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright" 
querystring="Tallinn" polygon="false" 
exclude_place_ids="98174326,11438224,6000303521,6919504,6893196,86869124,15103978,5983246058" 
more_url="http://nominatim.openstreetmap.org/search?format=xml&
exclude_place_ids=98174326,11438224,6000303521,6919504,6893196,86869124,15103978,5983246058&accept-language=en-
US,en;q=0.5&q=Tallinn">
<place place_id="98174326" osm_type="relation" osm_id="2164745" place_rank="16" 
boundingbox="59.351806640625,59.5915794372559,24.5501689910889,24.9262847900391" lat="59.4372155" 
lon="24.7453688" display_name="Tallinn, Harju maakond, Estonia" class="place" type="city" 
importance="0.7819722223575" icon="http://nominatim.openstreetmap.org/images/mapicons/poi_place_city.p.20.png"/>
...
</searchresults>

Tulemuseks saate mitu erinevat kohta, mille nimi on Tallinn (või nimes sisaldub selline sõna). Kõige esimene vaste meie programmi jaoks sobib. Seega loete välja esimese "place" elemendi. Kuna Twitteri päringu jaoks on meil vaja koordinaati ning raadiust (kui suure ala pealt tulemusi otsitakse), siis huvitavad meid atribuudid "lat" ja "lon" (latitude ja longitude), mis määravad ära keskpunkti, ning atribuut "boundingbox", mis näitab antud asukoha ümbritseva ala piirjooni. Antud näite näite puhul lat="59.4372155", lon="24.7453688", boundingbox="59.351806640625,59.5915794372559,24.5501689910889,24.9262847900391".

Twitteri päringus otsitav piirkond on märgitud keskpunkti ning raadiusega. Keskpunktiks võib kasutada otse eelnevalt saadud "lat" ja "lon" väärtusi. Raadiuse leidmiseks võib kasutada "boundingbox" väärtust. Kuna raadius peab olema esitatud näiteks kilomeetrites, siis tuleks boundingbox argumentide järgi leida mõistlik raadius. Tähelepanu, erinevas maakera piirkonnas on näiteks longitude 0.1 ühikuline erinevus oluliselt erineva pikkusega. Antud ülesande jaoks ei pea te arvutama väga täpse raadiuse, mis piiratud alasse sisse jääb. Piisab, kui te suurusjärgu panete paika. Siin ülesande kirjelduses konkreetset valemit või näidet toodud ei ole - selle võrra tulevad loodetavasti esitatud kodused ülesanded võimalikult erinevad. Väga täpseks ja põhjalikuks ei tasu ka minna - boonuspunkte selle arvutuse eest üldjuhul ei saa. Oluline on, et oluliselt erineva suurusega linnad annaksid erineva raadiuse (New York > > Tallinn > Haapsalu).

Seega teil on oluline, et oskate vajalikud andmed välja lugeda ning need teisendada keskpunktiks ja raadiuseks.

Märkus. Põhiosa lahendamiseks sobib ka see, kui kasutate mõnda muud API-t (näiteks Google Maps'i oma).

Twitteri API

Twitteri API (https://dev.twitter.com/docs/api/1.1) võimaldab programmiga teha automaatseid päringuid sotsiaalvõrgustiku Twitter andmetest. Antud ülesande lahendamiseks ei pea te olema aktiivne Twitteri kasutaja.

Twitteri API kasutamiseks on teil vajalik siiski luua konto ning selle alla App (application). Kui olete twitteri konto teinud ja sisse loginud, peaksite nägema oma rakendusi sellelt lehelt: https://apps.twitter.com/ (link on olemas ka dev.twitter.com veebilehe lõpus "TOOLS" nimekirja all). Seal looge oma app, kus võite veebileheks panna suvalise URL-i (kasvõi kursuse veebilehe).

Kui olete oma rakenduse loonud, näete seda oma applications nimekirjas. Kui avate loodud rakenduse, siis "API keys" tääbi alt avanevad rakenduse seaded. Sealt huvitavad meid "API key" ja "API secret". Neid kahte väärtust on vaja, et teha päringuid Twitter API-st.

Päring ise, mida peab kasutama, on kirjeldatud siin: https://dev.twitter.com/rest/public/search ja https://dev.twitter.com/rest/reference/get/search/tweets

Näiteks võiks päring olla selline: https://api.twitter.com/1.1/search/tweets.json?q=&geocode=59.437215524.7453688,1km&result_type=recent

Mainitud link brauseris ei peagi tulemust andma, kuna te pole eelnevalt sisse loginud. See annab Tallinnas säutse 1km raadiuses.

Natuke informatsiooni, kuidas rakendust vastu Twitteri API-t autentida: https://dev.twitter.com/oauth .

Selleks, et kogu protsess ei oleks liiga töömahukas ja keeruline, soovitame antud ülesande jaoks kasutada mõnda teeki (library), mis oskab autentimise ja ka pärimise teie eest ära teha. Üks selline, mille kohta on allpool ka paar koodinäidet, on siin: http://twitter4j.org/ . Kui tahate ja oskate, võite kasutada ka mõnda muud.

twitter4j puhul on teil vaja kätte saada järgmine fail: twitter4j-core-4.0.2.jar . Kui tõmbate alla zip-formaadis arhiivi, paikneb see fail kaustas "lib". Kirjutamise hetkel oli kasutusel versioon 4.0.2, see võib vabalt muutuda - vastavalt on siis ka failinimi erinev. Selle jar-faili peate oma Eclipse'i projekti lisama: project properties > java build path > libraries tääb > add external jars ... ning otsite üles nimetatud faili.

Konfigureerimise üks võimalus on selline: <source lang="java"> ConfigurationBuilder cb = new ConfigurationBuilder(); cb.setDebugEnabled(true) .setApplicationOnlyAuthEnabled(true); cb.setOAuthConsumerKey(TWITTER_CUSTOMER_KEY) .setOAuthConsumerSecret(TWITTER_CUSTOMER_SECRET);

TwitterFactory tf = new TwitterFactory(cb.build()); twitter4j.Twitter twitter = tf.getInstance();

OAuth2Token token; try { token = twitter.getOAuth2Token(); } catch (TwitterException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } </source>

Üleval näites TWITTER_CUSTOMER_KEY ja TWITTER_CUSTOMER_SECRET on konstandid ja nende väärtused on võetud twitteri lehel loodud rakenduse lehelt (application key ja application secret vastavalt). Loomulikult võite seadistamise teha ka konfiguratsioonifailiga või muudmoodi (selle kohta leiate rohkem infot teegi kodulehelt).

Seda, kuidas nüüd teegiga vajalik päring teha, peate ise uurima. Aga selle kohta on veebilehel olemas ka paar näidet. Siin on ka üks näide: https://github.com/yusuke/twitter4j/blob/master/twitter4j-core/src/test/java/twitter4j/SearchAPITest.java (see on võetud testide kaustast. tihti sisaldavad testid palju rohkem koodinäiteid kui tegelikud koodinäited.)

Kui teil on Twitteri konto olemas, saate olemasoleva konto alla luua rakenduse. Kuigi üldiselt on ülesande eesmärk pärida avalikke säutse, võite teha rakenduse, mis pärib teie kasutajaga seotud säutse (ehk siis nende omasid, keda jälgite ja/või kes on sõbrad). Jällegi, üldjuhul see lisapunkte ei anna. Tähelepanu, kui teete päringuid oma sõbrade kohta, on teil lisaks rakenduse võtmele lisada juurde ka teie enda võtmed. Selle kohta leiate näiteid siit: http://twitter4j.org/en/configuration.html . Kõik sealsed näited käivadki selle olukorra kohta, kus on vaja teha päringuid konkreetselt teie kasutaja alt. Kui te oma kasutaja infot ei lisa, saab teostada vaid avalikke päringuid.


Põhiosa (5p)

Põhiosa võtab käsurealt asukoha (ja säutsude koguse, kui see on määratud), otsib vastavalt asukohale üles selle koordinaadid. Leitud koordinaatidega ja arvutatud raadiusega tehakse Twitteri päring. Tulemused kuvatakse kasutajale välja.

Kogu ülesanne peab olema realiseeritud ilma graafilise kasutajaliidese komponentideta. Kui kasutad mõnda komponenti nii, et teste see ei sega (kõik interface'ides etteantud meetodid töötavad otse käivitades ja teevad seda, mida on nõutud), siis otseselt punkte alla ei võeta. Aga soovitatav ei ole selliseid komponente kasutada (selle jaoks on järgmine ülesanne).

Põhiosa peaks töötama nii, et kasutajalt mingit sisendit programmi töö jooksul ei oodata (a la "siseta linn" või "tahad veel?"). Samuti ei tohiks ühtegi graafilise kasutajaliidese akent/dialoogi avaneda (mille puhul selle akna sulgemine oleks juba kasutaja sisend).

Interaktiivse kasutajaliidese lisaosas on kasutaja sisendi ootamine kohustuslik (et punktid kätte saada).

Põhiosa: käsurealt juhtimine

Programm peab olema juhitav käsurealt, näiteks (juhul, kui teil on vastavad lisaosad tehtud):

 java Twitter Tallinn -count 50 -sort date desc -search tere

Minimaalne käivitamine (põhiosa) toimub näiteks selliselt:

 java Twitter Tallinn

kus

  • java on java programm ise, mis hakkab teie programmi jooksutama.
  • Twitter on klassi nimi, mida käivitatakse
  • Tallinn on asukoht, mida otsitakse.

Seega sellise käivitamise puhul antakse teie programmi ette üks argument: "Tallinn"

Teine variant põhiosa jaoks (päritakse 40 säutsu):

 java Twitter Tallinn -count 40

Kui programm pannakse käima ilma argumentideta, tuleb kasutajale kuvada juhised, kuidas programmi käima panna.

Argumendid, mida programm peab ära tundma:

  • -help (põhiosa) - kuvab kasutajale juhise, kuidas programmi käima panna. Peale juhiste kuvamist pannakse programm kinni, väljumiskood (exit code) peaks olema 1. Samad juhised näidatakse (ja sama väljumiskood tagastatakse) siis, kui:
    • programm pannakse ilma argumentideta käima või
    • sisestatud argumendid on valed
  • -count num (põhiosa) - määrab ära, mitu säutsu välja näidatakse. Kui see puudub, siis peab programmis olema määratud vaikimisi päritav säutsude kogus 15.
  • -sort field [asc|desc] (lisaosa) - määrab ära, kuidas säutsud järjestatakse väljaprintimiseks. Väli võib olla kas: author, date või tweet. Valikuliselt võib kaasa panna kas asc või desc. Esimesel juhul toimub järjestamine kasvavalt, teisel juhul kahanevalt. Kui pole määratud, siis vaikimisi järjestatakse kasvavalt. Vaata ka vastavat lisaosa kirjeldust. Näide: -sort author asc ja -sort author annavad sama tulemuse.
  • -search keyword (lisaosa) - kuvatakse vaid säutsud, milles esineb etteantud otsisõna.
  • ...

Argumendid võivad tulla suvalises järjekorras. Esimene argument on alati asukoht. Ehk siis kaks järgnevat käivitamist peaks andma sama tulemuse:


 java Twitter Tallinn -count 50 -sort date desc -search tere
 java Twitter Tallinn -search tere -sort date desc -count 50

Lisaosa: Kohanimede puhverdamine faili (2p)

Kuna linnade/asukohtade koordinaadid ei ole ajas muutuvad, siis ei ole mõtet igal korral, kui kasutaja otsib "Tallinna" kohta säutse, uut koordinaatide päringut teha. Tulemus on väga suure tõenäosusega täpselt sama, mis eelmisel korral. Seoses sellega oleks mõistlik salvestada tulemused kuskile puhvrisse (faili) ning neid hiljem sealt lugeda.

Selle lisaosa funktsionaalsus on:

  • asukoha koordinaatide päringu tulemused salvestatakse faili, et järgmisel korral ei peaks neid uuesti küsima (kohalik cache)
  • nimetatud faili saab lisada alternatiivseid kohanimesid (näiteks "kodu", "TTÜ" jne)

Puhverdamiseks kasuta vaikimisi faili "kohad.csv", mis peab olema sinu programmile kättesaadav (soovitavalt paikneb samas kataloogis käivitatava klassiga) ja peab koosnema CSV kujul ridadest:

   ametlik_nimi,latitude,longitude,raadius_km,alternatiivnenimi_1,..,alternatiivnenimi_N

või ridadest, kus koordinaadid ja raadius on puudu:

   ametlik_nimi,,,,alternatiivnenimi_1,...,alternatiivnenimi_N

kus

  • ametlik_nimi on kohanimi, mida otsitakse API-st (näiteks tallinn)
  • alternatiivnimi_1, ..., alternatiivnimi_N on nimed, mida kasutaja saab sisestada. Näiteks saab kasutaja siin määrata "kodu". Kui vastav päring tehakse, otsitakse tegelikult ametlik_nimi asukohta (või kasutatakse juba olemasoelvaid koordinaate ja raadiust, kui need on olemas) (näiteks kodu,elupaik)
  • latitude, longitude ja raadius_km on standardse tähendusega. Need võivad puududa. (näiteks: 59.4,24.5,10)

Sinu programm kasutab puhvrifaili järgmiselt:

  • Enne asukoha API poole pöördumist vaatab programm, kas vastav kohanimi on selles failis olemas
    • Kui jah, ja koordinaadid-raadius on antud, kasutab ta koordinaate ja raadiust Twitteri päringu tegemiseks. Asukoha päringut ei tehta
    • Kui jah, aga koordinaadid on puudu, siis
      • teeb uue asukoha API päringu ametliku kohanime järgi, leiab koordinaadid ja arvutab raadiuse
      • kirjutab saadud koordinaadid ja raadiuse vastava rea juurde. Järgmisel korral sama päringu puhul pole vaja asukoha API-t enam kasutada.
    • Kui ei, siis tehakse uus päring ning puhverdatakse tulemused faili (kirjutatakse uus rida, kus on ametlik_nimi, koordinaadid ja raadius: pärnu,58.3800572,24.5200466,5).

Näited:

1) kohad.csv:

   tallinn,59.4,24.5,10,kodu,ttü

Kui tehakse otsing "tallinn", siis kasutatakse koordinaate 59.4 ja 24.5, raadius = 10km. Sama juhtub, kui teha päring "ttü", "kodu". kohad.csv fail ei muutu.


2) kohad.csv:

   pärnu,,,,vanaema,suvila

Kui tehakse otsing "pärnu" või "vanaema" või "suvila", siis otsitakse asukoha API-ga üles "pärnu", loetakse välja koordinaadid ja arvutatakse välja raadius. Tulemuseks on sama rida failis:

   pärnu,58.3,24.5,5,vanaema,suvila

3) kohad.csv:

   tallinn,59.4,24.5,10,kodu,ttü

Kui tehakse otsing "pärnu", siis tehakse asukoha otsing "pärnu" ja salvestatakse koordinaadid ja raadius faili. Tulemuseks on fail:

   tallinn,59.4,24.5,10,kodu,ttü
   pärnu,58.3,24.5,5

4) kohad.csv

   tallinn,59.4,24.5,10,kodu,pärnu
   pärnu,58.3,24.5,5

Kui tehakse otsing "pärnu", siis kasutatakse infot teiselt realt. Ehk siis ametlik nimi on prioriteetsem kui alternatiivsed nimed. Kui sellist ametlikku nime ei leidu, otsitakse alternatiivsete nimede seast.

Faili sisu ei tohi olla tõstutundlik, ehk siis otsingud jm toimub case-insensitive printsiibil, kus suur- ja väiketäht on võrdsed ("Pärnu", "pärnu" ja "PÄRNU" on kõik samad).

Teie programmis mingeid muid operatsioone ei pea failiga tegema (näiteks kustuta rida või muuda vms). Faili muutmine toimub käsitsi. Samuti ei pea te otseselt tegelema valesti formaaditud failiga. Samas, kui tekib viga andmete lugemisel, ei tohiks see programmi kinni panna. Pigem kui cache'i ei suudega lugeda, siis arvestada olukorraga nagu cache puudub (kõik päringud tehakse veebist).

See lisaosa täielikult realiseerituna annab 2 punkti.


Lisaosa: sortimine ja filtreerimine(otsimine) (1p)

Võimaldab säutse sorteerida vastavalt etteantud väljale. Sorteerida saab järgmiste väljade järgi:

  • autor
  • postituse kuupäev
  • postitus (ehk siis säutsu tekst)

Sorteerida saab nii kasvavas (väiksemad ees, näiteks: a, b, c, ... või 1, 3, 5, ...) kui kahanevas (suuremad ees, näiteks: ü, ö, ä, ... või 9, 8, 4, ...) järjekorras.

Samuti on võimalik anda ette otsisõna. Näidatakse välja vaid neid säutse, kus otsisõna esineb. Vihjeks: teie kasutada olev teek võimaldab otsingut suhteliselt lihtsalt teha.

Selle lisaosa täielik realiseerimine annab 1 punkti.

Lisaosa: interaktiivne juhtimine (1-2p)

Põhiosa nõue oli, et programm oleks juhitav käsurea argumentidega:

 java Twitter Tallinn -count 50 -sort date desc -search tere

Selle lisaosa eesmärk on luua interaktiivne keskkond, mille kaudu saab programmi juhtida. Põhiosas pandi programm käima ning see lõpetas töö ilma, et oleks kasutajalt mingit sisendit oodanud. Interaktiivne keskkond tähendab seda, et programm ootab kasutajalt sisendit ja täidab etteantud käsud. Peale käsu täitmist ootab programm järgmist käsku jne (nagu command prompt või terminal). Näiteks:

> setcount 50
> query Tallinn
> print
> query Pärnu 10
> sort date desc
> print
> search tere
> print
> exit

Programm peab tundma järgmisi käske:

  • query location [count] (põhiosa) - tehakse uus päring vastavalt etteantud asukohaga location. Päringuga on võimalik kohe kaasa anda ka tulemuste kogus. Päring ei kuva automaatselt säutse välja (vt. print. Näiteks query Tallinn teeb päringu "Tallinn", säutsude kogus on see, mis viimati programmis määratud või vaikimisi 15. query Pärnu 10 teeb päringu "Pärnu" ja kasutab säutuse kogusena 10. See päring ei muuda mälus hoitavat säutsude kogust (vt setcount)
  • print [count] (põhiosa) - prindib viimase päringu tulemuse välja. print prindib kõik säutsud, mis viimase päringuga on saadud. print 10 prindib viimasest päringust 10 esimest säutsu (sorteeritud tulemuse puhul on oluline, et määratud kogus võetakse algusest järjest). Kui säutse tuli viimase päringuga vähem, siis tuleb kõik tulemused printida.
  • setcount num (põhiosa) - määrab päritavate säutsude arvu. Määratud arv jääb meelde ja kasutatakse kõikide järgmiste päringute korral (kui päringus eraldi kogust ei määrata, vt. query). Näiteks: setcount 30 - edaspidi query päringus küsitakse ja print käsuga kuvatakse vaikimisi 30 säutsu.
  • sort field [asc|desc] (lisaosa) - tulemuste sorteerimine. Käsku rakendatakse viimase päringu kohta. Kui peale sorteerimist tehakse uus päring, siis uue päringu puhul enam seda sama järjestamist rakendama ei pea. Seega selle käsu tulemusel järjestatakse viimane tulemus. Väli (field) võib olla kas author, date või tweet. Lisaks võib juurde määrata järjestamise suuna: asc - kasvav, desc - kahanev. Vt rohkem #Lisaosa: sortimine ja filtreerimine(otsimine) (1p).
  • search keyword (lisaosa) - teostatakse viimane päring uuesti (ehk siis kõik see, mis viimase query käsuga tehti), seekord kasutatakse määratud märksõna keyword. Seega, kui eelnevalt otsiti "Tallinn" ja nüüd tuleb käsk search kevad, tehakse uus päring Tallinna kohta, kus otsisõnaks on "kevad". Kui seejärel käivitatakse käsk search suvi, tehakse uus päring Tallina kohta, seekord otsitakse märksõna "suvi" jne.
  • exit (põhiosa) - väljub programmist.

Eelnevate käskude korrektne realiseerimine annab 1p.

Täiendava punkti saab siis, kui nii käsurealt saadavad argumendid kui ka siin määratud käsud käivitatakse täpselt sama loogikaga. Mõlemast kohast saadud käsud teisendatakse samale kujule ning seejärel need käivitatakse. Programmi jaoks ei ole vahet, kas käsk tuli käsurealt või kasutaja poolt standardsisendist (või failist - pole antud ülesandes vajalik). Kui kunagi on teil soov täiendada programmi sedasi, et rakendust saab juhtida ka näiteks väljaspoolt üle veebi, siis piisab sellest, kui realiseerite selle osa, mis käsud vastu võtab ja tõlgendab nad juba siin mainitud ühtsele kujule. Käskude täitmise osa on teil juba realiseeritud.

Kui nii käsurealt kui interaktiivsest keskkonnast saadud käsud protsessitakse täpselt samamoodi, saab lisaosa eest täiendava 1p (ehk siis kokku 2p). Kui lahendate ülesande vastavalt etteantud mallile (interface'idele), siis toimub käskude parsimine ühtselt niiehknaa. Ehk siis käsud tõlgitakse Action objektideks ja need käivitatakse juba ühtemoodi. Seega kui see lisaosa on realiseeritud, saab selle eest 2p.

Lisaosa (keerulisem): trendid (2p)

Lisaosa eesmärk on vastavalt määratud asukohale leida selle piirkonna trendid (ehk siis populaarsed märksõnad, teemad, hastagid). Seejärel kuvatakse välja vaid need säutsud, mis kuuluvad trendide hulka (sisaldavad mõnda märksõna, hashtagi vms).

Realiseerimise kirjeldus ilmub lähiajal. Kuigi kui te lahendate selle mingil muul kujul, siis saate ka punktid kätte.

Üks võimalik lahendus:

Lisaosa jaoks tuleb täiendav muudatus malli, mis võimaldaks lisaosa funktsionaalsust testida.

Lisaosa (keerulisem): streaming (2p)

Lisaosa eesmärk on kuulata Twitteri voogu (stream) ning salvestada saadud säutsud faili. Hiljem on võimalik salvestatud failiga opereerida: vaadata kõiki säutse, vaadata statistikat (mitu säutsu, mitme erineva kasutaja poolt, kõige rohkem säutse teinud kasutaja), otsing.

Võimalik lahendus:

Lisaosa jaoks tuleb täiendav muudatus malli, mis võimaldaks lisaosa funktsionaalsust testida.


Mall

Lae alla interface'ide failid: Meedia:ITI0011-Twitter_interfaces_v0.2.zip (v0.2, 25. märts). Muudatused võrreldes v0.1-ga:

  • FilterAction jagunes kaheks eraldi Actioniks: SortAction ja SearchAction.
  • Lisandus PrintAction (interaktiivses keskkonnas on vaja print käsu jaoks ka Action objekti)
  • Säutsude nimekiri oli enne keerulise tüübiga List<? extends Tweet>, nüüd muudetud lihtsalt List<Tweet>. Sinna listi saate lisada loomulikult ka Tweet alamtüüpi objekte (näiteks MyTweet).
  • Action interface'i sai lisatud meetod execute, mis vaikimisi on tühi (default implementatsioon on tühi, ehk siis see meetod ei tee midagi. Soovi korral võib kasutada iga Action'i juures seda meetodit, et vastav tegevus reaalselt "ära teha". Muidu on ülesandes eraldi TwitterApplication.executeAction() meetod, mis peaks iga erinevat tüüpi Actioni käivitamise ära tegema. Selle asemel võite teha nii, et iga Action teab ise, kuidas teda käima pannakse.

Paar märkust koodi kohta:

  • Klass, mis implementeerib TwitterApplication interface'i, peaks sisaldama main-meetodit (ehk siis sealt pannakse programm käima).
  • Kõik failid peavad olema ühe package (ehk kausta) sees.
  • Kõik projektis kasutatavad jar-failid tuleb panna lib kausta alla (HW2/lib/twitter4j.jar näiteks). Peale twitter4j teegi võite kasutada ka mõnda muud teeki.
  • Keerulisemate lisaosade kohta praegune mall ei vasta.

TwitterApplication.java: <source lang="java">


import java.util.List;

/**

* The core interface for your application.

*

* The setup of this class is the following: *

    *
  • in the constructor (not described here) * all the different service objects should be set. * E.g. setLocationSearch(), setTwitterSearch(), setCache() etc. *
  • the actual start of the application is done with: * application.run(args); *

*

* The constructor of the class which implements TwitterApplication * could be the following: *

 * public AwesomeTwitterApplication() {
 *     LocationSearch locSearch = new AwesomeLocationSearch();
 *     this.setLocationSearch(locSearch);
 *     Cache cache = new AwesomeCache();
 *     this.setCache(cache);
 *     TwitterSearch twitterSearch = new AwesomeTwitterSearch();
 *     this.setTwitterSearch(twitterSearch);
 * }
 * 
* 
* Constructor should not do anything else. The actual execution
* of the program starts with run(args).

*

* Setting all your implementations of the services in the constructor * gives the test system opportunity to test each one of those. * @author Ago * @see TwitterApplication#run(String[]) * */ public interface TwitterApplication { /** * The application will be run using arguments * from the command line (should be passed here * directly from the main method). * runWithArgs() method will be called. *

* If the arguments are empty, runInteractive() is run. * * @param args Arguments from command line (the same * which are passed to the main method). * @see TwitterApplication#runWithArgs(String[]) * @see TwitterApplication#runInteractive() */ default public void run(String[] args) { if (args.length == 0) { runInteractive(); } else { runWithArgs(args); } } /** * Tries to run the program with command line * arguments. *

* If command line arguments are not correct, * the program can exit with an error code. * @param args Arguments from command line. */ public void runWithArgs(String[] args); /** * The application will be run in an interactive mode * where the user can enter different statements * to control the program. */ public void runInteractive(); /** * Given a command as a String (in interactive mode), * this method should parse the input and return * a list of Action instances. * Usually one command should create one action, this * method gives the opportunity to have combined actions * for one command line ("query tallinn 30" - query + count). * If you don't use combined actions, just return a list * with one element in it - the Action instance to be * executed. * @param action Command string from interactive mode * @return List of actions to be executed */ public List<Action> getActionsFromInput(String action); /** * Given command line arguments this method parses * the arguments and returns a list of Action instances. * As the command line can accept several different actions * (for example query, sort and search), this method * return a list of all the actions. * @param args Command line arguments (from main method) * @return List of actions to be executed */ public List<Action> getActionsFromArguments(String[] args); /** * Given an instance of Action, it will be executed. * If you choose to implement Action.execute() * for every action, then the body of this method can just be: * action.execute() * @param action Action to be executed */ public void executeAction(Action action); /** * Executes all the actions given as a list. * The default implementation just iterates over * all the actions and calls executeAction. * @param actions A list of actions */ default public void executeActions(List<Action> actions) { for (Action action : actions) { executeAction(action); } } /** * Executes a location search using location search set with * setLocationSearch(). * Returns a query object which holds all the values for Twitter search. * Note that this method has a default implementation which * just executes a method from local location search and * returns its return value. * Use this default implementation if you don't have caching implemented. * If you need caching, you need to override this method. * @param location The location which is to be searched for * @return Query object which holds all the necessary information * about Twitter query * @see TwitterApplication#setLocationSearch(LocationSearch) */ default public TwitterQuery getQueryFromLocation(String location) { LocationSearch locationSearch = getLocationSearch(); return locationSearch.getQueryFromLocation(location); } /** * Executes a search of tweets on TwitterSearch object which * is stored via setTwitterSearch(). * Returns a list of received tweets. * @param query Query object which holds all the necessary values * @return List of Tweet objects received from Twitter search. * null if nothing received. * @see TwitterApplication#setTwitterSearch(TwitterSearch) */ default public List<Tweet> getTweets(TwitterQuery query) { TwitterSearch twitterSearch = getTwitterSearch(); return twitterSearch.getTweets(query); } /** * Stores location search object which will * be used to make queries to location search API. * This should be called from the constructor. * @param locationSearch Implementation of LocationSearch, which * can find information about location (city, country etc.). */ public void setLocationSearch(LocationSearch locationSearch); /** * Returns currently stored location search object. * @return Implementation of LocationSeach * which will be used for location search. */ public LocationSearch getLocationSearch(); /** * Stores Twitter search object which will be used * to query tweets from Twitter API. * Should be called from the constructor. * @param twitterSearch Implementation of TwitterSearch */ public void setTwitterSearch(TwitterSearch twitterSearch); /** * Returns currently stored Twitter search object. * @return Implementation of TwitterSearch * which will be used for queries. */ public TwitterSearch getTwitterSearch(); /** * Stores cache object which will be used * to cache locations in the file. * Should be called from the constructor. * @param cache Implementation of Cache */ public void setCache(Cache cache); /** * Returns currently stored cache object. * @return Implementation of Cache * which will be used for location caching. */ public Cache getCache(); /** * Stores the latest state of tweets list. * You should store your tweets using this * method after querying, sorting, searching. * @param tweets A list of tweets */ public void setTweets(List<Tweet> tweets); /** * Get the latest state of tweets list. * This method should be used for printing * and when applying sorting. * @return A list of tweets */ public List<Tweet> getTweets(); } </source>