Init version

This commit is contained in:
2024-10-03 18:43:04 +07:00
commit f80052961f
186 changed files with 71676 additions and 0 deletions

View 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
View 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

View 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());
}

View 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

View 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();
}

View 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

View 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
View 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

View 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();
}
}

View 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
View 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
View 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