Wednesday, August 27, 2014

Perbedaan quantifier dalam Regex

Terdapat tiga modus quantifier dalam regex, yang pertama adalah greedy, kedua adalah reluctant, dan yang ketiga adalah possessive. Berikut penjelasannya

13

Dalam modus greedy,  matcher pertama-tama  nge-match seluruh string. Jika tidak ditemukan yang match, dia akan melakukan backtracking dengan membuang satu huruf dari bagian yang match dari input string  (yang sudah menjadi bagian match-nya) untuk dipake/di-match oleh character berikutnya pada matcher. Misalnya jika  pattern-nya adalah .*foo ketika string input adalah  xfooasdasfsdfsdafoo maka yang terjadi adalah, bagian pertama dari matcher, yakni .* (yang artinya match semua jenis character dengan jumlah berapa saja, zero or more times), akan nge-match seluruh input string (greedy = rakus/sebanyak mungkin). Karena seluruh string sudah match dengan dia, otomatis bagian berikutnya dari matcher, yakni character f tidak akan mendapat jatah lagi, dan tidak match. Jadi quantifier tadi, yakni *,  akan membuang satu character dari bagian  match-nya sehingga character o  pada input string  menjadi unmatch (di luar dari bagian match-nya), dan ini yang selanjutnya akan di-match dengan character f dari matcher. Namun belum match, dia buang lagi  o berikutnya, dan belum match juga dengan  pada matcher, maka f tadi dibuang lagi dari bagian match dari matcher .* sehingga bisa dipake oleh character f dari matcher, dan ini baru match. Kemudian character berikutnya dari matcher yakni o dan o, dengan sendirinya akan match dengan dua character sebelumnya yang sudah dibuang oleh matcher .* yakni o dan o.

Dalam modus recultant, dia akan nge-match sesedikit mungkin (berkebalikan dengan modus greedy tadi).  Jadi dalam  input yang diberikan, yakni xfooasdasfsdfsdafoo, matcher .*? akan ngematch sesedikit mungkin, yakni  pertama match dengan string dengan zero-length, atau  “” (tanda kutip di sini menunjukkan ada string di situ yang tidak keliatan), sesuai dengan defenisinya (zero or more times). Selanjutnya bagian berikutnya dari matcher, yakni  f,  akan mencoba nge-match dengan mengambil satu-satu dari string yang tersisa, yakni  xfooasdasfsdfsdafoo (di luar string zero-length tadi), di mana pertama-tama dia mencoba nge-match dengan character x. Karena tidak match, maka quantifier *? akan melahap satu lagi dari string input (melakukan backtrack) yakni x, sehingga bagian pertama dari matcher, yakni .*? akan menyisakan fooasdasfsdfsdafoo untuk di match dengan bagian berikutnya dari matcher, yakni f. Karena sudah match,  maka  bagian  berikutnya dari input string yang  tersisa yakni character o dari ooasdasfsdfsdafoo yang akan dimatch dengan bagian berikutnya dari matcher yakni o, demikian pula untuk o berikutnya.

Modus possessive sama sekali tidak melakukan backtracking. Jadi quantifier .*+ akan melahap semua string input, dan sama sekali tidak menyisakan untuk bagian berikutnya dari matcher, yakni f, o, dan o. Sehingga hasil keseluruhannya adalah string input sama sekali tidak match dengan matcher.

Saturday, August 23, 2014

Cross di dalam Lingkaran

qewqewq
Dalam postingan kali ini sebenarnya saya ingin berbagi permasalahan sekaligus ilmu yang mungkin bermanfaat bagi pembaca sekalian. Gambar di atas dikutip dari bukunya Edwin J.Purcell pada bab aplikasi turunan/derivatif, spesifiknya bagaimana menggunakan turunan dalam memecahkan persoalan optimisasi. Saya kemarin sudah mencoba menjawab soal ini, namun saya merasa kurang confidence dengan jawaban saya. Entah di mana kesalahan penurunannya yang menggiring saya pada kesimpulan bahwa sudut yang dimaksud adalah nol.
Akhirnya saya buat sebuah aplikasi yang mengkonfirmasi dugaan saya itu. Dan ternyata dugaan saya salah. Nilai maksimumnya bukan terletak ketika sudutnya sama dengan nol seperti yang terlihat pada gambar di bawah ini. Animasinya saya buat dengan JavaFX, sebagaimana animasi lainnya di blog ini. Dan Anda bisa melihat source-nya di Github. Dan saya sampai sekarang belum menemukan kesalahan penurunannya, atau jawaban yang benar untuk membuktikan nilai sudut ketika luas cross di dalam lingkaran tersebut bernilai maksimum.
Mudah-mudahan ada pembaca yang tertarik menyelesaikan persoalan di atas untuk mendapatkan jawaban analitisnya.
1

Friday, August 15, 2014

Mencari data terduplikasi dengan menggunakan Java HashMap

Dalam tutorial kali ini, saya mencoba mendemonstrasikan kegunaan hashmap di java, yakni dalam mencari tahu apakah suatu data terduplikasi. Contohnya adalah biasa dalam sebuah database berbasis SQL ada perintah distinct yang mana secara kasar bisa dikatakan bahwa perintah ini menggunakan hashmap dalam implementasinya.

Saya berikan contoh, adalah bagaimana mencari dalam suatu file pada baris ke berapa saja kolom ke-x mengalami duplikasi. Sebenarnya ini perluasan dari pertanyaan fundamental yakni, apakah suatu data memiliki jumlah lebih dari satu dalam suatu kumpulan data. Kemudian saya melakukan perluasan dengan memberikan jawaban mengenai di baris mana saja data tersebut mengalami duplikasi. Potongan kodenya dapat dilihat pada script berikut:

Untuk mendemonstrasikan apakah script ini berjalan dengan baik, ada baiknya pembaca membuat sendiri test-case nya. Buat aja beberapa baris yang data pada kolom-kolomnya itu beda, kecuali pada beberapa kolom yang dibuat sama. Kemudian selanjutnya pembaca jalankan aja script ini untuk mengetesnya.

Tuesday, July 29, 2014

Bagaimana mendownload video dengan TOR browser

Dalam tulisan kali saya mencoba sedikit pengalaman saya yang mungkin berguna bagi majelis blogger sekalian. Yang saya maksud dengan pengalaman ini murni dengan niatan share of knowledge alias membagi pengetahuan (mudah-mudahan ejaan inggris saya benar). Jika nanti para majelis blogger sekalian melakukan tindakan yang melawan hukum akibat dari isi tulisan saya ini, maka saya katakan dengan tegas bahwa itu di luar tanggung jawab saya (put it in the context).  Karena teknologi itu ibarat pisau bermata dua: punya sisi baik dan punya sisi buruk.

Bahan-bahan yang perlu disiapkan sebagai bagian dari tutorial kali ini hanya dua macam, yakni TOR browser dan flash video downloader. Untuk saat ini saya tidak bisa menjelaskan secara rinci bagaimana mekanisme kerja dan detail implementasi dari kedua bahan tersebut, yang jelas secara garis besar saya bisa katakan kalo bahan yang pertama berfungsi untuk menghilangkan jejak kita dalam browsing di dunia maya sementara bahan yang kedua berguna untuk mengkonversi tayangan flash dari video di berbagai situs di internet menjadi alamat video tersebut pada komputer server (yang bisa di-download). Untuk bahan pertama, cara instalasinya sangat mudah, Anda download Tor browser bundle (di mana vidalia dan mozilla browser sudah terintegrasi---dalam hal ini yang ditampilkan pada bagian atas link yang saya berikan) dan install sebagaimana halnya Anda menginstall software yang lain. Kemudian untuk bahan yang kedua, Anda buka aja link tersebut dengan Tor browser (karena dia mozilla firefox hakikatnya) dan Anda tekan tombol download, yang dengan otomatis akan membuat Tor browser menginstall plugins seperti halnya bagaimana browser mozilla firefox menginstall plugins.  Jika majelis sekalian sudah memiliki kedua bahan tersebut maka yang saya lakukan kali ini adalah demo bagaimana memperlakukan keduanya untuk kepentingan majelis sekalian.

Pertama,  saudara buka halaman web yang mengandung video yang ingin saudara download, misalnya youtube dan langsung ke alamat video yang ingin didownload:


Kemudian Anda klik tombol panah warna biru, hingga muncul tampilan menu mengenai video yang akan di-download. Selanjutnya dalam menu tersebut letakkan mouse Anda pada satu link di bagian bawah dan biarkan beberapa saat hingga muncul menu  di sampingnya (seperti terlihat pada kotak kuning):


Kemudian pada menu yang ditampilkan tersebut klik "copy URL to keyboard". Kata orang barat the rest is hystory. Anda peste link tersebut pada "new tab" atau "new window" dari TOR browser. Dan  selanjutnya tinggal "save as" ke harddisk Anda.


Dan sebagai penutup, saya belum melakukan test apapun untuk mencari tahu pada kasus mana tutorial ini tidak bekerja.



Tuesday, July 15, 2014

Statistik Quick Count

"There are three kinds of falsehoods: lies, damned lies, and statistics." Benjamin Desraili
Kebenaran itu bukan ditentukan oleh siapa Anda, apa gelar Anda, seberapa cerdas Anda, tapi ditentukan oleh seberapa terbuka Anda untuk membuang kefanatikan di kepala Anda, lantaran terobsesi dengan seabrek pencapaian yang Anda miliki.
Sebuah kebenaran bisa dicapai melalui diskusi. Tapi yang aneh, tidak sedikit kita mendengar umpatan semisal, “gue itu doktor lulusan Harvard, lu siape?” yang hakikatnya pernyataan yang sangat takabur dalam menilai kemampuan orang lain dalam menggagaskan kebenaran. Bahkan seorang profesor hebat dalam matematika pun ketika dikatakan ada yang salah dengan tulisannya, biasanya dia langsung menanyakan salahnya di mana.
Jadi dalam tulisan ini, saya menyatakan saya bukan seorang ahli, saya hanya pencari kebenaran. Jika seorang men-self-declaration dirinya seorang ahli, berarti dia itu bukan ahli. Karena ada banyak celah yang bisa kita cari untuk menjungkirbalikkan pernyataannya tersebut.
Berbicara tentang quick count yang sekarang ini menjadi bahan olok-olokan di media, sebenarnya saya hanya mengajukan pertanyaan sederhana, yakni bagaimana bisa pernyataan yang didasarkan pada data dari sample sebuah populasi bisa mengganti data yang diperoleh dari keseluruhan populasi tersebut. Saya bahkan pernah baca sebuah handbook yang katanya mengatur tentang bagaimana membuat sebuah quick count walaupun kenyataannya di dalamnya tidak terdapat sebuah pun standar operasi (SOP) dalam statistik disebutkan. Sebuah kebenaran harus punya alur logika yang jelas. Dalam hal ini penarikan sampel ala quick count mestinya menyertakan argumen-argumen dasar tentang alasan kita untuk mempercayai kesimpulan yang dihasilkan melalui metode tersebut. Berbicara tentang statistik, sebenarnya saya juga bukan orang statistik, dan saya juga g pernah baca paper-paper tentang kelayakan penggunaan quick count dalam men-judge hasil pemilu sebuah negara. Tapi argumen fundamental saya berkenaan dengan pemilu Indonesia adalah senada dengan kalimat Desraili di atas, bagaimana kita bisa memastikan data dari 2 ribuan TPS bisa digunakan untuk menjudge data dari 500 ribuan TPS? Ingat 2/500 = 0.4 persen. Kecuali Anda orang dungu, Anda akan tahu seberapa kecil signifikansi nilai 0.4 persen terhadap kebenaran yang 100 persen. Saya g tau, apakah di Indonesia semuanya orang bodoh, tapi saya melihat bahwa quick count ini tidak lebih dari akal-akalan LSM-LSM global dalam mencari dana/duit.
Argumennya itu mana? Misalnya saja quick count diambil untuk 5 TPS dari 20 TPS di kampung saya. Dan pada akhirnya didapatkan dari 5 TPS tadi, pasangan X itu menang, maka apa dasar lembaga quick count untuk mengatakan kalo di 15 TPS yang lain si X tadi juga menang. Ingat lo, ini manusia yang punya pikiran yang complex, dalam satu keluarga aja orang beda plihan kok. Dalam satu Individu pun, hari ini bicaranya mau pilih X, nyatanya bisa jadi besok di TPS pilih Y (saya rasa Anda saksikan sendiri fenomena seperti ini), lantas bagaimana kita bisa menjudge-nya dengan begitu yakin? Bisa jadi yang terjadi adalah pembenaran lembaga quick count ini hanya didasarkan pada feeling saja: “ah, jangan-jangan si X memang menang di TPS yang lain.” Tapi kan feeling bukan fakta ilmiah. Untuk sampai pada tahap kebenaran yang mendekati 100 persen, makan argumen yang valid dan data yang melimpah harus tersedia dengan jelas.

Sunday, May 11, 2014

Gerak Pada Bidang Miring: Kesalahan Terbesar Microsoft Excel VBA

Dalam tulisan kali ini saya sedikit berbagi pengalaman dalam menggunakan Microsoft Excel. Kebetulan kemarin saya mencoba membuat sebuah animasi mengenai bidang miring dengan menggunakan VBA ala Microsoft Excel. Masalahnya adalah rumusan saya tentang posisi kotak pada bidang miring itu sudah benar 100 persen. Yang bikin heran kok hasil penggambaran di Microsoft Excel tidak sesuai yang saya harapkan?

Gambar 1. Geometri Bidang Miring


Pada gambar 1, dengan mengingat bahwa koordinat monitor menggunakan titik asal pada TOP-LEFT, maka dapat diberlakukan persamaan: \begin{eqnarray} x_1 = x_2 - w \cdot \sin(\alpha) \\ y_1 = y_2 + w \cdot \cos(\alpha) \end{eqnarray} yang mengakibatkan \begin{eqnarray} x_2 = x_1 + w \cdot \sin (\alpha) \\ y_2 = y_1 - w \cdot \cos(\alpha) \end{eqnarray} Nah, rumusan ini berhasil saya terapkan dengan sempurna di JavaFX. Tapi entah kenapa ketika saya ganti ke VBA dari Microsoft Excel, semuanya kacau dan tidak sesuai harapan. Yang saya heran di Microsoft Excel, kok menghitung fungsi matematika yang berkaitan dengan trigonometri, dia menggunakan sudut radian. Ketika dia menentukan rotasi suatu objek, dia menggunakan sudut derajat. Mungkin saja ini penyebabnya atau satu dan lain hal, saya juga g tau.

Berikut ini adalah cuplikan video hasil implementasi dari rumus di atas di JavaFX:



Sementara source code untuk implementasi tersebut dapat anda lihat di github.

Adapun video dari keanehan Microsoft Excel yang dimaksud adalah:



di mana contoh implementasinya adalah
Sub TestAnimasi()
    total_iterasi = 0
    
    Dim shape As shape
    namaBenda = "Kotak"
    
    Set shape = Sheet1.shapes(namaBenda)
    Dim segitiga As shape
    Set segitiga = Sheet1.shapes("Bidang Miring")
    
    lokasiSegitigaX = segitiga.Left
    lokasiSegitigaY = segitiga.Top
    
    panjang = segitiga.Width
    lebar = segitiga.Height
    
    ' Hitung kemiringan bidang
    Dim sudutDerajat As Double
    sudut = Math.Atn(lebar / panjang)
    sudutDerajat = sudut / WorksheetFunction.Pi * 180
    shape.Rotation = sudutDerajat
    
    'Hitung default posisi
    defaultX = segitiga.Left + shape.Height * Sin(sudut)
    defaultY = segitiga.Top - shape.Height * Cos(sudut)
    
    'Letakkan kotak pada bagian awal dari bidang miring
    shape.Left = defaultX
    shape.Top = defaultY
    
    n = Sheet1.Cells(12, 13)
  
    Sheet1.Cells(22, 16) = sudutDerajat
    
    panjangLintasan = Math.Sqr(lebar * lebar + panjang * panjang)
    spasiLintasan = panjangLintasan / n
    lintasanAwal = 0
     Do
        DoEvents
        shape.Left = shape.Left + spasiLintasan * Cos(sudut)
        shape.Top = shape.Top + spasiLintasan * Sin(sudut)
        total_iterasi = total_iterasi + 1
        lintasanAwal = lintasanAwal + spasiLintasan
        timeout (0.2)
    Loop Until total_iterasi = n - 1
End Sub

Sub timeout(waktu As Double)
    StartTime = Timer
    Do
    DoEvents
    Loop Until (Timer - StartTime) >= waktu
End Sub

Monday, April 21, 2014

Penggunaan FXML dalam membentuk GUI dengan javaFX

Dalam kesempatan kali ini saya memberikan sedikit contoh penggunaan FXML dalam membentuk GUI di javaFX. FXML sendiri merupakan penarapan konsep MVC di java yakni dengan menggunakan bantuan java reflection. Terdapat beberapa tag yang cukup penting dalam javaFX. Yakni fx:include dan fx:root. Tutorial ini mencoba memberikan proof of concept mengenai tag yang kedua. Tag fx:root digunakan untuk melompati pendefenisian controller pada  file fxml. Jadi dengan tag ini maka class controller yang digunakan di-inisialisasi selama runtime.  Untuk maksud ini, maka terdapat  menu option pada javaFX scenebuilder yang bisa digunakan  yang bisa dilihat pada gambar berikut

:

Sehingga file fxml yang  sebelumnya berbentuk: <!--xml version="1.0" encoding="UTF-8"?--> <!--import java.lang.*?--> <!--import java.util.*?--> <!--import javafx.scene.*?--> <!--import javafx.scene.control.*?--> <!--import javafx.scene.layout.*?--> <AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="fjr.example.mediaplayer.playlist.PlayerController"> <children> <StackPane layoutX="49.0" layoutY="14.0" prefHeight="150.0" prefWidth="200.0" /> </children> </AnchorPane> akan berubah menjadi <!--xml version="1.0" encoding="UTF-8"?--> <!--import java.lang.*?--> <!--import java.util.*?--> <!--import javafx.scene.*?--> <!--import javafx.scene.control.*?--> <!--import javafx.scene.layout.*?--> <fx:root type="javafx.scene.layout.AnchorPane" id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2"> <children> <StackPane layoutX="49.0" layoutY="14.0" prefHeight="150.0" prefWidth="200.0" /> </children> </fx:root> Nah agar properti dari file fxml tersebut bisa diakses, maka dalam kelas controller kita harus defenisikan root-nya yang contohnya bisa dilihat pada potongan berikut:
    public PlayerController(Group root) throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("Player.fxml"));
        loader.setController(this);
        loader.setRoot(this);
        loader.load();
        root.getChildren().add(this);
        this.root = root;
        this.mainStage = (Stage) root.getScene().getWindow();
    }
Untuk melengkapi tutorial kali ini, saya memberikan sebuah proyek kecil yakni membuat sebuah media player dengan playlist dengan menggunakan javaFX. Playlist yang dimaksud dapat digunakan layaknya playlist di media player yang biasa kita kenal (semacam winamp, jet audio atau lain-lain) yakni dapat di-repeat kembali ke daftar pertama ketika lagu terakhir selesai. Bagi pembaca yang tertarik mencoba, dapat meng-clone source code-nya di github: https://github.com/gunungloli666/example-media-player-with-playlist/tree/master/src/fjr/example/mediaplayer/playlist

Thursday, April 17, 2014

Benchmarking operasi matriks pengganti loop di MATLAB

Dalam tulisan ini saya hanya sedikit mengulangi kembali beberapa hal yang saya peroleh dari pengalaman selama menggunakan MATLAB. Khususnya berkaitan dengan filosofi dari MATLAB itu sendiri yang merupakan laboratorium  matriks (matrix laboratory). Seperti kita ketahui dalam MATLAB semua operasi pemgrograman ditekankan dalam skema matriks. Jadi bagi pengguna yang terbiasa dengan bahasa lain, maka ada baiknya mempelajari beberapa operasi-operasi dasar dalam manipulasi matriks di MATLAB.

Sebenarnya tulisan ini hanya sekedar mengulangi apa yang sudah saya singgung di tulisan sebelum-nya mengenai seberapa besar pengaruh penggunaan operasi matriks dalam mereduksi waktu komputasi di MATLAB. Namun dalam tulisan ini saya lebih menekankan pada proses benchmarking-nya. Untuk membuktikan perbedaan besar antara menggunakan operasi matriks dengan menggunakan standar pemrograman biasa  (loop: for, while, dll) di MATLAB maka anda bisa mengetes potongan script berikut:
clear all ;
clc; 

% buat matriks M ukuran 5000 x 5000 yang elemennya bilangan bulat acak dari 1 sampai 10
M = randi(10,5000,5000);
% buat matriks N yang ukuran dan nilai elemennya sama dengan matriks M
% ingat, tanda  '='  di MATLAB bukan menandakan pointer kalo merujuk
% pada matriks. Jadi operasi pada elemen M tidak akan berpengaruh pada elemen N. 
N = M; 

[a,b] = size(M);
tic; 
for i=1:a,
    for j=1:b,
        if M(i,j) > 5
            M(i,j) = 20000; 
        end
    end
end
disp(['lama pake loop = ', num2str(toc)]);

tic; 
N(N>5) = 20000;
disp(['lama pake indeks = ', num2str(toc)]);

% cek apakah elemen kedua matriks sama... 
% tanda '==' pada MATLAB bukan menandakan cek objek, tapi cek elemen
if M==N,
    disp('yes..'); 
end
Hasil eksekusinya untuk situasi komputer saya (core i3 dengan ram 4 giga) adalah operasi matriks mampu mereduksi waktu komputasi hingga 5 kali lipat.


Mungkin ada yang menduga jangan-jangan ini dikarenakan waktu pertama running saja. Artinya andaikan operasi ini dilakukan berulang-ulang dalam waktu yang lama, maka hasilnya hampir mirip antara loop dengan operasi matriks. Anda bisa melakukan sedikit modifikasi pada script di atas yakni sebagai berikut:
clear all ;
clc; 
lama_loop = 0; 
lama_indeks = 0;
iter = 0; 
while iter < 23
    M = randi(10,5000,5000);
    N = M; 
    [a,b] = size(M);
    tic; 
    for i=1:a,
        for j=1:b,
            if M(i,j) > 5
                M(i,j) = 20000; 
            end
        end
    end
    lama_loop = lama_loop + toc; 
    tic; 
    N(N>5) = 20000;
    lama_indeks = lama_indeks + toc; 
    iter = iter + 1; 
end

disp(['lama operasi loop untuk 100 iterasi = ', num2str(lama_loop)]);
disp(['lama operasi matriks untuk 100 iterasi = ', num2str(lama_indeks)]);
Hasilnya kurang lebih sama.


Baru satu logika if dan satu loop sudah sekian waktu yang bisa dihemat dengan mengganti loop dengan operasi matriks. Sementara pada kenyataannya dalam suatu proyek komputasi ada banyak loop-loop yang sebenarnya tidak perlu dilakukan karena bisa diganti dengan operasi matriks. 

Intinya operasi matriks ini sangat berfungsi dalam kasus modifikasi elemen-elemen pada matriks. Bahkan hampir semua algoritma yang berhubungan  dengan operasi pada elemen-elemen matriks bisa dinotasikan ke dalam operasi matriks. 

Sunday, April 13, 2014

Menghitung luas area yang gelap pada image di MATLAB



Pada tulisan kali ini saya akan memberikan sedikit tutorial mengenai bagaimana menentukan persentase area pada gambar yang nilai pixel RGB-nya memilik karakter warna tertentu (misalnya gelap atau hitam). Tanpa perlu berbasa-basi saya langsung saja membagikan script disertai komentar seperlunya yang bisa saudara coba di MATLAB.
clc;
clear all ;
[a,b] = imread('polpot.jpg'); 
[m,n,o] = size(a);
% pertama akan ditentukan apakah nilai RGB pada koordinat seragam. Misalnya
% kita ambil sampel koordinat dari 10 baris pertama dan 10 kolom pertama. 
HJ = (a(1:10,1:10,1) == a(1:10,1:10,3) ) & ((a(1:10,1:10,1) == a(1:10,1:10,2) )) ;
HJ
%% 
% yang ternyata elemen matriks HJ  semua 1 yang menandakan semua nilai RGB piksel seragam.
% Untuk  membuktikan, coba kita Print 
% nilai elemen pada baris dan kolom tersebut
a(1:10,1:10,:)
%%
% sekarang karena outputnya seragam maka otomatis nilai sum terhadap
% seluruh matriks HJ akan sama dengan penjumlahan terhadap seluruh matrix
% 'ones' yang ukurannya sama dengan HJ. Jika logika ini kita perumum, akan bisa digunakan pada
% kasus matrik HH yang mencakup seluruh area dari image, yang  akan kita
% peroleh adalah
HH = (a(:,:,1) == a(:,:,2)) & (a(:,:,1) == a(:,:,3)); 
if sum(sum(HH)) == sum(sum(ones(m,n)))
    M  = a(:,:,1) <10;
    disp(['persen area yang nilai pixel-nya di bawah 10 (nilai 0 berarti hitam): ',... 
    num2str(sum(sum(M))/sum(sum(ones(m,n)))*100), ' persen']);
else 
    disp('nilai pixel tidak seragam')
    % karena nilai pixel tidak seragam, maka kita bisa gunakan asumsi bahwa
    % nilai pixel yang mendekati warna gelap itu yang nilai pixel-nya
    % kurang dari 5 untuk R, 5 untuk G, dan 5 untuk B. Memang nilai pixel
    % yang benar-benar hitam adalah R = 0, G = 0, dan B = 0. Akan tetapi
    % kita hanya mendapat sedikit porsi dari area image  untuk nilai tersebut. 
    % Jadi kita gunakan pendekatan tadi. 
    M = (a(:,:,1) < 5) & (a(:,:,2) < 5) & (a(:,:,3) < 5); 
    disp(['persen area yang nilai pixel untuk R < 5; G  < 5, dan B < 5: ',... 
    num2str(sum(sum(M))/sum(sum(ones(m,n)))*100), ' persen']);
end
%% 
% Kita juga bisa menentukan pada baris dan kolom mana saja yang nilai pixel
% R, G, B tidak seragam
logic = (a(:,:,1)== a(:,:, 2)) & (a(:,:,1)== a(:,:,3)); 
[x1,x2,x3] = ind2sub(size(a),find(~logic)); 
disp('10 baris pertama dan 10 kolom pertama yang pikselnya tidak seragam: '); 
x1(1:10)'
x2(1:10)'
disp('nilai RGB pada baris dan kolom tersebut: '); 
a(x1(1:10),x2(1:10),:)

Sunday, March 16, 2014

Clock follow Mouse di javaFX

Dalam demo ini saya sebenarnya ingin menunjukkan beberapa konsep pada javaFX yang sebenarnya kurang sempurna, atau mungkin saya saja yang belum tahu persis teknik yang paling bagus. Yakni bagaimana menjalankan beberapa animasi yang mengalami delay satu sama lain. Misalnya TranslateTransition di javaFx itu mau tidak mau harus dibikin secara bersamaan mulainya. Tidak bisa kita memulai secara terpisah. Ketika kita panggil perintah animation play, maka otomatis kesemuanya instance dari TranslateTransition itu jalan secara serta merta. Padahal saya menginginkan suatu kasus di mana antara masing-masing instance terdapat delay sehingga satu instance akan lebih dulu jalan ketimbang yang lain, dan pada masing-masing instance terdapat delay waktu. Saya mendapati suatu teknik yang bisa dipake, hanya saja teknik ini bisa dianggap kotor (dirty) dalam pemrograman javaFX, dan memang tidak sesuai dengan yang saya harapkan. Kotor dalam artian bukan pendekatan yang seharusnya diambil. Yakni dengan menggunakan java default Thread. Hasil yang diperoleh adalah Scenegraph dalam Thread berjalan dengan berat dan lambat. Demonya bisa dilihat di video berikut:



Makanya saya tidak bisa mewujudkan keinginan saya untuk merespon koordinat mouse saat ini bukan sekedar posisi klik dari mouse. Karena memang berat.

Concurrent programming untuk javaFX menggunakan Task dan Service class. Masalahnya adalah kedua kelas ini tidak bisa digunakan untuk memanipulasi Scenegraph. Hanya untuk keperluan-keperluan lain misalnya mendownload video, mengextract file atau lain-lain di luar manipulasi scenegraph. Sementara kita tidak mungkin menginterupsi main Thread dari program untuk memberi delay dari animasi.

Untuk source dari demo di atas Anda bisa lihat di sini:
https://github.com/gunungloli666/jam_follow_mouse/blob/master/src/fjr/mouse/follower/MouseFollowerPlugin.java