Programowanie Aplikacji Internetowych w Językach Skryptowych Laboratorium Język Groovy i platforma Grails Aleksander Mielczarek, 2014 Spis treści Zajęcia 1 Pierwsze kroki z Groovy, konstrukcje sterujące...2 Zajęcia 2 Kontenery i ciągi znaków...5 Zajęcia 3 Klasy i aplikacje okienkowe AWT/Swing...7 Zajęcia 4 Komunikacja sieciowa z perspektywy klienta...7 Zajęcia 5 Platforma Grails...7
Zajęcia 1 Pierwsze kroki z Groovy, konstrukcje sterujące Instalacja pobrać i rozpakować Groovy 2.3 (http://groovy.codehaus.org/download) pobrać GVM (http://gvmtool.net/) (curl -s get.gvmtool.net bash) zainstalować Grails (gvm install grails) uruchomić tutorial Grails (http://grails.org/ => Learn => Quick Start) O Groovy Groovy jest językiem na platformę JAVA, wykonuje się w JVM Lekka wersja JAVY, duża część kodu zgodna Język skryptowy z możliwością kompilacji Nowe metody rozszerzające podstawowe typy danych Język dynamiczny Bezpieczniejsza nawigacja?. Metody domyślnie publiczne Nazwane argumenty new Robot(type: 'arm', width: 10, height: 40) Argumenty opcjonalne Domyślna ewaluacja do typu Boolean Identyczny system komentarzy i generacji dokumentacji Podstawianie zmiennych w łańcuchach znakowych Domyślnie importowana część pakietów
Wprowadzenie Jak wygląda najprostsza aplikacja napisana w języku JAVA? public class Greetings { public static void main(string[] args) { System.out.println("Hello World!"); Odpowiadający kod Groovy: println 'Hello World!' Narzędzia: groovy wsadowy interpreter języka Groovy groovyc kompilator groovy do klas JVM groovysh internaktywna konsola grape menedżer pakietów i zależności dla Groovy groovydoc generator dokumentacji na bazie kodu groovyconsole graficzny edytor kodu Groovy (niezbyt przydatny) Zadanie 1 Zadanie z gwiazdką Wyświetlić ciąg składający się z 80 gwiazdek. Proponowane rozwiązania: for(i = 0; i < 80; i++) print("*") print "*" * 80 Zadanie 2 Pętle for Należy wygenerować 10 losowych wartości z zakresu 1-100. Okazja do zademonstrowania kilku rodzajów pętli: for(i = 0; i < 5; i++) print("$i ") 5.times { print "$it " 5.times { abc -> print "$abc < " 0.upto(4) { print "$it " 0.step(5, 1) { print "$it " I do tego stara klasa java.util.random: r = new Random() print "" + r.nextint(3) //0..2
Zadanie 3 Pętle po kolekcjach Należy wygenerować następującą listę: * jeden ** dwa ********** dziesięć korzystając z listy liczebników: lista = ['jeden', 'dwa', 'trzy', 'cztery', 'pięć', 'sześć', 'siedem', 'osiem', 'dziewięć', 'dziesięć'] Proponowane rozwiązania: for(i = 0; i < lista.size(); i++) { println("*" * i + " " + lista[i]) n = 1; for(it in lista) { println("*" * n++ + " " + it) n = 1; lista.each { println("*" * n++ + " " + it) lista.eachwithindex { itm, idx -> println("*" * (idx + 1) + " " + itm) Zadanie 4 Problem Collatza Program definiuje zmienną całkowitą o pewnej dodatniej wartości. Jeśli jest ona parzysta, dzieli ją przez 2, w przeciwnym przypadku mnoży przez 3 i dodaje 1. Algorytm kończy się, gdy otrzymamy wartość 1. Należy wydrukować kolejne wartości jakie przyjmuje zmienna. Proponowane rozwiązanie: int n = 27 //warto while (n!= 1) { println "n = $n" if(n % 2 == 0) n = n / 2 else n = 3 * n + 1 println "n = $n" Zadanie 5 Definiowanie funkcji Rysunek 1: http://xkcd.com/710/ Należy obudować kod z zadania 4 w funkcję pobierającą wartość do sprawdzenia. Korzystając z opracowanej funkcji zbadać zachowanie funkcji dla pierwszych 10000 liczb całkowitych dodatnich. def test(n) {...
Zajęcia 2 Kontenery i ciągi znaków Praca z listami Zdefiniujmy listę imion osób, które przyszły na przyjęcie: imiona = ["Ada", "Beata", "Czesław", "Dominika", "Eryk", "Feliks"] Zadanie 1 Powitania Jeśli każdy z gości przywita się z innym, to ile powitań odnotujemy? Zbudować nową listę opisującą powitania pomiędzy osobami i wyświetlić jej zawartość. powitania = [] n = 1 for(i = 0; i < imiona.size(); i++) for(j = i; j < imiona.size(); j++) powitania.add("${n++. ${imiona[i] - ${imiona[j]") for(p in powitania) println p Zadanie 2 Sortowanie Posortujmy osoby stosując za kryterium długość imienia i wyświetlmy wynik: imiona = imiona.sort { a, b -> a.length() - b.length() println "Posortowane: " + imiona.join(" ") Zadanie 3 Generacja nowej listy Zweryfikujmy pracę powyższego algorytmu przygotowując listę długości imion: dlugosci = imiona.collect { it.length() dlugosci.each { print "$it " println() Zadanie 4 Filtrowanie listy Wyodrębnijmy (dość naiwnie) i wypiszmy listę imion męskich i listę imion żeńskich: panie = imiona.findall { it.endswith("a") panowie = imiona panie println "Panowie: " + panowie println "Panie: " + panie Zadanie 5 Wybór fragmentu listy Odrzućmy pierwszą i ostatnią pozycję z listy: println "Wybrane imiona: " + imiona[1..-2]
Praca ze słownikami Zdefiniujmy słownik przypisujący wyrazom z języka obcego wyrazy polskie: dict = ["dieser" : "ten", "dufte" : "fajny", "Schulfach" : "przedmiot", "ist" : "jest"] Zadanie 1 Wyświetlenie słownika Jak najprościej wylistować zawartość słownika? println dict Należy wydrukować zawartość słownika w formacie: wyraz niemiecki => wyraz_polski println "Słownik niemiecko-polski" dict.each {println "${it.key => '${it.value'" Zadanie 2 Wyświetlenie słownika w zadanej kolejności Należy wylistować zawartość słownika w kolejności alfabetycznej wyrazów w języku obcym: keys = dict.keyset() keys = keys.sort { a, b -> a.tolowercase().compareto(b.tolowercase()) for(k in keys) println "$k => '${dict[k]'" Jak zmodyfikować ten program aby sortowanie odbywało się po wyrazach w języku polskim? Zadanie 3 Maszynowe tłumaczenie tekstu Przygotować skrypt tłumaczący wyraz po wyrazie pewien zadany tekst w języku obcym. Wyrazy oddzielone są spacjami a wielkości liter są identyczne z wpisami w słowniku. source = "dieser Schulfach ist dufte" println source.split(" ").collect({ dict[it] ).join(" ") Ciągi znaków Zadanie 1 Badanie leniwej ewaluacji Co wyświetli poniższy przykład? (słownik ulegnie zmianie) lst = ["abc"] tekst = "Lista zawiera $lst" println tekst lst.add("def") println tekst Co wyświetli poniższy przykład? (liczba nie ulegnie zmianie) liczba = 5 tekst = "Liczba to $liczba" println tekst liczba++ println tekst A gdyby zamiast podwójnych cudzysłowów zastosować pojedyncze?
Zajęcia 3 Klasy i aplikacje okienkowe AWT/Swing Kalkulator Należy oprogramować prostą aplikację pełniącą funkcję kalkulatora. Przyciski (od 1 do 9 lub wszystkie), wraz z ich obsługą wygenerować za pomocą pętli. Obsługa zdarzeń za pomocą domknięcia rzutowanego na typ Listenera. Obsługiwane działania: +, -, *, = Możliwość wyczyszczenia bieżącego stanu kalkulatora import javax.swing.* import java.awt.* import java.awt.event.* frame = new JFrame(size: [300, 400], layout: new GridBagLayout(), defaultcloseoperation: WindowConstants.EXIT_ON_CLOSE) GridBagConstraints c = new GridBagConstraints() c.weightx = c.weighty = 1 textfield = new JtextField(); c.fill = GridBagConstraints.HORIZONTAL c.gridwidth = 4; c.gridx = 0; c.gridy = 0 frame.add(textfield, c) c.gridwidth = 1 ops = ['+', '-', '*', '='] current_op = ''; last_val = 0 textfield.text = "0"; clear = true void clicked_button(btn) { if(btn in ops) { tv = textfield.text.tointeger() switch(current_op) { case '+': last_val += tv; break case '-': last_val -= tv; break case '*': last_val *= tv; break if(btn == '=') { textfield.text = last_val.tostring() else { current_op = btn clear = true last_val = tv
else if(btn == 'C') { current_op = '' last_val = 0 textfield.text = "0" clear = true else { if(clear) { textfield.text = "" clear = false textfield.text += btn for(i in 1..9) { button = new Jbutton("$i") def bt = button.text button.addactionlistener({ clicked_button(bt) as ActionListener) c.fill = GridBagConstraints.BOTH c.gridx = (i - 1) % 3; c.gridy = (i - 1) / 3 + 1 frame.add(button, c) for(i in 1..4) { button = new JButton(ops[i 1]) def bt = button.text button.addactionlistener({ clicked_button(bt) as ActionListener) c.fill = GridBagConstraints.BOTH c.gridx = 3; c.gridy = i frame.add(button, c) button = new Jbutton("0") button.addactionlistener({ clicked_button("0") as ActionListener) c.fill = GridBagConstraints.BOTH c.gridwidth = 2 c.gridx = 0; c.gridy = 4 frame.add(button, c) c.gridwidth = 1 button = new Jbutton("C") button.addactionlistener({ clicked_button("c") as ActionListener) c.fill = GridBagConstraints.BOTH c.gridx = 2; c.gridy = 4 frame.add(button, c) frame.show()
Zajęcia 4 Komunikacja sieciowa z perspektywy klienta Pobieranie zasobów przez HTTP Ekstrakcja danych z pliku XML Dekodowanie danych w formacie JSON Komunikacja z bazą danych MySQL Zajęcia 5 Platforma Grails