#include <qwidget.h>
#include <qobject.h>
#include <qframe.h>
#include <exception>
#include <map>
#include <vector>

#include "ScienceNode.h"
#include "ui_ScienceTreeWidget.h"
#include "ScienceTree.h"
#include "softProj\clientServer\structs.h"

ScienceTree::ScienceTree(Ui_treeWidget * treeWidget, int depth)
{
	treeWidget_ = treeWidget;
	
	depth_ = depth;		
	freeTokens_ = 500000;
	selectedNode_ = NULL;

	tokensMultiplicators_ = new double[depth];
	
	for (int i = 0; i < depth; ++i)
	{
		tokensMultiplicators_[i] = 1;
	}
	
	itemsWidget_ = new ListDetailsViewWidget(treeWidget->itemsLayout, 5);

	hideParamsWidget();
	setupNodeWidget(NULL);
}

ScienceTree::~ScienceTree()
{
	delete [] tokensMultiplicators_;
	
	for (NodesIterator it = nodesList_.begin(); it != nodesList_.end(); ++it)
	{
		delete (it->second);
	}

	delete itemsWidget_;
}

int ScienceTree::getFreeTokens() const
{
	return freeTokens_;
}

void ScienceTree::setRoot(const std::string & nodeName, QLabel * label, NodeWidget * root)
{
	ScienceNode * createdRoot = new ScienceInnerNode(nodeName, root, label);
		
	nodesList_.insert(std::make_pair(nodeName, createdRoot));
	createdRoot->setDepth(0);
}

ScienceNode * ScienceTree::findNode(const std::string & name) {
	NodesIterator nodeIterator = nodesList_.find(name);

	if (nodeIterator != nodesList_.end()) {
		return nodeIterator->second;
	}
	else {
		return NULL;
	}
}

CompositeItem * ScienceTree::findParameter(const std::string & name) {
	ParamsIterator paramsIterator = paramsList_.find(name);

	if (paramsIterator != paramsList_.end()) {
		return paramsIterator->second;
	}
	else {
		return NULL;
	}
}

void ScienceTree::appendChild(const std::string & parentName, const std::string & nodeName, QLabel * label, NodeWidget * nodeWidget, bool isInner)
{
	ScienceNode * currentNode = findNode(parentName);

	if (currentNode != NULL)
	{
		if (currentNode->isInner())
		{
			ScienceNode * appendedNode = NULL;
				
			if (isInner)
			{
				appendedNode = new ScienceInnerNode(nodeName, nodeWidget, label);
			}
			else
			{
				appendedNode = new ScienceLeafNode(nodeName, nodeWidget, label);
				leafsList_.push_back(appendedNode);
			}				

			currentNode->appendChild(appendedNode);
			nodesList_.insert(std::make_pair(nodeName, appendedNode));
		}
	}
	else {
		throw new std::exception("Cannot find node with given name in method appendChild");
	}
}

void ScienceTree::appendChild(const std::string & parentName, const std::string & nodeName, QLabel * label, NodeWidget * nodeWidget)
{
	appendChild(parentName, nodeName, label, nodeWidget, true);
}

void ScienceTree::appendLeaf(const std::string & parentName, const std::string & nodeName, QLabel * label, NodeWidget * nodeWidget)
{
	appendChild(parentName, nodeName, label, nodeWidget, false);
}

void ScienceTree::appendComposite(const std::string & parentName, const std::string & compositeName, QString graphicalName)
{		
	ScienceNode * currentNode = findNode(parentName);

	if (currentNode != NULL)
	{
		CompositeItem * appendedComposite = new CompositeItem(compositeName, graphicalName);
		currentNode->appendComposite(appendedComposite);

		paramsList_.insert(std::make_pair(compositeName, appendedComposite));
	}
	else
	{
		throw new std::exception("Cannot find node with given name in method appendComposite");
	}
}

void ScienceTree::setTokenMultiplicators(double * values, int count)
{
	for (int i = 0; (i < count) && (i + 1 < depth_); ++i)
	{
		tokensMultiplicators_[i+1] = values[i];
	}

	propagateMultiplicators();
}

void ScienceTree::propagateMultiplicators()
{
	int currentDepth = 0;

	for (NodesIterator it = nodesList_.begin();
		it != nodesList_.end();
		++it)
	{
		(it)->second->setTokensMultiplicator(tokensMultiplicators_[(it)->second->getDepth()]);
	}
}

bool ScienceTree::addTokens(ScienceNode * targetNode, int value)
{
	if (freeTokens_ >= value)
	{
		if (targetNode)
		{
			targetNode->addTokens(value);
			freeTokens_ -= value;
			return true;
		}
	}
		
	return false;
}

void ScienceTree::setupNodeWidget(ScienceNode * selectedNode)
{
	if (selectedNode)
	{
		treeWidget_->tokensCountSpinBox->setEnabled(true);
		treeWidget_->tokensCountSlider->setEnabled(true);

		int maxTokens = freeTokens_ + selectedNode->getAssignedTokens();

		treeWidget_->tokensCountSlider->setMaximum(maxTokens);
		treeWidget_->tokensCountSpinBox->setMaximum(maxTokens);	

		treeWidget_->nodeNameLabel->setText(selectedNode->getName());			
		treeWidget_->pointsCountLabel->setText(QString::number(selectedNode->getAssignedPoints() - selectedNode->getAssignedTokens()));

		treeWidget_->totalsLabel->setText(QString::number(selectedNode->getAssignedPoints()));

		int assignedTokens = selectedNode->getAssignedTokens();

		treeWidget_->tokensCountSlider->setValue(assignedTokens);
		treeWidget_->tokensCountSpinBox->setValue(assignedTokens);

		treeWidget_->nodeDescriptionLabel->setText(QString::fromUtf16(L"Nastav vybraný uzel"));
	}
	else
	{
		treeWidget_->nodeNameLabel->setText("-");			
		treeWidget_->pointsCountLabel->setText("-");
		
		treeWidget_->tokensCountSpinBox->setEnabled(false);
		treeWidget_->tokensCountSlider->setEnabled(false);

		treeWidget_->nodeDescriptionLabel->setText(QString::fromUtf16(L"Vyber si uzel, se kterým chceš pracovat. Žádný uzel není zatím vybraný"));
	}

	treeWidget_->freeTokensCountLabel->setText(QString::number(freeTokens_));
}

void ScienceTree::enableNodeChanges()
{
	isNodeChangesEnabled_ = true;
}

void ScienceTree::disableNodeChanges()
{
	isNodeChangesEnabled_ = false;
}

void ScienceTree::setupParamsWidget()
{
	if (selectedNode_ && selectedNode_->isLeaf())
	{
		std::vector<CompositeItem *> & composites = selectedNode_->getCompositeItems();

		itemsWidget_->showContent();		

		int index = 0;
		for (ScienceLeafNode::ParamsIterator it = composites.begin(); it != composites.end(); ++it)
		{
			itemsWidget_->setupRow((*it), index);
			QObject::connect((*it), SIGNAL(freePercentsChanged()), this, SLOT(freePercentsChanged()));
			index++;
		}

		itemsWidget_->setFreePercents(selectedNode_->getFreePercents());

		itemsWidget_->hideAllRowsFrom(composites.size());

		showParamsWidget();

		treeWidget_->freePercentsLabel->setText(QString::number(selectedNode_->getFreePercents()));
		treeWidget_->pointsLabel->setText(QString::number(selectedNode_->getAssignedPoints()));		
	}
}


void ScienceTree::setupBackParamsWidget()
{
	std::vector<CompositeItem *> & composites = selectedNode_->getCompositeItems();

	int index = 0;
	for (ScienceLeafNode::ParamsIterator it = composites.begin(); it != composites.end(); ++it)
	{
		itemsWidget_->setupRowBack(index);
		QObject::disconnect((*it), SIGNAL(freePercentsChanged()), this, SLOT(freePercentsChanged()));
		index++;
	}
}

void ScienceTree::scienceNodeMousePressed(NodeWidget * pressedNodeWidget)
{
	disableNodeChanges();

	ScienceNode * pressedNode = pressedNodeWidget->getLogicalNode();
	setupNodeWidget(pressedNodeWidget->getLogicalNode());						

	if (selectedNode_ != pressedNode)
	{
		if (selectedNode_)
		{
			if (!selectedNode_->isInner())
			{
				setupBackParamsWidget();
			}
		}

		selectedNode_ = pressedNode;

		if (!selectedNode_->isInner())
		{				
			setupParamsWidget();
		}
		else
		{
			hideParamsWidget();
		}
	}

	enableNodeChanges();
}

void ScienceTree::hideParamsWidget()
{
	treeWidget_->descriptionLabel->setText(
		QString::fromUtf16(L"Žádný list není vybrán"));

	treeWidget_->freePercentsLabel->hide();
	treeWidget_->freePercentsHeader->hide();

	treeWidget_->pointsHeader->hide();
	treeWidget_->pointsLabel->hide();

	itemsWidget_->hide();
}

void ScienceTree::showParamsWidget()
{
	treeWidget_->descriptionLabel->setText(
		QString::fromUtf16(L"Parametry listu"));

	treeWidget_->freePercentsHeader->show();
	treeWidget_->freePercentsLabel->show();

	treeWidget_->pointsHeader->show();
	treeWidget_->pointsLabel->show();
}

void ScienceTree::freePercentsChanged()
{
	treeWidget_->freePercentsLabel->setText(QString::number(selectedNode_->getFreePercents()));		
	itemsWidget_->setFreePercents(selectedNode_->getFreePercents());

	emit freePercentsChangedSignal(selectedNode_->getFreePercents());
}

void ScienceTree::tokensCountChanged(int value)
{
	if (selectedNode_)
	{
		if (isNodeChangesEnabled_)
		{
			int addedTokens = value - selectedNode_->getAssignedTokens();
			addTokens(selectedNode_, addedTokens);
			setupNodeWidget(selectedNode_);

			if (selectedNode_->isLeaf())
			{
				treeWidget_->pointsLabel->setText(QString::number(selectedNode_->getAssignedPoints()));
			}

			emit assignedPointsChanged(value);
		}
	}
}

unsigned long ScienceTree::getSciencePoints(const std::string & name) {
	CompositeItem * param = findParameter(name);

	if (param != NULL) {
		return param->getAssignedPercents();
	}
	else {
		throw new std::exception("Cannot find parameter with given name in method getSciencePoints");
	}
}

void ScienceTree::setSciencePoints(const std::string & name, unsigned long value) {
	CompositeItem * param = findParameter(name);

	if (param != NULL) {
		// We call this because we want to also adjust parent composite and leaf
		param->assignedPercentsChanged(value);
	}
	else {
		throw new std::exception("Cannot find parameter with given name in method getSciencePoints");
	}
}

void ScienceTree::setRealScientificPoints(const std::string & name, unsigned long value) {
	CompositeItem * param = findParameter(name);

	if (param != NULL) {
		return param->setCreatedPoints(value);
	}
	else {
		throw new std::exception("Cannot find node with given name in method setRealScientificPoints");
	}
}

unsigned long ScienceTree::getNodeTokens(const std::string & name) {
	ScienceNode * node = findNode(name);

	if (node != NULL) {
		return node->getAssignedTokens();
	}
	else {
		throw new std::exception("Cannot find node with given name in method getNodeTokens");
	}
}

void ScienceTree::setNodeTokens(const std::string & name, unsigned long value) {
	ScienceNode * node = findNode(name);

	if (node != NULL) {
		node->setAssignedTokens(value);
		freeTokens_ -= value;
	}
	else {
		throw new std::exception("Cannot find node with given name in method setNodeTokens");
	}
}

void ScienceTree::setShowTokens(EShowingOptions option)
{
	for (NodesIterator it = nodesList_.begin(); it != nodesList_.end(); ++it)
	{
		if (option == ALL)
		{
			it->second->setShowTokens(true);
		}
		else if (option == LEAF)
		{
			if (it->second->isLeaf())
			{
				it->second->setShowTokens(true);
			}
			else
			{
				it->second->setShowTokens(false);
			}
		}
		else if (option == INNER)
		{
			if (it->second->isInner())
			{
				it->second->setShowTokens(true);
			}
			else
			{
				it->second->setShowTokens(false);
			}
		}
		else 
		{
			it->second->setShowTokens(false);
		}
	}
}

void ScienceTree::setShowPoints(EShowingOptions option)
{
	for (NodesIterator it = nodesList_.begin(); it != nodesList_.end(); ++it)
	{
		if (option == ALL)
		{
			it->second->setShowPoints(true);
		}
		else if (option == LEAF)
		{
			if (it->second->isLeaf())
			{
				it->second->setShowPoints(true);
			}
			else
			{
				it->second->setShowPoints(false);
			}
		}
		else if (option == INNER)
		{
			if (it->second->isInner())
			{
				it->second->setShowPoints(true);
			}
			else
			{
				it->second->setShowPoints(false);
			}
		}
		else 
		{
			it->second->setShowPoints(false);
		}
	}
}


void ScienceTree::clearState() {
	for (NodesIterator it = nodesList_.begin(); it != nodesList_.end(); ++it) {
		(it)->second->clearState();
	}
}

void ScienceTree::setMaximumTokens(unsigned long value) {

	freeTokens_ = value;

	for (NodesIterator it = nodesList_.begin(); it != nodesList_.end(); ++it) {
		(it)->second->setMaximumTokens(value);
	}
}

void ScienceTree::setState(ScienceTreeRawUpdateData & data) {
	clearState();

	setMaximumTokens(data.totalTokens);

	/* Tokens */

    setNodeTokens(TOKENS_SCIENCE_ENTITY_SHIPS, data.tokensSCIENCE_ENTITY_SHIPS);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_BASES, data.tokensSCIENCE_ENTITY_BASES);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_ENERGETIC_ACCUMULATOR, data.tokensSCIENCE_ENTITY_ENERGETIC_ACCUMULATOR);
	setNodeTokens(TOKENS_SCIENCE_ENTITY_NAVIGATION_COMPUTER, data.tokensSCIENCE_ENTITY_NAVIGATION_COMPUTER);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_QUARK_GLUON_CORE, data.tokensSCIENCE_ENTITY_QUARK_GLUON_CORE);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_SUBSPACE_BEACON, data.tokensSCIENCE_ENTITY_SUBSPACE_BEACON);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_INERTIAL_DAMPERS, data.tokensSCIENCE_ENTITY_INERTIAL_DAMPERS);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_IMPULS_JET_ENGINE, data.tokensSCIENCE_ENTITY_IMPULS_JET_ENGINE);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_MECHANICAL_DAMPERS, data.tokensSCIENCE_ENTITY_MECHANICAL_DAMPERS);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_DEFLECTOR_SHIELDS, data.tokensSCIENCE_ENTITY_DEFLECTOR_SHIELDS);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_WEAPON_ENERGY_CIRCUIT, data.tokensSCIENCE_ENTITY_WEAPON_ENERGY_CIRCUIT);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_DRONE_MISSILE_LAUNCHER, data.tokensSCIENCE_ENTITY_DRONE_MISSILE_LAUNCHER);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_DRONE_MISSILES , data.tokensSCIENCE_ENTITY_DRONE_MISSILES);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_LASER_GUN, data.tokensSCIENCE_ENTITY_LASER_GUN);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_TRANSPORT_BEAM_GENERATOR, data.tokensSCIENCE_ENTITY_TRANSPORT_BEAM_GENERATOR);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_MAGNETICAL_COLLECTORS_OF_PLASMA, data.tokensSCIENCE_ENTITY_MAGNETICAL_COLLECTORS_OF_PLASMA);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_SUBMERSIBLE_FILTRATION_TANK, data.tokensSCIENCE_ENTITY_SUBMERSIBLE_FILTRATION_TANK);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_SUBMARINE_MINING_MACHINE, data.tokensSCIENCE_ENTITY_SUBMARINE_MINING_MACHINE);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_UNDERGROUND_DRILLING_MACHINE, data.tokensSCIENCE_ENTITY_UNDERGROUND_DRILLING_MACHINE);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_PROBE, data.tokensSCIENCE_ENTITY_PROBE);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_HIGH_RESOLUTION_SENSORS, data.tokensSCIENCE_ENTITY_HIGH_RESOLUTION_SENSORS);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_LONG_RANGE_SENSORS, data.tokensSCIENCE_ENTITY_LONG_RANGE_SENSORS);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_CLOAKING_DEVICE , data.tokensSCIENCE_ENTITY_CLOAKING_DEVICE);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_ANDROIDS, data.tokensSCIENCE_ENTITY_ANDROIDS);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_SCIENTIFIC_LAB, data.tokensSCIENCE_ENTITY_SCIENTIFIC_LAB);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_LIFE_SUPPORT, data.tokensSCIENCE_ENTITY_LIFE_SUPPORT);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_MAINFRAME, data.tokensSCIENCE_ENTITY_MAINFRAME);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_HANGAR, data.tokensSCIENCE_ENTITY_HANGAR);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_MAGNETICAL_FILTER , data.tokensSCIENCE_ENTITY_MAGNETICAL_FILTER);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_DEUTERIUM_DECOMPOSER, data.tokensSCIENCE_ENTITY_DEUTERIUM_DECOMPOSER);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_ZIRCONIUM_REACTOR, data.tokensSCIENCE_ENTITY_ZIRCONIUM_REACTOR);
    setNodeTokens(TOKENS_SCIENCE_ENTITY_ILMENITE_FURNACE, data.tokensSCIENCE_ENTITY_ILMENITE_FURNACE);

    setNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_SCIENCE, data.tokensSCIENCE_SUPREME_ENTITY_SCIENCE);

    setNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_DRIVE, data.tokensSCIENCE_SUPREME_ENTITY_DRIVE);
    setNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_PLATFORM, data.tokensSCIENCE_SUPREME_ENTITY_PLATFORM);
    setNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_MODULES, data.tokensSCIENCE_SUPREME_ENTITY_MODULES);
    setNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_PRODUCTION, data.tokensSCIENCE_SUPREME_ENTITY_PRODUCTION);

    setNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_SUBSPACE_DRIVE, data.tokensSCIENCE_SUPREME_ENTITY_SUBSPACE_DRIVE);
    setNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_IMPULS_DRIVE, data.tokensSCIENCE_SUPREME_ENTITY_IMPULS_DRIVE);
    setNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_CONSTRUCTION, data.tokensSCIENCE_SUPREME_ENTITY_CONSTRUCTION);
    setNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_EQUIPMENT, data.tokensSCIENCE_SUPREME_ENTITY_EQUIPMENT);
    setNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_ENERGETIC_RING, data.tokensSCIENCE_SUPREME_ENTITY_ENERGETIC_RING);
    setNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_RECOGNITION_DEVICES, data.tokensSCIENCE_SUPREME_ENTITY_RECOGNITION_DEVICES);
    setNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_FACTORIES, data.tokensSCIENCE_SUPREME_ENTITY_FACTORIES);
    setNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_QUARRYING_MACHINES, data.tokensSCIENCE_SUPREME_ENTITY_QUARRYING_MACHINES);

	/** Special points (percents) */

	setSciencePoints(SPEC_PTS_QUARK_GLUON_CORE_SPEED, data.specPtsQUARK_GLUON_CORE_SPEED);
    setSciencePoints(SPEC_PTS_QUARK_GLUON_CORE_CONSUMPTION, data.specPtsQUARK_GLUON_CORE_CONSUMPTION);

	setSciencePoints(SPEC_PTS_NAVIGATION_COMPUTER_SPEED, data.specPtsNAVIGATION_COMPUTER_SPEED);

    setSciencePoints(SPEC_PTS_SUBSPACE_BEACON_SPEED, data.specPtsSUBSPACE_BEACON_SPEED);

    setSciencePoints(SPEC_PTS_INERTIAL_DAMPERS_SPEED, data.specPtsINERTIAL_DAMPERS_SPEED);

    setSciencePoints(SPEC_PTS_IMPULS_ENGINE_FORCE, data.specPtsIMPULS_ENGINE_FORCE);
    setSciencePoints(SPEC_PTS_IMPULS_ENGINE_CONSUMPTION, data.specPtsIMPULS_ENGINE_CONSUMPTION);

    setSciencePoints(SPEC_PTS_MECHANICAL_DAMPERS_ACCELERATION, data.specPtsMECHANICAL_DAMPERS_ACCELERATION);

    setSciencePoints(SPEC_PTS_DRONE_MISSILES_DAMAGE, data.specPtsDRONE_MISSILES_DAMAGE);
    setSciencePoints(SPEC_PTS_DRONE_MISSILES_PRECISION, data.specPtsDRONE_MISSILES_PRECISION);
    setSciencePoints(SPEC_PTS_DRONE_MISSILES_RANGE, data.specPtsDRONE_MISSILES_RANGE);

    setSciencePoints(SPEC_PTS_DRONE_MISSILE_LAUNCHER_ACCUMULATOR, data.specPtsDRONE_MISSILE_LAUNCHER_ACCUMULATOR);
    setSciencePoints(SPEC_PTS_DRONE_MISSILE_LAUNCHER_CHARGING, data.specPtsDRONE_MISSILE_LAUNCHER_CHARGING);

    setSciencePoints(SPEC_PTS_SHIPS_LEVEL, data.specPtsSHIPS_LEVEL);

    setSciencePoints(SPEC_PTS_BASES_LEVEL, data.specPtsBASES_LEVEL);

    setSciencePoints(SPEC_PTS_HANGARS_LEVEL, data.specPtsHANGARS_LEVEL);

    setSciencePoints(SPEC_PTS_ANDROIDS_LEVEL, data.specPtsANDROIDS_LEVEL);
    setSciencePoints(SPEC_PTS_ANDROIDS_CONSUMPTION, data.specPtsANDROIDS_CONSUMPTION);

    setSciencePoints(SPEC_PTS_ENERGETIC_ACCUMULATOR_ACCUMULATOR, data.specPtsENERGETIC_ACCUMULATOR_ACCUMULATOR);
    setSciencePoints(SPEC_PTS_ENERGETIC_ACCUMULATOR_CHARGING, data.specPtsENERGETIC_ACCUMULATOR_CHARGING);

    setSciencePoints(SPEC_PTS_MAINFRAME_BIO_NODES, data.specPtsMAINFRAME_BIO_NODES);
    setSciencePoints(SPEC_PTS_MAINFRAME_PREDICTION, data.specPtsMAINFRAME_PREDICTION);
    setSciencePoints(SPEC_PTS_MAINFRAME_TIME_REUSABILITY, data.specPtsMAINFRAME_TIME_REUSABILITY);
    setSciencePoints(SPEC_PTS_MAINFRAME_CONSUMPTION, data.specPtsMAINFRAME_CONSUMPTION);

    setSciencePoints(SPEC_PTS_SCIENTIFIC_LABS_LEVEL, data.specPtsSCIENTIFIC_LABS_LEVEL);

    setSciencePoints(SPEC_PTS_LIFE_SUPPORT_CAPACITY, data.specPtsLIFE_SUPPORT_CAPACITY);
    setSciencePoints(SPEC_PTS_LIFE_SUPPORT_CONSUMPTION, data.specPtsLIFE_SUPPORT_CONSUMPTION);

    setSciencePoints(SPEC_PTS_WEAPON_ENERGY_CIRCUIT_CHARGING, data.specPtsWEAPON_ENERGY_CIRCUIT_CHARGING);

    setSciencePoints(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_ACCUMULATOR, data.specPtsTRANSPORT_BEAM_GENERATOR_ACCUMULATOR);
    setSciencePoints(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_CHARGING, data.specPtsTRANSPORT_BEAM_GENERATOR_CHARGING);
    setSciencePoints(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_FORCIBILITY, data.specPtsTRANSPORT_BEAM_GENERATOR_FORCIBILITY);
    setSciencePoints(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_PRECISION, data.specPtsTRANSPORT_BEAM_GENERATOR_PRECISION);
    setSciencePoints(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_RANGE, data.specPtsTRANSPORT_BEAM_GENERATOR_RANGE);

    setSciencePoints(SPEC_PTS_LASER_GUN_ACCUMULATOR, data.specPtsLASER_GUN_ACCUMULATOR);
    setSciencePoints(SPEC_PTS_LASER_GUN_CHARGING, data.specPtsLASER_GUN_CHARGING);
    setSciencePoints(SPEC_PTS_LASER_GUN_FORCIBILITY, data.specPtsLASER_GUN_FORCIBILITY);
    setSciencePoints(SPEC_PTS_LASER_GUN_PRECISION, data.specPtsLASER_GUN_PRECISION);
    setSciencePoints(SPEC_PTS_LASER_GUN_RANGE, data.specPtsLASER_GUN_RANGE);

    setSciencePoints(SPEC_PTS_DEFLECTOR_SHIELDS_GENERATOR_SOLIDITY, data.specPtsDEFLECTOR_SHIELDS_GENERATOR_SOLIDITY);
    setSciencePoints(SPEC_PTS_DEFLECTOR_SHIELDS_GENERATOR_ACCUMULATOR, data.specPtsDEFLECTOR_SHIELDS_GENERATOR_ACCUMULATOR);
    setSciencePoints(SPEC_PTS_DEFLECTOR_SHIELDS_GENERATOR_CHARGING, data.specPtsDEFLECTOR_SHIELDS_GENERATOR_CHARGING);

    setSciencePoints(SPEC_PTS_HIGH_RESOLUTION_SENSORS_LEVEL, data.specPtsHIGH_RESOLUTION_SENSORS_LEVEL);
    setSciencePoints(SPEC_PTS_HIGH_RESOLUTION_SENSORS_RANGE, data.specPtsHIGH_RESOLUTION_SENSORS_RANGE);
    setSciencePoints(SPEC_PTS_HIGH_RESOLUTION_SENSORS_CONSUMPTION, data.specPtsHIGH_RESOLUTION_SENSORS_CONSUMPTION);

    setSciencePoints(SPEC_PTS_LONG_RANGE_SENSORS_LEVEL, data.specPtsLONG_RANGE_SENSORS_LEVEL);
    setSciencePoints(SPEC_PTS_LONG_RANGE_SENSORS_RANGE, data.specPtsLONG_RANGE_SENSORS_RANGE);
    setSciencePoints(SPEC_PTS_LONG_RANGE_SENSORS_CONSUMPTION, data.specPtsLONG_RANGE_SENSORS_CONSUMPTION);

    setSciencePoints(SPEC_PTS_CLOAKING_DEVICE_LEVEL, data.specPtsCLOAKING_DEVICE_LEVEL);
    setSciencePoints(SPEC_PTS_CLOAKING_DEVICE_CONSUMPTION, data.specPtsCLOAKING_DEVICE_CONSUMPTION);

    setSciencePoints(SPEC_PTS_PROBE_DEVICE_LEVEL, data.specPtsPROBE_DEVICE_LEVEL);

    setSciencePoints(SPEC_PTS_MAGNETICAL_FILTER_PRODUCTION, data.specPtsMAGNETICAL_FILTER_PRODUCTION);

    setSciencePoints(SPEC_PTS_DEUTERIUM_DECOMPOSER_PRODUCTION, data.specPtsDEUTERIUM_DECOMPOSER_PRODUCTION);
    setSciencePoints(SPEC_PTS_DEUTERIUM_DECOMPOSER_METAMORPHOSIS, data.specPtsDEUTERIUM_DECOMPOSER_METAMORPHOSIS);

    setSciencePoints(SPEC_PTS_ZIRCONIUM_REACTOR_PRODUCTION, data.specPtsZIRCONIUM_REACTOR_PRODUCTION);
    setSciencePoints(SPEC_PTS_ZIRCONIUM_REACTOR_METAMORPHOSIS, data.specPtsZIRCONIUM_REACTOR_METAMORPHOSIS);

    setSciencePoints(SPEC_PTS_ILMENITE_FURNACE_PRODUCTION, data.specPtsILMENITE_FURNACE_PRODUCTION);
    setSciencePoints(SPEC_PTS_ILMENITE_FURNACE_METAMORPHOSIS, data.specPtsILMENITE_FURNACE_METAMORPHOSIS);

    setSciencePoints(SPEC_PTS_MAGNETICAL_COLLECTORS_OF_PLASMA_WINDING_SPEED, data.specPtsMAGNETICAL_COLLECTORS_OF_PLASMA_WINDING_SPEED);

    setSciencePoints(SPEC_PTS_SUBMERSIBLE_FILTRATION_TANK_WINDING_SPEED, data.specPtsSUBMERSIBLE_FILTRATION_TANK_WINDING_SPEED);
    setSciencePoints(SPEC_PTS_SUBMERSIBLE_FILTRATION_TANK_RANGE, data.specPtsSUBMERSIBLE_FILTRATION_TANK_RANGE);

    setSciencePoints(SPEC_PTS_SUBMARINE_MINING_MACHINE_WINDING_SPEED, data.specPtsSUBMARINE_MINING_MACHINE_WINDING_SPEED);
    setSciencePoints(SPEC_PTS_SUBMARINE_MINING_MACHINE_RANGE, data.specPtsSUBMARINE_MINING_MACHINE_RANGE);

    setSciencePoints(SPEC_PTS_UNDERGROUND_DRILLING_MACHINE_WINDING_SPEED, data.specPtsUNDERGROUND_DRILLING_MACHINE_WINDING_SPEED);
    setSciencePoints(SPEC_PTS_UNDERGROUND_DRILLING_MACHINE_RANGE, data.specPtsUNDERGROUND_DRILLING_MACHINE_RANGE);   

	/** Real scientific points */

    setRealScientificPoints(SPEC_PTS_QUARK_GLUON_CORE_SPEED, data.realPtsQUARK_GLUON_CORE_SPEED);
    setRealScientificPoints(SPEC_PTS_QUARK_GLUON_CORE_CONSUMPTION, data.realPtsQUARK_GLUON_CORE_CONSUMPTION);

	setRealScientificPoints(SPEC_PTS_NAVIGATION_COMPUTER_SPEED, data.realPtsNAVIGATION_COMPUTER_SPEED);

    setRealScientificPoints(SPEC_PTS_SUBSPACE_BEACON_SPEED, data.realPtsSUBSPACE_BEACON_SPEED);

    setRealScientificPoints(SPEC_PTS_INERTIAL_DAMPERS_SPEED, data.realPtsINERTIAL_DAMPERS_SPEED);

    setRealScientificPoints(SPEC_PTS_IMPULS_ENGINE_FORCE, data.realPtsIMPULS_ENGINE_FORCE);
    setRealScientificPoints(SPEC_PTS_IMPULS_ENGINE_CONSUMPTION, data.realPtsIMPULS_ENGINE_CONSUMPTION);

    setRealScientificPoints(SPEC_PTS_MECHANICAL_DAMPERS_ACCELERATION, data.realPtsMECHANICAL_DAMPERS_ACCELERATION);

    setRealScientificPoints(SPEC_PTS_DRONE_MISSILES_DAMAGE, data.realPtsDRONE_MISSILES_DAMAGE);
    setRealScientificPoints(SPEC_PTS_DRONE_MISSILES_PRECISION, data.realPtsDRONE_MISSILES_PRECISION);
    setRealScientificPoints(SPEC_PTS_DRONE_MISSILES_RANGE, data.realPtsDRONE_MISSILES_RANGE);

    setRealScientificPoints(SPEC_PTS_DRONE_MISSILE_LAUNCHER_ACCUMULATOR, data.realPtsDRONE_MISSILE_LAUNCHER_ACCUMULATOR);
    setRealScientificPoints(SPEC_PTS_DRONE_MISSILE_LAUNCHER_CHARGING, data.realPtsDRONE_MISSILE_LAUNCHER_CHARGING);

    setRealScientificPoints(SPEC_PTS_SHIPS_LEVEL, data.realPtsSHIPS_LEVEL);

    setRealScientificPoints(SPEC_PTS_BASES_LEVEL, data.realPtsBASES_LEVEL);

    setRealScientificPoints(SPEC_PTS_HANGARS_LEVEL, data.realPtsHANGARS_LEVEL);

    setRealScientificPoints(SPEC_PTS_ANDROIDS_LEVEL, data.realPtsANDROIDS_LEVEL);
    setRealScientificPoints(SPEC_PTS_ANDROIDS_CONSUMPTION, data.realPtsANDROIDS_CONSUMPTION);

    setRealScientificPoints(SPEC_PTS_ENERGETIC_ACCUMULATOR_ACCUMULATOR, data.realPtsENERGETIC_ACCUMULATOR_ACCUMULATOR);
    setRealScientificPoints(SPEC_PTS_ENERGETIC_ACCUMULATOR_CHARGING, data.realPtsENERGETIC_ACCUMULATOR_CHARGING);

    setRealScientificPoints(SPEC_PTS_MAINFRAME_BIO_NODES, data.realPtsMAINFRAME_BIO_NODES);
    setRealScientificPoints(SPEC_PTS_MAINFRAME_PREDICTION, data.realPtsMAINFRAME_PREDICTION);
    setRealScientificPoints(SPEC_PTS_MAINFRAME_TIME_REUSABILITY, data.realPtsMAINFRAME_TIME_REUSABILITY);
    setRealScientificPoints(SPEC_PTS_MAINFRAME_CONSUMPTION, data.realPtsMAINFRAME_CONSUMPTION);

    setRealScientificPoints(SPEC_PTS_SCIENTIFIC_LABS_LEVEL, data.realPtsSCIENTIFIC_LABS_LEVEL);

    setRealScientificPoints(SPEC_PTS_LIFE_SUPPORT_CAPACITY, data.realPtsLIFE_SUPPORT_CAPACITY);
    setRealScientificPoints(SPEC_PTS_LIFE_SUPPORT_CONSUMPTION, data.realPtsLIFE_SUPPORT_CONSUMPTION);

    setRealScientificPoints(SPEC_PTS_WEAPON_ENERGY_CIRCUIT_CHARGING, data.realPtsWEAPON_ENERGY_CIRCUIT_CHARGING);

    setRealScientificPoints(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_ACCUMULATOR, data.realPtsTRANSPORT_BEAM_GENERATOR_ACCUMULATOR);
    setRealScientificPoints(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_CHARGING, data.realPtsTRANSPORT_BEAM_GENERATOR_CHARGING);
    setRealScientificPoints(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_FORCIBILITY, data.realPtsTRANSPORT_BEAM_GENERATOR_FORCIBILITY);
    setRealScientificPoints(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_PRECISION, data.realPtsTRANSPORT_BEAM_GENERATOR_PRECISION);
    setRealScientificPoints(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_RANGE, data.realPtsTRANSPORT_BEAM_GENERATOR_RANGE);

    setRealScientificPoints(SPEC_PTS_LASER_GUN_ACCUMULATOR, data.realPtsLASER_GUN_ACCUMULATOR);
    setRealScientificPoints(SPEC_PTS_LASER_GUN_CHARGING, data.realPtsLASER_GUN_CHARGING);
    setRealScientificPoints(SPEC_PTS_LASER_GUN_FORCIBILITY, data.realPtsLASER_GUN_FORCIBILITY);
    setRealScientificPoints(SPEC_PTS_LASER_GUN_PRECISION, data.realPtsLASER_GUN_PRECISION);
    setRealScientificPoints(SPEC_PTS_LASER_GUN_RANGE, data.realPtsLASER_GUN_RANGE);

    setRealScientificPoints(SPEC_PTS_DEFLECTOR_SHIELDS_GENERATOR_SOLIDITY, data.realPtsDEFLECTOR_SHIELDS_GENERATOR_SOLIDITY);
    setRealScientificPoints(SPEC_PTS_DEFLECTOR_SHIELDS_GENERATOR_ACCUMULATOR, data.realPtsDEFLECTOR_SHIELDS_GENERATOR_ACCUMULATOR);
    setRealScientificPoints(SPEC_PTS_DEFLECTOR_SHIELDS_GENERATOR_CHARGING, data.realPtsDEFLECTOR_SHIELDS_GENERATOR_CHARGING);

    setRealScientificPoints(SPEC_PTS_HIGH_RESOLUTION_SENSORS_LEVEL, data.realPtsHIGH_RESOLUTION_SENSORS_LEVEL);
    setRealScientificPoints(SPEC_PTS_HIGH_RESOLUTION_SENSORS_RANGE, data.realPtsHIGH_RESOLUTION_SENSORS_RANGE);
    setRealScientificPoints(SPEC_PTS_HIGH_RESOLUTION_SENSORS_CONSUMPTION, data.realPtsHIGH_RESOLUTION_SENSORS_CONSUMPTION);

    setRealScientificPoints(SPEC_PTS_LONG_RANGE_SENSORS_LEVEL, data.realPtsLONG_RANGE_SENSORS_LEVEL);
    setRealScientificPoints(SPEC_PTS_LONG_RANGE_SENSORS_RANGE, data.realPtsLONG_RANGE_SENSORS_RANGE);
    setRealScientificPoints(SPEC_PTS_LONG_RANGE_SENSORS_CONSUMPTION, data.realPtsLONG_RANGE_SENSORS_CONSUMPTION);

    setRealScientificPoints(SPEC_PTS_CLOAKING_DEVICE_LEVEL, data.realPtsCLOAKING_DEVICE_LEVEL);
    setRealScientificPoints(SPEC_PTS_CLOAKING_DEVICE_CONSUMPTION, data.realPtsCLOAKING_DEVICE_CONSUMPTION);

    setRealScientificPoints(SPEC_PTS_PROBE_DEVICE_LEVEL, data.realPtsPROBE_DEVICE_LEVEL);

    setRealScientificPoints(SPEC_PTS_MAGNETICAL_FILTER_PRODUCTION, data.realPtsMAGNETICAL_FILTER_PRODUCTION);

    setRealScientificPoints(SPEC_PTS_DEUTERIUM_DECOMPOSER_PRODUCTION, data.realPtsDEUTERIUM_DECOMPOSER_PRODUCTION);
    setRealScientificPoints(SPEC_PTS_DEUTERIUM_DECOMPOSER_METAMORPHOSIS, data.realPtsDEUTERIUM_DECOMPOSER_METAMORPHOSIS);

    setRealScientificPoints(SPEC_PTS_ZIRCONIUM_REACTOR_PRODUCTION, data.realPtsZIRCONIUM_REACTOR_PRODUCTION);
    setRealScientificPoints(SPEC_PTS_ZIRCONIUM_REACTOR_METAMORPHOSIS, data.realPtsZIRCONIUM_REACTOR_METAMORPHOSIS);

    setRealScientificPoints(SPEC_PTS_ILMENITE_FURNACE_PRODUCTION, data.realPtsILMENITE_FURNACE_PRODUCTION);
    setRealScientificPoints(SPEC_PTS_ILMENITE_FURNACE_METAMORPHOSIS, data.realPtsILMENITE_FURNACE_METAMORPHOSIS);

    setRealScientificPoints(SPEC_PTS_MAGNETICAL_COLLECTORS_OF_PLASMA_WINDING_SPEED, data.realPtsMAGNETICAL_COLLECTORS_OF_PLASMA_WINDING_SPEED);

    setRealScientificPoints(SPEC_PTS_SUBMERSIBLE_FILTRATION_TANK_WINDING_SPEED, data.realPtsSUBMERSIBLE_FILTRATION_TANK_WINDING_SPEED);
    setRealScientificPoints(SPEC_PTS_SUBMERSIBLE_FILTRATION_TANK_RANGE, data.realPtsSUBMERSIBLE_FILTRATION_TANK_RANGE);

    setRealScientificPoints(SPEC_PTS_SUBMARINE_MINING_MACHINE_WINDING_SPEED, data.realPtsSUBMARINE_MINING_MACHINE_WINDING_SPEED);
    setRealScientificPoints(SPEC_PTS_SUBMARINE_MINING_MACHINE_RANGE, data.realPtsSUBMARINE_MINING_MACHINE_RANGE);

    setRealScientificPoints(SPEC_PTS_UNDERGROUND_DRILLING_MACHINE_WINDING_SPEED, data.realPtsUNDERGROUND_QUARRYING_WINDING_SPEED);
    setRealScientificPoints(SPEC_PTS_UNDERGROUND_DRILLING_MACHINE_RANGE, data.realPtsUNDERGROUND_QUARRYING_RANGE); 

	setupNodeWidget(selectedNode_);
}

sciencetree_raw_data ScienceTree::getState() {
	sciencetree_raw_data data;

	/* Tokens */

    data.tokensSCIENCE_ENTITY_SHIPS = getNodeTokens(TOKENS_SCIENCE_ENTITY_SHIPS);
    data.tokensSCIENCE_ENTITY_BASES = getNodeTokens(TOKENS_SCIENCE_ENTITY_BASES);
    data.tokensSCIENCE_ENTITY_ENERGETIC_ACCUMULATOR = getNodeTokens(TOKENS_SCIENCE_ENTITY_ENERGETIC_ACCUMULATOR);
	data.tokensSCIENCE_ENTITY_NAVIGATION_COMPUTER = getNodeTokens(TOKENS_SCIENCE_ENTITY_NAVIGATION_COMPUTER);
    data.tokensSCIENCE_ENTITY_QUARK_GLUON_CORE = getNodeTokens(TOKENS_SCIENCE_ENTITY_QUARK_GLUON_CORE);
    data.tokensSCIENCE_ENTITY_SUBSPACE_BEACON = getNodeTokens(TOKENS_SCIENCE_ENTITY_SUBSPACE_BEACON);
    data.tokensSCIENCE_ENTITY_INERTIAL_DAMPERS = getNodeTokens(TOKENS_SCIENCE_ENTITY_INERTIAL_DAMPERS);
    data.tokensSCIENCE_ENTITY_IMPULS_JET_ENGINE = getNodeTokens(TOKENS_SCIENCE_ENTITY_IMPULS_JET_ENGINE);
    data.tokensSCIENCE_ENTITY_MECHANICAL_DAMPERS = getNodeTokens(TOKENS_SCIENCE_ENTITY_MECHANICAL_DAMPERS);
    data.tokensSCIENCE_ENTITY_DEFLECTOR_SHIELDS = getNodeTokens(TOKENS_SCIENCE_ENTITY_DEFLECTOR_SHIELDS);
    data.tokensSCIENCE_ENTITY_WEAPON_ENERGY_CIRCUIT = getNodeTokens(TOKENS_SCIENCE_ENTITY_WEAPON_ENERGY_CIRCUIT);
    data.tokensSCIENCE_ENTITY_DRONE_MISSILE_LAUNCHER = getNodeTokens(TOKENS_SCIENCE_ENTITY_DRONE_MISSILE_LAUNCHER);
    data.tokensSCIENCE_ENTITY_DRONE_MISSILES = getNodeTokens(TOKENS_SCIENCE_ENTITY_DRONE_MISSILES );
    data.tokensSCIENCE_ENTITY_LASER_GUN = getNodeTokens(TOKENS_SCIENCE_ENTITY_LASER_GUN);
    data.tokensSCIENCE_ENTITY_TRANSPORT_BEAM_GENERATOR = getNodeTokens(TOKENS_SCIENCE_ENTITY_TRANSPORT_BEAM_GENERATOR);
    data.tokensSCIENCE_ENTITY_MAGNETICAL_COLLECTORS_OF_PLASMA = getNodeTokens(TOKENS_SCIENCE_ENTITY_MAGNETICAL_COLLECTORS_OF_PLASMA);
    data.tokensSCIENCE_ENTITY_SUBMERSIBLE_FILTRATION_TANK = getNodeTokens(TOKENS_SCIENCE_ENTITY_SUBMERSIBLE_FILTRATION_TANK);
    data.tokensSCIENCE_ENTITY_SUBMARINE_MINING_MACHINE = getNodeTokens(TOKENS_SCIENCE_ENTITY_SUBMARINE_MINING_MACHINE);
    data.tokensSCIENCE_ENTITY_UNDERGROUND_DRILLING_MACHINE = getNodeTokens(TOKENS_SCIENCE_ENTITY_UNDERGROUND_DRILLING_MACHINE);
    data.tokensSCIENCE_ENTITY_PROBE = getNodeTokens(TOKENS_SCIENCE_ENTITY_PROBE);
    data.tokensSCIENCE_ENTITY_HIGH_RESOLUTION_SENSORS = getNodeTokens(TOKENS_SCIENCE_ENTITY_HIGH_RESOLUTION_SENSORS);
    data.tokensSCIENCE_ENTITY_LONG_RANGE_SENSORS = getNodeTokens(TOKENS_SCIENCE_ENTITY_LONG_RANGE_SENSORS);
    data.tokensSCIENCE_ENTITY_CLOAKING_DEVICE = getNodeTokens(TOKENS_SCIENCE_ENTITY_CLOAKING_DEVICE );
    data.tokensSCIENCE_ENTITY_ANDROIDS = getNodeTokens(TOKENS_SCIENCE_ENTITY_ANDROIDS);
    data.tokensSCIENCE_ENTITY_SCIENTIFIC_LAB = getNodeTokens(TOKENS_SCIENCE_ENTITY_SCIENTIFIC_LAB);
    data.tokensSCIENCE_ENTITY_LIFE_SUPPORT = getNodeTokens(TOKENS_SCIENCE_ENTITY_LIFE_SUPPORT);
    data.tokensSCIENCE_ENTITY_MAINFRAME = getNodeTokens(TOKENS_SCIENCE_ENTITY_MAINFRAME);
    data.tokensSCIENCE_ENTITY_HANGAR = getNodeTokens(TOKENS_SCIENCE_ENTITY_HANGAR);
    data.tokensSCIENCE_ENTITY_MAGNETICAL_FILTER = getNodeTokens(TOKENS_SCIENCE_ENTITY_MAGNETICAL_FILTER );
    data.tokensSCIENCE_ENTITY_DEUTERIUM_DECOMPOSER = getNodeTokens(TOKENS_SCIENCE_ENTITY_DEUTERIUM_DECOMPOSER);
    data.tokensSCIENCE_ENTITY_ZIRCONIUM_REACTOR = getNodeTokens(TOKENS_SCIENCE_ENTITY_ZIRCONIUM_REACTOR);
    data.tokensSCIENCE_ENTITY_ILMENITE_FURNACE = getNodeTokens(TOKENS_SCIENCE_ENTITY_ILMENITE_FURNACE);

    data.tokensSCIENCE_SUPREME_ENTITY_SCIENCE = getNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_SCIENCE);

    data.tokensSCIENCE_SUPREME_ENTITY_DRIVE = getNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_DRIVE);
    data.tokensSCIENCE_SUPREME_ENTITY_PLATFORM = getNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_PLATFORM);
    data.tokensSCIENCE_SUPREME_ENTITY_MODULES = getNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_MODULES);
    data.tokensSCIENCE_SUPREME_ENTITY_PRODUCTION = getNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_PRODUCTION);

    data.tokensSCIENCE_SUPREME_ENTITY_SUBSPACE_DRIVE = getNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_SUBSPACE_DRIVE);
    data.tokensSCIENCE_SUPREME_ENTITY_IMPULS_DRIVE = getNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_IMPULS_DRIVE);
    data.tokensSCIENCE_SUPREME_ENTITY_CONSTRUCTION = getNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_CONSTRUCTION);
    data.tokensSCIENCE_SUPREME_ENTITY_EQUIPMENT = getNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_EQUIPMENT);
    data.tokensSCIENCE_SUPREME_ENTITY_ENERGETIC_RING = getNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_ENERGETIC_RING);
    data.tokensSCIENCE_SUPREME_ENTITY_RECOGNITION_DEVICES = getNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_RECOGNITION_DEVICES);
    data.tokensSCIENCE_SUPREME_ENTITY_FACTORIES = getNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_FACTORIES);
    data.tokensSCIENCE_SUPREME_ENTITY_QUARRYING_MACHINES = getNodeTokens(TOKENS_SCIENCE_SUPREME_ENTITY_QUARRYING_MACHINES);

	/** Special points (percents) */

	data.specPtsQUARK_GLUON_CORE_SPEED = getSciencePoints(SPEC_PTS_QUARK_GLUON_CORE_SPEED);
    data.specPtsQUARK_GLUON_CORE_CONSUMPTION = getSciencePoints(SPEC_PTS_QUARK_GLUON_CORE_CONSUMPTION);

	data.specPtsNAVIGATION_COMPUTER_SPEED = getSciencePoints(SPEC_PTS_NAVIGATION_COMPUTER_SPEED);

    data.specPtsSUBSPACE_BEACON_SPEED = getSciencePoints(SPEC_PTS_SUBSPACE_BEACON_SPEED);

    data.specPtsINERTIAL_DAMPERS_SPEED = getSciencePoints(SPEC_PTS_INERTIAL_DAMPERS_SPEED);

    data.specPtsIMPULS_ENGINE_FORCE = getSciencePoints(SPEC_PTS_IMPULS_ENGINE_FORCE);
    data.specPtsIMPULS_ENGINE_CONSUMPTION = getSciencePoints(SPEC_PTS_IMPULS_ENGINE_CONSUMPTION);

    data.specPtsMECHANICAL_DAMPERS_ACCELERATION = getSciencePoints(SPEC_PTS_MECHANICAL_DAMPERS_ACCELERATION);

    data.specPtsDRONE_MISSILES_DAMAGE = getSciencePoints(SPEC_PTS_DRONE_MISSILES_DAMAGE);
    data.specPtsDRONE_MISSILES_PRECISION = getSciencePoints(SPEC_PTS_DRONE_MISSILES_PRECISION);
    data.specPtsDRONE_MISSILES_RANGE = getSciencePoints(SPEC_PTS_DRONE_MISSILES_RANGE);

    data.specPtsDRONE_MISSILE_LAUNCHER_ACCUMULATOR = getSciencePoints(SPEC_PTS_DRONE_MISSILE_LAUNCHER_ACCUMULATOR);
    data.specPtsDRONE_MISSILE_LAUNCHER_CHARGING = getSciencePoints(SPEC_PTS_DRONE_MISSILE_LAUNCHER_CHARGING);

    data.specPtsSHIPS_LEVEL = getSciencePoints(SPEC_PTS_SHIPS_LEVEL);

    data.specPtsBASES_LEVEL = getSciencePoints(SPEC_PTS_BASES_LEVEL);

    data.specPtsHANGARS_LEVEL = getSciencePoints(SPEC_PTS_HANGARS_LEVEL);

    data.specPtsANDROIDS_LEVEL = getSciencePoints(SPEC_PTS_ANDROIDS_LEVEL);
    data.specPtsANDROIDS_CONSUMPTION = getSciencePoints(SPEC_PTS_ANDROIDS_CONSUMPTION);

    data.specPtsENERGETIC_ACCUMULATOR_ACCUMULATOR = getSciencePoints(SPEC_PTS_ENERGETIC_ACCUMULATOR_ACCUMULATOR);
    data.specPtsENERGETIC_ACCUMULATOR_CHARGING = getSciencePoints(SPEC_PTS_ENERGETIC_ACCUMULATOR_CHARGING);

    data.specPtsMAINFRAME_BIO_NODES = getSciencePoints(SPEC_PTS_MAINFRAME_BIO_NODES);
    data.specPtsMAINFRAME_PREDICTION = getSciencePoints(SPEC_PTS_MAINFRAME_PREDICTION);
    data.specPtsMAINFRAME_TIME_REUSABILITY = getSciencePoints(SPEC_PTS_MAINFRAME_TIME_REUSABILITY);
    data.specPtsMAINFRAME_CONSUMPTION = getSciencePoints(SPEC_PTS_MAINFRAME_CONSUMPTION);

    data.specPtsSCIENTIFIC_LABS_LEVEL = getSciencePoints(SPEC_PTS_SCIENTIFIC_LABS_LEVEL);

    data.specPtsLIFE_SUPPORT_CAPACITY = getSciencePoints(SPEC_PTS_LIFE_SUPPORT_CAPACITY);
    data.specPtsLIFE_SUPPORT_CONSUMPTION = getSciencePoints(SPEC_PTS_LIFE_SUPPORT_CONSUMPTION);

    data.specPtsWEAPON_ENERGY_CIRCUIT_CHARGING = getSciencePoints(SPEC_PTS_WEAPON_ENERGY_CIRCUIT_CHARGING);

    data.specPtsTRANSPORT_BEAM_GENERATOR_ACCUMULATOR = getSciencePoints(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_ACCUMULATOR);
    data.specPtsTRANSPORT_BEAM_GENERATOR_CHARGING = getSciencePoints(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_CHARGING);
    data.specPtsTRANSPORT_BEAM_GENERATOR_FORCIBILITY = getSciencePoints(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_FORCIBILITY);
    data.specPtsTRANSPORT_BEAM_GENERATOR_PRECISION = getSciencePoints(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_PRECISION);
    data.specPtsTRANSPORT_BEAM_GENERATOR_RANGE = getSciencePoints(SPEC_PTS_TRANSPORT_BEAM_GENERATOR_RANGE);

    data.specPtsLASER_GUN_ACCUMULATOR = getSciencePoints(SPEC_PTS_LASER_GUN_ACCUMULATOR);
    data.specPtsLASER_GUN_CHARGING = getSciencePoints(SPEC_PTS_LASER_GUN_CHARGING);
    data.specPtsLASER_GUN_FORCIBILITY = getSciencePoints(SPEC_PTS_LASER_GUN_FORCIBILITY);
    data.specPtsLASER_GUN_PRECISION = getSciencePoints(SPEC_PTS_LASER_GUN_PRECISION);
    data.specPtsLASER_GUN_RANGE = getSciencePoints(SPEC_PTS_LASER_GUN_RANGE);

    data.specPtsDEFLECTOR_SHIELDS_GENERATOR_SOLIDITY = getSciencePoints(SPEC_PTS_DEFLECTOR_SHIELDS_GENERATOR_SOLIDITY);
    data.specPtsDEFLECTOR_SHIELDS_GENERATOR_ACCUMULATOR = getSciencePoints(SPEC_PTS_DEFLECTOR_SHIELDS_GENERATOR_ACCUMULATOR);
    data.specPtsDEFLECTOR_SHIELDS_GENERATOR_CHARGING = getSciencePoints(SPEC_PTS_DEFLECTOR_SHIELDS_GENERATOR_CHARGING);

    data.specPtsHIGH_RESOLUTION_SENSORS_LEVEL = getSciencePoints(SPEC_PTS_HIGH_RESOLUTION_SENSORS_LEVEL);
    data.specPtsHIGH_RESOLUTION_SENSORS_RANGE = getSciencePoints(SPEC_PTS_HIGH_RESOLUTION_SENSORS_RANGE);
    data.specPtsHIGH_RESOLUTION_SENSORS_CONSUMPTION = getSciencePoints(SPEC_PTS_HIGH_RESOLUTION_SENSORS_CONSUMPTION);

    data.specPtsLONG_RANGE_SENSORS_LEVEL = getSciencePoints(SPEC_PTS_LONG_RANGE_SENSORS_LEVEL);
    data.specPtsLONG_RANGE_SENSORS_RANGE = getSciencePoints(SPEC_PTS_LONG_RANGE_SENSORS_RANGE);
    data.specPtsLONG_RANGE_SENSORS_CONSUMPTION = getSciencePoints(SPEC_PTS_LONG_RANGE_SENSORS_CONSUMPTION);

    data.specPtsCLOAKING_DEVICE_LEVEL = getSciencePoints(SPEC_PTS_CLOAKING_DEVICE_LEVEL);
    data.specPtsCLOAKING_DEVICE_CONSUMPTION = getSciencePoints(SPEC_PTS_CLOAKING_DEVICE_CONSUMPTION);

    data.specPtsPROBE_DEVICE_LEVEL = getSciencePoints(SPEC_PTS_PROBE_DEVICE_LEVEL);

    data.specPtsMAGNETICAL_FILTER_PRODUCTION = getSciencePoints(SPEC_PTS_MAGNETICAL_FILTER_PRODUCTION);

    data.specPtsDEUTERIUM_DECOMPOSER_PRODUCTION = getSciencePoints(SPEC_PTS_DEUTERIUM_DECOMPOSER_PRODUCTION);
    data.specPtsDEUTERIUM_DECOMPOSER_METAMORPHOSIS = getSciencePoints(SPEC_PTS_DEUTERIUM_DECOMPOSER_METAMORPHOSIS);

    data.specPtsZIRCONIUM_REACTOR_PRODUCTION = getSciencePoints(SPEC_PTS_ZIRCONIUM_REACTOR_PRODUCTION);
    data.specPtsZIRCONIUM_REACTOR_METAMORPHOSIS = getSciencePoints(SPEC_PTS_ZIRCONIUM_REACTOR_METAMORPHOSIS);

    data.specPtsILMENITE_FURNACE_PRODUCTION = getSciencePoints(SPEC_PTS_ILMENITE_FURNACE_PRODUCTION);
    data.specPtsILMENITE_FURNACE_METAMORPHOSIS = getSciencePoints(SPEC_PTS_ILMENITE_FURNACE_METAMORPHOSIS);

    data.specPtsMAGNETICAL_COLLECTORS_OF_PLASMA_WINDING_SPEED = getSciencePoints(SPEC_PTS_MAGNETICAL_COLLECTORS_OF_PLASMA_WINDING_SPEED);

    data.specPtsSUBMERSIBLE_FILTRATION_TANK_WINDING_SPEED = getSciencePoints(SPEC_PTS_SUBMERSIBLE_FILTRATION_TANK_WINDING_SPEED);
    data.specPtsSUBMERSIBLE_FILTRATION_TANK_RANGE = getSciencePoints(SPEC_PTS_SUBMERSIBLE_FILTRATION_TANK_RANGE);

    data.specPtsSUBMARINE_MINING_MACHINE_WINDING_SPEED = getSciencePoints(SPEC_PTS_SUBMARINE_MINING_MACHINE_WINDING_SPEED);
    data.specPtsSUBMARINE_MINING_MACHINE_RANGE = getSciencePoints(SPEC_PTS_SUBMARINE_MINING_MACHINE_RANGE);

    data.specPtsUNDERGROUND_DRILLING_MACHINE_WINDING_SPEED = getSciencePoints(SPEC_PTS_UNDERGROUND_DRILLING_MACHINE_WINDING_SPEED);
    data.specPtsUNDERGROUND_DRILLING_MACHINE_RANGE = getSciencePoints(SPEC_PTS_UNDERGROUND_DRILLING_MACHINE_RANGE);   

	return data;
}