Categories

Custom Java Events

To create custom Java events we need basicly three classes:

  1. The event class which will be fired
  2. An interface which indicating responsibility of event listeners of this event
  3. The class which fires the Java events

When these classes are prepared, other classes can subscribe to events  by providing their event listener.

An event class must extend java.util.EventObject class. Below you can see an event class example which I used in an application that exchanges messages over TCP/IP sockets.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package prototype.communication.events;

import java.util.EventObject;

/**
 *
 * @author Server
 */

public class CommunicationEvent extends EventObject {


    private int eventType;
    public static final int ConnectionLost = 0;
    public static final int MessageReceived = 1;
    public static final int ConnectionEstablished = 2;
    public static final int ServerSocketFailed = 3;

    public CommunicationEvent(Object source, int eventType) {
        super(source);
        this.eventType = eventType;
    }

    public int getEventType() {
        return eventType;
    }
}

Coding the interface is usually trivial, note that this interface must extend java.util.EventListener interface which is a tagging interface.

1
2
3
4
5
6
7
8
9
10
11
package prototype.communication.events;

import java.util.EventListener;

/**
 *
 * @author Server
 */

public interface CommunicationEventListener extends EventListener{
    public void communicationEventReceived(CommunicationEvent event);
}

The third class which will fire should provide following functions to enable other class to subscribe to events:

1
2
public synchronized void addEventListener(CommunicationEventListener l);
public synchronized void removeEventListener(CommunicationEventListener l);

Following field can be used to store event listeners:

1
private List eventListeners;

Then implementation of add and remove functions follows intuitively:

1
2
3
4
5
6
7
public synchronized void addEventListener(CommunicationEventListener l) {
    eventListeners.add(l);
}

public synchronized void removeEventListener(CommunicationEventListener l) {
    eventListeners.remove(l);
}

Whenever this class needs to fire an event it will iterate over listeners and will call communicationEventReceived method of EventListener interface. You can see an example function that fires an event:

1
2
3
4
5
6
7
private synchronized void fireCommunicationEvent(int eventType) {
    CommunicationEvent event = new CommunicationEvent(this, eventType);
    Iterator listeners = eventListeners.iterator();
    while (listeners.hasNext()) {
        listeners.next().communicationEventReceived(event);
    }
}

Basketball Game: Robot (www.onlinegames.com/basketball/)

I have coded another helper program to a popular game using Robot class of Java. In this game, players are trying to score baskets in a 2d pitch by shooting the ball random positions to a basket of which position remains unchanged. The players only decide highest point of the path of the ball. By observation, it can be noticed that path of the ball is a parabola. Therefore the problem can be reduced to finding highest point of a parabolum of which two points (position of basket and initial position of ball) are known. Of course, countless different parabola can pass through two points. So setting height of highest point is also needed. Also note that basket and ball are on the separate arms of parabola. Consequently, we have the following known values

Coordinates of basket: Px,Py

Coordinates of ball: Tx,Ty

Height of highest point: H

Parabola equation: y = a(x-X)^2 + H

We need to find axis of highest point: X

Since we know that basket and position are on the parabola, we have following two equations:

1: Py=a(Px-X)^2 + H

2: Ty=a(Tx-X)^2 + H

Find value of a from 1 and 2, these values will also be equal:

Py–H / (Px-X)^2 = Ty-H / (Tx-X)^2

Py – H / Ty – H = (Px – X)^2 / (Tx – X)^2

(Py – H / Ty – H)^1/2 = |Px – X| / |Tx – X|

You can see that Px < X < Tx by looking at positions of basket and ball in the game.

(Py – H / Ty – H)^1/2 = (X – Px) / (Tx – X)

Tx * (Py – H / Ty – H)^1/2 – X * (Py – H / Ty – H)^1/2 = X – PX

Tx * (Py – H / Ty – H)^1/2 + Px = X + X * (Py – H / Ty – H)^1/2

X = (Tx * (Py – H / Ty – H)^1/2 + Px) / (1 + (Py – H / Ty – H)^1/2)

So we have axis of the highest point expressed in terms of known values.

The Java program below helps you to play the game using the calculations above. Things you have to do: Start program and open the game. Put your mouse to the lowest point of the ball. Then wait a moment for program to calculate and move your mouse to shooting position. Click your mouse to shoot. When new ball appears put your mouse to the lowest point of the ball and make the loop continue.

N.B. Coordinates of basket can be different for each screen. You can update the values in your program, since the program prints positions of the mouse to standard output. Put your mouse in the middle of the basket to see its coordinates in standard output. Then update basketPositionX and basketPositionY values in the code.

N.B. Since the movement of the ball is not a perfect parabola, the calculations fail during long shots. There is a variable called optCons to regulate calculations for long shots. So if the program fails in your computer, try increasing and decreasing this variable by small amounts (like 0.01 or 0.005).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import java.awt.AWTException;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Robot;

/**
 *
 * @author Server
 */

public class Main {

    /* screen dependent variables */
        public static final double basketPositionX = 143;
        public static final double basketPositionY = 336;
        public static final double optCons = 0.03;
    /* end of screen dependent variables */

    public static final double shootHeightY = -44;

    public static void main(String[] args) throws AWTException, InterruptedException {
        Robot robot = new Robot();
        Point lastLocation = MouseInfo.getPointerInfo().getLocation();
        Point location = MouseInfo.getPointerInfo().getLocation();
        int counter = 0;

        while (true) {

            Thread.sleep(100);
            location = MouseInfo.getPointerInfo().getLocation();

            if (lastLocation.x != location.x || lastLocation.y != location.y) {
                lastLocation = location;
                counter = 0;
            } else {
                counter++;
                if (counter == 5) {
                    Point calculatedLocation = calculate(location);
                    robot.mouseMove(calculatedLocation.x, calculatedLocation.y);
                    System.out.println("Coordinate Get:" + location.x + "," + location.y);
                    counter = 0;
                }
            }
        }

    }

    private static Point calculate(Point location) {
        double x1 = location.x;
        double y1 = -location.y ;
        double h = shootHeightY;

        double opt;

        double a = Math.sqrt(basketPositionY + shootHeightY);
        double b = Math.sqrt(Math.abs( -y1 + h));

        double r = (x1 * a + basketPositionX * b) / (a + b);
        System.out.println(r);
        opt = (x1-r) * optCons;
        r += opt;

        return new Point((int) r, (int) -h);
    }
}

DL – Safe SWRL Rules on OWL DL Ontologies with Pellet

Here is a simple example to understand the meaning of DL Safety.

In a DL Safe rule execution, only explicitly named individuals are bound to the variables in the rule.

Lets say we have a transitive object property named ancestorOf.

Can we simulate this transitivity using a DL-Safe SWRL rule rather than defining the ancestorOf property as transitive?

At the first glance it seems possible since transitivity is simply: transitive_property(?X, ?Y), transitive_property(?Y, ?Z) –> transitive_property(?X, ?Z)

To illustrate more clearly lets create the following ontology. I used Protégé 4.0 and Pellet Reasoner Plug-in 1.0 for Protégé.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
test:AncestorOfOlympian
a       owl:Class ;
owl:equivalentClass
[ a       owl:Restriction ;
owl:onProperty test:ancestorOf ;
owl:someValuesFrom test:Olympian
] .test:Olympian
a       owl:Class .test:AncestorOfChronos
a       owl:Class ;
owl:equivalentClass
[ a       owl:Restriction ;
owl:hasValue test:Chronos ;
owl:onProperty test:ancestorOf
] .
a       owl:Ontology .test:ancestorOf
a       owl:TransitiveProperty , owl:ObjectProperty .test:Uranus
a       owl:Thing ;
test:ancestorOf test:Chronos .

test:Chronos
a       test:AncestorOfOlympian , owl:Thing .

As expected the inferred class hierarchy is :

Now remove the transitive characteristic of ancestorOf. And Add the rule shown below.

Now classify the ontology again and look at the inferred class hierarchy.

In the first case the inference mechanism determines that AncestorOfOlympian is a super class of AncestorOfChronos.

Because Chronos is already an ancestor of some unknown individual of type Olympian and ancestorOf is transitive, then ancestor of Chronos is already an ancestor of Olympian.

Also Uranus is listed as an instance of AncestorOfOlympian.

In the second case , since there is no individual of Olympian is present, the inferences mentioned above can not be done.

Note that if we add an instance of Olympian (e.g. Zeus) and make Chronos ancestor of Zeus then Uranus is listed as an instance of AncestorOfOlympian however the inferred class hierarchy remains unchanged.

P.S. This example is a simplified version of weblog entry of Bijan Parsia.

Setting Java Character Encoding

When operations on different character sets need to be done in Java, we need to initialize JVM with required options.

First lets have a look at basics of java character encodings.

  • Internally the JVM always operates with Unicode.
  • Data transferred in or out of the JVM is converted to a format specified in the file.encoding property of the JVM
    • Data transferred in the JVM is converted from the format specified at file.encoding to Unicode
    • Data transferred out of the JVM is converted from Unicode to the format specified at file.encoding
  • When data need to be processed from Java Program other than the format specified in file.encoding the following classes which allows usage of encodings that takes precedence over the default one can be used
    • java.io.InputStreamReader
    • java.io.FileReader
    • java.io.OutputStreamReader
    • java.io.FileWriter

Default character set of the JVM varies across platform. Following piece of code shows how to get default character set of JVM.

1
2
3
4
5
6
System.out.println(System.getProperty("file.encoding"));
System.out.println(
new java.io.OutputStreamWriter(
new java.io.ByteArrayOutputStream()).getEncoding()
);
System.out.println(java.nio.charset.Charset.defaultCharset().name());

Output on linux

1
2
3
ANSI_X3.4-1968
ASCII
US-ASCII

This property can be set using System.setProperty(“file.encoding”, {desired encoding});

However doing this did not help me much since, the core Java libraries does not use this mechanism to determine default encoding.

My problem was to read from an java.net.URLConnection so i used the following piece of code:

1
2
URL url = new URL(urlStr);
URLConnection connection = url.openConnection();
1
2
3
//Create InputStreamReader with UTF8 Charset
BufferedReader in = new BufferedReader(new InputStreamReader(connection
.getInputStream(), Charset.forName("UTF-8")));
1
2
 // If we need to read this stream into a string we need to create the string like:
String str = new String(bytes, Charset.forName("UTF-8"));

BlazeDS - Remote Object Service Tutorial

Remoting Object Service of BlazeDS , is used for making remote procedure calls from Flex applications to Java Server.

Having BlazeDS deployed on an application server (Tomcat is used here) , following steps shows the server and client side coding for a simple scenario where a flex application is used to display instances of  Person and Car classes send by Java Web Application as a result of remote procedure call.

Server Side Coding and Configuration

Net Beans is used for creating Java Web Application. Here are the classes of the application

Class definition of the Java class of which methods will be invoked from Flex application must conform following specification :

  • Access modifier of the class must be “public”
  • Access modifier of the methods to be invoked must be “public”

Here is my deneme.Manager class that will send some Person instances to Flex application :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package deneme;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Cihan
 */

public class Manager {

    public List<Person> persons = new ArrayList<Person>();

    public Manager() {
        //We have no persistence
        //So create some dummy data to send
        Person person1 = new Person();
        Person person2 = new Person();
        Car car1 = new Car();
        Car car2 = new Car();

        person1.setName("Person1");
        person2.setName("Person2");

        car1.setModel("Model1");
        car2.setModel("Model2");

        person1.addCar(car1);
        person2.addCar(car2);

        persons.add(person1);
        persons.add(person2);

    }

    //The method that will be invoked
    public List<Person> getPersons() {
        return persons;
    }
}

There are two things left to do on the server side :

  • Copy the folders under directory {Project_Root}/build/web/WEB-INF/classes to {BlazeDS_Root}/WEB-INF/classes
  • Add the following XML element as a child of {BlazeDS_Root}/WEB-INF/flex/remoting-config.xml ‘s “service“ element
1
2
3
4
5
6
7
8
9
<destination id="PersonManager">
        <properties>
            <source>deneme.Manager</source>
            <scope>application</scope>
        </properties>
       
        <adapter ref="java-object" >
        </adapter>
    </destination>

Client Side Coding

I used a flex project with J2EE as server technology and LiveCycle Data Services as remote object access service with following server configuration :

The only thing we need to make remote procedure call is to create a mx.rpc.remoting.RemoteObject in ActionScript and call getPersons() method.

The call is asynchronous and server will respond this call in one of following forms (How to handle these events are shown in the code) :

  • An mx.rpc.events.ResultEvent of which result field  contains the return value of the invoked method
  • An mx.rpc.events.FaultEvent if any error occurs during remote procedure call

Here is the .mxml and .as files of the Flex application:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="{init()}">
    <mx:Script>
        <![CDATA[
            import deneme.Car;
            import mx.events.ListEvent;
            import mx.events.DataGridEvent;
            import mx.controls.Alert;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
            import mx.rpc.remoting.RemoteObject;
            import mx.collections.ArrayCollection;
            import deneme.Person;
           
           
            private var manager:RemoteObject;
           
            [Bindable]
            private var persons:ArrayCollection;
           
            [Bindable]
            private var selectedPerson:Person;
           
            [Bindable]
            private var selectedCars:ArrayCollection;
           
           
           
            private function init():void{
                //Argument given to the constructor should be same as the 'id' of the destination  
                manager = new RemoteObject("PersonManager");
               
                //Add EventListener for result case
                manager.addEventListener(ResultEvent.RESULT, onGetPersonsResult);
                //Add EventListener for fault case
                manager.addEventListener(FaultEvent.FAULT, onGetPersonsFault);
                //Call function using the same name as the method of Java class
                manager.getPersons();
            }
           
            private function onGetPersonsResult(event:ResultEvent):void{
                //Remove EventListeners
                manager.removeEventListener(ResultEvent.RESULT, onGetPersonsResult);
                manager.removeEventListener(FaultEvent.FAULT, onGetPersonsFault);
               
                //Store result in a variable
                persons = event.result as ArrayCollection;
               
            }
           
            private function onGetPersonsFault(event:FaultEvent):void{
                //Remove EventListeners
                manager.removeEventListener(ResultEvent.RESULT, onGetPersonsResult);
                manager.removeEventListener(FaultEvent.FAULT, onGetPersonsFault);
               
                //Display fault message in a popup window
                Alert.show(event.fault.message);
            }
           
            private function onChange(event:Event):void{
                selectedPerson = person_dg.selectedItem as Person;
                selectedCars = (person_dg.selectedItem as Person).cars;
           
            }  
           
        ]]>
    </mx:Script>
    <mx:DataGrid id="person_dg" x="10" y="10" dataProvider="{persons}" change="{onChange(event)}">
        <mx:columns>
            <mx:DataGridColumn headerText="Name" dataField="name"/>
        </mx:columns>
    </mx:DataGrid>
    <mx:DataGrid  x="120" y="10" dataProvider="{selectedCars}" >
        <mx:columns>
            <mx:DataGridColumn headerText="Model" dataField="model" />
        </mx:columns>
    </mx:DataGrid>
   
</mx:Application>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package deneme
{
    //Remote Class alias should be the fully qualified name of the Remote Class
    [RemoteClass(alias="deneme.Car") ]
   
    public class Car
    {
       
        //fields should be declared as "public" with same name and type
        public var model:String;
       
        //Default constructor should be declared
        public function Car()
        {
        }

    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package deneme
{
    import mx.collections.ArrayCollection;
   
    [RemoteClass(alias="deneme.Person") ]
    public class Person
    {
       
        public var name:String;
        [Bindable]
        public var cars:ArrayCollection;
       
       
        public function Person()
        {
        }
       
       
       

    }
}

Here is the .java files for Person and Car

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package deneme;

public class Car {
    public String model;

    public Car() {
    }

    public void setModel(String model) {
        this.model = model;
    }

    public String getModel() {
        return model;
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package deneme;

import java.util.ArrayList;
import java.util.List;

public class Person {

    public String name;
    public List<Car> cars;

    public Person() {
        cars= new ArrayList<Car>();
    }

    public void setCars(List<Car> cars) {
        this.cars = cars;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Car> getCars() {
        return cars;
    }

    public String getName() {
        return name;
    }

    public void addCar(Car car) {
        cars.add(car);
    }
}

Farmville: Clicking Robot

Too many clicks are needed while playing games like farmville. To this automatically, firstly I used a tool named xdotools which generates false keyboard and mouse input. But, since xdotools only supports X11, I switched to Java to have a platform independent program.

java.awt.Robot class can be used to generate false input in Java. You can easily imitate effects of moving mouse, rotating mouse wheel, pressing keyboard buttons or mouse buttons by utilizing this class.

Below, you can see a very simple Java program that moves mouse and clicks.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.InputEvent;

public class Main {

        public static void main(String[] args) throws AWTException {
                Robot robot = new Robot();

                robot.mouseMove(100, 100); //move mouse
                robot.mousePress(InputEvent.BUTTON1_MASK); //press left button of mouse
                robot.mouseRelease(InputEvent.BUTTON1_MASK); //release left button
        }
}
Here is the full code for a farm of one of my friends.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package farmville;

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.InputEvent;

/**
 *
 * @author Server
 */

public class Main {

        /**
         * @param args the command line arguments (not used)
         * @throws AWTException
         * @throws InterruptedException
         */

        public static void main(String[] args) throws AWTException, InterruptedException {
                Robot rbt = new Robot();

                int startX = 718;
                int startY = 706;
                int startPosX = 718;
                int startPosY = 706;
                Thread.sleep(3500); //sleep while I switch to facebook and make the window fulscreen
                rbt.mouseMove(startPosX, startPosY); // start at x=718 and y=706
                int x = 25;
                int y = 12;
                for (int j = 1; j < 23; j++) {
                        for (int i = 1; i < 22; i++) {
                                rbt.mousePress(InputEvent.BUTTON1_MASK);
                                rbt.mouseRelease(InputEvent.BUTTON1_MASK);
                                rbt.mouseMove(startPosX += x, startPosY -= y);
                        }
                        rbt.mousePress(InputEvent.BUTTON1_MASK);
                        rbt.mouseRelease(InputEvent.BUTTON1_MASK);
                        startX -= x;
                        startY -= y;
                        startPosX = startX;
                        startPosY = startY;
                        rbt.mouseMove(startPosX, startPosY);
                }
        }
}

Dealing with lots of paranthesis…

While dealing with lambda calculus expression that I mentioned in my previos post, from time to time many paranthesis appears. Exampli gratia: While trying to SKI equivalent of

λx.λy.+ x y,

intermediate expressions like

S (S (K S) (S (K (S (K +))) (S (λx K) (λx x)))) (λx I)

can be encountered. While dealing with such expression text editor of KDE named Kate may help you. Use highlighting support of Kate for Scheme language which colors nested paranthesis with seven different colors. To enable this feature select Tools->Highlighting->Scripts->Scheme from menu of Kate. The same effect can also be achieved by changing extension of the file you are working on to “scm”, “scheme”, “guile” or “ss”.

You can see calculation of SKI equivalent of λx.λy.+ x y with colored paranthesis

Finding SKI Equivalents of λ-Calculus Expressions

Define S, K and I as

S x y z = x z (y z)

K x y = x

I x = x

Apply following transformations to lambda calculus expression until the expression becomes free of lambda abstractions and variables.

1) λx.e1 e2 => S (λx e1) (λx e2)

2) λx.x => I

3) λx.c => K c [Here, c should not contain any free variable x.]

E.g.:

Lets find SKI equivalent of λx.+ x x

Since function application is left-associative in lambda calculus

λx.+ x x = (λx(+x) x)

Apply transformation 1:

(S (λx + x) (λx x))

Apply transformation 1, again:

(S (S (λx +) (λx x)) (λx x))

Appyle transformation 3,2 and 2 again:

(S (S (K +) I) I)

We are done, since we have a variable and lambda abstraction free expression. Now we can check our result by applying a number.

For example, apply 3:

(S (S (K +) I) I) 3 [Use definition of combinators to evaluate this expression. We began with S x y z = x z (y z)]

(S (K +) I 3) (I 3)

(K + 3) (I 3) (I 3)

+ 3 3

6

MySQL Workbench ile MySQL veritabanı oluşturma

Bir masaüstü ya da web uygulaması geliştirirken çoğunlukla süreklilik gösterecek (persistent) veriye gereksinim duyulur. Süreklilik gösterecek veriler dosya sistemi ya da veritabanı gibi araçlar kullanarak saklanıp kullanılabilir. Bu yazımda MySQL Workbench kullanarak nasıl veritabanı oluşturulacağından söz edeceğim.

MySQL’de komut satırı kullanarak veritabanı, tablo vs. oluşturmaktansa MySQL Workbench kullanarak verimizi daha hızlı bir biçimde tasarlayıp verimize uygun veritabanını kolayca oluşturabiliriz.

MySQL Workbench, Geliştirilmiş Varlık İlişki (Enhanced Entity Relationship) diyagramları yoluyla verimizi modelleme olanağı sunar. Workbenchte bu diyagramları kullanarak veritabanı tablolarımızı ve tablolarımız arasındaki ilişkileri tanımlayabiliriz. Bu işlem Workbench’i çalıştırdıktan sonra şu adımlar izlenerek hızlıca yapılabilir.

  1. EER Diagrams sekmesinin altında “Add Diagram” seçeneğini çift tıklayın.
  2. Açılan model oluşturma paneline her varlığınız için “Place a New Table” şeçeneğini kullanarak bir tablo ekleyin.
  3. Tablonuza “id” sütunu otomatik olarak eklenecektir. Bunu tablonuza çift tıkladıktan sonra aşağıda açılacak sekmelerden “Columns” u tıklayarak görebilirsiniz. Tercihen “id”  sütunu için AI(Automatic Incremental – Otomatik Artırma) seçeneğini işaretleyerek, bu tabloya eklenecek her girdi için id değerinin bir artıtılmasını sağlayabilirsiniz.
  4. Tablonuza istediğiniz diğer sütunları da ekleyin.
  5. Bütün varlıklarınızı oluşturduktan sonra artık ilişkileriniz çok kolay bir biçimde oluşturabilirsiniz. İlişki türünüzü seçin (1:1, 1:n, n:m) ve ilişkide görev alacak tabloları birer kez sırayla tıklayın. Yeni bir ilişki için ya yeni bir tablo oluşturulacaktır ya da var olan tabloların birine bir sutün eklenecektir.
  6. Bütün tablolarınız ve ilişkileriniz oluştuktan sonra menü çubuğundan “Database” -> “Forward Engineer” seçeneğini tıklayın.
  7. İlk iki ekrandaki seçeneklerden size uygun olanları işaretleyin. Emin değilseniz yalnızca ilk seçenekleri işaretleyip “Next” ile devam edin.
  8. 3. basamakta veritabanınızı oluşturacak SQL betiği karşınıza gelecektir. “Next” ile devam edin.
  9. 4. basamakta veritabanı ulaşım ayarlarınızı (sunucu adı, port numarası, kullanıcı adı ve şifre) girin.
  10. “Execute” tuşuna basarak işlemi sonlandırın.

Bu işlem sonunda bağlantı bilgileriniz doğru ve MySQL sunucunuz erişilebilir durumdaysa, veritabanınız oluşturulacaktır.