Friday, November 29, 2013

Modeling a simple system in Mason...

In this post I'm describing how to implement a simple agent model in Mason multiagent simulation environment. See introductory post for additional details about this endeavour.

Installing Mason

Mason installation is easy. Just download cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 newest archive and unpack it somewhere on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 disk. That's all that has to be done. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following text I'm referring to this unpacked installation, and anything done is done within that directory. It doesn't have to, but it is easier for a start.

Running simulation

The next thing is how to run Mason simulation. But it turns out to be easy. As an example I'll show you how to run Tutorial2 example. This example simulates Conway's game of life and has a GUI that can be used to control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 simulation. So, go to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 directory where you unpacked archive that you've downloaded in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous step and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n enter sim/app/tutorial1and2 subdirectory. Java file is already precompiled, but nevercá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365less, we'll compile it again because it is easy and instructive. To compile Tutorial2 issue cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following command:
CLASSPATH=../../../jar/mason.17.jar javac Tutorial2.java
Note that Mason framework is in mason.17.jar and that you have to specify it to Java compiler using CLASSPATH variable. The previous command shouldn't give you any messages. To run compiled example, issue cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following command:
CLASSPATH=../../../jar/mason.17.jar:. java sim.app.tutorial1and2.Tutorial2
All in all, compiling and running models built using Mason framework is relatively straightforward.

Evolving cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target system

The idea I'll pursue in this section is to gradually build a simulation system. The simulation system will be represented by one class that will instantiate and control all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r classes. Those ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r classes I'll call agents. There will be an agent that represents a job, one for server(s) and one for a queue that will hold jobs until cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server is free to take cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m.

The simplest possible simulation

We'll start with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 simplest possible simulation in Mason, and that is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following one:
package hr.fer.zemris.queue;

import sim.engine.*;

public class QueueSystem extends SimState
{
    public QueueSystem(long seed)
    {
        super(seed);
    }

    public static void main(String[] args)
    {
        doLoop(QueueSystem.class, args);
        System.exit(0);
    }
}
To compile it you have to place it into hr/fer/zemris/queue directory (corresponds to package statement at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 beginning of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source). I'll assume that this directory is in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mason's toplevel directory. The name of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Java file has to be QueueSystem.java. In order to compile it, issue cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following command:
CLASSPATH=jar/mason.17.jar javac hr/fer/zemris/queue/QueueSystem.java
and run it in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following way:
$ CLASSPATH=jar/mason.17.jar:. java hr/fer/zemris/queue/QueueSystem
MASON Version 17.  For furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r options, try adding ' -help' at end.
Job: 0 Seed: -1713501367
Starting hr.fer.zemris.queue.QueueSystem
Exhausted
Don't forget that dot at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 CLASSPATH variable's value, or else, you'll get an error about being unable to find a class.

This simulation is a very simple one and, as expected, it doesn't do anything useful. All it does is call doLoop method of SimState class which will instantiate QueueSystem object. In our case, we didn't specify anything for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 simulation, so nothing happens.

In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following text this simulation will be extended so that it create and coordinate ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r agents.

First agent

Ok, let's create an agent. Our initial agent will, again, be very simple. It will only print it was instantiated, but nothing else. So, here it is:
package hr.fer.zemris.queue;

import sim.engine.*;

public class Server implements Steppable
{
    public Server()
    {
        System.out.println("Instantiated one Server");
    }

    public void step(final SimState state)
    {
        System.out.println("step() method called");
    }
}
Note that we have to define step() method, because it is required by Steppable interface. But, for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 moment, it doesn't do anything.

Ok, to compile this agent, use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 usual command:
CLASSPATH=jar/mason.17.jar javac hr/fer/zemris/queue/Server.java
Again, I assumed that you are positioned into mason's root directory, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 agent is placed within hr/fer/zemris/queue directory and it is called Server.java.

Note that you can not directly run agents, at least not in this form (i.e. without main method). So, we'll instantiate and schedule execution of our agent in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main class that represents cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 whole simulation. The change is simple, in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class QueueSystem.java add cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following method:
public void start()
{
    super.start();

    Server server = new Server();
    schedule.scheduleOnce(server);
}
Now, recompile QueueSystem.java class, and run it:
$ CLASSPATH=jar/mason.17.jar:. java hr/fer/zemris/queue/QueueSystem
MASON Version 17. For furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r options, try adding ' -help' at end.
Job: 0 Seed: -1710667392
Starting hr.fer.zemris.queue.QueueSystem
Instantiated one Server
step() method called
Exhausted
Note cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lines in bold. First line is printed when constructor of our simple agent was called. The second one is outputted when agent's step() method was called. Note that step method was called only once, and that is because we used method scheduleOnce() that schedules a single occurrence of an event. Try to change scheduleOnce() into scheduleRepeating() and see what will change.

There is also a question of when this event was called. We used a simple version of schedule methods that schedule execution 1 time unit in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 future, i.e. in getTime() + 1.0. Well, at least documentation says so! Try to check it by youself. Hint: to get current time in agent's step() method use state.schedule.getTime() method.

Creating jobs

Jobs are a bit different. They are not created at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 start of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 simulation, but instead are created dynamically according to Poisson distribution. So, what I'm going to do is to create class named JobFactory that will create Job. Each job will be represented using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following class:
package hr.fer.zemris.queue;

import sim.engine.*;

public class Job
{
    public double createTime;
    public double processingTime;
    public double finishTime;
}
Note that job isn't agent! It doesn't have step() method neicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r it's subclassed from some Mason's class. What I decided is that Job class will only have fields to keep statistical data and that's it.

To create jobs, I written JobFactory agent. Here is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 agent:
package hr.fer.zemris.queue;

import sim.engine.*;
import sim.util.distribution.*;
import ec.util.MersenneTwisterFast;

public class JobFactory implements Steppable
{
    private Poisson poisson;
    private Exponential exponential;
    private QueueSystem queueSystem;

    public JobFactory(double lambda, double mu, QueueSystem qs)
    {
        MersenneTwisterFast randomGenerator = new MersenneTwisterFast();
        poisson = new Poisson(lambda, randomGenerator);
        exponential = new Exponential(mu, randomGenerator);
        queueSystem = qs;
    }

    public void step(final SimState state)
    {
        double currentTime = state.schedule.getTime();
        double nextEventTime = currentTime + poisson.nextDouble();

        Job job = new Job();
        job.createTime = currentTime;
        job.processingTime = exponential.nextDouble();
        queueSystem.pushNewJob(job);

        state.schedule.scheduleOnce(nextEventTime, this);
    }
}
So, how this JobFactory agent works? First, we have a constructor. Constructor instantiates two classes, Poisson and Exponential, that will be used to generate random numbers from respective distributions. The first two parameters of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 constructor define distributions' mean values. The third parameter is used for sending newly created jobs into a system queue.

Note that, apart from generating new jobs according to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Poisson distribution, we also have to specify for how long will a single job be processed within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server. I think that a natural place to determine this is when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 job is created since it is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 characteristic of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 job itself.

I thought about sending Job objects directly to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server agent. But cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 problem with that approach is that server has to schedule itself in case cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are no ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r jobs waiting, i.e. cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 job immediately enters server. Namely, server has to wake up when some job is finished and remove it from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system.

But, in order to be able to do scheduling I had to have access to SimState object, which is accessible only from step() method. Now, I could save this object internally, but it would be a hack. Namely, I would have to somehow provoke step() to be executed immediately at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 beginning. Oh, yeah, I could send SimState object via constructor. But in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end, I gave up from pursuing this approach as I haven't been able to find someone else already doing this (nor in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 examples directory, nor on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Internet).

The second part of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JobFactory class, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 its workhorse, is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method step(). What this method does is create a new Job class initializes its processing time (job.processingTime) and adds it to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 queue of jobs waiting for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server (via call to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method queueSystem.pushNewJob). Finally, this method draws new random number for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Poisson distribution which defines when a new job will be created. It schedules itself at that point in time.

Ok, our simulation class, QueueSystem, has to have a method for accepting new jobs. This method has name pushNewJob, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following:
public void pushNewJob(Job job)
{
    jobQueue.add(job);

    if (jobQueue.size() == 1)
        schedule.scheduleOnce(schedule.getTime() + job.processingTime, server);
}
jobQueue is a linked list, i.e. FIFO queue, that is used to hold jobs while being processed in Server and waiting for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Server. The job that is in front of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 queue is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 job that is currently processed by Server. Maybe I should have written code a bit differently, i.e. so that Server holds cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 job it processes in some internal attribute, but I did it this way and I didn't bocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r to rewrite it.

Apart from adding new job to a queue cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is one additional thing I had to do. In case cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is no job in queue, that means cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server is idle, and it is not scheduled for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 execution! So, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 if statement checks this condition, and if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server is idle it schedules its execution when jobs is finished! Ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise, server will execute at some point and it will take next job and schedule itself. We'll come to that part a bit later.

One more thing hasn't been specified with respect to QueueSystem, namely jobQueue and activation of JobFactory. Server isn't activated until cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a job, and that is handled by pushNewJob method.

So, in order to take care of that case, here is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new start() method of QueueSystem simulation/class:
public void start()
{
    double alpha = 3;
    double beta = 5;

    super.start();

    jobQueue = new LinkedList();

    server = new Server(jobQueue);

    jobFactory = new JobFactory(alpha, beta, this);
    schedule.scheduleOnce(jobFactory.getFirstInvocationTimeStamp(), jobFactory);
}
So, what's going on in this method. There are alpha and beta parameters for M/M/1 queue. Next, I'm initializing FIFO queue, jobQueue. It's defined as follows as a QueueSystem's class atribute:
Queue jobQueue;
Then, server agent is instantiated. Note that I'm sending queue to server. That is necessary since server has to take jobs from a queue. I'm also instantiating JobFactory agent. Finally, I'm scheduling initial run of JobFactory.

There is a small probelm. Namely, I have to schedule first invocation according to Poisson distribution. It is not correct to invoke it immediately, at least not in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 form I wrote it. And, this class, QueueSystem, doesn't have access to poison distribution in order to get first random number. It would be also error to create anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r Poisson distribution. So, I added a method to JobFactory class/agent that will return me first random number. It is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following method:
public double getFirstInvocationTimeStamp()
{
    return exponential.nextDouble();
}
and you should place it in JobFactory agent/class.

Ok, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 final piece of puzzle, Server agent. First, constructor is now a bit different, namely, it has to take queue reference:
public Server(Queue jq)
{
    jobQueue = (LinkedList)jq;
}
step() method is also a bit more involved:
public void step(final SimState state)
{
    Job job = jobQueue.remove();
    job.finishTime = state.schedule.getTime();

    jobs++;
    systemTimeAvg = systemTimeAvg + (job.finishTime - job.createTime - systemTimeAvg) / jobs;
    jobNumberAvg = jobNumberAvg + (jobQueue.size() - jobNumberAvg) / jobs;
    currentStep++;
    if (skipSteps == currentStep) {
        System.out.println(systemTimeAvg + " " + jobNumberAvg);
        currentStep = 0;
    }

    if (jobQueue.size() > 0) {
        job = jobQueue.peek();
        state.schedule.scheduleOnce(state.schedule.getTime() + job.processingTime, this);
    }
}
What does this method do? First, it pops a job from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 front of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 queue, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 job that was processed within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server. Then, it updates and prints some statistics. Finally, it checks if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r job in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 queue, and if it is, it schedules invocation of itself when that particular job has to finish.

Basically, that's it.

Wednesday, November 27, 2013

GnuCash - evidencija plaćanja debitnom karticom

Evidencija plaćanja debitnom karticom gotovo je identična evidenciji plaćanja u gotovini, jedino što je tijekom upisa odakle se povlače novci potrebno staviti tekući račun - budući da vam debitna kartica skida s tekućeg računa.

U tom smislu, pretpostavimo da ste platili debitnom karticom gablec u restoranu. Kako bi to upisali, prvo je potrebno odrediti u koju stavku će to biti zavedeno. Možete si otvoriti zaseban račun za to, ili kao u mom slučaju, možete voditi unutar stavke Hrana. Dakle, kada upišete u tu stavku račun, to će izgledati otprilike kao na idućoj slici:


Dakle, jedina razlika je što se kao izvor sredstava navodi tekući račun.

Tuesday, November 26, 2013

Lecture about agile software development

On November 22nd and 25th, 2013, I gave a lecture about agile software development to a group of employees of Croatian Telecom. This lecture was part of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir internal education in which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y were educated about different IT and business technologies. The goal of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lecture was not to teach cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m specifics of agile software development but to give cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m some kind of an overview of agile development, to contrast it to a more traditional methods, more specifically to waterfall development model, and to compare cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m mutually. With that in mind, I ended up with a presentation that has cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following parts:
  1. Introduction and motivation
  2. Why is software development hard?
  3. Traditional methodologies
  4. Principles of Agile software development.
  5. Some specific agile software development methodologies.
  6. Problems encountered when introducing agile methods.
  7. Experiences gained during introduction of agile methods from some companies.
  8. History of agile methods.
  9. Conclusion.
The presentation is in Croatian, and available here. In case cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is demand, I'll translate it to English. I plan to enhance and improve cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 presentation (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is lot of place to do so). If I upload newer version I'll expand this post. But also, filename will be changed (it includes date of a release). Accompanying this presentations are references I deemed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 most interesting for those employes. They can be downloaded as a single ZIP file. Note that those references are in English!

I'm using some pictures from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Internet in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 presentation and I hope that I didn't broke any licence or copyright agreements. The same holds for papers in ZIP file which are given for purely educational purposes. In case I didn't do right something, please notify me.

Sunday, November 24, 2013

GnuCash - evidencija plaćanja gotovinom

Pretpostavimo kako ste si ujutro u pekari kupili sendvič za doručak. Dobili ste račun i odlučili ste to sada upisati u GnuCash. Račun je iznosio 14kn.

Kako bi upisali tu stavku u GnuCash, pokrenite program i potom odaberite gdje ćete voditi te troškove. Ja sam odlučio voditi zasebno troškove o hrani i za to sam si otvorio odgovarajuću stavku:


Svjestan sam kako navedena stavka nije baš najpreciznija, ali kao što rekoh, u hodu ću rješavati sve probleme. Kako bi se upisao račun potrebno je dva puta kliknuti na stavku, u ovom slučaju Hrana, te se potom otvara kartica gdje je potrebno upisati što je kupljeno. Inače, moguće je voditi evidenciju o svakoj kupljenoj stavci, međutim, ja sam se odlučio voditi evidenciju samo o računima pri čemu razmišljam da svaki račun slikam fotoparatom (nemam skener!) i pohranjujem slike na računalo. :) Vidjet ćemo kako će to ići. U međuvremenu, ovako izgleda upisan račun:


Primjetite da sam upisao i broj računa. To radim kako bi mogao povezati svaku stavku sa svakim računom, da kasnije ne moram pretraživati po iznosu. Još bolje bi bilo kada bi mogao negdje upisati JIR ili ZKI, ali nećemo pretjerivati. ;)

Primjetite također da je u kolonu Transfer upisano odakle sam uzimao novce za plaćanje. Plaćao sam gotovinom, iz novčanika, te je zato odabrana opcija Assets: Novčanik - Kune.

Stanje nakon te transakcije je sada sljedeće:


Kao što se vidi, u novčaniku sad moram imati 186Kn. Ako ih nema tamo, onda imam problem. :)

To je to što se tiče upisivanja računa. U osnovi, svaki drugi račun koji je plaćen gotovinom iz novčanika upisuje se na isti način.

Vođenje osobnog knjigovodstva upotrebom GnuCash alata - Uvod i postavljanje okoline

Već neko vrijeme razmišljam kako bi bilo dobro voditi evidenciju gdje trošim novce. Svako malo mi se desi da se uhvatim u razmišljanju gdje sam uspio potrošiti plaću i naravno da se ne mogu sjetiti. Drugo pitanje koje me muči s vremena na vrijeme je: Koliko novaca mi odlazi na režije mjesečno, godišnje? U tom smislu, prošao sam nekoliko faza. Prva faza je bila redovito skidanje izvoda iz banke te sam u LibreCalcu računao jednostavni zbroj potrošnje svaki mjesec koji sam potom uspoređivao s plaćom. To je bilo OK, ali nedovoljno precizno. Recimo, nisam znao koliko sam mjesečno trošio na režije unatrag zadnje godine dana (ili više). Zbog toga sam prešao na iduću fazu. Druga faza je bila vođenje evidencije u LibreCalcu gdje sam svaki mjesec upisivao koliko sam potrošio na što. To je bilo bolje, međutim, još uvijek nisam bio zadovoljan jer sam mislio kako su mi mogućnosti upravljanja i analize podataka relativno ograničene. Pri tome nisu ograničene zbog mogućnosti same aplikacije (LibreCalc) već zbog mog vođenja evidencije. Konačno, to me je potaknulo da krenem u treću fazu, korištenje programa GnuCash. U biti, imao sam jedan izlet u taj program puno ranije, međutim, nisam bio uporan i s obzirom kako je ipak nužno upoznati se s nekim temeljnim pojmovima iz knjigovodstva, brzo sam odustao. No, ovaj puta sam ozbiljnije odlučio pokušati koristiti tu aplikaciju.

Tome je pripomogao i relativno dobar uvod u Gnucash program sam pronašao na YouTubeu. Naime, na temelju tog videa sam se odlučio na pristup od jednostavnijeg prema složenijem, tj. da započnem koristiti program na najjednostanviji mogući način, baš kao što se u videu i pokazuje. S vremenom bi potom proširivao količinu podataka kako se pokazuje potreba za njima. Dodatno, odlučio sam iskoristiti mogućnosti prilagodbe različitih podataka kako bi što bolje reflektirali specifičnosti Hrvatske, odnosno, onoga što meni treba.

Inače, razlog zašto sam se odlučio za GnuCash je činjenica kako je besplatan, radi na svim bitnim platformama (Windows, Linux, Mac OS X) i često se spominje kao vrlo kvalitetan program. Osim osobnog knjigovodstva, moguće je voditi i poslovanje u njemu, a ima i Python API pa se može proširivati.

Uglavnom, nakon instalacije GnuCasha i njegovog prvog pokretanja otvara se dijalog New Account Hierarchy Setup.


Nakon odabira tipke Forward, nudi se odabir podrazumijevane valute. Tu nema puno nedoumica, u Hrvatskoj je podrazumijevana valuta kuna, tj. HRK. Konačno, dolazi odabir načina vođenja stavki. Tu sam odabrao opciju 'A Simple Checkbook'.


Konačno, još sam dva puta odabrao Forward i potom Apply. Zatim je trebalo odabrati mjesto na disku gdje će biti pohranjena datoteka. Pripazite kako GnuCash automatski čuva stare verzije datoteke, a istovremeno vodi evidenciju o promjenama (logs). U tom smislu, kreirajte zaseban direktorij u kojemu će biti pohranjeni ti podaci i u njega spremite datoteku.

Nakon toga, pobrisao sam sve što mi se nije sviđalo, te sam preveo i dodao određene stvari. Konkretno, izmjene koje sam napravio su sljedeće:
  • Checking Account sam preveo kao Tekući račun i premjestio ga direktno pod Assets stavku. Tekući račun je za fizičke osobe (pojedince) u HR temeljna stvar.
  • Current Assets stavku sam izbrisao.
  • Nadalje, pod Assets sam još dodao stavke Žiro račun i Novčanik - Kune. Ako imate gotovinu u devizama dodajte još stavku Novčanik - EUR (ili koja vam je već valuta u pitanju). Ovdje bi, osim toga, dodali i razne fondove u kojima držite novce, ako ih imate. U osnovi, dodajete sve gdje držite novce. U krajnjem slučaju, ako u nekoj čarapi držite novce, onda dodajete to tu.
  • Riječ Expenses sam preveo u Troškovi i potom sam tamo dodao stavke Auto, Internet, Mobilni telefon, Hrana, Režije. Pod Auto dodatno Gorivo, Servis, Registracija i Ostalo, te pod režije Struja, Voda, i slično.
  • Konačno, riječ Income sam pretvorio u Prihodi, a onda sam i tu dodao podstavku Plaća. Ako tijekom vremena budem imao nekakav drugi prihod, onda ću ga dodatni naknadno. Slično vrijedi i za troškove.
Promjene su se svodile na uređivanje postojeće stavke, odnosno, dodavanje nove. Dodavanje nove stavke obavlja se tako da kliknete desnom tipkom na stavku unutar koje želite dodati novu stavku i potom odaberete opciju New Account... Promjena postojeće stavke se obavlja slično, kliknete desnom tipkom na stavku koju želite izmjeniti i potom odaberete opciju Edit Account...

Nakon svih tih mojih uređivanja, ono što sam ja imao bilo je sljedeće:


Mogao sam tu još uređivati pojedine elemente, ali za sada sam stao na ovom stanju. S vremenom ću to poboljšavati i mijenjati.

Bitna stvar je da s GnuCashom počinjete voditi evidenciju o stanju svojih računa i troškovima počevši od jednog specifičnog trenutka. Taj trenutak može biti proizvoljan, ali stvar je u tome da negdje morate upisati koliko čega imate u tom početnom trenutku. Ja sam odabrao kako ću početi voditi knjigovodstvo od dana kada sam započeo upotrebljavati GnuCash. Za definiranje početnog stanja služi stavka Equity. Unutar te stavke ima stavka Opening Balances. Tamo sam dodao stavke koje su opisivale koliko imam na tekućem računu, deviznom, u novčaniku i slično. S obzirom da sam imao nešto deviza, a Opening Balances je u kunama, dodao sam i podstavku Devize. Tamo sam potom upisao eure. Možda ima nekakav način da se u jednu podstavku upisuju različite valute, ali trenutno to ne znam napraviti. Osim toga, GnuCash je prilično fleksibilan i moguće je naknadno napraviti reorganizaciju. Prema tome, nema potrebe težiti savršenstvu odmah od prve već je moguće s vremenom poboljšavati proces.

Primjera radi, pretpostavit ću da sam na tekućem računu započeo s 3000kn, na žiro računau 50kn, te na deviznom računu 100EUR. Dodatno, u novčaniku sam imao 200kn i 10EUR. Prvo sam, dakle, dodao sve kune koje imam. Dodavanje se obavlja tako da se dva puta klikne na opciju Opening balances te se potom upisuju odgovarajuće stavke. Nakon upisa, stanje je bilo sljedeće:


Iduće što je trebalo upisati su euri. S obzirom da ne znam način kako se može na stavke koje su definirane u kunama (Opening Balances je u kunama) upisivati druga valuta, konkretno euri, zbog toga sam otvorio novu kategoriju pod Equity naziva Početno stanje - EUR. Istovremeno s tim, stavku Opening Balances sam promijenio u Početno stanje - Kune.


U tu stavku sam potom upisao početne vrijednosti u Eurima:


Eto, to je što se tiče postavljanja inicijalnog stanja. Sada slijedi skupljanje računa i vođenje evidencije o onome što potrošite i što zaradite. O tome ću u drugim postovima:
  1. Evidencija pristigle plaće.
  2. Evidencija troškova na MasterCard kartici.
  3. Plaćanje gotovinom u trgovini.
  4. Plaćanje debitnom karticom u trgovini.
  5. Podmirenje troškova kreditne kartice.
Za kraj, par napomena:

  1. Volio bi kada bi me neki knjigovođa ispravio u vezi pojmova koje sam upotrebljavao, a također, ako koji savjet oko boljeg korištenja ovog alata bi jako dobro došao. S vremenom će se sigurno iskristalizirati nekakve prakse, no, bolje je preskočiti lutanje ako je moguće. :)
  2. Ako ima koji stručnjak za GnuCash alat, također bi volio da malo prokomentira moj post, a i kasnije postove!
  3. Kada započnete voditi evidenciju troškova u GnuCash-u, ili bilo kojem sličnom alatu, to trebate raditi detaljno jer u suprotnom neće biti poklapanja između stanja vaših računa (i novčanika) i onoga što piše u programu te je cijeli postupak besmislen.

About Me

scientist, consultant, security specialist, networking guy, system administrator, philosopher ;)

Blog Archive