logic: IDE Communication

Network code and controller added to communicate with IDE plugins. Does not include GUI integration though.
This commit is contained in:
Manuel Dobusch
2015-10-14 15:40:10 +02:00
parent 4e4cb25540
commit 0664f9a81b
31 changed files with 993 additions and 57 deletions
@@ -0,0 +1,33 @@
#include "IDECommunicationController.h"
#include "utility/messaging/type/MessageActivateTokens.h"
#include "utility/logging/logging.h"
#include "component/controller/helper/NetworkProtocolHelper.h"
IDECommunicationController::IDECommunicationController()
{
}
IDECommunicationController::~IDECommunicationController()
{
}
void IDECommunicationController::handleIncomingMessage(const std::string& message)
{
LOG_WARNING_STREAM(<< message);
NetworkProtocolHelper::NetworkMessage parsedMessage = NetworkProtocolHelper::parseMessage(message);
if (parsedMessage.valid)
{
// TODO: set active token
}
}
void IDECommunicationController::handleMessage(MessageMoveIDECursor* message)
{
std::string networkMessage = NetworkProtocolHelper::buildMessage(message->FilePosition, message->Row, message->Column);
sendMessage(networkMessage);
}
@@ -0,0 +1,26 @@
#ifndef IDE_COMMUNICATION_CONTROLLER_H
#define IDE_COMMUNICATION_CONTROLLER_H
#include <string>
#include "utility/messaging/MessageListener.h"
#include "utility/messaging/type/MessageMoveIDECursor.h"
#include "component/controller/Controller.h"
class IDECommunicationController
: public Controller
, public MessageListener<MessageMoveIDECursor>
{
public:
IDECommunicationController();
virtual ~IDECommunicationController();
void handleIncomingMessage(const std::string& message);
private:
virtual void handleMessage(MessageMoveIDECursor* message);
virtual void sendMessage(const std::string& message) const = 0;
};
#endif // IDE_COMMUNICATION_CONTROLLER_H
@@ -0,0 +1,9 @@
#include "component/controller/NetworkFactory.h"
NetworkFactory::NetworkFactory()
{
}
NetworkFactory::~NetworkFactory()
{
}
@@ -0,0 +1,17 @@
#ifndef NETWORK_FACTORY_H
#define NETWORK_FACTORY_H
#include <memory>
class IDECommunicationController;
class NetworkFactory
{
public:
NetworkFactory();
virtual ~NetworkFactory();
virtual std::shared_ptr<IDECommunicationController> createIDECommunicationController() const = 0;
};
#endif // NETWORK_FACTORY_H
@@ -2,12 +2,14 @@
#include "component/view/GraphViewStyle.h"
unsigned int GraphPostprocessor::s_cellSize = GraphViewStyle::s_gridCellSize;
unsigned int GraphPostprocessor::s_cellWidth = GraphViewStyle::s_gridCellSize;
unsigned int GraphPostprocessor::s_cellHeight = GraphViewStyle::s_gridCellSize;
unsigned int GraphPostprocessor::s_cellPadding = GraphViewStyle::s_gridCellPadding;
void GraphPostprocessor::doPostprocessing(std::vector<DummyNode>& nodes)
{
unsigned int atomarGridSize = s_cellSize;
unsigned int atomarGridWidth = s_cellWidth;
unsigned int atomarGridHeight = s_cellHeight;
if (nodes.size() < 2)
{
@@ -16,42 +18,43 @@ void GraphPostprocessor::doPostprocessing(std::vector<DummyNode>& nodes)
}
// determine center of mass (CoD) which is used to get outliers closer to the rest of the graph
int divisor = 999999;
int maxNodeSize = 0;
int divisorWidth = 999999;
int divisorHeight = 999999;
int maxNodeWidth = 0;
int maxNodeHeight = 0;
Vec2i centerOfMass(0, 0);
float totalMass = 0.0f;
for (const DummyNode& node : nodes)
{
const Vec2i& size = node.size;
if (size.x < divisor)
if (node.size.x < divisorWidth)
{
divisor = size.x;
divisorWidth = node.size.x;
}
if (size.y < divisor)
if (node.size.y < divisorHeight)
{
divisor = size.y;
divisorHeight = node.size.y;
}
if (size.x > maxNodeSize)
if (node.size.x > maxNodeWidth)
{
maxNodeSize = size.x;
maxNodeWidth = node.size.x;
}
else if (size.y > maxNodeSize)
else if (node.size.y > maxNodeHeight)
{
maxNodeSize = size.y;
maxNodeHeight = node.size.y;
}
float nodeMass = size.getLengthSquared();
float nodeMass = node.size.x * node.size.y;
centerOfMass += node.position * nodeMass;
totalMass += nodeMass;
}
centerOfMass /= totalMass;
divisor = (int)atomarGridSize + s_cellPadding; //std::min(divisor, (int)atomarGridSize);
divisorWidth = (int)atomarGridWidth + s_cellPadding; //std::min(divisor, (int)atomarGridSize);
divisorHeight = (int)atomarGridHeight + s_cellPadding;
resolveOutliers(nodes, centerOfMass);
@@ -62,9 +65,9 @@ void GraphPostprocessor::doPostprocessing(std::vector<DummyNode>& nodes)
alignNodeOnRaster(node);
}
MatrixDynamicBase<unsigned int> heatMap = buildHeatMap(nodes, divisor, maxNodeSize);
MatrixDynamicBase<unsigned int> heatMap = buildHeatMap(nodes, divisorWidth, divisorHeight, maxNodeWidth, maxNodeHeight);
resolveOverlap(nodes, heatMap, divisor);
resolveOverlap(nodes, heatMap, divisorWidth, divisorHeight);
}
void GraphPostprocessor::alignNodeOnRaster(DummyNode& node)
@@ -74,7 +77,7 @@ void GraphPostprocessor::alignNodeOnRaster(DummyNode& node)
Vec2i GraphPostprocessor::alignOnRaster(Vec2i position)
{
int rasterPosDivisor = s_cellSize + s_cellPadding;
int rasterPosDivisor = s_cellWidth + s_cellPadding;
if (position.x % rasterPosDivisor != 0)
{
@@ -148,20 +151,17 @@ void GraphPostprocessor::resolveOutliers(std::vector<DummyNode>& nodes, const Ve
}
MatrixDynamicBase<unsigned int> GraphPostprocessor::buildHeatMap(
const std::vector<DummyNode>& nodes, const int atomarNodeSize, const int maxNodeSize
){
// theoretically the nodes could horizontally or vertically far from the center, therefore '*5' (it's kinda arbitrary,
// generally *2 should suffice, I use *5 to prevent problems in extrem cases)
int heatMapWidth = (maxNodeSize * nodes.size() / atomarNodeSize) * 5;
int heatMapHeight = heatMapWidth;
const std::vector<DummyNode>& nodes, const int atomarNodeWidth, const int atomarNodeHeight, const int maxNodeWidth, const int maxNodeHeight)
{
int heatMapWidth = (maxNodeWidth * nodes.size() / atomarNodeWidth) * 5; // theoretically the nodes could horizontally or vertically far from the center, therefore '*5' (it's kinda arbitrary, generally *2 should suffice, I use *5 to prevent problems in extrem cases)
int heatMapHeight = (maxNodeHeight * nodes.size() / atomarNodeHeight) * 5;
MatrixDynamicBase<unsigned int> heatMap(heatMapWidth, heatMapHeight);
for (const DummyNode& node : nodes)
{
int left = node.position.x / atomarNodeSize + heatMapWidth / 2;
int up = node.position.y / atomarNodeSize + heatMapHeight / 2;
int left = node.position.x / atomarNodeWidth + heatMapWidth/2;
int up = node.position.y / atomarNodeHeight + heatMapHeight/2;
Vec2i size = calculateRasterNodeSize(node);
int width = size.x;
int height = size.y;
@@ -193,8 +193,8 @@ MatrixDynamicBase<unsigned int> GraphPostprocessor::buildHeatMap(
}
void GraphPostprocessor::resolveOverlap(
std::vector<DummyNode>& nodes, MatrixDynamicBase<unsigned int>& heatMap, const int divisor
){
std::vector<DummyNode>& nodes, MatrixDynamicBase<unsigned int>& heatMap, const int divisorWidth, const int divisorHeight)
{
int heatMapWidth = heatMap.getColumnsCount();
int heatMapHeight = heatMap.getRowsCount();
@@ -211,9 +211,9 @@ void GraphPostprocessor::resolveOverlap(
for (DummyNode& node : nodes)
{
Vec2i nodePos;
nodePos.x = node.position.x / divisor + heatMapWidth / 2;
nodePos.y = node.position.y / divisor + heatMapHeight / 2;
Vec2i nodePos(0, 0);
nodePos.x = node.position.x / divisorWidth + heatMapWidth/2;
nodePos.y = node.position.y / divisorHeight + heatMapHeight/2;
Vec2i nodeSize = calculateRasterNodeSize(node);
if (nodePos.x + nodeSize.x > heatMapWidth || nodePos.x < 0)
@@ -254,28 +254,29 @@ void GraphPostprocessor::resolveOverlap(
modifyHeatmapArea(heatMap, nodePos, nodeSize, -1);
// move node to new position
int xOffset = grad.x * divisor;
int yOffset = grad.y * divisor;
int xOffset = grad.x * divisorWidth;
int yOffset = grad.y * divisorHeight;
int maxOffset = 2 * divisor;
int maxXOffset = 2*divisorWidth;
int maxYOffset = 2*divisorHeight;
// prevent the graph from "exploding" again...
if (xOffset > maxOffset)
if (xOffset > maxXOffset)
{
xOffset = maxOffset;
xOffset = maxXOffset;
}
else if (xOffset < -maxOffset)
else if (xOffset < -maxXOffset)
{
xOffset = -maxOffset;
xOffset = -maxXOffset;
}
if (yOffset > maxOffset)
if (yOffset > maxYOffset)
{
yOffset = maxOffset;
yOffset = maxYOffset;
}
else if (yOffset < -maxOffset)
else if (yOffset < -maxYOffset)
{
yOffset = -maxOffset;
yOffset = -maxYOffset;
}
node.position += Vec2i(xOffset, yOffset);
@@ -283,8 +284,8 @@ void GraphPostprocessor::resolveOverlap(
alignNodeOnRaster(node);
// re-add node to heat map at new position
nodePos.x = node.position.x / divisor + heatMapWidth / 2;
nodePos.y = node.position.y / divisor + heatMapHeight / 2;
nodePos.x = node.position.x / divisorWidth + heatMapWidth/2;
nodePos.y = node.position.y / divisorHeight + heatMapHeight/2;
modifyHeatmapArea(heatMap, nodePos, nodeSize, 1);
@@ -442,8 +443,8 @@ Vec2i GraphPostprocessor::calculateRasterNodeSize(const DummyNode& node)
while (size.x > 0)
{
size.x = size.x - s_cellSize;
if (size.x > 0)
size.x = size.x - s_cellWidth;
if(size.x > 0)
{
size.x = size.x - s_cellPadding;
}
@@ -453,8 +454,8 @@ Vec2i GraphPostprocessor::calculateRasterNodeSize(const DummyNode& node)
while (size.y > 0)
{
size.y = size.y - s_cellSize;
if (size.y > 0)
size.y = size.y - s_cellHeight;
if(size.y > 0)
{
size.y = size.y - s_cellPadding;
}
@@ -17,12 +17,14 @@ public:
static Vec2i alignOnRaster(Vec2i position);
private:
static unsigned int s_cellSize;
static unsigned int s_cellWidth;
static unsigned int s_cellHeight;
static unsigned int s_cellPadding;
static MatrixDynamicBase<unsigned int> buildHeatMap(const std::vector<DummyNode>& nodes, const int atomarNodeSize, const int maxNodeSize);
static MatrixDynamicBase<unsigned int> buildHeatMap(const std::vector<DummyNode>& nodes, const int atomarNodeWidth, const int atomarNodeHeight, const int maxNodeWidth, const int maxNodeHeight);
static void resolveOutliers(std::vector<DummyNode>& nodes, const Vec2i& centerPoint);
static void resolveOverlap(std::vector<DummyNode>& nodes, MatrixDynamicBase<unsigned int>& heatMap, const int divisor);
static void resolveOverlap(std::vector<DummyNode>& nodes, MatrixDynamicBase<unsigned int>& heatMap, const int divisorWidth, const int divisorHeight);
static void modifyHeatmapArea(MatrixDynamicBase<unsigned int>& heatMap, const Vec2i& leftUpperCorner, const Vec2i& size, const int modifier);
static bool getHeatmapGradient(Vec2f& outGradient, const MatrixDynamicBase<unsigned int>& heatMap, const Vec2i& leftUpperCorner, const Vec2i& size);
static Vec2f heatMapRayCast(const MatrixDynamicBase<unsigned int>& heatMap, const Vec2f& startPosition, const Vec2f& direction, unsigned int minValue);
@@ -0,0 +1,95 @@
#include "NetworkProtocolHelper.h"
#include <sstream>
#include <string>
std::string NetworkProtocolHelper::m_divider = ">>";
std::string NetworkProtocolHelper::m_setActiveTokenPrefix = "setActiveToken";
std::string NetworkProtocolHelper::m_moveCursorPrefix = "moveCursor";
std::string NetworkProtocolHelper::m_endOfMessageToken = "<EOM>";
NetworkProtocolHelper::NetworkMessage NetworkProtocolHelper::parseMessage(const std::string& message)
{
NetworkMessage networkMessage;
std::string tmpMessage = removeEndOfMessageToken(message);
size_t pos = tmpMessage.find(m_setActiveTokenPrefix);
if(pos != std::string::npos)
{
tmpMessage = "";
getSubstringAfterString(message, m_divider, tmpMessage); // just get rid of message type
std::string fileLocation = getSubstringAfterString(tmpMessage, m_divider, tmpMessage);
std::string row = getSubstringAfterString(tmpMessage, m_divider, tmpMessage);
std::string column = tmpMessage; // getSubstringAfterString(tmpMessage, "", tmpMessage); // there should be nothing left in the message but the column number
if(fileLocation.length() <= 0
|| row.length() <= 0
|| column.length() <= 0
|| isDigits(row) == false
|| isDigits(column) == false)
{
return networkMessage;
}
else
{
networkMessage.fileLocation = fileLocation;
networkMessage.row = std::stoi(row);
networkMessage.column = std::stoi(column);
networkMessage.valid = true;
}
}
return networkMessage;
}
std::string NetworkProtocolHelper::buildMessage(const std::string& fileLocation, const unsigned int row, const unsigned int column)
{
std::stringstream messageStream;
messageStream << m_moveCursorPrefix;
messageStream << m_divider;
messageStream << fileLocation;
messageStream << m_divider;
messageStream << row;
messageStream << m_divider;
messageStream << column;
messageStream << m_endOfMessageToken;
return messageStream.str();
}
std::string NetworkProtocolHelper::removeEndOfMessageToken(const std::string& message)
{
size_t pos = message.find(m_endOfMessageToken);
if (pos != std::string::npos)
{
return message.substr(0, pos);
}
else
{
return message;
}
}
std::string NetworkProtocolHelper::getSubstringAfterString(const std::string& message, const std::string& searchString, std::string& subMessage)
{
std::string result = "";
size_t pos = message.find(searchString);
if(pos != std::string::npos)
{
result = message.substr(0, pos);
subMessage = message.substr(pos + searchString.length());
}
return result;
}
bool NetworkProtocolHelper::isDigits(const std::string& text)
{
return (text.find_first_not_of("0123456789") == std::string::npos);
}
@@ -0,0 +1,40 @@
#ifndef NETWORK_PROTOCOL_HELPER_H
#define NETWORK_PROTOCOL_HELPER_H
#include <string>
class NetworkProtocolHelper
{
public:
struct NetworkMessage
{
public:
NetworkMessage()
: fileLocation("")
, row(0)
, column(0)
, valid(false)
{}
std::string fileLocation;
unsigned int row;
unsigned int column;
bool valid;
};
static NetworkMessage parseMessage(const std::string& message);
static std::string buildMessage(const std::string& fileLocation, const unsigned int row, const unsigned int column);
private:
static std::string removeEndOfMessageToken(const std::string& message);
static std::string getSubstringAfterString(const std::string& message, const std::string& searchString, std::string& subMessage);
static bool isDigits(const std::string& text);
static std::string m_divider;
static std::string m_setActiveTokenPrefix;
static std::string m_moveCursorPrefix;
static std::string m_endOfMessageToken;
};
#endif // NETWORK_PROTOCOL_HELPER_H