Chciałbym zaprezentować wszystkim nasze ostatnie przedsięwzięcie: video-it.pl
Ostatnio zacząłem oglądać trochę filmów z różnych konferencji i z kumplami stwierdziliśmy, że przydałoby się miejsce w którym byłby wszystkie interesujące filmiki pod ręką. Video-IT.pl ma być właśnie takim miejscem. Każdy film można ocenić oraz skomentować.
W chwili obecnej portal ma nieco ponad 60 nagrań z różnych informatycznych konferencji – w wolnym czasie zbiór ten powinien być wzbogacany o kolejne nagrania.
Mamy nadzieje, że taki zbiór filmów przypadnie Wam do gustu. Jeśli macie jakieś sugestie – zapraszamy do podzielenia się nimi w komentarzu.
Na początek po długiej przerwie lekko, szybko i przyjemnie, głównie żeby się przełamać i zacząć coś jednak pisać ;)
Tak więc podstawy cURL w PHP na przykładzie dość oklepanym, ale też użytecznym, czyli odczytanie podstawowych danych z google.
$curl = curl_init(); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_URL, "http://www.google.pl"); $google = curl_exec($curl); curl_close($curl);
Pierwsza linijka to otwarcie sesji cURL, następne 2 linijki to ustawienie opcji, pierwsza informuje, że będziemy chcieli odczytać zwrotną informację z danej strony, a druga ustawia jaki adres chcemy odwiedzić. 4. linijka to wykonanie połączenia i przypisanie zwrotnej informacji do zmiennej, gdybyśmy nie ustawili w 2. linijce opcji, że chcemy odczytać informację zwrotną wówczas 4. linijka wykonałaby tylko połączenie. Ostatnia linijka to zamknięcie sesji cURL.
Jak by nie patrzeć nic szczególnego, proste połączenie, teraz jednak lekka modyfikacja i stworzymy już w miarę przydatny skrypt, który będzie pobierał z google 2 chyba najczęściej sprawdzane informacje (przynajmniej przeze mnie ;)) czyli ilość podstron za indeksowanych przez google i pozycje naszej witryny na daną frazę.
$q = trim($_GET['q']);
$q = strip_tags($q);
$q = str_replace(" ", "+", $q);
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_URL, "http://www.google.pl/search?q=".$q);
$google = curl_exec($curl);
curl_close($curl);
Zmienna q przyjmować będzie frazę, jaką wpisujemy normalnie w wyszukiwarce (u mnie dla prostoty bez formularzy zmienna pobierana metodą GET), usunięte tagi i następnie zamiana spacji na znak „+” jak to ma miejsce w google. Gdy już mamy zapytanie, tworzymy połączenie, jak w poprzednim przykładzie z odpowiednio zmodyfikowanym adresem. Teraz nie pozostaje nam już nic innego jak przetworzyć tekst ze zmiennej google.
function ilePodstron($google) {
$tmp = strpos($google, "resultStats") + 11;
$start = strpos($google, " ", $tmp) + 1;
$koniec = strpos($google, " ", $start);
$wynik = substr($google, $start, $koniec - $start);
$wynik = str_replace(",", "", $wynik);
return $wynik;
}
Powyższa funkcja wyświetli nam ilość podstron za indeksowanych na daną frazę, 2. linia sprawdza pozycję wystąpienia ciągu „resultStats”, po którym następuje wypisanie ilość wyników w google, następnie szukamy pierwszej spacji po tym ciągu (dokładne określenie miejsca w którym zaczyna się liczba), potem wyszukanie kolejnej spacji (miejsce gdzie kończy się liczba ;)), 5. linia to już pobranie ze zmiennej google tylko fragmentu zawierającego liczbę, później jeszcze usuwam zbędny przecinek i zwracam wynik, prawda że proste ;) (co do informacji, ile mamy za indeksowanych podstron naszej konkretnej witryny frazę należy zmodyfikować do postaci „site:adres_strony”)
Teraz troszkę trudniejsza funkcja, czyli sprawdzenie miejsca naszej witryny w google pod daną frazą.
function ktoraPozycja($google) {
$s = trim($_GET['s']);
$s = strip_tags($s);
$s = strtolower($s);
if(!$s)
return;
$start = 0;
$wynik = 1;
while(true) {
$start = strpos($google, "<cite>", $start);
if($start === false)
return;
$start += 6;
$koniec = strpos($google, "</cite>", $start);
$strona = strip_tags(strtolower(substr($google, $start, $koniec - $start)));
if(strpos($strona, $s) !== false)
return $wynik;
$wynik++;
}
}
Jak wcześniej, tak i teraz dla prostoty adres interesującej nas strony pobieram metodą GET do zmiennej s. Aby nie mieć problemów później, to od razu zmieniam sobie adres na małe litery (4. linia), później sprawdzenie, czy w ogóle chce się sprawdzać stronę (czy w adresie jest zmienna s ;)). Teraz już najważniejsza część, czyli pętla, która wykonuje się, do puki w zmiennej google znajdujemy ciąg „<cite>” (w tych tagach google umieszcza adresy kolejnych witryn), linie 10. i 11. to sprawdzają i jeżeli ciąg taki nie występuje wychodzi z funkcji. Linia 13. to ustawienie zmiennej start po ciągu „<cite>”, czyli w miejscu rozpoczęcia występowania adresu witryny, linia 14. to ustawienie końca występowania adresu strony, linia 15. to wycięcie adresu strony ze zmiennej google, zamienienie adresu na małe litery i usunięcie zbędnych tagów (czasem zdarza się tag <b>). 16. linia sprawdza czy pobrany przed chwilą adres pasuje do tego jaki szukamy i jeżeli tak, to zwraca pozycję naszej strony i kończy działanie funkcji.
No to by było na tyle po powrocie ;)
A i jeżeli by ktoś nie zauważył, zaszła też zmiana w adresie bloga ;)
Ostatnio ktoś mi powiedział, że używanie takiej kobyły (Maven) do takiego programiku mija się z celem, może i tak, ale dobre praktyki się przydają, to raz, a dwa trochę bibliotek będzie potrzebnych do uruchomienia programu, więc aby nie było problemów, to Maven zrobi to za nas :D
Na początek odpalamy eclipse i tworzymy nowy projekt maven (do tego celu używam wtyczki m2eclipse) jako groupId podaje pl.xon.lewy jako artifactId openjpa i klikam finisz (wsześniej podczas tworzenia zaznaczyłem, że chcę pominąć sekcję z archetypami), podobny efekt do tego, który osiągnąłem można uzyskać poprzez wydanie w konsoli poleceń mvn archetype:create -DgroupId=pl.xon.lewy -DartifactId=openjpa -Dversion=1.0 następnie polecenie mvn eclipse:eclipse i już projekt jest gotowy do zaimportowania do eclipse.
Na początek dodajemy do projektu kilka niezbędnych bibliotek, pierwsza z nich odpowidzialna za głównego bohatera naszego wpisu, czyli OpenJPA, najprościej dokonać tego poprzez kliknięcie prawym przyciskiem myszy na nazwie projektu, nastepnie Maven i Add Dependency i wyszukujemy openjpa, ja wybieram wersję 2.0.0-M3, taki sam efekt uzyskać można poprzez dodanie wpisu w sekcji dependencies w pliku pom.xml
<dependencies> <dependency> <groupId>org.apache.openjpa</groupId> <artifactId>openjpa</artifactId> <version>2.0.0-M3</version> </dependency> </dependencies>
Następny krok to biblioteka HSQLDB, dodaje się ją w taki sam sposób, w moim przypadku wersja 1.8.0.10
<dependency> <groupId>hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>1.8.0.10</version> </dependency>
No to dodanie zależności do naszego projektu mamy za sobą, kolejnym ważnym krokiem jest utworzenie pliku persistence.xml, w którym zapisujemy konfigurację dla JPA, jak wiadomo Maven ma ściśle określoną strukturę plików, tak więc plik presistence.xml też ma „swoje” miejsce i znajdować musi się w katalogu NASZ_PROJEKT/src/main/resources/META-INF/presistence.xml, jego wygląd uzależniony jest w pewnym sensie od bazy i dostawcy JPA jakiego używamy, dla HSQLDB i OpenJPA mój plik wygląda tak
<?xml version="1.0"?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"> <persistence-unit name="default"> <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider> <class>pl.xon.lewy.Klasa</class> <properties> <property name="openjpa.ConnectionURL" value="jdbc:hsqldb:file:test.db;shutdown=true" /> <property name="openjpa.ConnectionDriverName" value="org.hsqldb.jdbcDriver" /> <property name="openjpa.ConnectionUserName" value="sa" /> <property name="openjpa.ConnectionPassword" value="" /> <property name="openjpa.jdbc.Schema" value="PUBLIC" /> <property name="openjpa.Log" value="DefaultLevel=ERROR, Tool=INFO" /> <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)" /> </properties> </persistence-unit> </persistence>
mam nadzieję, że większość linijek jest zrozumiała i nie trzeba ich omawiać, ważne na pewno jest name w presistence-unit, ponieważ po nim identyfikujemy baze jakiej używamy, gdyż w pliku presistence.xml możemy zdefiniować sobie ich więcej, kolejna ciekawa linijka to ta z <class> gdyż w tym miejscu definiujemy klasy, które będą mapowane w danej bazie (linijek takich może pojawić się wiecej niż jedna).
Dobra gdy wszystko skonfigurowane czas napisać jakąś encję (klasę, która będzie odzwierciedlana w bazie danych), u mnie ona oczywiście nazywa się Klasa i jest w paczce pl.xon.lewy, aby klasa stała się encją, przed jej nazwą należy dodać adnotacje @Entity, w klasie dodałem też jakieś zmienne, które będą kolumnami w bazie, plik wygląda mniej więcej tak
package pl.xon.lewy;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Klasa {
@Id
@GeneratedValue
private int id;
@Column
private int jakasLiczba;
@Column
private String jakisNapis;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getJakasLiczba() {
return jakasLiczba;
}
public void setJakasLiczba(int jakasLiczba) {
this.jakasLiczba = jakasLiczba;
}
public String getJakisNapis() {
return jakisNapis;
}
public void setJakisNapis(String jakisNapis) {
this.jakisNapis = jakisNapis;
}
}
adnotacja @Column nie jest niezbędna, przydaje się, gdybyśmy chcieli jakąś zmienną umieszczać w kolumnie o innej nazwie (@Column(name=”liczba”)).
Gdy mamy już naszą klase, należy stworzyć jeszcze klasę główną programu (u mnie nazwa Main)
package pl.xon.lewy;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
public class Main {
private static EntityManagerFactory jpaFactory = Persistence.createEntityManagerFactory("default");
@SuppressWarnings("unchecked")
public static void main(String[] args) {
if(args.length == 2) {
EntityManager jpa = jpaFactory.createEntityManager();
jpa.getTransaction().begin();
Klasa k = new Klasa();
k.setJakasLiczba(Integer.parseInt(args[0]));
k.setJakisNapis(args[1]);
jpa.persist(k);
jpa.getTransaction().commit();
jpa.close();
} else {
EntityManager jpa = jpaFactory.createEntityManager();
Query zapytanie = jpa.createQuery("SELECT k FROM Klasa k");
List<Klasa> wyniki = zapytanie.getResultList();
for(Klasa k : wyniki) {
System.out.println("[klasa]");
System.out.println("id: " + k.getId());
System.out.println("liczba: " + k.getJakasLiczba());
System.out.println("napis: " + k.getJakisNapis());
}
jpa.close();
}
}
}
Na koniec pozostało jeszcze trochę konfiguracji Maven’a, dodanie kilku pluginów, które ulatwią życie ;)
Pierwszy z nich odpowiedzialny jest za stworzenie pliku jar, wraz z odpowiednim plikiem manifestu dla niego i wygląda mniej więcej tak
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.2</version> <configuration> <archive> <manifest> <mainClass>pl.xon.lewy.Main</mainClass> <packageName>pl.xon.lewy</packageName> <addClasspath>true</addClasspath> <classpathPrefix>lib</classpathPrefix> </manifest> </archive> </configuration> </plugin>
Kolejnym pluginem jest plugin ustawiający z jakiej wersji JAVY będziemy korzystać podczas kompilacji projektu, tutaj ważne jest aby była to JAVA w wersji minimum 5, ponieważ dopiero wtedy wprowadzono adnotacje
<plugin> <inherited>true</inherited> <artifactId>maven-compiler-plugin</artifactId> <version>2.0.2</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin>
Teraz chyba najważniejszy dla naszej aplikacji plugin, który odpowiedzialny jest za OpenJPA
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>openjpa-maven-plugin</artifactId> <version>1.0</version> <configuration> <addDefaultConstructor>true</addDefaultConstructor> <enforcePropertyRestrictions>true</enforcePropertyRestrictions> </configuration> <executions> <execution> <id>enhancer</id> <phase>process-classes</phase> <goals> <goal>enhance</goal> </goals> </execution> </executions> </plugin>
Ostatnim pluginem, który wykorzystam w mojej aplikacji jest plugin umożliwiający tworzenie wersji nadających się do rozpowszechnienia
<plugin> <artifactId>maven-assembly-plugin</artifactId> <version>2.2-beta-2</version> <configuration> <descriptor>src/main/assembly/src.xml</descriptor> </configuration> </plugin>
jak widać wtyczka ta potrzebuje jeszcze odpowiednio napisanego pliku deskryptora, u mnie wygląda on mniej więcej tak
<assembly> <id>bin</id> <formats> <format>zip</format> </formats> <fileSets> <fileSet> <directory>target</directory> <outputDirectory>/</outputDirectory> <includes> <include>*.jar</include> </includes> </fileSet> </fileSets> <dependencySets> <dependencySet> <outputDirectory>/lib</outputDirectory> <includes> <include>*:jar</include> </includes> </dependencySet> </dependencySets> </assembly>
w 4 linijce podane jest jakiego formatu ma być plik wynikowy, nastepna sekcja informuje o umieszczenie wszystkich plików z rozszerzeniem jar z folderu target w głównym folderze w archiwum, w dependency dodaje informację o umieszczeniu wszystkich potrzebnych bibliotek w katalogu lib
No i tak dotarliśmy do końca, pozostaje już tylko wywołanie polecenia mvn assembly:assembly, które możemy wykonać z poziomu eclipse, klikamy prawym przyciskiem myszy na nazwie projektu, nastepnie Run As i Maven assembly:assembly i w ten sposób otrzymujemy plik zip z naszym projektem, inną ciekawą opcją mvn assembly jest wywołanie mvn assembly:directory, które od poprzedniego różni się tym iż nie ładuje wszystkiego do pliku zip, który musimy wypadować i dopiero na nim działać, a poprostu zamiast archiwum tworzy folder z jego zawartością.
teraz możemy uruchomić program, np wywołanie
java -jar openjpa-1.0.jar 13 „to jest szczesliwa liczba”
doda do bazy instancję naszej klasa z liczbą 13 i napisem „to jest szczesliwa liczba”, sprawdzić to możemy poprzez wywołanie programu bez parametrów
Na moim wydziale od jakiegoś czasu odbywa się kółko informatyków dotyczące technologii .NET. Sam uczęszczam na nie już dość długo, ale raczej tak po prostu przejść się, zobaczyć o co chodzi, niż dla wiedzy (coś w myśl zasady, że przyjaciół trzeba mieć blisko siebie, a wrogów jeszcze bliżej ;)). Jednak w tym roku prowadzący postanowił poprowadzić spotkania w jakimś bliżej ustalonym z góry harmonogramie i wymyślił przygotowanie do egzaminu 70-536. Tak więc każde kolejne spotkanie to omówienie zagadnienia z kolejnego rozdziału z książki przygotowującej do tego egzaminu.
Jako, że spotkania odbywają się pod hasłem „studenci dla studentów” (sam wymyśliłem :P) no to sami zapisywaliśmy się do przedstawienia jakiegoś działu. Zanim kartka z zapisami do mnie doszła najciekawsze tematy zostały już „zaklepane” no i zapisałem się na pierwszy wykład, co by przetrzeć szlaki.
Prezentację, jaką przygotowałem można zobaczyć tutaj, jest to skrótowy opis pierwszego działu opisującego podstawy .NETa (framework fundamentials).
A poziom prezentacji, cóż nie mnie to oceniać, ale podobno za szybko mówiłem (fakt miałem 1.5h, a wyrobiłem się w 20 min), no ale kurcze są to takie podstawy, że ciężko mówić o tym długo, o tym dogłębnie uczą studia, ja starałem się tylko pokazać jak to wygląda w .NET i jak to „zapisuje” się przy pomocy C kratka :P
Jak wiadomo PHP demonem szybkoście nie jest i skrypty napisane w nim też do najszybszych nie należą, tak więc dość ważne jest abyśmy sami ich dodatkowo nie zwalniali. Poniżej zaprezentuję parę uwag, jak pisać skrypty w php, aby choć odrobinę szybciej chodziły, taka mała optymalizacja php ;)
po pierwsze echo jest szybsze niż print
przy wyświetlaniu znaków należy stosować ‘ zamiast „, gdyż w cudzysłowach możemy umieścić zmienne i wyświetlana jest ich wartość, a nie nazwa jak ma to miejsce w apostrofach, tak więc tekst umieszony między ” jest dodatkow przetwarzany przez co wydłuża się praca skryptu
przy wykonywaniu pętli, która ma sprawdzić wszystkie elementy tablicy należy najpierw odczytać ilość elementów w tablicy ($ilosc = count($tablica)) i używać zmiennej w pętli (for($i = 0; $i < $ilosc; $i++)), a unikać takiego zapisu (for($i = 0; $i < count($tablica); $i++))
przy podmienianiu napisów, lepiej stosować szybsze str_replace niż prag_replace
bloki „else if ” są szybsze niż switch/case
wytłumienie błędów za pomocą @ jest bardzo wolne i lepiej nie używać, gdy nie ma ogromnej potrzeby
stosowanie $row['id'] jest około 7 razy szybsze niż $row[id]
preinkrementacja (++$i) jest szybsza od postinkrementacji ($i++)
inkrementacja zmiennych w obiekcie ($this->i++) jest około 3 razy wolniejsza niż zmiennych lokalnych ($i++)
mam nadzieję, że te parę uwag choć odrobine pozwoli przyśpieszyć pisane przez was skrypty ;)
Od 2 dni teoretycznie mogę chwalić się wykształceniem wyższym, dokładnie jak to leci nie wiem, ale powinno być coś w stylu licencjat informatyki (nie mam jeszcze papierka, ale jak dostanę, na pewno napiszę ;)). Jak to przebiegał egzamin pisać mnie się też nie chce, napisze tylko tyle, że dostałem pytanie z działu, którego miało nie być, na pozostałe 2 odpowiedziałem i ocena 3, no nic, liczy się papier :P
Wpis ten nie pojawia się, w celach chwalenia się, ale raczej jako zakończenie pewnego etapu w życiu, teraz jeszcze magisterka, ale w międzyczasie samodokształcanie, za które zaraz się będę brał i mam nadzieję, że już niebawem będę mógł coś o postępach w tym kierunku napisać, bo przecież wyższe już do czegoś zobowiązuje :D
No w zasdzie 2 września dziś, no ale co zrobić ;) Wpis ten to takie podsumowanie wakacji, choć dla mnie się one jeszcze nie kończą, wszak student dopiero 1 października startuje :D
Dobra a teraz do konkretów, wakacje miały upłynąć pod znakiem (a raczej literką) D. Język D był jednym z przedmiotów, które musiałem zaliczyć na studiach aby ukończyć 3 rok i móc podejść do egzaminu licencjackiego. Przedmiot ukończyć udało się pozytywnie bez większych problemów, jednak język sam w sobie mnie nie urzekł, co można zobaczyć po dość małej ilości wpisów na jego temat. Problemy były prawie od samego początku, brak dobrego IDE (żadne nie miało przyzwoitego uzupełniania składni), ostatecznie wybrałem Entice’a, znajomy korzystał z wtyczki do eclipse – Descent, ale też szału nie ma. Napisanie prostego „Hello World” większych problemów nie sprawia, jednak po pewnym czasie okaże się, że Phobos to nienajlepsza biblioteka i zechcemy korzystać z Tango, niby wszystko ok, jednak nie da się połączyć pisania programu w tych 2 bibliotekach (no przynajmniej mnie się to nie udało), a do tego musiałem posiadać, albo 2 wersje kompilatorów jedna z bibliotekom standardową, druga z Tango i używać tej, która skompiluje mi dany projekt albo jakoś się nakombinować, czego z racji mojego lenistwa nie robiłem. Kolejny program do napisania i kolejny problem, program miał posiadać GUI, wybrałem DWT, pisanie z użyciem tej biblioteki nie było najtrudniejsze, mnogość tutoriali (również tych do SWT, bo pisze się niemal tak samo) na pewno na duży plus, jednak aby skompilować te „wypociny” ponownie trzeba było się namęczyć i korzystać z niejakiego dsss (opis instalacji DWT tutaj). O 3d w D już pisałem wcześniej, więc rozpisywać się na ten temat nie będą, w każdym bądź razie też trochę czasu nad konfiguracją trzeba było spędzić, aby skompilować program. Później miałem jeszcze ambicje popisać jakieś programy wielowątkowe i sieciowe, jednak po około 3 godzinach spędzonych nad wątkami, gdzie przepisałem przykłady z tutoriali i żaden nie działał (używałem Tango), poprostu odechciało mnie się tego języka na dobre i zaprzestałem jakiejkolwiek współpracy z nim, gdyby jednak ktoś miał więcej samozaparcia do tego języka i chciał pisać aplikacje wielowątkowe to być może uda mu się to z Tango, gdyby jednak nie, to znalazłem taki opis przy pomocy biblioteki standardowej – Język D: Wielowątkowość. Po tych wszystkich przeżyciach niestety, ale jeżeli będę musiał coś napisać i nie uda się to w Javie, to skorzystam z C++, a nie D, jednak na pewno nie mogę powiedzieć, że już nigdy nie skorzystam z tego języka.
Co do innych osiągnięć wakacyjnych to standardowo po wielkich planach, efekt nimal niewidoczny. Trochę poczytałem o JUnit i Springu, ale na dobrą sprawę nic nie pisałem z użyciem tego. Jednak mam nadzieję, że po 10 września (egzamin licencjacki) ulegnie to zminie i zaczne na poważnie ukierunkowywać się w pewną strone, a że jakiś czas temu wybór padł na Jave, a główni J2EE i rzeczy z tym związane, to gdy tylko wezmę się do roboty efekty będzie można zobaczyć na blogu w postaci wpisów, tak więc do zobaczenia(?) ;)
Po dłuższej przerwie postanowiłem coś znowu „spłodzić”, tym razem będzie trochę o tym jak tworzyć grafikę 3d za pomocą języka D. Nie będzie to na pewno kurs tworzenia grafiki 3d bo sporo tego w sieci, powiem tylko jak skonfigurować wszystko aby kompilować programy oraz podam kilka przydatnych linków ;).
Po pierwsze musimy posiadać kompilator dmd z biblioteką standardową (z Tango nie działało mi). Do kompilacji używać będziemy też build’a (po ściągnięciu zmieniamy nazwę na build i umieszczamy w katalogu bin kompilatora dmd, zatroszczyć się również musimy, aby ścieżka do folderu bin znajdowała się w zmiennej środowiskowej PATH). Korzystać będziemy z biblioteki derelict, najnowszą wersję możemy pobrać stąd. Po rozpakowaniu zobaczymy sporą ilość folderów np. DerelictGL, a w nim folder derelict i tak będzie w kilku przypadkach, a nam dla łatwiejszej kompilacji potrzebne będą tylko foldery derelict ze swoimi zawartościami. Aby tego dokonać (wersja dla Windowsa:)) będąc w folderze trunk klikamy na F3 i wyszukujemy foldery z frazą derelict, kopiujemy je (tylko te o nazwie derelict!) do np. folderu sciezka\do\twojego\dmd\src\ext\. No i to by było na tyle jeżeli chodzi o konfigurację, czy działa możemy sprawdzić próbując skompilować następujący kod:
import derelict.opengl.gl;
import std.stdio;
void main()
{
try {
DerelictGL.load();
writefln("Successfully loaded the OpenGL shared library.");
} catch (Exception e) {
writefln("Could not load the OpenGL shared library.");
}
}
Kompilujemy program używając polecenia:
build nazwa_pliku.d -Isciezka\do\twojego\dmd\src\ext gdi32.lib -exec
Możemy również skopiować cały katalog derelict do katalogu w którym znajduje się nasz plik z kodem i kompilować program w następujący sposób:
build nazwa_pliku.d gdi32.lib -exec
gdi32.lib w podanym przykładzie nie jest niezbędny, jednak czasem biblioteka ta jest potrzebna do skompilowania niektórych aplikacji.
Na koniec jak obiecałem parę linków jeszcze ;)
tu jest ciekawy szablon dla aplikacji pisanych z wykorzystaniem OpenGL (ostatni kod)
a tu kurs OpenGL za pomocą którego można nauczyć się tworzyć figury, bryły, obracać nimi, używać światła, tekstur itp., a nabytą wiedzę wykorzystujemy w szablonie i cieszymy się umiejętności pisania programów z użyciem grafiki 3d ;)
Ostatnio pisząc jakiś programik w D poczułem potrzebę użycia listy, chwilę pomyślałem no i doszedłem do wniosku, że takie coś musi być w bibliotece, przecież nie będę tego pisał sam, jak to miało miejsce w c ;). Przeszukuję tego Phobosa i niestety na nic nie natrafiłem (nie wykluczam, że nie istnieje), tak więc pozostaje użycie czegoś takiego:
Typ tab[]; Typ a = new Typ(); tab ~= a;
Owszem jest to ciekawy krok w przód w porównaniu do c, ładnie tablica sama zwiększa rozmiar, ale to nie to czego szukałem. Jako osoba ostatnimi czasy pisząca w Javie miałem „potrzebę” używania wspaniałych ArrayList i HashMap, dalsze poszukiwania doprowadziły mnie do Tango i takiego odkrycia:
import tango.io.Stdout;
import tango.util.container.LinkedList;
import tango.util.container.HashMap;
void main() {
LinkedList!(int) q = new LinkedList!(int);
q.append(2); q.prepend(1); q.append(3);
foreach(i; q) {
Stdout(i).newline();
}
q.add(4);
Stdout(q.get(0)).newline();
q.size(); //ilosc elementow w liscie
q.head(); //zwraca pierwszy element listy, nie usuwa go
q.removeHead(); //zwraca pierwszy element listy i usuwa go
q.tail(); //ostatni element listy
q.removeTail();
q.remove(1); //usuwa z listy element o podanej wartosci
q.removeAt(0); //usuwa z listy element z danej pozycji
q.clear(); //usuwa wszystkie elementy z listy
HashMap!(int, int) m = new HashMap!(int, int);
m.add(1, 12); m.add(2, 43); m.add(3, 34);
foreach(i; m) {
Stdout(i).newline();
}
int x; m.get(1, x);
Stdout(x).newline();
Stdout(m.opIndex(1)).flush();
m.size(); //ilosc elementow w odwzorowaniu
m.containsKey(1); //sprawdza czy dany klucz istnieje, zwraca true lub false
m.contains(12); //sprawdza czy taka wartosc istnieje, zwraca true lub false
m.removeKey(1); //usuwa z odwzorowania element o danym kluczu
m.remove(43); //usuwa z odwzorowania element o danej wartosci
m.clear(); //usuwa wszystkie elementy z odwzorowania
}
prawda, że wygląda lepiej :D
Przejdźmy teraz do krótkiego omówienia kodu. 6 linia to deklaracja listy, która będzie przechowywała zmienne typu int, ogólnie trochę dziwnie to wygląda, do tej pory spotkałem się z zapisem <typ> a tutaj !(typ), no ale nic idziemy dalej. 7 linia to dodanie elementów do listy, append dodaje element na koniec listy, prepend na początek, kolejna linia to wspaniała pętla foreach, która „przechodzi” przez wszystkie elementy listy udostępniając je jako zmienną (w moim przypadku i). Linia 11 wygląda ładnie, jednak dla mnie nie była zbyt intuicyjna, przyzwyczajony, że add dodaje element na końcu listy tutaj się trochę zdziwiłem, gdyż jest to alias do prepend a nie append (co sprawdzamy w kolejnej linii). Linii 13-20 nie będę opisywał, jest to kilka funkcji jakie oferuje klasa LinkedList i opisane są w kodzie.
Przejdźmy teraz do HashMap, najprościej mówiąc jest to odwzorowanie przekształcające jedną wartość na drugą, np. jako klucz możemy mieć czyjś nick, a jako wartość jego numer telefonu ;), oczywiście klucze muszą być unikatowe. Jednak dla uproszczenia zastosowałem int i int, gdyż nie ważny jest przykład a idea :D. Najpierw tworzymy zmienną HashMap, podajemy jej dwa typy, pierwszy to typ klucza, a drugi to typ wartości. W linii 23 dodajemy elementy do mapy (klucz, wartość), następnie prezentacja wspomnianej już pętli foreach. 27 linia może być dość ciekawa, funkcja get ponownie dość mało intuicyjna, gdyż nie zwraca nam wartości przyjmując jako parametr klucz, tylko przyjmuje dwie wartości, pierwsza klucz, a druga to zmienna pod jaką ma zostać zapisana wartość, zwraca true (jeżeli podany klucz istnieje) lub false (jeżeli nie istnieje). Rozwiązanie może i ciekawe, ale jeżeli ktoś woli stare „podejście” to może użyć funkcji opIndex (linia 29), która zwraca wartość po podaniu klucza. Dalsze funkcje klasy HashMap opisane są w kodzie.
Oczywiście wypisałem tutaj tylko 2 częściej używane moim zdaniem kontenery i to nie z wszystkimi oferowanymi przez nie funkcjami, po dalszą wiedzę odsyłam do dokumentacji biblioteki Tango.
Ostatnio trochę z musu niestety (sam pewnie bym się za to nie zabrał :P) zacząłem programować w języku D. Dlaczego z musu(?), a no dlatego, że jest to przedmiot na studiach, który muszę zaliczyć ;)
Jeden z programów, który muszę napisać ma za zadanie obsługę plików, jako że nie znalazłem w sieci (słaby w googlowaniu jestem ;)) nic po polsku o plikach w języku D, to postanowiłem takie coś skrobnąć, może się komuś przyda, na początek kodzik:
import std.stdio;
import std.stream;
void main() {
File plik = new File();
plik.open("plik.txt", FileMode.OutNew); //"nowy" plik
plik.writeLine("linia tekstu");
plik.close();
plik.open("plik.txt", FileMode.In); //plik do czytania
while(!plik.eof()) {
writefln("%s", plik.readLine());
}
plik.close();
plik.open("plik.txt", FileMode.Append); //dopisywanie do pliku
plik.writef("kolejna linia tekstu");
plik.close();
writefln();
plik.open("plik.txt", FileMode.In); //plik do czytania
while(!plik.eof()) {
writefln("%s", plik.readLine());
}
plik.close();
}
a teraz parę słów o nim :)
Pierwsze linijki to standardowo import potrzebnych paczek, następnie tworzymy nowy obiekcik typu File, w moim przypadku „pusty” obiekcik, ale można też wykonać to w taki sposób:
File plik = new File("plik.txt", FileMode.OutNew);
6 linia to otwarcie pliku „plik.txt” do pisania w taki sposób, aby to był jakby nowy plik (czyli jeżeli nie ma takiego pliku to jest on tworzony, a jeżeli taki plik istnieje to cała jego zawartość jest kasowana). W 7 linii następuje zapis linii tekstu do pliku (łącznie ze znakiem nowego wiersza), linia 8 to jak się można domyśleć zamknięcie pliku. W linii 10 następuje otwarcie pliku do czytania, linia 11 to pętla, która wykonuje się do momentu napotkania znaku końca pliku, pętla ta wypisuje każda linię na standardowe wyjście (linia 12). W linii 16 następuje otwarcie pliku do pisania w taki sposób, że zachowuje aktualną zawartość pliku i ustawia wskaźnik na jego końcu, czyli dopisywanie do pliku.
To była obsługa plików w Phobosie, a teraz kodzik robiący to samo, ale za pomocą biblioteki Tango
import tango.io.device.File;
import tango.io.Stdout;
void main() {
File.set("plik.txt", "linia tekstu\r\n");
char[] tekst = cast(char[])File.get("plik.txt");
Stdout(tekst);
File.append("plik.txt", "kolejna linia tekstu");
Stdout.newline();
tekst = cast(char[])File.get("plik.txt");
Stdout(tekst);
}
Na początku standardowo czyli import potrzebnych paczek, 5 linia to zapis tekstu do pliku, zapis ten nadpisuje aktualną zawartość pliku, linia 7 to pobranie zawartości pliku do zmiennej, linia 10 to natomiast dopisanie nowego tekstu do już istniejącego w pliku.
No i to by było na tyle, mam nadzieję, że się komuś przyda ;)