<file_sep>#include "agent.h"

Agent::Agent(QObject *parent, QTableWidget *tab, uint maxSteps) :
    QObject(parent)
{
    maxSteps_ = maxSteps;
    stepsLimit = maxSteps;
    stepNo = 0;
    tab_ = tab;

    timer.setParent(this);
    timer.setInterval(5);

    dtimer.setParent(this);
    dtimer.setInterval(500);

    connect(&timer, SIGNAL(timeout()), this, SLOT(nextStep()));
    connect(&dtimer, SIGNAL(timeout()), this, SLOT(nextDemoStep()));
}

void Agent::nextStep()
{
    qDebug()<< stepNo <<"step. Limit "<<maxSteps_ << "x="<<lPos.x << "y="<<lPos.y;
    tab_->item(lPos.y,lPos.x)->setBackgroundColor(Qt::white);//zeruje kolor
    maxSteps_--;
    stepNo++;

    //nastepna pozycja
    position nPos = nextMove(lPos);//

    updateValue(lPos, nPos);

    if(tab_->item(nPos.y,nPos.x)->backgroundColor() == Qt::green)
    {
        qDebug()<<"znalazl wyjscie";
        stop();
        return;
    }

    tab_->item(nPos.y,nPos.x)->setBackgroundColor(Qt::yellow);
    lPos = nPos;

    if(maxSteps_ > 1)
    {
        timer.start();
    }else{
        stop();
        qDebug()<<"limit krokow";
        return;
    }
}

position Agent::nextMove(position pos)
{
   position nextPos = Nav::randomMove(pos);

   while(1)///bedzie szukal az znajdzie nastepne dobry spot
   {
   if (tab_->item(nextPos.y,nextPos.x) != 0 && tab_->item(nextPos.y,nextPos.x)->backgroundColor() != Qt::gray)
    return nextPos;

   nextPos = Nav::randomMove(pos);
   }

}

void Agent::stop()
{
    timer.stop();
    tab_->item(lPos.y,lPos.x)->setBackgroundColor(Qt::white);//zeruje kolor

    repeats_--;
    if(repeats_>0)
        start(stepsLimit,repeats_);
}

void Agent::start(uint maxSteps, uint repeats)
{
    reset();
    stepNo = 0;

    maxSteps_ = maxSteps;
    repeats_ = repeats;

    QList<QTableWidgetItem*> selections = tab_->selectedItems();

    if (selections.count() == 0)
    {
        sPos = setStart();
        tab_->setCurrentCell(sPos.y, sPos.x,QItemSelectionModel::Select);
    }
    else{
        sPos.x = selections.at(0)->column();
        sPos.y = selections.at(0)->row();
    };
    qDebug()<< "agent start at position: " <<sPos.x<<sPos.y;

    lPos = sPos;
    tab_->item(lPos.y,lPos.x)->setBackgroundColor(Qt::blue);

    timer.start();
}

void Agent::reset()
{
    itemValue v;
    v.value=0;
    v.numerator=0;
    v.divisor=1; //wstepna wartosc to pierwsza wartosc

    v.dval = 0;
    v.p.clear();

    int rowCount = tab_->rowCount();

    for(int i = 0; i<rowCount;i++)
    {
        for(int j =0; j<rowCount;j++)
        {
            arr[i][j].divisor = 1;
            arr[i][j].numerator = 0;
            arr[i][j].p.clear();
            arr[i][j].value = 0;
            if(tab_->item(i,j)->text().toInt() > 0)
            {
                arr[i][j].value = tab_->item(i,j)->text().toInt();
                arr[i][j].dval = tab_->item(i,j)->text().toInt();/// i tak przepisuje tylko pelne setki
            };
        }
    }

}

void Agent::updateValue(position lastPos, position newPos)
{
    itemValue it;// next item
    itemValue lit;//last item
    ///arr podreczna tablica wartosci
    ///tab_ tutaj wpisujemy wynik

    it = arr[newPos.y][newPos.x];// wartosc z nowego pola
    lit = arr[lastPos.y][lastPos.x]; // wartosc ze starego pola
    ///SMA simple moving average
//        int X = it.value;
//        //wartosc do starego pola
//        it = arr[lastPos.y][lastPos.x];
//        it.numerator += X;
//        it.divisor ++;
//        X = it.value = it.numerator / it.divisor;
//        tab_->item(lastPos.y,lastPos.x)->setText(QString::number(X));

    ///WMA  weighted moving average
        double X = arr[newPos.y][newPos.x].dval * 0.99;          //bierzemy wartosc z nowego pola
        double num = 0;// podreczny licznik i mianownik
        double div = 0;

        lit.p.append(X);
        lit.n.append(stepNo);
        int c = lit.p.count();    // ile elementow w kontenerach
        for(int i = 0; i < c; i++)
        {
            num = num + lit.p.at(i)/lit.n.at(i);        ///sumowanie licznika
            div = div + 1/lit.n.at(i);                  ///sumowanie mianownika
            qDebug()<< "               i:" << i << "num" << num << "div" << div;
        };


        lit.dval = X = num / div; // nowa wartosc
        qDebug()<<"                                                        X"<<X;

        arr[lastPos.y][lastPos.x] = lit; // item spowrotem do starego w tablicy
        tab_->item(lastPos.y,lastPos.x)->setText(QString::number(X));

}

position Agent::setStart()
{
    position p;
    ///srodek planszy
    p.x = tab_->rowCount()/2;
    p.y = tab_->columnCount()/2;

    for (int i= 0; i < 20; i++)
    {
        if(tab_->item(p.y,p.x)->backgroundColor() !=Qt::white) //sprawdza czy nie ma sciany
        {
            p = Nav::randomMove(p);
        }else
            return p;
    }
    return p;
}

void Agent::startDemo()
{
//    sPos
    tab_->item(sPos.y,sPos.x)->setBackgroundColor(Qt::blue);
    lPos = sPos;
    dtimer.start();
}

void Agent::nextDemoStep()
{
    ///tab_->item(lPos.y,lPos.x)->setBackgroundColor(Qt::white);//zeruje kolor///nie zerujemy koloru, zaznacza tam gdzie byl

    if(tab_->item(lPos.y,lPos.x)->text().toInt() == 100)// jezeli koniec
    {
        tab_->item(lPos.y,lPos.x)->setBackgroundColor(Qt::yellow);
        qDebug()<<"koniec ";
        dtimer.stop();
        return;
    }

     ///wybierz najlepsze miejsce dookoła
    position nextPos, temp;
    double bestValue = 0;

    temp.y = lPos.y - 1;
    temp.x = lPos.x;
    if(tab_->item(temp.y,temp.x) != 0 && tab_->item(temp.y,temp.x)->text().toDouble() > bestValue && tab_->item(temp.y,temp.x)->backgroundColor() != Qt::blue){
        bestValue = tab_->item(temp.y,temp.x)->text().toDouble();
        nextPos = temp;
    };
    temp.x = lPos.x + 1;
    temp.y = lPos.y;
    if(tab_->item(temp.y,temp.x) != 0 && tab_->item(temp.y,temp.x)->text().toDouble() > bestValue && tab_->item(temp.y,temp.x)->backgroundColor() != Qt::blue){
        bestValue = tab_->item(temp.y,temp.x)->text().toDouble();
        nextPos = temp;
    };
    temp.y = lPos.y + 1;
    temp.x = lPos.x;
    if(tab_->item(temp.y,temp.x) != 0 && tab_->item(temp.y,temp.x)->text().toDouble() > bestValue && tab_->item(temp.y,temp.x)->backgroundColor() != Qt::blue){
        bestValue = tab_->item(temp.y,temp.x)->text().toDouble();
        nextPos = temp;
    };
    temp.x = lPos.x - 1;
    temp.y = lPos.y;
    if(tab_->item(temp.y,temp.x) != 0 && tab_->item(temp.y,temp.x)->text().toDouble() > bestValue && tab_->item(temp.y,temp.x)->backgroundColor() != Qt::blue){
        bestValue = tab_->item(temp.y,temp.x)->text().toDouble();
        nextPos = temp;
    };

    if(bestValue == 0)
        nextPos = nextMove(lPos); // zrobi losowy krok jezeli same zera dookola


    if((lPos.x == nextPos.x) && (lPos.y == nextPos.y))
    {
        qDebug()<<"stoimy ";
        tab_->item(lPos.y,lPos.x)->setBackgroundColor(Qt::red);
        dtimer.stop();
    }else{
        qDebug()<<"best move ";
        lPos = nextPos;
        tab_->item(nextPos.y,nextPos.x)->setBackgroundColor(Qt::blue);
        dtimer.start();
    }


}




<file_sep>#ifndef AGENT_H
#define AGENT_H

#include <QObject>
#include <QTimer>
#include <QTableWidget>
#include <QDebug>
#include <QVector>
#include <array>


#include "nav.h"
#include "Helpers.h"

class Agent : public QObject
{
    Q_OBJECT
public:
    Agent(QObject *parent, QTableWidget *tab, uint maxSteps);

signals:

public slots:
    void start(uint maxSteps, uint repeats);
    void startDemo();
    void reset();
    void stop();

private slots:
    void nextStep();
    void nextDemoStep();

private:
    QTimer timer;
    QTimer dtimer;//demo timer
    uint maxSteps_;
    uint stepsLimit;
    int stepNo;
    QTableWidget *tab_;
    uint repeats_;

    position sPos;//start
    position lPos;//last position
    position aPos;//actual

    QTableWidgetItem *prevItem;

    position setStart();
    position nextMove(position pos);
    void updateValue(position lastPos, position newPos);
    //std::array<std::array<itemValue,100>,100> arr;
    itemValue arr[100][100];

};

#endif // AGENT_H
<file_sep>#ifndef NAV_H
#define NAV_H

#include "Helpers.h"
#include <QApplication>
#include <QDebug>

/// agent navigation

class Nav
{
public:

static position randomMove(position p);


};

#endif // NAV_H
<file_sep>#include "nav.h"

/// losowy wybor jednego z 4 kierunkow
position Nav::randomMove(position p)
{
    int dir = qrand() % 4;
    switch (dir) {
    case 0:
        p.x --;//lewo
        qDebug()<<"left";
        break;
    case 1:
        p.y --;//gora
        qDebug()<<"up";
        break;
    case 2:
        p.x ++;//prawo
        qDebug()<<"right";
        break;
    case 3:
        p.y ++;//dol
        qDebug()<<"down";
        break;
    default:
        break;
    };
    return p;
}
<file_sep>#ifndef HELPERS_H
#define HELPERS_H

#include <qvector.h>

struct position{
    int x;          //column
    int y;          //row
};

struct itemValue{
    ///prosta srednia wazona
    int value;      //wartosc pola
    int numerator;  //licznik
    int divisor;    //dzielnik,mianownik

    ///wazona srednia kroczaca
    double dval;
    QVector<double> p; //kontener wartosci
    QVector<double> n;

    ///wlasny

};

#endif // HELPERS_H
<file_sep>#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QDebug>


#include "agent.h"

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private slots:
    void on_spinBox_2_valueChanged(int arg1);

    void on_spinBox_valueChanged(int arg1);

    void on_wallGenButton_clicked();

    void on_spinBox_M_valueChanged(int arg1);

    void on_learnButton_clicked();

    void on_runButton_clicked();

    void on_refreshButton_clicked();

private:
    Ui::Dialog *ui;

    int worldSize;
    int m;
    int learningSteps;
    int M;

    void updateLearningSteps();
    void deleteWalls();
    void createItems();
    void setExit(int row, int column);

    void cleanWorld();

    QTableWidget *tab;

    Agent *agent;
};

#endif // DIALOG_H
<file_sep>#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);

    tab = ui->tableWidget;

    tab->verticalHeader()->hide();
    tab->horizontalHeader()->hide();

    m = 20;
    worldSize = 8;
    on_spinBox_valueChanged(ui->spinBox->value());

    on_spinBox_M_valueChanged(ui->spinBox_M->value());

    on_spinBox_2_valueChanged(ui->spinBox_2->value());

    updateLearningSteps();

    agent = new Agent(this, ui->tableWidget, learningSteps);
}

Dialog::~Dialog()
{
    delete ui;
}

void Dialog::updateLearningSteps()
{
    learningSteps = ui->spinBox->value() * ui->spinBox_2->value();
    ui->label_3->setText(QString::number(learningSteps));
}

void Dialog::on_spinBox_2_valueChanged(int arg1)
{
    m = arg1;
    updateLearningSteps();
}

///zmiana rozmiaru swiata
void Dialog::on_spinBox_valueChanged(int arg1)
{
    worldSize = arg1;
    qDebug()<< "world size changed to: " << worldSize;

    ui->tableWidget->setColumnCount(worldSize);
    ui->tableWidget->setRowCount(worldSize);

    ui->tableWidget->setAutoFillBackground(true);
    QSize tableSize, cellSize;

    tableSize = ui->tableWidget->size();
    cellSize.setHeight(tableSize.height() / worldSize -1);
    cellSize.setWidth(tableSize.width() / worldSize -1);


    qDebug()<< tableSize.width() << "tableSize " << tableSize.height();
    qDebug()<< cellSize.width() << "cellSize " << cellSize.height();

    for(int i=0; i < worldSize ;i++)
    {
        ui->tableWidget->setRowHeight(i,cellSize.height());
        ui->tableWidget->setColumnWidth(i,cellSize.width());
    }

    createItems();

    updateLearningSteps();
}

///generowanie scian na planszy
void Dialog::on_wallGenButton_clicked()
{
    int prob;
    int up,down,right,left;
    int ws = worldSize;
    prob = ui->horizontalSlider->value();
    deleteWalls();


    //qDebug()<< "prob value"<< prob << "qrand" << qrand() % 100;
    ///wall generation
    for(int y =0;y < worldSize; y++){
        for(int x =0;x < worldSize; x++){

            y-1<0 ? up=y :up=y-1;
            y+1>ws ? down=y : down=y+1;
            x+1>ws ? right=x : right=x+1;
            x-1<0 ? left=x :left=x-1;
            //qDebug()<<"up down right left"<< up<<down<<right<<left << "cords: " << x << y;

            if((qrand() % 100) < prob){
                if(tab->item(up,x)->backgroundColor() != Qt::gray &&
                   tab->item(y,left)->backgroundColor() != Qt::gray)
                tab->item(y,x)->setBackgroundColor(Qt::gray);
            };
        };
    };

    ///exits generation
    int egdeItems = 4*worldSize -4;
    int temp;
    QVector<int> exits;
    //qDebug()<< "egditems: "<<egdeItems<< "exits"<< M;

    for(int q=1; q <= M; q++)//////rozdanie wyjsc równomiernie wokoło klatki
    {
        temp = q * egdeItems/M;
        //qDebug()<<"temp"<<temp;
        exits.append(temp);
    };
    temp=0;

    for(int pg=0; pg < worldSize;pg++)///gorna krawedz w prawo//////przebieg po każdej z 4 krawędzi
    {
        temp++;
        if(temp == exits.at(0))
        {
            setExit(0,pg);
            exits.pop_front();
        }
    };
    for(int dp=1; dp < worldSize-1; dp++)
    {
        temp++;
        if(temp == exits.at(0))
        {
            setExit(dp,worldSize-1);
            exits.pop_front();
        }
    };
    for(int ld=9; ld > -1; ld--)
    {
        temp++;
        if(temp == exits.at(0))
        {
            setExit(worldSize-1,ld);
            exits.pop_front();
        }
    };
    for(int gl=8; gl > 0; gl--)
    {
        temp++;
        if(temp == exits.at(0))
        {
            setExit(gl,0);
            exits.pop_front();
        }
    };
}

/// wyczyszczenie swiata
/// 1. usuniecie sciana
/// 2. wyzerowanie textow // TODO
void Dialog::deleteWalls()
{
    for(int i =0;i < worldSize; i++){
        for(int j =0;j < worldSize; j++){
                ui->tableWidget->item(i,j)->setBackgroundColor(Qt::white);
                ui->tableWidget->item(i,j)->setText("");
        };
    };

    agent->reset();
}

void Dialog::setExit(int row, int column)
{
    tab->item(row,column)->setBackgroundColor(Qt::green);
    tab->item(row,column)->setText("100");
    tab->item(row,column)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
}

///alokacja itemow w tabeli
void Dialog::createItems()
{
    for(int i =0;i < worldSize; i++){
        for(int j =0;j < worldSize; j++){

                ui->tableWidget->setItem(i, j, new QTableWidgetItem);
        };
    };
}

void Dialog::on_spinBox_M_valueChanged(int arg1)
{
    M = arg1;
}

///proces uczenia sie
void Dialog::on_learnButton_clicked()
{
    uint reps = ui->spinBox_repeats->value();
    qDebug ()<<"starting "<< reps << "learning runs";
    agent->start(learningSteps,reps);
}

///proces poruszania sie po "wyuczonym" swiecie
void Dialog::on_runButton_clicked()
{
    agent->startDemo();
    qDebug()<<"start demo";
}

/// wyczyszczenie swiata
void Dialog::on_refreshButton_clicked()
{
    deleteWalls();
}


