Init version
This commit is contained in:
79
DEC_GUI/Agressor/agent.cpp
Normal file
79
DEC_GUI/Agressor/agent.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#include "agent.h"
|
||||
#include <iostream>
|
||||
#include <QLineF>
|
||||
|
||||
Agent::Agent(uint agentId, uint agr, uint prot, uint mod, uint str, uint rad, uint sp, QObject *parent) :
|
||||
id(agentId), agressor(agr), protector(prot), mode(mod), strategy(str), radius(rad),
|
||||
speed(sp), distTarget(0), contentment(0), QObject(parent) {}
|
||||
|
||||
uint Agent::getID(){
|
||||
return this->id;
|
||||
}
|
||||
void Agent::setID(uint agentId){
|
||||
this->id = agentId;
|
||||
}
|
||||
uint Agent::getAgressor(){
|
||||
return this->agressor;
|
||||
}
|
||||
void Agent::setAgressor(uint agr){
|
||||
this->agressor = agr;
|
||||
}
|
||||
uint Agent::getProtector(){
|
||||
return this->protector;
|
||||
}
|
||||
void Agent::setProtector(uint prot){
|
||||
this->protector = prot;
|
||||
}
|
||||
qreal Agent::getCoordX(){
|
||||
return this->coordX;
|
||||
}
|
||||
void Agent::setCoordX(qreal x){
|
||||
this->coordX = x;
|
||||
}
|
||||
qreal Agent::getCoordY(){
|
||||
return this->coordY;
|
||||
}
|
||||
void Agent::setCoordY(qreal y){
|
||||
this->coordY = y;
|
||||
}
|
||||
uint Agent::getMode() {
|
||||
return this->mode;
|
||||
}
|
||||
void Agent::setMode(uint mod) {
|
||||
this->mode = mod;
|
||||
}
|
||||
uint Agent::getStrategy() {
|
||||
return this->strategy;
|
||||
}
|
||||
void Agent::setStratedy(uint str){
|
||||
this->strategy = str;
|
||||
}
|
||||
int Agent::getRadius(){
|
||||
return this->radius;
|
||||
}
|
||||
void Agent::setRadius(uint rad){
|
||||
this->radius = rad;
|
||||
}
|
||||
uint Agent::getSpeed(){
|
||||
return this->speed;
|
||||
}
|
||||
void Agent::setSpeed(uint sp){
|
||||
this->speed = sp;
|
||||
}
|
||||
qreal Agent::getDistTarget(){
|
||||
return this->distTarget;
|
||||
}
|
||||
void Agent::setDistTarget(qreal dist){
|
||||
this->distTarget = dist;
|
||||
}
|
||||
qreal Agent::getContentmemt(){
|
||||
return this->contentment;
|
||||
}
|
||||
void Agent::setContentment(qreal cont){
|
||||
this->contentment = cont;
|
||||
}
|
||||
void Agent::gameEvent(QLineF shift){
|
||||
setCoordX(getCoordX() + shift.dx());
|
||||
setCoordY(getCoordY() + shift.dy());
|
||||
//std::cout << "new coord X: " << getCoordX() << ", new coord Y: " << getCoordY() << std::endl;
|
||||
}
|
||||
51
DEC_GUI/Agressor/agent.h
Normal file
51
DEC_GUI/Agressor/agent.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef AGENT_H
|
||||
#define AGENT_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class Agent : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Agent(uint agentId, uint agr, uint prot, uint mod, uint str, uint rad, uint sp, QObject *parent = 0);
|
||||
// setters, getters
|
||||
uint getID();
|
||||
void setID(uint);
|
||||
uint getAgressor();
|
||||
void setAgressor(uint agr);
|
||||
uint getProtector();
|
||||
void setProtector(uint prot);
|
||||
qreal getCoordX();
|
||||
void setCoordX(qreal x);
|
||||
qreal getCoordY();
|
||||
void setCoordY(qreal y);
|
||||
uint getMode();
|
||||
void setMode(uint mod);
|
||||
uint getStrategy();
|
||||
void setStratedy(uint str);
|
||||
int getRadius();
|
||||
void setRadius(uint rad);
|
||||
uint getSpeed();
|
||||
void setSpeed(uint sp);
|
||||
qreal getDistTarget();
|
||||
void setDistTarget(qreal dist);
|
||||
qreal getContentmemt();
|
||||
void setContentment(qreal cont);
|
||||
|
||||
void gameEvent(QLineF shift); // смена положения
|
||||
|
||||
private:
|
||||
uint id; // порядковый номер
|
||||
uint agressor; // номер игрока А (условно - агрессора)
|
||||
uint protector; // номер игрока В (условно - защитника)
|
||||
qreal coordX; // координата x
|
||||
qreal coordY; // координата y
|
||||
uint mode; // режим: 0 - режим труса, 1 - режим защитника
|
||||
uint strategy; // стратегия: 0 - движение по медиане/антимедиане, 1 - движение по нормали
|
||||
uint radius; // радиус (для расчёта столкновений)
|
||||
uint speed; // скорость
|
||||
qreal distTarget; // расстояние до желаемых координат
|
||||
qreal contentment; // неудовлетворённость агента
|
||||
};
|
||||
|
||||
#endif // AGENT_H
|
||||
26
DEC_GUI/Agressor/agentitem.cpp
Normal file
26
DEC_GUI/Agressor/agentitem.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <QPainter>
|
||||
#include "agentitem.h"
|
||||
|
||||
AgentItem::AgentItem(Agent *ag, QColor col) :
|
||||
agent(ag), color(col){
|
||||
}
|
||||
QRectF AgentItem::boundingRect()const {
|
||||
int radius = agent->getRadius();
|
||||
return QRectF(-radius, -radius, 2*radius, 2*radius);
|
||||
}
|
||||
void AgentItem::paint(QPainter * painter, const QStyleOptionGraphicsItem *option,
|
||||
QWidget *widget){
|
||||
int radius = agent->getRadius();
|
||||
painter->setBrush(color);
|
||||
painter->drawEllipse(-radius, -radius, 2*radius, 2*radius);
|
||||
}
|
||||
|
||||
/*
|
||||
* Событие: обновление текущих координат
|
||||
*/
|
||||
void AgentItem::agentEvent(){
|
||||
//std::cout << "coordX: " << agent->getCoordX() << " coordY: " << agent->getCoordY() << std::endl;
|
||||
setPos(agent->getCoordX(), agent->getCoordY());
|
||||
}
|
||||
21
DEC_GUI/Agressor/agentitem.h
Normal file
21
DEC_GUI/Agressor/agentitem.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef AGENTITEM_H
|
||||
#define AGENTITEM_H
|
||||
|
||||
#include <QGraphicsItem>
|
||||
#include "agent.h"
|
||||
|
||||
class AgentItem : public QGraphicsItem
|
||||
{
|
||||
public:
|
||||
explicit AgentItem(Agent *agent, QColor col);
|
||||
|
||||
QRectF boundingRect() const; // ограничивающий прямоугольник
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); // отрисовка
|
||||
void agentEvent(); // событие: обновление текущих координат
|
||||
|
||||
private:
|
||||
Agent *agent;
|
||||
QColor color;
|
||||
};
|
||||
|
||||
#endif // AGENTITEM_H
|
||||
187
DEC_GUI/Agressor/aphistory.cpp
Normal file
187
DEC_GUI/Agressor/aphistory.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include "aphistory.h"
|
||||
|
||||
/*
|
||||
* Конструктор
|
||||
*/
|
||||
APHistory::APHistory() {
|
||||
//
|
||||
}
|
||||
|
||||
/*
|
||||
* Добавление отдельного контейнера для каждого запуска модели
|
||||
*/
|
||||
void APHistory::addClassHistory() {
|
||||
QList<qreal> content;
|
||||
avContenmentHistory.push_back(content);
|
||||
}
|
||||
|
||||
/*
|
||||
* Добавление отдельного контейнера для данных по группам каждого запуска модели
|
||||
*/
|
||||
void APHistory::addClassGroupHistory() {
|
||||
QList<qreal> groupsContent;
|
||||
QVector<QList<qreal> > modelsContent(4, groupsContent);
|
||||
groupAvContenmentHistoty.push_back(modelsContent);
|
||||
}
|
||||
|
||||
/*
|
||||
* Добавление данных о модели с номером iModel
|
||||
*/
|
||||
void APHistory::addAvContenmentData(int iModel, qreal avContenmentData){
|
||||
avContenmentHistory[iModel].push_back(avContenmentData);
|
||||
}
|
||||
|
||||
/*
|
||||
* Добавление данных о модели с номером iModel по группам
|
||||
*/
|
||||
void APHistory::addGroupAvContenmentData(int iModel, QVector<qreal> avContenmentData){
|
||||
for (int iGroup = 0; iGroup < 4; iGroup++) {
|
||||
groupAvContenmentHistoty[iModel][iGroup].push_back(avContenmentData[iGroup]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Вывод в файл всех данных по модели с номером iModel
|
||||
*/
|
||||
void APHistory::postPrintModelData(int iModel){
|
||||
QString directoryName("Output_for_model_");
|
||||
directoryName += QString::number(iModel);
|
||||
QDir directory(directoryName);
|
||||
if (!directory.exists()){
|
||||
directory.mkpath(".");
|
||||
}
|
||||
std::stringstream fileName;
|
||||
fileName << "./Output_for_model_" << iModel << "/avContenment_model" << iModel << ".txt";
|
||||
std::ofstream avContOutput(fileName.str().c_str());
|
||||
for(int i = 0; i < avContenmentHistory[iModel].size(); i++){
|
||||
avContOutput << avContenmentHistory[iModel][i] << std::endl;
|
||||
}
|
||||
avContOutput.close();
|
||||
}
|
||||
|
||||
void APHistory::postPrintGroupData(int iModel){
|
||||
QString directoryName("Output_for_model_");
|
||||
directoryName += QString::number(iModel);
|
||||
QDir directory(directoryName);
|
||||
if (!directory.exists()){
|
||||
directory.mkpath(".");
|
||||
}
|
||||
for (int j = 0; j < 4; j++){
|
||||
std::stringstream ss;
|
||||
ss << "./Output_for_model_" << iModel << "/avContenment_model" << iModel << "_group" << j << ".txt";
|
||||
std::ofstream groupAvContOutput(ss.str().c_str());
|
||||
for(int i = 0; i < groupAvContenmentHistoty[iModel][j].size(); i++){
|
||||
groupAvContOutput << groupAvContenmentHistoty[iModel][j][i] << std::endl;
|
||||
}
|
||||
groupAvContOutput.close();
|
||||
}
|
||||
}
|
||||
|
||||
void APHistory::postPrintGlobalAverage() {
|
||||
for (int iGroup = 0; iGroup < 4; iGroup++) {
|
||||
QList<qreal> data = getAverageForGroup(iGroup);
|
||||
QString directoryName("Output_for_average");
|
||||
QDir directory(directoryName);
|
||||
if (!directory.exists()){
|
||||
directory.mkpath(".");
|
||||
}
|
||||
std::stringstream ss;
|
||||
ss << "./Output_for_average/avContenmentForAllModels_group" << iGroup << ".txt";
|
||||
std::ofstream averageForGroups(ss.str().c_str(), std::ios::app);
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
averageForGroups << data[i] << std::endl;
|
||||
}
|
||||
averageForGroups.close();
|
||||
}
|
||||
QList<qreal> data = getAverageForAllModels();
|
||||
std::ofstream averageForAll("./Output_for_average/avContenmentForAllModels.txt");
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
averageForAll << data[i] << std::endl;
|
||||
}
|
||||
averageForAll.close();
|
||||
}
|
||||
|
||||
/*
|
||||
* Вывод в файл последних данных по модели с номером iModel
|
||||
*/
|
||||
void APHistory::printCurrentContentmentData(int iModel){
|
||||
QString directoryName("Output_for_model_");
|
||||
directoryName += QString::number(iModel);
|
||||
QDir directory(directoryName);
|
||||
if (!directory.exists()){
|
||||
directory.mkpath(".");
|
||||
}
|
||||
std::stringstream ss;
|
||||
ss << "./Output_for_model_" << iModel << "/avContenment_model" << iModel << ".txt";
|
||||
std::ofstream currentAvContOutput(ss.str().c_str(), std::ios::app);
|
||||
currentAvContOutput << avContenmentHistory[iModel].last() << std::endl;
|
||||
currentAvContOutput.close();
|
||||
}
|
||||
|
||||
void APHistory::printCurrentContentmentGroupData(int iModel){
|
||||
QString directoryName("Output_for_model_");
|
||||
directoryName += QString::number(iModel);
|
||||
QDir directory(directoryName);
|
||||
if (!directory.exists()){
|
||||
directory.mkpath(".");
|
||||
}
|
||||
for (int iGroup = 0; iGroup < 4; iGroup++){
|
||||
std::stringstream ss;
|
||||
ss << "./Output_for_model_" << iModel << "/avContenment_model" << iModel << "_group" << iGroup <<".txt";
|
||||
std::ofstream currentAvContOutput(ss.str().c_str(), std::ios::app);
|
||||
currentAvContOutput << groupAvContenmentHistoty[iModel][iGroup].last() << std::endl;
|
||||
currentAvContOutput.close();
|
||||
}
|
||||
}
|
||||
|
||||
QList<qreal> APHistory::getHistory(int iModel) {
|
||||
return avContenmentHistory[iModel];
|
||||
}
|
||||
|
||||
QList<qreal> APHistory::getGroupHistory(int iModel, int iGroup) {
|
||||
return groupAvContenmentHistoty[iModel][iGroup];
|
||||
}
|
||||
|
||||
QList<qreal> APHistory::getAverageForAllModels() {
|
||||
QList<qreal> average;
|
||||
int nModels = avContenmentHistory.size();
|
||||
if (nModels > 0){
|
||||
int nIterations = avContenmentHistory[0].size();
|
||||
for (int j = 0; j < nIterations; j++){
|
||||
qreal buffer = 0;
|
||||
for (int i = 0; i < nModels; i++) {
|
||||
buffer += avContenmentHistory[i][j];
|
||||
}
|
||||
average.push_back(buffer/nModels);
|
||||
}
|
||||
}
|
||||
return average;
|
||||
}
|
||||
|
||||
QList<qreal> APHistory::getAverageForGroup(int group) {
|
||||
QList<qreal> average;
|
||||
int nModels = groupAvContenmentHistoty.size();
|
||||
if (nModels > 0){
|
||||
int nIterations = groupAvContenmentHistoty[0][group].size();
|
||||
for (int j = 0; j < nIterations; j++){
|
||||
qreal buffer = 0;
|
||||
for (int i = 0; i < nModels; i++) {
|
||||
buffer += groupAvContenmentHistoty[i][group][j];
|
||||
}
|
||||
average.push_back(buffer/nModels);
|
||||
}
|
||||
}
|
||||
return average;
|
||||
}
|
||||
|
||||
void APHistory::clearHistory() {
|
||||
avContenmentHistory.clear();
|
||||
groupAvContenmentHistoty.clear();
|
||||
}
|
||||
29
DEC_GUI/Agressor/aphistory.h
Normal file
29
DEC_GUI/Agressor/aphistory.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef APHISTORY_H
|
||||
#define APHISTORY_H
|
||||
|
||||
#include <QList>
|
||||
|
||||
class APHistory
|
||||
{
|
||||
public:
|
||||
APHistory();
|
||||
void addClassHistory ();
|
||||
void addClassGroupHistory();
|
||||
void addAvContenmentData(int iModel, qreal avContenmentData); // Добавление данных о модели с номером iModel
|
||||
void addGroupAvContenmentData(int iModel, QVector<qreal> avContenmentData);
|
||||
void postPrintModelData(int iModel); // Вывод в файл всех данных по модели с номером iModel
|
||||
void postPrintGroupData(int iModel);
|
||||
void postPrintGlobalAverage();
|
||||
void printCurrentContentmentData(int iModel); // Вывод в файл последних данных по модели с номером iModel
|
||||
void printCurrentContentmentGroupData(int iModel);
|
||||
QList<qreal> getHistory(int iModel);
|
||||
QList<qreal> getGroupHistory(int iModel, int iGroup);
|
||||
QList<qreal> getAverageForAllModels();
|
||||
QList<qreal> getAverageForGroup(int group);
|
||||
void clearHistory();
|
||||
private:
|
||||
QList<QList<qreal> > avContenmentHistory; // Хранитель данных о ср.неудовлетворённости
|
||||
QList<QVector<QList<qreal> > > groupAvContenmentHistoty;
|
||||
};
|
||||
|
||||
#endif // APHISTORY_H
|
||||
687
DEC_GUI/Agressor/manager.cpp
Normal file
687
DEC_GUI/Agressor/manager.cpp
Normal file
@@ -0,0 +1,687 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <cmath>
|
||||
#include <QLabel>
|
||||
#include <QString>
|
||||
#include <QThread>
|
||||
#include "QtConcurrent/qtconcurrentrun.h"
|
||||
#include "manager.h"
|
||||
|
||||
enum Group {CM, PM, CN, PN};
|
||||
static const bool multipleThreads = true;
|
||||
static const int nThreads = 4;
|
||||
static const bool blackAndWhite = false;
|
||||
|
||||
/*
|
||||
* Конструктор
|
||||
*/
|
||||
Manager::Manager(QObject *parent) : manItem(0),
|
||||
xCoord(100, 0), yCoord(100, 0), cowardMedian(0), cowardNormal(0), protectorMedian(0), protectorNormal(0),
|
||||
agentRadius(0), speedDistr(0), gamerSpeed(0), period(0), initDistr(0), enmity(0), newEnmity(0),
|
||||
viewOrPackageMode(0), nIterations(1), nModels(1), outputToTxt(false), typeContentment(0), radiusLocality(0), QObject(parent)
|
||||
{
|
||||
window = new QWidget;
|
||||
base = new QGridLayout;
|
||||
QGroupBox *settings = new QGroupBox;
|
||||
initSettings(settings);
|
||||
tabWindow = new QTabWidget;
|
||||
initTab(tabWindow);
|
||||
|
||||
base->addWidget(settings, 0, 1);
|
||||
base->addWidget(tabWindow, 0, 0);
|
||||
|
||||
window->setLayout(base);
|
||||
window->setWindowTitle("Agressor-Protector");
|
||||
window->show();
|
||||
|
||||
// создание таймера
|
||||
timer = new QTimer(this);
|
||||
timer->setInterval(1000/10);
|
||||
timer->stop();
|
||||
|
||||
// хранитель данных
|
||||
history = new APHistory(); // ToDo: setNModel
|
||||
}
|
||||
|
||||
/*
|
||||
* Создание окна настроек
|
||||
*/
|
||||
void Manager::initSettings(QGroupBox *set){
|
||||
QVBoxLayout *box = new QVBoxLayout;
|
||||
|
||||
QGroupBox *box1 = new QGroupBox;
|
||||
QGroupBox *box2 = new QGroupBox;
|
||||
QGroupBox *box3 = new QGroupBox;
|
||||
QGroupBox *box4 = new QGroupBox;
|
||||
QGroupBox *box5 = new QGroupBox;
|
||||
|
||||
QGridLayout *hbox1 = new QGridLayout;
|
||||
QGridLayout *hbox2 = new QGridLayout;
|
||||
QGridLayout *hbox3 = new QGridLayout;
|
||||
QGridLayout *hbox4 = new QGridLayout;
|
||||
QVBoxLayout *hbox5 = new QVBoxLayout;
|
||||
|
||||
QLabel *labelMode1 = new QLabel("Gamer is a coward");
|
||||
QLabel *labelMode2 = new QLabel("Gamer is a protector");
|
||||
QLabel *labelStrategy1 = new QLabel("Along median");
|
||||
QLabel *labelStrategy2 = new QLabel("Along normal");
|
||||
QSpinBox *spinCM = new QSpinBox;
|
||||
spinCM->setMaximum(1000);
|
||||
connect (spinCM, SIGNAL(valueChanged(int)), this, SLOT(setCowardMedian(int)));
|
||||
QSpinBox *spinCN = new QSpinBox;
|
||||
spinCN->setMaximum(1000);
|
||||
connect (spinCN, SIGNAL(valueChanged(int)), this, SLOT(setCowardNormal(int)));
|
||||
QSpinBox *spinPM = new QSpinBox;
|
||||
spinPM->setMaximum(1000);
|
||||
connect (spinPM, SIGNAL(valueChanged(int)), this, SLOT(setProtectorMedian(int)));
|
||||
QSpinBox *spinPN = new QSpinBox;
|
||||
spinPN->setMaximum(1000);
|
||||
connect (spinPN, SIGNAL(valueChanged(int)), this, SLOT(setProtectorNormal(int)));
|
||||
|
||||
QLabel *labelRadius = new QLabel("Gamer radius:");
|
||||
QSpinBox *boxRadius = new QSpinBox;
|
||||
connect(boxRadius, SIGNAL(valueChanged(int)), this, SLOT(setAgentRadius(int)));
|
||||
QLabel *labelEnmity = new QLabel("Enmity:");
|
||||
QSpinBox *spinBoxEnmity = new QSpinBox;
|
||||
connect(spinBoxEnmity, SIGNAL(valueChanged(int)), this, SLOT(setNewEnmity(int)));
|
||||
// QLabel *labelSpeedDistr = new QLabel("Speed distribution:");
|
||||
// QComboBox *comboSpeedDistr = new QComboBox;
|
||||
// comboSpeedDistr->addItem("homogeneous");
|
||||
QLabel *labelSpeed = new QLabel("Gamer speed:");
|
||||
QSpinBox *spinSpeed = new QSpinBox;
|
||||
spinSpeed->setMaximum(10);
|
||||
connect(spinSpeed, SIGNAL(valueChanged(int)), this, SLOT(setGamerSpeed(int)));
|
||||
QLabel *labelCont = new QLabel("Type of contenment calculation: ");
|
||||
QComboBox *comboContent = new QComboBox;
|
||||
comboContent->addItem("absolute");
|
||||
comboContent->addItem("comparative");
|
||||
connect(comboContent, SIGNAL(currentIndexChanged(int)), this, SLOT(setTypeContenment(int)));
|
||||
QLabel *labelLocality = new QLabel("Radius of locality");
|
||||
spinLocality = new QSpinBox;
|
||||
spinLocality->setEnabled(false);
|
||||
connect(spinLocality, SIGNAL(valueChanged(int)), this, SLOT(setRadiusLocality(int)));
|
||||
connect(comboContent, SIGNAL(currentIndexChanged(int)), this, SLOT(manageSpinLocality(int)));
|
||||
|
||||
QCheckBox *checkPeriod = new QCheckBox;
|
||||
checkPeriod->setText("Periodicity");
|
||||
connect(checkPeriod, SIGNAL(toggled(bool)), this, SLOT(setPeriodicity(bool)));
|
||||
QLabel *label = new QLabel("Initial distribution:");
|
||||
QComboBox *comboDistr = new QComboBox;
|
||||
comboDistr->addItem("random");
|
||||
comboDistr->addItem("on the circle");
|
||||
connect(comboDistr, SIGNAL(currentIndexChanged(int)), this, SLOT(setDistr(int)));
|
||||
|
||||
createButton = new QPushButton;
|
||||
createButton->setText("Create");
|
||||
connect(createButton, SIGNAL(clicked()), this, SLOT(resetProgressBarAndHistory()));
|
||||
connect(createButton, SIGNAL(clicked()), this, SLOT(initModel()));
|
||||
|
||||
QLabel *labelViewOrPackage = new QLabel("Type of job: ");
|
||||
viewOrPackage = new QComboBox;
|
||||
viewOrPackage->addItem("one model in detail");
|
||||
viewOrPackage->addItem("processing");
|
||||
connect(viewOrPackage, SIGNAL(currentIndexChanged(int)), this, SLOT(setviewOrPackageMode(int)));
|
||||
connect(viewOrPackage, SIGNAL(currentIndexChanged(int)), this, SLOT(managePackageOptions(int)));
|
||||
checkLink = new QCheckBox;
|
||||
checkLink->setText("Show links");
|
||||
checkOutputToTxt = new QCheckBox;
|
||||
checkOutputToTxt->setText("Output to txt");
|
||||
connect(checkOutputToTxt, SIGNAL(toggled(bool)), this, SLOT(setOutputToTxt(bool)));
|
||||
QLabel *label3 = new QLabel("Updating frequency: ");
|
||||
comboTime = new QComboBox;
|
||||
comboTime->addItem("1000/10");
|
||||
comboTime->addItem("1000/20");
|
||||
comboTime->addItem("1000/30");
|
||||
comboTime->addItem("1000/50");
|
||||
comboTime->addItem("1000/100");
|
||||
connect(comboTime, SIGNAL(currentIndexChanged(int)), this, SLOT(timerRestart(int)));
|
||||
QLabel *labelIterations = new QLabel("Number of iterations: ");
|
||||
spinIterations = new QSpinBox;
|
||||
spinIterations->setMinimum(1);
|
||||
spinIterations->setMaximum(10000);
|
||||
spinIterations->setEnabled(false);
|
||||
connect(spinIterations, SIGNAL(valueChanged(int)), this, SLOT(setNIterations(int)));
|
||||
QLabel *labelModels = new QLabel("Number of models: ");
|
||||
spinModels = new QSpinBox;
|
||||
spinModels->setMinimum(1);
|
||||
spinModels->setMaximum(1000);
|
||||
spinModels->setEnabled(false);
|
||||
connect(spinModels, SIGNAL(valueChanged(int)), this, SLOT(setNModels(int)));
|
||||
buttonTime = new QPushButton;
|
||||
buttonTime->setText("Start");
|
||||
connect(buttonTime, SIGNAL(clicked()), this, SLOT(handleButton()));
|
||||
buttonTime->setEnabled(false);
|
||||
|
||||
hbox1->addWidget(labelMode1, 0, 1);
|
||||
hbox1->addWidget(labelMode2, 0, 2);
|
||||
hbox1->addWidget(labelStrategy1, 1, 0);
|
||||
hbox1->addWidget(labelStrategy2, 2, 0);
|
||||
hbox1->addWidget(spinCM, 1, 1);
|
||||
hbox1->addWidget(spinCN, 2, 1);
|
||||
hbox1->addWidget(spinPM, 1, 2);
|
||||
hbox1->addWidget(spinPN, 2, 2);
|
||||
box1->setLayout(hbox1);
|
||||
box1->setTitle("Gamers number");
|
||||
|
||||
hbox2->addWidget(labelRadius, 0, 0);
|
||||
hbox2->addWidget(boxRadius, 0, 1);
|
||||
hbox2->addWidget(labelEnmity, 1, 0);
|
||||
hbox2->addWidget(spinBoxEnmity, 1, 1);
|
||||
// hbox2->addWidget(labelSpeedDistr, 2, 0);
|
||||
// hbox2->addWidget(comboSpeedDistr, 2, 1);
|
||||
hbox2->addWidget(labelSpeed, 3, 0);
|
||||
hbox2->addWidget(spinSpeed, 3, 1);
|
||||
hbox2->addWidget(labelCont, 4, 0);
|
||||
hbox2->addWidget(comboContent, 4, 1);
|
||||
hbox2->addWidget(labelLocality, 5, 0);
|
||||
hbox2->addWidget(spinLocality, 5, 1);
|
||||
box2->setLayout(hbox2);
|
||||
box2->setTitle("Gamer settings");
|
||||
|
||||
hbox3->addWidget(checkPeriod, 0, 0);
|
||||
hbox3->addWidget(label, 1, 0);
|
||||
hbox3->addWidget(comboDistr, 1, 1);
|
||||
box3->setLayout(hbox3);
|
||||
box3->setTitle("Scene settings");
|
||||
|
||||
hbox4->addWidget(labelViewOrPackage, 0, 0);
|
||||
hbox4->addWidget(viewOrPackage, 0, 1);
|
||||
hbox4->addWidget(checkLink, 1, 0);
|
||||
hbox4->addWidget(checkOutputToTxt, 1, 1);
|
||||
hbox4->addWidget(label3, 2, 0);
|
||||
hbox4->addWidget(comboTime, 2, 1);
|
||||
hbox4->addWidget(labelIterations, 3, 0);
|
||||
hbox4->addWidget(spinIterations, 3, 1);
|
||||
hbox4->addWidget(labelModels, 4, 0);
|
||||
hbox4->addWidget(spinModels, 4, 1);
|
||||
box4->setLayout(hbox4);
|
||||
|
||||
hbox5->addWidget(createButton);
|
||||
hbox5->addWidget(buttonTime);
|
||||
box5->setLayout(hbox5);
|
||||
|
||||
box->addWidget(box1);
|
||||
box->addWidget(box2);
|
||||
box->addWidget(box3);
|
||||
box->addWidget(box4);
|
||||
box->addWidget(box5);
|
||||
box->addStretch();
|
||||
|
||||
set->setLayout(box);
|
||||
}
|
||||
|
||||
void Manager::initTab(QTabWidget *tabs){
|
||||
// Первая вкладка - визуализация одной модели (сцена + график)
|
||||
QWidget *viewTab = new QWidget;
|
||||
QGridLayout *viewLayout = new QGridLayout;
|
||||
// Создание и заполнение сцены
|
||||
scene = new QGraphicsScene;
|
||||
scene->setSceneRect(-300, -300, 600, 600);
|
||||
scene->setItemIndexMethod(QGraphicsScene::NoIndex);
|
||||
|
||||
QGraphicsView *view = new QGraphicsView(scene);
|
||||
view->setRenderHint(QPainter::Antialiasing);
|
||||
view->setCacheMode(QGraphicsView::CacheBackground);
|
||||
view->resize(800, 800);
|
||||
view->setMinimumWidth(600);
|
||||
view->show();
|
||||
|
||||
// Создание графика ср.неудовлетворённости
|
||||
QLabel *labelGraph = new QLabel("Dynamics of average contenment");
|
||||
labelContent = new QLabel("Average contentment: ");
|
||||
plot = new QCustomPlot;
|
||||
plot->addGraph();
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
xCoord[i] = i;
|
||||
}
|
||||
plot->graph(0)->setData(xCoord, yCoord);
|
||||
plot->yAxis->setRange(0, 1);
|
||||
plot->graph(0)->rescaleAxes();
|
||||
plot->yAxis->setVisible(false);
|
||||
plot->xAxis->setTickLabels(false);
|
||||
|
||||
viewLayout->addWidget(view, 0, 0, 1, 2);
|
||||
viewLayout->addWidget(labelGraph, 1, 0);
|
||||
viewLayout->addWidget(labelContent, 1, 1);
|
||||
viewLayout->addWidget(plot, 2, 0, 1, 2);
|
||||
|
||||
viewTab->setLayout(viewLayout);
|
||||
|
||||
// Вторая вкладка - пакетное задание (прогресс-бар)
|
||||
QWidget *packageTab = new QWidget;
|
||||
QGridLayout *packageLayout = new QGridLayout;
|
||||
|
||||
prBar = new QProgressBar;
|
||||
prBar->setValue(0);
|
||||
QLabel *graphComboLabel = new QLabel("Compose the graphic for: ");
|
||||
graphCombo = new QComboBox;
|
||||
graphCombo->setEnabled(false);
|
||||
graphCombo->addItem("---");
|
||||
connect(graphCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(composeGraph(int)));
|
||||
|
||||
batchPlot = new QCustomPlot;
|
||||
batchPlot->addGraph();
|
||||
batchPlot->addGraph();
|
||||
batchPlot->addGraph();
|
||||
batchPlot->addGraph();
|
||||
batchPlot->addGraph();
|
||||
batchPlot->graph(0)->setPen(QPen(Qt::black, 2));
|
||||
if (blackAndWhite) {
|
||||
batchPlot->graph(CM + 1)->setPen(QPen(Qt::SolidLine));
|
||||
batchPlot->graph(PM + 1)->setPen(QPen(Qt::DashDotLine));
|
||||
batchPlot->graph(CN + 1)->setPen(QPen(Qt::DashLine));
|
||||
QPen * pen = new QPen(QPen(Qt::DashDotDotLine));
|
||||
pen->setWidth(2);
|
||||
batchPlot->graph(PN + 1)->setPen(*pen);
|
||||
} else {
|
||||
batchPlot->graph(CM + 1)->setPen(QPen(Qt::red));
|
||||
batchPlot->graph(PM + 1)->setPen(QPen(Qt::yellow));
|
||||
batchPlot->graph(CN + 1)->setPen(QPen(Qt::darkBlue));
|
||||
batchPlot->graph(PN + 1)->setPen(QPen(Qt::cyan));
|
||||
}
|
||||
batchPlot->graph(0)->setName("Average for all agents");
|
||||
batchPlot->graph(CM + 1)->setName("Average for coward-median");
|
||||
batchPlot->graph(PM + 1)->setName("Average for all protector-median");
|
||||
batchPlot->graph(CN + 1)->setName("Average for all coward-normal");
|
||||
batchPlot->graph(PN + 1)->setName("Average for all protector-normal");
|
||||
|
||||
xBatchCoord.resize(100);
|
||||
yBatchCoord.resize(100);
|
||||
yBatchCoord.fill(0);
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
xBatchCoord[i] = i;
|
||||
}
|
||||
batchPlot->graph(0)->setData(xBatchCoord, yBatchCoord);
|
||||
batchPlot->yAxis->setRange(0, 1.05);
|
||||
QVector<qreal> ticks;
|
||||
qreal i = 0;
|
||||
while (i <= 1.05) {
|
||||
ticks << i;
|
||||
i += 0.1;
|
||||
}
|
||||
batchPlot->yAxis->setAutoTicks(false);
|
||||
batchPlot->yAxis->setTickVector(ticks);
|
||||
batchPlot->graph(0)->rescaleAxes();
|
||||
|
||||
QLabel *labelSaveWithName = new QLabel("Save with name: ");
|
||||
lineSaveWithName = new QLineEdit;
|
||||
lineSaveWithName->setPlaceholderText("For example: default_name");
|
||||
QPushButton *buttonSaveGraph = new QPushButton;
|
||||
buttonSaveGraph->setText("Save as jpeg");
|
||||
connect(buttonSaveGraph, SIGNAL(clicked()), this, SLOT(saveGragh()));
|
||||
|
||||
packageLayout->addWidget(prBar, 0, 0, 1, 2);
|
||||
packageLayout->addWidget(graphComboLabel, 1, 0, 1, 1);
|
||||
packageLayout->addWidget(graphCombo, 1, 1, 1, 1);
|
||||
packageLayout->addWidget(batchPlot, 2, 0, 2, 2);
|
||||
packageLayout->addWidget(labelSaveWithName, 4, 0, 1, 1);
|
||||
packageLayout->addWidget(lineSaveWithName, 4, 1, 1, 1);
|
||||
packageLayout->addWidget(buttonSaveGraph, 5, 1, 1, 1);
|
||||
packageTab->setLayout(packageLayout);
|
||||
|
||||
tabs->addTab(viewTab, "One model in detail");
|
||||
tabs->addTab(packageTab, "Batch processing");
|
||||
connect(tabs, SIGNAL(currentChanged(int)), viewOrPackage, SLOT(setCurrentIndex(int)));
|
||||
}
|
||||
|
||||
QVector<qreal> Manager::calculateAvContenmentForGroups(uint typeCalc, uint iModel){
|
||||
qreal max = 0;
|
||||
qreal res = 0;
|
||||
QVector<qreal> cont(4, 0);
|
||||
QList <Agent *> neibours;
|
||||
QVector<uint> nAgents;
|
||||
nAgents << cowardMedian << protectorMedian << cowardNormal << protectorNormal;
|
||||
if (modelList[iModel]->getAgentList().size() == 0){
|
||||
return cont;
|
||||
}
|
||||
// С оглядкой на всех агентов
|
||||
else if (typeCalc == 0){
|
||||
int ind = 0;
|
||||
for (int i = 0; i < modelList[iModel]->getAgentList().size(); i++){
|
||||
if (modelList[iModel]->getAgentList()[i]->getMode() == 0) {
|
||||
ind = modelList[iModel]->getAgentList()[i]->getStrategy() == 0 ? 0 : 2;
|
||||
}
|
||||
else {
|
||||
ind = modelList[iModel]->getAgentList()[i]->getStrategy() == 0 ? 1 : 3;
|
||||
}
|
||||
if (modelList[iModel]->getAgentList()[i]->getDistTarget() > max){
|
||||
max = modelList[iModel]->getAgentList()[i]->getDistTarget();
|
||||
}
|
||||
else{}
|
||||
if (max > 0.0) {
|
||||
modelList[iModel]->getAgentList()[i]->setContentment(modelList[iModel]->getAgentList()[i]->getDistTarget()/max);
|
||||
cont[ind] += modelList[iModel]->getAgentList()[i]->getDistTarget()/max;
|
||||
}
|
||||
else{
|
||||
modelList[iModel]->getAgentList()[i]->setContentment(1);
|
||||
cont[ind] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// С оглядкой на агентов внутри окрестности
|
||||
else if (typeCalc == 1){
|
||||
for (int i = 0; i < modelList[iModel]->getAgentList().size(); i++){
|
||||
int ind = 0;
|
||||
if (modelList[iModel]->getAgentList()[i]->getMode() == 0) {
|
||||
ind = modelList[iModel]->getAgentList()[i]->getStrategy() == 0 ? 0 : 2;
|
||||
}
|
||||
else {
|
||||
ind = modelList[iModel]->getAgentList()[i]->getStrategy() == 0 ? 1 : 3;
|
||||
}
|
||||
|
||||
neibours = modelList[iModel]->DangerGamer(i, 0, 0, radiusLocality);
|
||||
max = modelList[iModel]->getAgentList()[i]->getDistTarget();
|
||||
for (int j = 0; j < neibours.size(); j++){
|
||||
if (neibours[j]->getDistTarget() > max){
|
||||
max = neibours[j]->getDistTarget();
|
||||
}
|
||||
else{}
|
||||
}
|
||||
if (max > 0.0) {
|
||||
modelList[iModel]->getAgentList()[i]->setContentment(modelList[iModel]->getAgentList()[i]->getDistTarget()/max);
|
||||
cont[ind] += modelList[iModel]->getAgentList()[i]->getDistTarget()/max;
|
||||
}
|
||||
else{
|
||||
modelList[iModel]->getAgentList()[i]->setContentment(1);
|
||||
cont[ind] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = CM; i < PN + 1; i++){
|
||||
if (nAgents[i] != 0) {
|
||||
res += cont[i];
|
||||
cont[i] = cont[i]/nAgents[i];
|
||||
}
|
||||
}
|
||||
modelList[iModel]->setAvContentment(res/modelList[iModel]->getAgentList().size());
|
||||
yCoord.removeFirst();
|
||||
yCoord.push_back(res/modelList[iModel]->getAgentList().size());
|
||||
return cont;
|
||||
}
|
||||
|
||||
/*
|
||||
* Создание модели по полученным данным
|
||||
*/
|
||||
void Manager::initModel(){
|
||||
|
||||
buttonTime->setText("Start");
|
||||
createButton->setText("Recreate");
|
||||
|
||||
yCoord.fill(0);
|
||||
graphCombo->setCurrentIndex(0);
|
||||
graphCombo->setEnabled(false);
|
||||
|
||||
// Визуализация одной модели
|
||||
if (viewOrPackageMode == 0){
|
||||
timer->stop();
|
||||
history->addClassHistory();
|
||||
history->addClassGroupHistory();
|
||||
Model *model = new Model(0, cowardMedian, cowardNormal, protectorMedian, protectorNormal, agentRadius, gamerSpeed, period, initDistr, enmity, newEnmity);
|
||||
modelList.push_back(model);
|
||||
if (manItem != 0){
|
||||
delete manItem;
|
||||
}
|
||||
batchPlot->clearItems();
|
||||
batchPlot->replot();
|
||||
// Создание управленца визуализацией
|
||||
manItem = new ManagerItem(model->getAgentList(), scene, cowardMedian, cowardNormal, protectorMedian);
|
||||
connect(timer, SIGNAL(timeout()), this, SLOT(timerEvent()));
|
||||
connect(timer, SIGNAL(timeout()), manItem, SLOT(gameEvent()));
|
||||
connect(checkLink, SIGNAL(toggled(bool)), manItem, SLOT(setLink(bool)));
|
||||
}
|
||||
// Пакетное задание
|
||||
else {
|
||||
// Очистка сцены и графика на первой вкладке
|
||||
scene->clear();
|
||||
plot->graph(0)->setData(xCoord, yCoord);
|
||||
plot->replot();
|
||||
|
||||
prBar->setMinimum(0);
|
||||
prBar->setMaximum(nIterations*nModels);
|
||||
}
|
||||
setEnmity(newEnmity);
|
||||
buttonTime->setEnabled(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Событие игры. Вычисление новых координат для всех игроков на сцене
|
||||
*/
|
||||
void Manager::timerEvent(){
|
||||
modelList[0]->modelIteration();
|
||||
history->addGroupAvContenmentData(0, calculateAvContenmentForGroups(typeContentment, 0));
|
||||
history->addAvContenmentData(0, modelList[0]->getAvContentment());
|
||||
if (outputToTxt) {
|
||||
history->postPrintModelData(0);
|
||||
history->postPrintGroupData(0);
|
||||
}
|
||||
plot->graph(0)->setData(xCoord, yCoord);
|
||||
plot->replot();
|
||||
history->addGroupAvContenmentData(0, calculateAvContenmentForGroups(typeContentment, 0));
|
||||
history->addAvContenmentData(0, modelList[0]->getAvContentment()); // запись в хранитель данных
|
||||
labelContent->setText("Average contenment: " + QString::number(modelList[0]->getAvContentment()));
|
||||
}
|
||||
|
||||
void Manager::iteration(uint j) {
|
||||
Model *model = new Model(j, cowardMedian, cowardNormal, protectorMedian, protectorNormal, agentRadius, gamerSpeed, period, initDistr, enmity, newEnmity);
|
||||
modelList.append(model);
|
||||
for(int i = 0; i < nIterations; i++){
|
||||
model->modelIteration();
|
||||
history->addGroupAvContenmentData(modelList.indexOf(model), calculateAvContenmentForGroups(typeContentment, modelList.indexOf(model)));
|
||||
history->addAvContenmentData(modelList.indexOf(model), model->getAvContentment());
|
||||
//qApp->processEvents();
|
||||
}
|
||||
if (outputToTxt) {
|
||||
history->postPrintModelData(modelList.indexOf(model));
|
||||
history->postPrintGroupData(modelList.indexOf(model));
|
||||
}
|
||||
model->clear();
|
||||
//delete model;
|
||||
}
|
||||
|
||||
void Manager::handlePrBar() {
|
||||
//prBar->setValue(prBar->value() + nIterations);
|
||||
std::cout << "handlePrBar" << std::endl;
|
||||
}
|
||||
|
||||
/*
|
||||
* Остановка/возобновление игры
|
||||
*/
|
||||
void Manager::handleButton(){
|
||||
// Визуализация модели
|
||||
if(viewOrPackageMode == 0){
|
||||
if (timer->isActive()){
|
||||
timer->stop();
|
||||
buttonTime->setText("Start");
|
||||
}
|
||||
else {
|
||||
timer->start(timer->interval());
|
||||
buttonTime->setText("Pause");
|
||||
}
|
||||
}
|
||||
// Пакетное задание (без возможности остановки)
|
||||
else{
|
||||
buttonTime->setText("In process...");
|
||||
buttonTime->setEnabled(false);
|
||||
createButton->setEnabled(false);
|
||||
tabWindow->setTabEnabled(0, false);
|
||||
//prBar->setValue(0);
|
||||
|
||||
if(!multipleThreads){
|
||||
for (int i = 0; i < nModels; i++) {
|
||||
history->addClassHistory();
|
||||
history->addClassGroupHistory();
|
||||
iteration(i);
|
||||
prBar->setValue(prBar->value() + nIterations);
|
||||
}
|
||||
}
|
||||
else {
|
||||
QVector<QFuture<void> > futureVector;
|
||||
QVector<QFutureWatcher<void> *> watcherVector;
|
||||
for (int i = 0; i < nThreads; i++) {
|
||||
QFuture<void> future;
|
||||
futureVector.append(future);
|
||||
QFutureWatcher<void> *watcher = new QFutureWatcher<void>;
|
||||
watcherVector.append(watcher);
|
||||
//connect(watcherVector[i], SIGNAL(finished()), this, SLOT(handlePrBar()));
|
||||
}
|
||||
|
||||
for(int i = 0; i < nModels; i++) {
|
||||
history->addClassHistory();
|
||||
history->addClassGroupHistory();
|
||||
}
|
||||
|
||||
for(int j = 0; j < nModels/nThreads; j++){
|
||||
for (int i = 0; i < nThreads; i++) {
|
||||
//qApp->processEvents();
|
||||
futureVector[i] = QtConcurrent::run(this, &Manager::iteration, j*nThreads + i);
|
||||
watcherVector[i]->setFuture(futureVector[i]);
|
||||
}
|
||||
qApp->processEvents();
|
||||
prBar->setValue(prBar->value() + nThreads*nIterations);
|
||||
for (int i = 0; i < nThreads; i++) {
|
||||
watcherVector[i]->waitForFinished();
|
||||
//modelList[j*nThreads + i]->clear();
|
||||
//prBar->setValue(prBar->value() + nIterations);
|
||||
}
|
||||
}
|
||||
//qApp->processEvents();
|
||||
if (nModels % nThreads != 0) {
|
||||
for (int i = 0; i < nModels % nThreads; i++) {
|
||||
futureVector[i] = QtConcurrent::run(this, &Manager::iteration, nThreads*(nModels/nThreads) + i);
|
||||
watcherVector[i]->setFuture(futureVector[i]);
|
||||
}
|
||||
prBar->setValue(prBar->value() + (nModels % nThreads)*nIterations);
|
||||
for (int i = 0; i < nModels % nThreads; i++) {
|
||||
watcherVector[i]->waitForFinished();
|
||||
//modelList[nThreads*(nModels/nThreads) + i]->clear();
|
||||
//prBar->setValue(prBar->value() + nIterations);
|
||||
}
|
||||
}
|
||||
}
|
||||
qDeleteAll(modelList.begin(), modelList.end());
|
||||
modelList.clear();
|
||||
if (outputToTxt) {
|
||||
history->postPrintGlobalAverage();
|
||||
}
|
||||
disconnect(graphCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(composeGraph(int)));
|
||||
graphCombo->clear();
|
||||
graphCombo->addItem("---");
|
||||
for(int i = 0; i < nModels; i++){
|
||||
QString comboString = "Model ";
|
||||
comboString += QString::number(i + 1);
|
||||
graphCombo->addItem(comboString);
|
||||
}
|
||||
if (nModels > 1) {
|
||||
graphCombo->addItem("Average for all models");
|
||||
}
|
||||
connect(graphCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(composeGraph(int)));
|
||||
buttonTime->setText("Start");
|
||||
buttonTime->setEnabled(true);
|
||||
graphCombo->setEnabled(true);
|
||||
createButton->setEnabled(true);
|
||||
tabWindow->setTabEnabled(0, true);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Перезапуск таймера
|
||||
*/
|
||||
void Manager::timerRestart(int index){
|
||||
if (index == 0){
|
||||
timer->setInterval(1000/10);
|
||||
}
|
||||
else if(index == 1){
|
||||
timer->setInterval(1000/20);
|
||||
}
|
||||
else if(index == 2){
|
||||
timer->setInterval(1000/30);
|
||||
}
|
||||
else if(index == 3){
|
||||
timer->setInterval(1000/50);
|
||||
}
|
||||
else if (index == 4){
|
||||
timer->setInterval(1000/100);
|
||||
}
|
||||
else{}
|
||||
}
|
||||
|
||||
void Manager::resetProgressBarAndHistory(){
|
||||
prBar->setValue(0);
|
||||
history->clearHistory();
|
||||
}
|
||||
/*
|
||||
* Вкл/выкл спинбокс для радиуса окрестности
|
||||
*/
|
||||
void Manager::manageSpinLocality(int value){
|
||||
if (value == 0){
|
||||
spinLocality->setEnabled(false);
|
||||
}
|
||||
else{
|
||||
spinLocality->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Вкл/выкл спинбокс для числа итераций и спинбокс для числа запусков модели
|
||||
*/
|
||||
void Manager::managePackageOptions(int val){
|
||||
if(val == 0){
|
||||
spinIterations->setEnabled(false);
|
||||
spinModels->setEnabled(false);
|
||||
checkLink->setEnabled(true);
|
||||
comboTime->setEnabled(true);
|
||||
}
|
||||
else {
|
||||
timer->stop();
|
||||
spinIterations->setEnabled(true);
|
||||
spinModels->setEnabled(true);
|
||||
checkLink->setEnabled(false);
|
||||
comboTime->setEnabled(false);
|
||||
}
|
||||
tabWindow->setCurrentIndex(val);
|
||||
}
|
||||
|
||||
void Manager::composeGraph(int iModel) {
|
||||
xBatchCoord.resize(nIterations);
|
||||
QVector<qreal> avCM(nIterations, 0);
|
||||
QVector<qreal> avPM(nIterations, 0);
|
||||
QVector<qreal> avCN(nIterations, 0);
|
||||
QVector<qreal> avPN(nIterations, 0);
|
||||
|
||||
for(int i = 0; i < nIterations; i++) {
|
||||
xBatchCoord[i] = i;
|
||||
}
|
||||
yBatchCoord.resize(nIterations);
|
||||
batchPlot->xAxis->setRange(0, nIterations + 1);
|
||||
if(iModel == 0) {
|
||||
yBatchCoord.fill(0);
|
||||
}
|
||||
else if (iModel == nModels + 1){
|
||||
yBatchCoord = history->getAverageForAllModels().toVector();
|
||||
avCM = history->getAverageForGroup(CM).toVector();
|
||||
avPM = history->getAverageForGroup(PM).toVector();
|
||||
avCN = history->getAverageForGroup(CN).toVector();
|
||||
avPN = history->getAverageForGroup(PN).toVector();
|
||||
} else {
|
||||
yBatchCoord = history->getHistory(iModel - 1).toVector();
|
||||
avCM = history->getGroupHistory(iModel - 1, CM).toVector();
|
||||
avPM = history->getGroupHistory(iModel - 1, PM).toVector();
|
||||
avCN = history->getGroupHistory(iModel - 1, CN).toVector();
|
||||
avPN = history->getGroupHistory(iModel - 1, PN).toVector();
|
||||
}
|
||||
batchPlot->graph(0)->setData(xBatchCoord, yBatchCoord);
|
||||
batchPlot->graph(CM + 1)->setData(xBatchCoord, avCM);
|
||||
batchPlot->graph(PM + 1)->setData(xBatchCoord, avPM);
|
||||
batchPlot->graph(CN + 1)->setData(xBatchCoord, avCN);
|
||||
batchPlot->graph(PN + 1)->setData(xBatchCoord, avPN);
|
||||
batchPlot->legend->setVisible(true);
|
||||
batchPlot->replot();
|
||||
}
|
||||
|
||||
void Manager::saveGragh() {
|
||||
batchPlot->saveJpg(lineSaveWithName->text() + ".jpg");
|
||||
}
|
||||
109
DEC_GUI/Agressor/manager.h
Normal file
109
DEC_GUI/Agressor/manager.h
Normal file
@@ -0,0 +1,109 @@
|
||||
#ifndef MANAGER_H
|
||||
#define MANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QtWidgets>
|
||||
#include "agent.h"
|
||||
#include "agentitem.h"
|
||||
#include "aphistory.h"
|
||||
#include "manageritem.h"
|
||||
#include "model.h"
|
||||
#include "Kolch_Shind/qcustomplot.h"
|
||||
|
||||
class Manager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Manager(QObject *parent = 0); // конструктор
|
||||
void initSettings(QGroupBox *set); // создание окна настроек
|
||||
void initTab(QTabWidget *tabs);
|
||||
QVector<qreal> calculateAvContenmentForGroups(uint typeCalc, uint iModel);
|
||||
void iteration(uint j);
|
||||
|
||||
// геттеры
|
||||
uint getCowardMedian(){return this->cowardMedian;}
|
||||
uint getCowardNormal(){return this->cowardNormal;}
|
||||
uint getProtectorMedian(){return this->protectorMedian;}
|
||||
uint getProtectorNormal(){return this->protectorNormal;}
|
||||
|
||||
private:
|
||||
QList<Model*> modelList;
|
||||
QVector<qreal> xCoord; // x координата для построения графика средней неудовлетворённости
|
||||
QVector<qreal> yCoord; // y координата для построения графика средней неудовлетворённости
|
||||
QVector<qreal> xBatchCoord;
|
||||
QVector<qreal> yBatchCoord;
|
||||
uint cowardMedian; // число игроков в режиме труса, движущихся по медиане
|
||||
uint cowardNormal; // число игроков в режиме труса, движущихся по нормали
|
||||
uint protectorMedian; // число игроков в режиме защитника, движущихся по медиане
|
||||
uint protectorNormal; // число игроков в режиме защитника, движущихся по нормали
|
||||
int agentRadius; // радиус шарика-агента (для передачи в конструктор)
|
||||
uint speedDistr; // распределение скоростей (однородное)
|
||||
uint gamerSpeed; // скорость агентов
|
||||
bool period; // метка периодичности краёв сцены (true - сцена периодична)
|
||||
uint initDistr; // метка начального распределения игроков сцены (0 - случайное, 1 - на круге)
|
||||
uint enmity; // минимальное расстояние, на которое игроки могут приближаются друг к другу, enmity = 0 - возможно покоординатное совпадение игроков
|
||||
uint newEnmity; // параметр enmity, полученный из диалогового окна
|
||||
int viewOrPackageMode; // 0 - визуализация одной модели, 1 - пакетное задание
|
||||
int nIterations; // число итераций для пакетного задания
|
||||
int nModels; // число запусков модели для пакетного задания
|
||||
uint typeContentment; // способ расчёта ср.неудовлетворённости: 0 - сравнение со всеми агентами, 1 - сравнение внутри окрестности
|
||||
//qreal avContentment; // ср.неудовлетворённость (ToDo: а надо ли?)
|
||||
uint radiusLocality; // радиус окрестности в случае typeContenment = 1
|
||||
QWidget *window;
|
||||
QGridLayout *base;
|
||||
QTabWidget *tabWindow;
|
||||
QGraphicsScene *scene;
|
||||
ManagerItem *manItem;
|
||||
QCustomPlot *plot;
|
||||
QPushButton *createButton; // кнопка создания модели
|
||||
QPushButton *buttonTime; // кнопка "Pause/Start"
|
||||
QLabel *labelContent;
|
||||
QSpinBox *spinLocality;
|
||||
QComboBox *viewOrPackage;
|
||||
QCheckBox *checkLink;
|
||||
QCheckBox *checkOutputToTxt;
|
||||
QComboBox *comboTime;
|
||||
QSpinBox *spinIterations;
|
||||
QSpinBox *spinModels;
|
||||
bool outputToTxt;
|
||||
QTimer *timer;
|
||||
QProgressBar *prBar;
|
||||
QComboBox *graphCombo;
|
||||
QCustomPlot *batchPlot;
|
||||
QLineEdit *lineSaveWithName;
|
||||
APHistory *history;
|
||||
|
||||
private slots:
|
||||
void setCowardMedian(int cm) {this->cowardMedian = cm;}
|
||||
void setCowardNormal(int cn) {this->cowardNormal = cn;}
|
||||
void setProtectorMedian(int pm) {this->protectorMedian = pm;}
|
||||
void setProtectorNormal(int pn) {this->protectorNormal = pn;}
|
||||
void setAgentRadius(int rad){this->agentRadius = rad;}
|
||||
void setSpeedDistr(int spDistr) {this->speedDistr = spDistr;}
|
||||
void setGamerSpeed(int gamerSp) {this->gamerSpeed = gamerSp;}
|
||||
void setPeriodicity(bool value) {this->period = value;}
|
||||
void setDistr(int distr){this->initDistr = distr;}
|
||||
void setEnmity(int enm) {this->enmity = enm;}
|
||||
void setNewEnmity(int nEnm){this->newEnmity = nEnm;}
|
||||
void setviewOrPackageMode(int val){this->viewOrPackageMode = val;}
|
||||
void setNIterations(int number){this->nIterations = number;}
|
||||
void setNModels(int number){this->nModels = number;}
|
||||
void setOutputToTxt(bool output) {this->outputToTxt = output;}
|
||||
void setTypeContenment(int type){this->typeContentment = type;}
|
||||
//void setAvContentment(qreal cont){this->avContentment = cont;}
|
||||
void setRadiusLocality(int rad){this->radiusLocality = rad;}
|
||||
|
||||
void initModel(); // создание модели по полученным данным
|
||||
void timerEvent(); // итерация игры - вычисление новых координат для всех игроков
|
||||
void handlePrBar();
|
||||
void handleButton(); // остановка/возобновление игры
|
||||
void timerRestart(int index); // перезапуск таймера
|
||||
void resetProgressBarAndHistory();
|
||||
void composeGraph(int iModel);
|
||||
void saveGragh();
|
||||
// вкл/выкл пункты окна настроеек
|
||||
void manageSpinLocality(int value);
|
||||
void managePackageOptions(int val);
|
||||
};
|
||||
|
||||
#endif // MANAGER_H
|
||||
160
DEC_GUI/Agressor/manageritem.cpp
Normal file
160
DEC_GUI/Agressor/manageritem.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <QGraphicsScene>
|
||||
#include <QPen>
|
||||
#include "manageritem.h"
|
||||
|
||||
static const qreal pi = 3.14159265358979323846264338327950288419717;
|
||||
|
||||
/*
|
||||
* Конструктор
|
||||
*/
|
||||
ManagerItem::ManagerItem(QList<Agent*> agents, QGraphicsScene *sceneParameter, int CM, int CN, int PM/*, int PN*/):
|
||||
agent(agents), scene(sceneParameter), link(0)
|
||||
{
|
||||
fillingScene(CM, CN, PM);
|
||||
}
|
||||
|
||||
/*
|
||||
* Отрисовка связей между агентами и их агрессорами, защитниками/защищаемыми
|
||||
*/
|
||||
void ManagerItem::drawLinks(){
|
||||
for(int i = 0; i < agent.size(); i++){
|
||||
Agent *gamer = agent[i];
|
||||
QGraphicsLineItem *item1 = new QGraphicsLineItem(QLineF(gamer->getCoordX(), gamer->getCoordY(),
|
||||
agent[gamer->getAgressor()]->getCoordX(), agent[gamer->getAgressor()]->getCoordY()));
|
||||
QGraphicsLineItem *item2 = new QGraphicsLineItem(QLineF(gamer->getCoordX(), gamer->getCoordY(),
|
||||
agent[gamer->getProtector()]->getCoordX(), agent[gamer->getProtector()]->getCoordY()));
|
||||
item1->setPen(QPen(Qt::blue));
|
||||
item2->setPen(QPen(Qt::green));
|
||||
links.push_back(item1);
|
||||
links.push_back(item2);
|
||||
scene->addItem(item1);
|
||||
scene->addItem(item2);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Отрисовка направлений связей
|
||||
*/
|
||||
void ManagerItem::drawArrow(){
|
||||
for(int i = 0; i < agent.size(); i++){
|
||||
Agent *gamer = agent[i];
|
||||
QLineF *line1 = new QLineF(gamer->getCoordX(), gamer->getCoordY(),
|
||||
agent[gamer->getAgressor()]->getCoordX(), agent[gamer->getAgressor()]->getCoordY());
|
||||
QLineF *line2 = new QLineF(gamer->getCoordX(), gamer->getCoordY(),
|
||||
agent[gamer->getProtector()]->getCoordX(), agent[gamer->getProtector()]->getCoordY());
|
||||
qreal angel1 = ::acos(line1->dx()/line1->length());
|
||||
qreal angel2 = ::acos(line2->dx()/line2->length());
|
||||
if (line1->dy() >= 0){
|
||||
angel1 = 2*pi - angel1;
|
||||
}
|
||||
if (line2->dy() >= 0){
|
||||
angel2 = 2*pi - angel2;
|
||||
}
|
||||
if (line1->length() > 20){
|
||||
line1->setLength(20);
|
||||
QPointF point1 = line1->p2();
|
||||
QPointF point2 = point1 + QPointF(sin(angel1 - pi/3)*10, cos(angel1 - pi/3)*10);
|
||||
QPointF point3 = point1 + QPointF(sin(angel1 - 2*pi/3)*10, cos(angel1 - 2*pi/3)*10);
|
||||
QGraphicsPolygonItem *poly1 = new QGraphicsPolygonItem(QPolygonF() << point1 << point2 << point3);
|
||||
poly1->setBrush(QBrush(Qt::blue));
|
||||
poly1->setPen(QPen(Qt::blue));
|
||||
arrows.push_back(poly1);
|
||||
scene->addItem(poly1);
|
||||
}
|
||||
else {}
|
||||
if (line2->length() > 20){
|
||||
line2->setLength(20);
|
||||
QPointF point4 = line2->p2();
|
||||
QPointF point5 = point4 + QPointF(sin(angel2 - pi/3)*10, cos(angel2 - pi/3)*10);
|
||||
QPointF point6 = point4 + QPointF(sin(angel2 - 2*pi/3)*10, cos(angel2 - 2*pi/3)*10);
|
||||
QGraphicsPolygonItem *poly2 = new QGraphicsPolygonItem(QPolygonF() << point4 << point5 << point6);
|
||||
poly2->setBrush(QBrush(Qt::green));
|
||||
poly2->setPen(QPen(Qt::green));
|
||||
arrows.push_back(poly2);
|
||||
scene->addItem(poly2);
|
||||
}
|
||||
else {}
|
||||
delete line1;
|
||||
delete line2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Заполнение сцены
|
||||
*/
|
||||
void ManagerItem:: fillingScene(int CM, int CN, int PM/*, int PN*/) {
|
||||
|
||||
clearScene();
|
||||
|
||||
QGraphicsRectItem *rect = new QGraphicsRectItem(-300, -300, 600, 600);
|
||||
rect->setPen(QPen(Qt::gray));
|
||||
scene->addItem(rect);
|
||||
|
||||
//std::cout << "start filling scene with number of gamers =" << agent.size() << std::endl;
|
||||
for(int i = 0; i < agent.size(); i++){
|
||||
AgentItem *agentIt;
|
||||
if (i < CM){
|
||||
agentIt = new AgentItem(agent[i], Qt::red);
|
||||
}
|
||||
else if (i < CM + CN){
|
||||
agentIt = new AgentItem(agent[i], Qt::darkBlue);
|
||||
}
|
||||
else if (i < CM + CN + PM){
|
||||
agentIt = new AgentItem(agent[i], Qt::yellow);
|
||||
}
|
||||
else {
|
||||
agentIt = new AgentItem(agent[i], Qt::cyan);
|
||||
}
|
||||
agentItems.push_back(agentIt);
|
||||
agentIt->setPos(agent[i]->getCoordX(), agent[i]->getCoordY());
|
||||
scene->addItem(agentIt);
|
||||
}
|
||||
//std::cout << "INFO: ManagerItem::fillingScene finished, number of items =" << agentItems.size() << std::endl;
|
||||
}
|
||||
|
||||
/*
|
||||
* Очистка сцены
|
||||
*/
|
||||
void ManagerItem:: clearScene(){
|
||||
scene->clear();
|
||||
qDeleteAll(agentItems.begin(), agentItems.end());
|
||||
agentItems.clear();
|
||||
qDeleteAll(links.begin(), links.end());
|
||||
links.clear();
|
||||
qDeleteAll(arrows.begin(), arrows.end());
|
||||
arrows.clear();
|
||||
}
|
||||
|
||||
void ManagerItem::setLink(bool val){
|
||||
this->link = val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Событие игры: перерисовка всех элементов сцены, графика
|
||||
*/
|
||||
void ManagerItem::gameEvent(){
|
||||
//std::cout << "INFO: ManagerItem::gameEvent start, agentItemsSize: " << agentItems.size() << std::endl;
|
||||
// Перерисовка агентов
|
||||
for(int i = 0; i < agentItems.size(); i++){
|
||||
agentItems[i]->agentEvent();
|
||||
}
|
||||
//Очистка сцены от связей
|
||||
for (int i = 0; i < links.size(); i++){
|
||||
scene->removeItem(links[i]);
|
||||
delete links[i];
|
||||
}
|
||||
for (int i = 0; i < arrows.size(); i++){
|
||||
scene->removeItem(arrows[i]);
|
||||
delete arrows[i];
|
||||
}
|
||||
links.clear();
|
||||
arrows.clear();
|
||||
|
||||
// Отрисовка актуальных связей (если необходимо)
|
||||
if(link == true){
|
||||
drawLinks();
|
||||
drawArrow();
|
||||
}
|
||||
}
|
||||
29
DEC_GUI/Agressor/manageritem.h
Normal file
29
DEC_GUI/Agressor/manageritem.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef MANAGERITEM_H
|
||||
#define MANAGERITEM_H
|
||||
|
||||
#include <QGraphicsItem>
|
||||
#include <QObject>
|
||||
#include "agent.h"
|
||||
#include "agentitem.h"
|
||||
|
||||
class ManagerItem : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ManagerItem(QList<Agent*> agents, QGraphicsScene *sceneParameter, int CM, int CN, int PM/*, int PN*/);
|
||||
void drawLinks(); // отрисовать связи
|
||||
void drawArrow(); // отрисовать направление связей
|
||||
void fillingScene(int CM, int CN, int PM); // заполнение сцены
|
||||
void clearScene(); // очистка сцены
|
||||
private:
|
||||
QList <Agent*> agent;
|
||||
QList <AgentItem *> agentItems;
|
||||
QList <QGraphicsLineItem *> links;
|
||||
QList <QGraphicsPolygonItem *> arrows;
|
||||
bool link; // флаг: отображать ли связи
|
||||
QGraphicsScene *scene;
|
||||
public slots:
|
||||
void setLink(bool val);
|
||||
void gameEvent(); // событие игры: перерисовка всех элементов сцены, графика
|
||||
};
|
||||
|
||||
#endif // MANAGERITEM_H
|
||||
356
DEC_GUI/Agressor/model.cpp
Normal file
356
DEC_GUI/Agressor/model.cpp
Normal file
@@ -0,0 +1,356 @@
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <QApplication>
|
||||
#include <QLabel>
|
||||
#include <QString>
|
||||
#include <QTime>
|
||||
#include "model.h"
|
||||
|
||||
static const qreal pi = 3.14159265358979323846264338327950288419717;
|
||||
|
||||
/*
|
||||
* Знак числа
|
||||
*/
|
||||
template <typename T> int sgn(T val) {
|
||||
return (T(0) < val) - (val < T(0));
|
||||
}
|
||||
|
||||
Model::Model(uint modelId, uint CM, uint CN, uint PM, uint PN, int radius, uint speed, bool period, uint distr,
|
||||
uint enmity, uint newEnmity, QObject *parent): id(modelId), cowardMedian(CM), cowardNormal(CN),
|
||||
protectorMedian(PM), protectorNormal(PN), agentRadius(radius), gamerSpeed(speed), period(period), initDistr(distr),
|
||||
enmity(enmity), newEnmity(newEnmity), avContentment(0), QObject(parent)
|
||||
{
|
||||
uint agr; // номер агрессора (для передачи в конструктор игрока)
|
||||
uint prot; // номер защитника (для передачи в конструктор игрока)
|
||||
|
||||
// Конструирование игроков, заполнение списка игроков
|
||||
uint gamerCount = cowardMedian + cowardNormal + protectorMedian + protectorNormal;
|
||||
QTime now = QTime::currentTime();
|
||||
qsrand(now.msec());
|
||||
|
||||
for(uint i = 0; i < gamerCount; i++){
|
||||
do {
|
||||
agr = qrand() % gamerCount;
|
||||
}
|
||||
while (agr == i); // игрок не может быть собственным агрессором
|
||||
do {
|
||||
prot = qrand() % gamerCount;
|
||||
}
|
||||
while(prot == i || prot == agr); // игрок и агрессор не могут быть защитниками
|
||||
|
||||
Agent *gamer = new Agent(i, agr, prot, 0, 0, agentRadius, gamerSpeed);
|
||||
if (i < cowardMedian){}
|
||||
else if (i < cowardMedian + cowardNormal){
|
||||
gamer->setStratedy(1);
|
||||
}
|
||||
else if (i < cowardMedian + cowardNormal + protectorMedian){
|
||||
gamer->setMode(1);
|
||||
}
|
||||
else {
|
||||
gamer->setMode(1);
|
||||
gamer->setStratedy(1);
|
||||
}
|
||||
uint d;
|
||||
if (initDistr == 0){
|
||||
d = qrand() % 220 + 70;
|
||||
}
|
||||
else {
|
||||
d = 200;
|
||||
}
|
||||
agentList.push_back(gamer);
|
||||
agentList[i]->setCoordX(::sin((i * 2 * pi) / gamerCount) * d);
|
||||
agentList[i]->setCoordY(::cos((i * 2 * pi) / gamerCount) * d);
|
||||
}
|
||||
setEnmity(newEnmity);
|
||||
}
|
||||
|
||||
/*
|
||||
* Функция, возвращающая модуль от числа
|
||||
*/
|
||||
qreal Model::mod(qreal a){
|
||||
qreal mod = (a > 0) ? a : -a;
|
||||
return mod;
|
||||
}
|
||||
|
||||
/* Функция, возвращающая список игроков, с которыми столкнётся игрок index
|
||||
* при сдвиге на вектор (x, y); dist - максимальное расстояние, на котором игроки считаются столкнувшимися
|
||||
*/
|
||||
QList<Agent *> Model::DangerGamer(uint index, qreal x, qreal y, uint dist){
|
||||
//std:: cout << "INFO: Manager::DangerGamer start" << std::endl;
|
||||
QList <Agent *> DangerGamers;
|
||||
for(int i = 0; i < agentList.size(); i++){
|
||||
if(i == index){
|
||||
continue;
|
||||
}
|
||||
else{
|
||||
QLineF toAgent = QLineF(agentList[index]->getCoordX() + x, agentList[index]->getCoordY() + y, agentList[i]->getCoordX(), agentList[i]->getCoordY());
|
||||
if(toAgent.length() <= dist){
|
||||
DangerGamers.push_back(agentList[i]);
|
||||
}
|
||||
else{}
|
||||
}
|
||||
}
|
||||
return DangerGamers;
|
||||
}
|
||||
|
||||
QList<QList<Agent *> > Model::DangerGamer(QList<QList<Agent *> > danger, int index, qreal x, qreal y, uint dist){
|
||||
//std:: cout << "INFO: Manager::DangerGamer start" << std::endl;
|
||||
for(int i = index + 1; i < agentList.size(); i++){
|
||||
QLineF toAgent = QLineF(agentList[index]->getCoordX() + x, agentList[index]->getCoordY() + y, agentList[i]->getCoordX(), agentList[i]->getCoordY());
|
||||
if(toAgent.length() <= dist){
|
||||
danger[index].push_back(agentList[i]);
|
||||
danger[i].push_back(agentList[index]);
|
||||
}
|
||||
else {}
|
||||
}
|
||||
return danger;
|
||||
}
|
||||
|
||||
/*
|
||||
* Проверка, выходит ли вектор checked в координатах игрока с номером gamerId за пределы сцены по координате x
|
||||
* возвращает true, если выходит, false - иначе.
|
||||
*/
|
||||
bool Model::leaveWindowX(uint agentId, QLineF checked){
|
||||
if(mod(agentList[agentId]->getCoordX() + checked.dx()) > 300 - agentList[agentId]->getRadius()){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Проверка, выходит ли вектор checked в координатах игрока с номером gamerId за пределы сцены по координате y
|
||||
* возвращает true, если выходит, false - иначе.
|
||||
*/
|
||||
bool Model::leaveWindowY(uint agentId, QLineF checked){
|
||||
if(mod(agentList[agentId]->getCoordY() + checked.dy()) > 300 - agentList[agentId]->getRadius()){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Преобразование координат из-за периодичности сцены
|
||||
* (при попытке выйти за пределы окна игрок должен "выйти" с противоположной стороны сцены)
|
||||
* параметры: номер игрока, вектор сдвига
|
||||
* возвращает преобразованный вектор сдвига
|
||||
*/
|
||||
QLineF Model::periodicTransf(uint index, QLineF tend){
|
||||
qreal x = tend.dx();
|
||||
qreal y = tend.dy();
|
||||
// Проверка на выход за пределы окна по координате x
|
||||
if (mod(tend.dx() + agentList[index]->getCoordX()) > 300 - agentList[index]->getRadius()){
|
||||
x = -1*(600 - 2*agentList[index]->getRadius())*sgn(tend.dx()) + tend.dx();
|
||||
}
|
||||
else{}
|
||||
// Проверка на выход за пределы окна по координате y
|
||||
if (mod(tend.dy() + agentList[index]->getCoordY()) > 300 - agentList[index]->getRadius()){
|
||||
y = -1*(600 - 2*agentList[index]->getRadius())*sgn(tend.dy()) + tend.dy();
|
||||
}
|
||||
else{}
|
||||
return QLineF(0, 0, x, y);
|
||||
}
|
||||
|
||||
/*
|
||||
* Вычисление новых координат для игрока под номером gamerId
|
||||
*/
|
||||
QLineF Model::requiredVector(uint agentId){
|
||||
//std:: cout << "req start" << std::endl;
|
||||
Agent *agressorAg = agentList[agentList[agentId]->getAgressor()];
|
||||
Agent *protectorAg = agentList[agentList[agentId]->getProtector()];
|
||||
// Вычисление координат агрессора и защитника
|
||||
qreal protectorX = protectorAg->getCoordX();
|
||||
qreal protectorY = protectorAg->getCoordY();
|
||||
qreal agressorX = agressorAg->getCoordX();
|
||||
qreal agressorY = agressorAg->getCoordY();
|
||||
|
||||
QLineF fromAtoPr(agressorX, agressorY, protectorX, protectorY);
|
||||
QLineF shiftVector;
|
||||
|
||||
if (agentList[agentId]->getStrategy() == 0){ // Агент движется вдоль медианы
|
||||
// Режим труса
|
||||
if(agentList[agentId]->getMode() == 0){
|
||||
qreal shiftX = agressorX + 2*fromAtoPr.dx() - agentList[agentId]->getCoordX();
|
||||
qreal shiftY = agressorY + 2*fromAtoPr.dy() - agentList[agentId]->getCoordY();
|
||||
shiftVector = QLineF(0, 0, shiftX, shiftY);
|
||||
}
|
||||
// Режим защитника
|
||||
else if(agentList[agentId]->getMode() == 1){
|
||||
qreal shiftX = agressorX + fromAtoPr.dx()/2 - agentList[agentId]->getCoordX();
|
||||
qreal shiftY = agressorY + fromAtoPr.dy()/2 - agentList[agentId]->getCoordY();
|
||||
shiftVector = QLineF(0, 0, shiftX, shiftY);
|
||||
}
|
||||
else {}
|
||||
agentList[agentId]->setDistTarget(shiftVector.length());
|
||||
// Проверка: не проскочить мимо цели
|
||||
if (shiftVector.length() > agentList[agentId]->getSpeed()){
|
||||
shiftVector.setLength(agentList[agentId]->getSpeed());
|
||||
}
|
||||
else{}
|
||||
}
|
||||
else if (agentList[agentId]->getStrategy() == 1){ // если агент движется вдоль нормали
|
||||
|
||||
// ToDo: поправить логику
|
||||
if((protectorY - agressorY == 0 && agressorX - protectorX == 0)){
|
||||
agentList[agentId]->setDistTarget(0);
|
||||
return QLineF(0, 0, 0, 0);
|
||||
}
|
||||
// Расстояние от игрока до прямой, на которой расположены агрессор и защитник
|
||||
qreal dist = (mod((protectorY - agressorY)*agressorX + (agressorX - protectorX)*agressorY)) /
|
||||
sqrt(pow((qreal)protectorY - agressorY, 2) + pow((qreal)agressorX - protectorX, 2));
|
||||
|
||||
// Игрок стремится к данной прямой по нормали.
|
||||
shiftVector = QLineF (0, 0, protectorY - agressorY, agressorX - protectorX);
|
||||
|
||||
// Если свободный член в уравнении прямой Ax + By + C = 0 больше нуля, нормаль нужно перевернуть + нормализация вектора.
|
||||
if (agressorX*(protectorY - agressorY) + agressorY*(agressorX - protectorX) < 0){
|
||||
shiftVector = QLineF(shiftVector.dx(), shiftVector.dy(), 0, 0);
|
||||
|
||||
}
|
||||
else {}
|
||||
// Установление места назначения в точности на пересечение нормали с прямой
|
||||
shiftVector.setLength(dist);
|
||||
|
||||
QLineF fromShiftToA (shiftVector.dx() + agentList[agentId]->getCoordX(), shiftVector.dy() + agentList[agentId]->getCoordY(), agressorX, agressorY);
|
||||
QLineF fromShiftToPr (shiftVector.dx() + agentList[agentId]->getCoordX(), shiftVector.dy() + agentList[agentId]->getCoordY(), protectorX, protectorY);
|
||||
|
||||
// Режим труса
|
||||
if(agentList[agentId]->getMode() == 0){
|
||||
// Проверка, не окажется ли место назначения между агрессором и протектором
|
||||
// (а то и вовсе за агрессором)
|
||||
if((fromShiftToA.length() < fromShiftToPr.length()) && (fromShiftToA.length() >= fromAtoPr.length())){
|
||||
// Установление желаемых координат в точности за защитником
|
||||
QLineF hide = fromAtoPr;
|
||||
hide.setLength(enmity);
|
||||
shiftVector = QLineF(0, 0, protectorX + hide.dx() - agentList[agentId]->getCoordX(), protectorY + hide.dy() - agentList[agentId]->getCoordY());
|
||||
}
|
||||
else{}
|
||||
agentList[agentId]->setDistTarget(shiftVector.length());
|
||||
// Проверка: не проскочить мимо цели
|
||||
if (shiftVector.length() >= agentList[agentId]->getSpeed()){
|
||||
shiftVector.setLength(agentList[agentId]->getSpeed());
|
||||
}
|
||||
else {}
|
||||
}
|
||||
// Режим защитника
|
||||
else if (agentList[agentId]->getMode() == 1){
|
||||
// Проверка, попадает ли точка назначения в промежуток между A и B
|
||||
if((fromAtoPr.length() < fromShiftToPr.length()) && (fromAtoPr.length() >= fromShiftToPr.length())){
|
||||
// Установление желаемых координат посередине между А и В
|
||||
QLineF AtoPr = fromAtoPr;
|
||||
AtoPr.setLength(fromAtoPr.length()/2);
|
||||
shiftVector = QLineF(0, 0, agressorX + AtoPr.dx() - agentList[agentId]->getCoordX(),
|
||||
agressorY + AtoPr.dy() - agentList[agentId]->getCoordY());
|
||||
}
|
||||
else {}
|
||||
agentList[agentId]->setDistTarget(shiftVector.length());
|
||||
// Проверка: не проскочить мимо цели
|
||||
if (shiftVector.length() >= agentList[agentId]->getSpeed()){
|
||||
shiftVector.setLength(agentList[agentId]->getSpeed());
|
||||
}
|
||||
else {}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
else{}
|
||||
//qApp->processEvents();
|
||||
|
||||
//ToDo: сократить код
|
||||
|
||||
// Для непериодичной сцены
|
||||
if (period == false){
|
||||
// Проверка на выход за пределы окна, "подрезание" вектора перемещения
|
||||
if (agentList[agentId]->getCoordX() + shiftVector.dx() > 300 - agentList[agentId]->getRadius()){
|
||||
shiftVector = QLineF(0, 0, 300 - agentList[agentId]->getRadius() - agentList[agentId]->getCoordX(), shiftVector.dy());
|
||||
}
|
||||
else if(agentList[agentId]->getCoordX() + shiftVector.dx() < -300 + agentList[agentId]->getRadius()){
|
||||
shiftVector = QLineF(0, 0, -300 + agentList[agentId]->getRadius() - agentList[agentId]->getCoordX(), shiftVector.dy());
|
||||
}
|
||||
else{}
|
||||
if(agentList[agentId]->getCoordY() + shiftVector.dy() > 300 - agentList[agentId]->getRadius()){
|
||||
shiftVector = QLineF(0, 0, shiftVector.dx(), 300 - agentList[agentId]->getRadius() - agentList[agentId]->getCoordY());
|
||||
}
|
||||
else if(agentList[agentId]->getCoordY() + shiftVector.dy() < -300 + agentList[agentId]->getRadius()){
|
||||
shiftVector = QLineF(0, 0, shiftVector.dx(), -300 + agentList[agentId]->getRadius() - agentList[agentId]->getCoordY());
|
||||
}
|
||||
else {}
|
||||
}
|
||||
// Для периодичной сцены
|
||||
else{
|
||||
// Пересчёт координат с учётом периодичности сцены
|
||||
shiftVector = periodicTransf(agentId, shiftVector);
|
||||
}
|
||||
//qApp->processEvents();
|
||||
|
||||
if(enmity > 0){
|
||||
// Проверка на столкновение
|
||||
//if (agentId < agentList.size() - 1){
|
||||
QList<Agent*> dangerAgents = DangerGamer(/*dangerAgents, */ agentId, shiftVector.dx(), shiftVector.dy(), enmity);
|
||||
//}
|
||||
//QList<Agent*> dangerAgents = DangerGamer(agentId, shiftVector.dx(), shiftVector.dy(), enmity);
|
||||
if(dangerAgents.isEmpty()){
|
||||
//std:: cout << "req start" << std::endl;
|
||||
return shiftVector;
|
||||
}
|
||||
else{
|
||||
// Попытка обойти все потенциальные угрозы стороной. Если не получается, игрок остаётся на месте
|
||||
for (int i = 0; i < dangerAgents.size(); i++){
|
||||
QLineF toAgent = QLineF(agentList[agentId]->getCoordX() + shiftVector.dx(), agentList[agentId]->getCoordY() + shiftVector.dy(),
|
||||
dangerAgents[i]->getCoordX(), dangerAgents[i]->getCoordY());
|
||||
shiftVector = toAgent.normalVector().unitVector();
|
||||
if (period == false){ // для непериодичной сцены - проверка на покидание окна + на новое столкновение
|
||||
QList<Agent*> futureDangerous = DangerGamer(agentId, shiftVector.dx(), shiftVector.dy(), enmity);
|
||||
if(futureDangerous.isEmpty() && leaveWindowX(agentId, shiftVector) && leaveWindowY(agentId, shiftVector) == false){
|
||||
return shiftVector;
|
||||
}
|
||||
else{}
|
||||
futureDangerous.clear();
|
||||
}
|
||||
else{ // для периодичной сцены - преобразование координат из-за периодичности + проверка на новое столкновение
|
||||
shiftVector = periodicTransf(agentId, shiftVector);
|
||||
QList<Agent*> futureDangerous = DangerGamer(agentId, shiftVector.dx(), shiftVector.dy(), enmity);
|
||||
if(futureDangerous.isEmpty()){
|
||||
return shiftVector;
|
||||
}
|
||||
else{}
|
||||
futureDangerous.clear();
|
||||
}
|
||||
//qApp->processEvents();
|
||||
//std::cout << agentId << " Check for crush is done" << std::endl;
|
||||
}
|
||||
//std:: cout << "req start" << std::endl;
|
||||
return QLineF(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//std::cout << "total shift X: " << shiftVector.dx() << " total shift Y: " << shiftVector.dy() << std::endl;
|
||||
//std:: cout << "req start" << std::endl;
|
||||
return shiftVector;
|
||||
}
|
||||
}
|
||||
|
||||
void Model::modelIteration() {
|
||||
QList <QLineF> shift;
|
||||
// Вычисление новых координат
|
||||
// QList<QList<Agent *>> dangerAgents;
|
||||
// for (int i = 0; i < agentList.size(); i++) {
|
||||
// QList<Agent *> content;
|
||||
// dangerAgents.push_back(content);
|
||||
// }
|
||||
for(int i = 0; i < agentList.size(); i++){
|
||||
shift.append(requiredVector(i));
|
||||
//std:: cout << "INFO: iteration: " << step << " agent: " << i << std::endl;
|
||||
}
|
||||
// Смена координат на новые
|
||||
for(int i = 0; i < agentList.size(); i++){
|
||||
agentList[i]->gameEvent(shift[i]);
|
||||
}
|
||||
//qApp->processEvents();
|
||||
shift.clear();
|
||||
}
|
||||
|
||||
void Model::clear() {
|
||||
qDeleteAll(agentList.begin(), agentList.end());
|
||||
agentList.clear();
|
||||
}
|
||||
49
DEC_GUI/Agressor/model.h
Normal file
49
DEC_GUI/Agressor/model.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef MODEL_H
|
||||
#define MODEL_H
|
||||
|
||||
#include <QObject>
|
||||
#include "agent.h"
|
||||
|
||||
|
||||
class Model : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Model(uint modelId, uint CM, uint CN, uint PM, uint PN, int radius, uint speed, bool period, uint distr,
|
||||
uint enmity, uint newEnmity, QObject *parent = 0);
|
||||
qreal mod(qreal a); // модуль числа
|
||||
QList <Agent *> DangerGamer(uint index, qreal x, qreal y, uint dist); // список игроков, с которыми возможно столкновение
|
||||
QList<QList<Agent *> > DangerGamer(QList<QList<Agent *> > danger, int index, qreal x, qreal y, uint dist);
|
||||
bool leaveWindowX(uint agentId, QLineF checked); // проверка на покидание окна по координате X
|
||||
bool leaveWindowY(uint agentId, QLineF checked); // проверка на покидание окна по координате Y
|
||||
QLineF periodicTransf(uint index, QLineF tend); // преобразование координат из-за перидочности сцены
|
||||
QLineF requiredVector(uint gamerId); // вычисление новых координат для игрока с номером gamerId
|
||||
void modelIteration();
|
||||
uint getId() {return id;}
|
||||
QList <Agent *> getAgentList() {return this->agentList;}
|
||||
void setEnmity(int enm) {this->enmity = enm;}
|
||||
void setAvContentment(qreal cont){this->avContentment = cont;}
|
||||
qreal getAvContentment(){return this->avContentment;}
|
||||
void clear();
|
||||
|
||||
private:
|
||||
uint id;
|
||||
QList <Agent *> agentList; // список указателей на игроков
|
||||
uint cowardMedian; // число игроков в режиме труса, движущихся по медиане
|
||||
uint cowardNormal; // число игроков в режиме труса, движущихся по нормали
|
||||
uint protectorMedian; // число игроков в режиме защитника, движущихся по медиане
|
||||
uint protectorNormal; // число игроков в режиме защитника, движущихся по нормали
|
||||
int agentRadius; // радиус шарика-агента (для передачи в конструктор)
|
||||
uint newEnmity; // параметр enmity, полученный из диалогового окна
|
||||
uint gamerSpeed; // скорость агентов
|
||||
bool period; // метка периодичности краёв сцены (true - сцена периодична)
|
||||
uint initDistr; // метка начального распределения игроков сцены (0 - случайное, 1 - на круге)
|
||||
uint enmity; // минимальное расстояние, на которое игроки могут приближаются друг к другу, enmity = 0 - возможно покоординатное совпадение игроков
|
||||
qreal avContentment;
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
};
|
||||
|
||||
#endif // MODEL_H
|
||||
Reference in New Issue
Block a user