Lekce 06 - Úkol 06 - Bezdomovci
Úkolem je vytvořit webovou aplikaci, která zobrazí seznam obličejů a umožní uživateli tipovat, který obličej patří bezdomovci a který univerzitnímu profesorovi. Po odeslání odpovědního formuláře aplikace vyhodnotí počet dosažených bodů (správně => 1 bod, špatně => 0 bodů). Inspirací pro tento úkol byly stránky https://www.proforhobo.com/.
Například takto:
Postup
Krok 1 - Seznam obrázků
Vložte do projektu do složky resources/static/images/obliceje
všechny obrázky obličejů.
Obličeje najdete v lekci 04 v podkladech nebo si sežeňte vlastní na internetu.
Připravte si soubor index.html
tak, aby se s využitím th:each
zobrazily všechny obrázky z výše zmíněné složky.
Atribut th:each
potřebuje nějaký zdroj dat ze třídy HlavniController
.
Bude proto potřeba připravit seznam jmen obrázků.
Jeden způsob, jak seznam naplnit, by bylo ruční vyplnění jmen souborů:
public class HlavniController {
private List<String> souborySObliceji;
public HlavniController() {
souborySObliceji = new ArrayList<>();
souborySObliceji.add("oblicej1.jpg");
souborySObliceji.add("oblicej2.jpg");
// a tak dale ...
}
}
Ale to je jen pro lamy. Více profi je sestavit seznam jmen souborů automaticky (podle obsahu složky).
Spring Framework na to má výbornou třídu ResourcePatternResolver
.
public class HlavniController {
private List<String> souborySObliceji;
public HlavniController() throws IOException {
ResourcePatternResolver prohledavacSlozek = new PathMatchingResourcePatternResolver();
List<Resource> resources = Arrays.asList(prohledavacSlozek.getResources("classpath:/static/images/obliceje/*"));
souborySObliceji = new ArrayList<>(resources.size());
for (Resource prvek : resources) {
souborySObliceji.add(prvek.getFilename());
}
}
}
Krok 2 - Formulář s tipovacími přepínači
Seznam obličejů bez formuláře by mohl být zapsaný schématicky zhruba takto:
<html>
<body>
<ul>
<li>
... obrazek ...
</li>
<li>
... obrazek ...
</li>
<li>
... obrazek ...
</li>
<li>
... obrazek ...
</li>
<li>
... obrazek ...
</li>
<li>
... obrazek ...
</li>
<li>
... obrazek ...
</li>
<li>
... obrazek ...
</li>
</ul>
</body>
</html>
Připravte si soubor .css
, kde budou jen ta stylovací pravidla, která používáte.
(Není nutné dodržet do puntíku, ale rozhodně si tam nenechávejte celou tu velkou hromadu z výchozí šablony.
U každého pravidla, které máte zapsané, byste měli vědět, co dělá.
Nevíte-li, co pravidlo dělá nebo proč tam je, zlikvidujte ho.)
Po přidání formuláře <form>
by to mohlo vypadat takto:
<html>
<body>
<form method="post">
<ul>
<li>
... obrazek ...
<label>
<input type="radio" name="odpoved0" value="true"/>
Bezdomovec
</label>
<label>
<input type="radio" name="odpoved0" value="false"/>
Profesor
</label>
</li>
<li>
... obrazek ...
<label>
<input type="radio" name="odpoved1" value="true"/>
Bezdomovec
</label>
<label>
<input type="radio" name="odpoved1" value="false"/>
Profesor
</label>
</li>
<li>
... obrazek ...
<label>
<input type="radio" name="odpoved2" value="true"/>
Bezdomovec
</label>
<label>
<input type="radio" name="odpoved2" value="false"/>
Profesor
</label>
</li>
... a tak dale ...
</ul>
<input type="submit" value="Odeslat"/>
</form>
</body>
</html>
Přepínač (radio button) vyrobíte pomocí značky <input type="radio" name="nazevOdpovedniSkupiny"/>
.
Přepínače, které mají být navzájem výlučné (tj. lze mít zapnutý vždy jen jeden z nich),
musejí patřit do stejné odpovědní skupiny a tedy musejí mít stejný atribut name
.
Javová třída BezdomovciForm
by potom mohla vypadat nějak takto:
public class BezdomovciForm {
private boolean odpoved0;
private boolean odpoved1;
private boolean odpoved2;
... a tak dále ...
public boolean getOdpoved0() { ... }
public void setOdpoved0(boolean newValue) { ... }
public boolean getOdpoved1() { ... }
public void setOdpoved1(boolean newValue) { ... }
... a tak dále ...
}
Krok 3 - Vyhodnocení odpovědí a zobrazení výsledkové stránky
Bude třeba naprogramovat metodu reagující na odeslaný formulář (post
) a v ní vypočítat výsledné score. Třeba takovouto:
@RequestMapping(value = "/", method = RequestMethod.POST)
public ModelAndView zpracujIndex(BezdomovciForm odpovedi)
Krok 4 - Seznam odpovědí
To, že třída BezdomovciForm
má přehršel vlastností, není příliš elegantní ani dobře udržovatelné.
V lekci jsme probírali seznamy (java.util.List
), a tak je zde použijte.
V javové třídě BezdomovciForm
můžete místo osmi vlastností typu boolean
nadeklarovat jen jednu vlastnost odpovedi
typu List<Boolean>
:
public class BezdomovciForm {
private List<Boolean> odpovedi;
public List<Boolean> getOdpovedi() {
return odpovedi;
}
public void setOdpovedi(List<Boolean> newValue) {
odpovedi = newValue;
}
}
V Thymeleafu můžete vyjádřit práci se seznamy pomocí hranatých závorek:
<html>
<body>
<form method="post">
<ul>
<li>
... obrazek ...
<label>
<input type="radio" name="odpovedi[0]" value="true"/>
Bezdomovec
</label>
<label>
<input type="radio" name="odpovedi[0]" value="false"/>
Profesor
</label>
</li>
<li>
... obrazek ...
<label>
<input type="radio" name="odpovedi[1]" value="true"/>
Bezdomovec
</label>
<label>
<input type="radio" name="odpovedi[1]" value="false"/>
Profesor
</label>
</li>
<li>
... obrazek ...
<label>
<input type="radio" name="odpovedi[2]" value="true"/>
Bezdomovec
</label>
<label>
<input type="radio" name="odpovedi[2]" value="false"/>
Profesor
</label>
</li>
... a tak dale ...
</ul>
<input type="submit" value="Odeslat"/>
</form>
</body>
</html>
Pokud použijete ve jméně skupiny hranaté závorky s číslem (<input name="jmenoSkupiny[CISLO]"/>
),
vloží se vám odeslaná odpověd v Javě sama do seznamu.
Tip: Pokud v Thymeleafu generujete řádky seznamu pomocí th:each="prvek : ${seznam}"
a potřebujete (vyjma samotného prvku) i index, na kterém se v seznamu nachází,
můžete použít rozšířenou syntax th:each="prvek, iterator : ${seznam}"
,
kde z proměnné iterator
lze získat vlastnost index
. Tím pádem můžete zapsat třeba toto:
<span th:text="${iterator.index}">Číslo</span>
<span th:text="${prvek}">Název</span>
Krok 5 - Seznam správných odpovědí
Vymyslete, jak optimálně reprezentovat seznam správných odpovědí a jak ho naplnit. Zen by byl, pokud by celý program byl nezávislý na počtu fotek a jen a pouze přidáním nové fotky by se automaticky dalo rozhodnout, zda jde o fotku bezdomovce nebo profesora.
Tip: Šlo by to poznat třeba podle jména souboru s fotkou.
Odevzdání domácího úkolu
Nejprve appku/appky zbavte přeložených spustitelných souborů.
Zařídíte to tak, že v IntelliJ IDEA vpravo zvolíte
Maven Projects -> Lifecycle -> Clean.
Úspěch se projeví tak, že v projektové složce zmizí
podsložka target
.
Následně složku s projektem
zabalte pomocí 7-Zipu pod jménem Ukol-CISLO-Vase_Jmeno.7z
.
(Případně lze použít prostý zip, například na Macu).
Takto vytvořený archív nahrajte na Google Drive do Odevzdávárny.
Vytvořte snímek obrazovky spuštěného programu (webové stránky) a vložte jej
do galerie Ukol CISLO
ve skupině našeho kurzu na Facebooku.
Pokud byste chtěli odevzdat revizi úkolu (např. po opravě),
zabalte ji a nahrajte ji na stejný Google Drive znovu,
jen tentokrát se jménem Ukol-CISLO-Vase_Jmeno-verze2.7z
.
Termín odevzdání je v neděli před další lekcí, nejpozději 23:59. Pokud úkol nebo revizi odevzdáte později, prosím pošlete svému opravujícímu kouči/lektorovi email nebo zprávu přes FB.