<commit_before>#include "gtest/gtest.h"
#include "ECSE/InputManager.h"

class InputManagerTest : public ::testing::Test
{
public:
    ECSE::InputManager manager;

    InputManagerTest()
    {
        manager.setRequireFocus(false);
    }
};

class InputManagerRunTest : public InputManagerTest
{
public:
    InputManagerRunTest()
    {
        resetValues();

        std::function<bool()> boolfn = []() { return false; };
        std::function<int()> intfn = []() { return 0; };
        std::function<float()> floatfn = []() { return 0.0f; };

        manager.bindInput(0, 0, boolfn);
        manager.bindInput(1, 0, intfn);
        manager.bindInput(2, 0, floatfn, 0.2f);

        manager.bindInput(0, 1, boolfn);
        manager.bindInput(1, 1, intfn);
        manager.bindInput(2, 1, floatfn, 0.4f);
    }

    void resetValues()
    {
        a = 0;
        b = 0;
        c = 0;
        d = 0;
    }

    void runLoop(int length)
    {
        for (int i = 0; i < length; ++i)
        {
            manager.update();

            bool anyPressed = false;
            if (manager.getIntValue(0) > 0)
            {
                a += 1;
                anyPressed = true;
            }

            if (manager.getFloatValue(1) >= 0.7)
            {
                b += 1;
                anyPressed = true;
            }

            if (manager.getIntValue(2) < 1)
            {
                c += 1;
                anyPressed = true;
            }

            if (!anyPressed)
            {
                d += 1;
            }
        }
    }

    int a, b, c, d;
};

TEST_F(InputManagerTest, TestIsBound)
{
    std::function<bool()> fn = []() { return false; };
    manager.bindInput(0, 0, fn);

    ASSERT_TRUE(manager.isBound(0));
}

TEST_F(InputManagerTest, TestBoolInput)
{
    bool value;

    std::function<bool()> fn = [&value]() { return value; };
    manager.bindInput(0, 0, fn);

    value = false;
    manager.update();

    ASSERT_EQ(0, manager.getIntValue(0));
    ASSERT_FLOAT_EQ(0.f, manager.getFloatValue(0));

    value = true;
    manager.update();

    ASSERT_EQ(1, manager.getIntValue(0));
    ASSERT_FLOAT_EQ(1.f, manager.getFloatValue(0));
}

TEST_F(InputManagerTest, TestIntInput)
{
    int value;

    std::function<int()> fn = [&value]() { return value; };
    manager.bindInput(0, 0, fn);

    value = 0;
    manager.update();

    ASSERT_EQ(0, manager.getIntValue(0));
    ASSERT_FLOAT_EQ(0.f, manager.getFloatValue(0));

    value = 1;
    manager.update();

    ASSERT_EQ(1, manager.getIntValue(0));
    ASSERT_FLOAT_EQ(1.f, manager.getFloatValue(0));

    value = -1;
    manager.update();

    ASSERT_EQ(-1, manager.getIntValue(0));
    ASSERT_FLOAT_EQ(-1.f, manager.getFloatValue(0));
}

TEST_F(InputManagerTest, TestFloatInput)
{
    float value;

    std::function<float()> fn = [&value]() { return value; };
    manager.bindInput(0, 0, fn);

    value = 0.f;
    manager.update();

    ASSERT_EQ(0, manager.getIntValue(0));
    ASSERT_FLOAT_EQ(0.f, manager.getFloatValue(0));

    value = 1.f;
    manager.update();

    ASSERT_EQ(1, manager.getIntValue(0));
    ASSERT_FLOAT_EQ(1.f, manager.getFloatValue(0));

    value = -1.f;
    manager.update();

    ASSERT_EQ(-1, manager.getIntValue(0));
    ASSERT_FLOAT_EQ(-1.f, manager.getFloatValue(0));
}

TEST_F(InputManagerTest, TestSensitivity)
{
    float value;
    float precision = 1 << ECSE_INPUT_PRECISION;

    std::function<float()> fn = [&value]() { return value; };
    manager.bindInput(0, 0, fn, 0.3f);

    value = 0.1f;
    manager.update();

    ASSERT_EQ(0, manager.getIntValue(0));
    ASSERT_NEAR(0.f, manager.getFloatValue(0), precision);

    value = 0.4f;
    manager.update();

    ASSERT_EQ(1, manager.getIntValue(0));
    ASSERT_NEAR(0.4f, manager.getFloatValue(0), precision);

    value = -0.4f;
    manager.update();

    ASSERT_EQ(-1, manager.getIntValue(0));
    ASSERT_NEAR(-0.4f, manager.getFloatValue(0), precision);
}

TEST_F(InputManagerTest, TestMultipleInputs)
{
    int val1, val2;

    std::function<int()> fn1 = [&val1]() { return val1; };
    manager.bindInput(0, 0, fn1);

    std::function<int()> fn2 = [&val2]() { return val2; };
    manager.bindInput(1, 0, fn2);

    val1 = 0;
    val2 = 0;
    manager.update();

    ASSERT_EQ(0, manager.getIntValue(0));
    ASSERT_EQ(0, manager.getIntValue(1));

    val1 = 1;
    val2 = 0;
    manager.update();

    ASSERT_EQ(1, manager.getIntValue(0));
    ASSERT_EQ(0, manager.getIntValue(1));

    val1 = 1;
    val2 = 1;
    manager.update();

    ASSERT_EQ(1, manager.getIntValue(0));
    ASSERT_EQ(1, manager.getIntValue(1));

    val1 = 0;
    val2 = 1;
    manager.update();

    ASSERT_EQ(0, manager.getIntValue(0));
    ASSERT_EQ(1, manager.getIntValue(1));
}

TEST_F(InputManagerTest, TestSwitchModes)
{
    int val1, val2;

    std::function<int()> fn1 = [&val1]() { return val1; };
    manager.bindInput(0, 0, fn1);

    std::function<int()> fn2 = [&val2]() { return val2; };
    manager.bindInput(0, 1, fn2);

    val1 = 0;
    val2 = 0;
    manager.update();

    manager.setInputMode(0);
    ASSERT_EQ(0, manager.getIntValue(0));
    manager.setInputMode(1);
    ASSERT_EQ(0, manager.getIntValue(0));

    val1 = 1;
    val2 = 0;
    manager.update();

    manager.setInputMode(0);
    ASSERT_EQ(1, manager.getIntValue(0));
    manager.setInputMode(1);
    ASSERT_EQ(0, manager.getIntValue(0));

    val1 = 1;
    val2 = 1;
    manager.update();

    manager.setInputMode(0);
    ASSERT_EQ(1, manager.getIntValue(0));
    manager.setInputMode(1);
    ASSERT_EQ(1, manager.getIntValue(0));

    val1 = 0;
    val2 = 1;
    manager.update();

    manager.setInputMode(0);
    ASSERT_EQ(0, manager.getIntValue(0));
    manager.setInputMode(1);
    ASSERT_EQ(1, manager.getIntValue(0));
}

TEST_F(InputManagerTest, TestMultipleModes)
{
    int val1, val2;

    std::function<int()> fn1 = [&val1]() { return val1; };
    manager.bindInput(0, 0, fn1);

    std::function<int()> fn2 = [&val2]() { return val2; };
    manager.bindInput(0, 1, fn2);

    val1 = 0;
    val2 = 0;
    manager.update();

    ASSERT_EQ(0, manager.getIntValue(0, 0));
    ASSERT_EQ(0, manager.getIntValue(0, 1));

    val1 = 1;
    val2 = 0;
    manager.update();

    ASSERT_EQ(1, manager.getIntValue(0, 0));
    ASSERT_EQ(0, manager.getIntValue(0, 1));

    val1 = 1;
    val2 = 1;
    manager.update();

    ASSERT_EQ(1, manager.getIntValue(0, 0));
    ASSERT_EQ(1, manager.getIntValue(0, 1));

    val1 = 0;
    val2 = 1;
    manager.update();

    ASSERT_EQ(0, manager.getIntValue(0, 0));
    ASSERT_EQ(1, manager.getIntValue(0, 1));
}

TEST_F(InputManagerRunTest, TestMonkey)
{
    manager.startMonkeyMode();
    runLoop(1000);

    // These always increase, so if the monkey is at all good at pressing buttons this should work
    ASSERT_FALSE(a == 0) << "Monkey may not be pressing buttons";
    ASSERT_FALSE(b == 0) << "Monkey may not be pressing buttons";
    ASSERT_FALSE(c == 0) << "Monkey may not be pressing buttons";

    // This should be pretty unlikely
    ASSERT_FALSE(a == b && b == c);
}

TEST_F(InputManagerRunTest, TestDemo)
{
    std::stringstream stream;

    manager.startMonkeyMode();
    manager.startRecording(stream);
    runLoop(1000);
    manager.stopRecording();
    manager.stopMonkeyMode();

    int prevA = a;
    int prevB = b;
    int prevC = c;
    int prevD = d;

    resetValues();
    manager.playDemo(stream);
    runLoop(1000);

    ASSERT_EQ(prevA, a);
    ASSERT_EQ(prevB, b);
    ASSERT_EQ(prevC, c);
    ASSERT_EQ(prevD, d);

    ASSERT_FALSE(manager.isPlayingDemo());
}

TEST_F(InputManagerRunTest, TestModeSwitchDemo)
{
    std::stringstream stream;

    manager.startMonkeyMode();
    manager.startRecording(stream);

    for (int i = 0; i < 100; ++i)
    {
        runLoop(10);

        if (rand() % 10 > 10)
        {
            manager.setInputMode(manager.getInputMode() == 0 ? 1 : 0);
        }
    }

    manager.stopRecording();
    manager.stopMonkeyMode();

    int prevA = a;
    int prevB = b;
    int prevC = c;
    int prevD = d;

    resetValues();
    manager.playDemo(stream);
    runLoop(1000);

    ASSERT_EQ(prevA, a);
    ASSERT_EQ(prevB, b);
    ASSERT_EQ(prevC, c);
    ASSERT_EQ(prevD, d);
}<commit_msg>Fixed a bug causing the mode switch test to not switch modes at all<commit_after>#include "gtest/gtest.h"
#include "ECSE/InputManager.h"

class InputManagerTest : public ::testing::Test
{
public:
    ECSE::InputManager manager;

    InputManagerTest()
    {
        manager.setRequireFocus(false);
    }
};

class InputManagerRunTest : public InputManagerTest
{
public:
    InputManagerRunTest()
    {
        resetValues();

        std::function<bool()> boolfn = []() { return false; };
        std::function<int()> intfn = []() { return 0; };
        std::function<float()> floatfn = []() { return 0.0f; };

        manager.bindInput(0, 0, boolfn);
        manager.bindInput(1, 0, intfn);
        manager.bindInput(2, 0, floatfn, 0.2f);

        manager.bindInput(0, 1, boolfn);
        manager.bindInput(1, 1, intfn);
        manager.bindInput(2, 1, floatfn, 0.4f);
    }

    void resetValues()
    {
        a = 0;
        b = 0;
        c = 0;
        d = 0;
    }

    void runLoop(int length)
    {
        for (int i = 0; i < length; ++i)
        {
            manager.update();

            bool anyPressed = false;
            if (manager.getIntValue(0) > 0)
            {
                a += 1;
                anyPressed = true;
            }

            if (manager.getFloatValue(1) >= 0.7)
            {
                b += 1;
                anyPressed = true;
            }

            if (manager.getIntValue(2) < 1)
            {
                c += 1;
                anyPressed = true;
            }

            if (!anyPressed)
            {
                d += 1;
            }
        }
    }

    int a, b, c, d;
};

TEST_F(InputManagerTest, TestIsBound)
{
    std::function<bool()> fn = []() { return false; };
    manager.bindInput(0, 0, fn);

    ASSERT_TRUE(manager.isBound(0));
}

TEST_F(InputManagerTest, TestBoolInput)
{
    bool value;

    std::function<bool()> fn = [&value]() { return value; };
    manager.bindInput(0, 0, fn);

    value = false;
    manager.update();

    ASSERT_EQ(0, manager.getIntValue(0));
    ASSERT_FLOAT_EQ(0.f, manager.getFloatValue(0));

    value = true;
    manager.update();

    ASSERT_EQ(1, manager.getIntValue(0));
    ASSERT_FLOAT_EQ(1.f, manager.getFloatValue(0));
}

TEST_F(InputManagerTest, TestIntInput)
{
    int value;

    std::function<int()> fn = [&value]() { return value; };
    manager.bindInput(0, 0, fn);

    value = 0;
    manager.update();

    ASSERT_EQ(0, manager.getIntValue(0));
    ASSERT_FLOAT_EQ(0.f, manager.getFloatValue(0));

    value = 1;
    manager.update();

    ASSERT_EQ(1, manager.getIntValue(0));
    ASSERT_FLOAT_EQ(1.f, manager.getFloatValue(0));

    value = -1;
    manager.update();

    ASSERT_EQ(-1, manager.getIntValue(0));
    ASSERT_FLOAT_EQ(-1.f, manager.getFloatValue(0));
}

TEST_F(InputManagerTest, TestFloatInput)
{
    float value;

    std::function<float()> fn = [&value]() { return value; };
    manager.bindInput(0, 0, fn);

    value = 0.f;
    manager.update();

    ASSERT_EQ(0, manager.getIntValue(0));
    ASSERT_FLOAT_EQ(0.f, manager.getFloatValue(0));

    value = 1.f;
    manager.update();

    ASSERT_EQ(1, manager.getIntValue(0));
    ASSERT_FLOAT_EQ(1.f, manager.getFloatValue(0));

    value = -1.f;
    manager.update();

    ASSERT_EQ(-1, manager.getIntValue(0));
    ASSERT_FLOAT_EQ(-1.f, manager.getFloatValue(0));
}

TEST_F(InputManagerTest, TestSensitivity)
{
    float value;
    float precision = 1 << ECSE_INPUT_PRECISION;

    std::function<float()> fn = [&value]() { return value; };
    manager.bindInput(0, 0, fn, 0.3f);

    value = 0.1f;
    manager.update();

    ASSERT_EQ(0, manager.getIntValue(0));
    ASSERT_NEAR(0.f, manager.getFloatValue(0), precision);

    value = 0.4f;
    manager.update();

    ASSERT_EQ(1, manager.getIntValue(0));
    ASSERT_NEAR(0.4f, manager.getFloatValue(0), precision);

    value = -0.4f;
    manager.update();

    ASSERT_EQ(-1, manager.getIntValue(0));
    ASSERT_NEAR(-0.4f, manager.getFloatValue(0), precision);
}

TEST_F(InputManagerTest, TestMultipleInputs)
{
    int val1, val2;

    std::function<int()> fn1 = [&val1]() { return val1; };
    manager.bindInput(0, 0, fn1);

    std::function<int()> fn2 = [&val2]() { return val2; };
    manager.bindInput(1, 0, fn2);

    val1 = 0;
    val2 = 0;
    manager.update();

    ASSERT_EQ(0, manager.getIntValue(0));
    ASSERT_EQ(0, manager.getIntValue(1));

    val1 = 1;
    val2 = 0;
    manager.update();

    ASSERT_EQ(1, manager.getIntValue(0));
    ASSERT_EQ(0, manager.getIntValue(1));

    val1 = 1;
    val2 = 1;
    manager.update();

    ASSERT_EQ(1, manager.getIntValue(0));
    ASSERT_EQ(1, manager.getIntValue(1));

    val1 = 0;
    val2 = 1;
    manager.update();

    ASSERT_EQ(0, manager.getIntValue(0));
    ASSERT_EQ(1, manager.getIntValue(1));
}

TEST_F(InputManagerTest, TestSwitchModes)
{
    int val1, val2;

    std::function<int()> fn1 = [&val1]() { return val1; };
    manager.bindInput(0, 0, fn1);

    std::function<int()> fn2 = [&val2]() { return val2; };
    manager.bindInput(0, 1, fn2);

    val1 = 0;
    val2 = 0;
    manager.update();

    manager.setInputMode(0);
    ASSERT_EQ(0, manager.getIntValue(0));
    manager.setInputMode(1);
    ASSERT_EQ(0, manager.getIntValue(0));

    val1 = 1;
    val2 = 0;
    manager.update();

    manager.setInputMode(0);
    ASSERT_EQ(1, manager.getIntValue(0));
    manager.setInputMode(1);
    ASSERT_EQ(0, manager.getIntValue(0));

    val1 = 1;
    val2 = 1;
    manager.update();

    manager.setInputMode(0);
    ASSERT_EQ(1, manager.getIntValue(0));
    manager.setInputMode(1);
    ASSERT_EQ(1, manager.getIntValue(0));

    val1 = 0;
    val2 = 1;
    manager.update();

    manager.setInputMode(0);
    ASSERT_EQ(0, manager.getIntValue(0));
    manager.setInputMode(1);
    ASSERT_EQ(1, manager.getIntValue(0));
}

TEST_F(InputManagerTest, TestMultipleModes)
{
    int val1, val2;

    std::function<int()> fn1 = [&val1]() { return val1; };
    manager.bindInput(0, 0, fn1);

    std::function<int()> fn2 = [&val2]() { return val2; };
    manager.bindInput(0, 1, fn2);

    val1 = 0;
    val2 = 0;
    manager.update();

    ASSERT_EQ(0, manager.getIntValue(0, 0));
    ASSERT_EQ(0, manager.getIntValue(0, 1));

    val1 = 1;
    val2 = 0;
    manager.update();

    ASSERT_EQ(1, manager.getIntValue(0, 0));
    ASSERT_EQ(0, manager.getIntValue(0, 1));

    val1 = 1;
    val2 = 1;
    manager.update();

    ASSERT_EQ(1, manager.getIntValue(0, 0));
    ASSERT_EQ(1, manager.getIntValue(0, 1));

    val1 = 0;
    val2 = 1;
    manager.update();

    ASSERT_EQ(0, manager.getIntValue(0, 0));
    ASSERT_EQ(1, manager.getIntValue(0, 1));
}

TEST_F(InputManagerRunTest, TestMonkey)
{
    manager.startMonkeyMode();
    runLoop(1000);

    // These always increase, so if the monkey is at all good at pressing buttons this should work
    ASSERT_FALSE(a == 0) << "Monkey may not be pressing buttons";
    ASSERT_FALSE(b == 0) << "Monkey may not be pressing buttons";
    ASSERT_FALSE(c == 0) << "Monkey may not be pressing buttons";

    // This should be pretty unlikely
    ASSERT_FALSE(a == b && b == c);
}

TEST_F(InputManagerRunTest, TestDemo)
{
    std::stringstream stream;

    manager.startMonkeyMode();
    manager.startRecording(stream);
    runLoop(1000);
    manager.stopRecording();
    manager.stopMonkeyMode();

    int prevA = a;
    int prevB = b;
    int prevC = c;
    int prevD = d;

    resetValues();
    manager.playDemo(stream);
    runLoop(1000);

    ASSERT_EQ(prevA, a);
    ASSERT_EQ(prevB, b);
    ASSERT_EQ(prevC, c);
    ASSERT_EQ(prevD, d);

    ASSERT_FALSE(manager.isPlayingDemo());
}

TEST_F(InputManagerRunTest, TestModeSwitchDemo)
{
    std::stringstream stream;

    manager.startMonkeyMode();
    manager.startRecording(stream);

    for (int i = 0; i < 100; ++i)
    {
        runLoop(10);

        if (rand() % 100 > 90)
        {
            manager.setInputMode(manager.getInputMode() == 0 ? 1 : 0);
        }
    }

    manager.stopRecording();
    manager.stopMonkeyMode();

    int prevA = a;
    int prevB = b;
    int prevC = c;
    int prevD = d;

    resetValues();
    manager.playDemo(stream);
    runLoop(1000);

    ASSERT_EQ(prevA, a);
    ASSERT_EQ(prevB, b);
    ASSERT_EQ(prevC, c);
    ASSERT_EQ(prevD, d);
}<|endoftext|>


<commit_before>/*
* Copyright 2010-2011 Research In Motion Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "stdafx.h"
#include "BuildServerManager.h"
#include "PortScanner.h"
#ifdef Q_WS_WIN
#include <windows.h>
#endif

BuildServerManager* BuildServerManager::_instance = 0;

BuildServerManager::BuildServerManager()
{
    _serverProcess = new QProcess(this);
    connect(_serverProcess, SIGNAL(started()), this, SLOT(serverStarted()));
    connect(_serverProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(onError(QProcess::ProcessError)));
    connect(_serverProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutput()));
    connect(_serverProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdError()));
}

BuildServerManager::~BuildServerManager(void)
{
}

BuildServerManager* BuildServerManager::getInstance()
{
    if ( _instance == 0 )
        _instance = new BuildServerManager();
    return _instance;
}

unsigned short BuildServerManager::start(QString server, int port)
{
    unsigned short serverPort = 0;
    QStringList arguments = server.split(" ");
    QString portStr;

    portStr.setNum(validatePort(port));
    arguments.replaceInStrings(QString("$PORT"), portStr);

    QFile command(server);

    server = arguments[0];
    QDir dir = server;
    server = dir.absolutePath();
    arguments.removeAt(0);
    arguments.join("");
#ifdef Q_WS_WIN
    server.append(".exe");
#endif

    QString tempDir = "/tmp";

#ifdef Q_WS_WIN
    tempDir = getenv("TEMP");
#endif

    QFile pidFile(tempDir + QString("/rbd_service.pid"));

    if (pidFile.open(QIODevice::ReadWrite | QIODevice::Text))
    {
        QString s_pidInfo = pidFile.readLine();

        if (s_pidInfo.split(";").length() > 1)
            serverPort = s_pidInfo.split(";")[1].toUInt();

        unsigned int pid = s_pidInfo.split(";")[0].toUInt();
#ifdef Q_WS_WIN
        HANDLE process = OpenProcess(SYNCHRONIZE, FALSE, pid);
        CloseHandle(process);
#else
        process = 0; // port is free, launch new proces
#endif
        if (process == 0)
        {
            _serverProcess->start(server, arguments);
            pidFile.close();
            pidFile.open(QIODevice::WriteOnly | QIODevice::Text);
            QString pidInfo = QString::number((int)_serverProcess->pid()) + ";" + portStr;
            pidFile.write(pidInfo.toAscii());
            pidFile.close();
        }
    }

    return serverPort;
}

void BuildServerManager::stop()
{
    if ( _serverProcess )
        _serverProcess->close();
    delete _instance;
    _instance = 0;
}

int BuildServerManager::validatePort(int port)
{
    PortScanner scanner;
    int usablePort = scanner.findUsablePort( (unsigned short)port);
    emit findUsablePort(usablePort);
    return usablePort;
}

void BuildServerManager::serverStarted()
{
    qDebug() << "Build Server started";
}

void BuildServerManager::onError(QProcess::ProcessError err)
{
    if ( err == QProcess::Crashed )
        qDebug() << "Server is killed by Ripple";
    else
        qDebug() << "Build Server can not be started. Error code: " << err;
}

void BuildServerManager::readStdOutput()
{
    qDebug() << _serverProcess->readAllStandardOutput();
}

void BuildServerManager::readStdError()
{
    qDebug() << _serverProcess->readAllStandardError();
}<commit_msg>Fixed compile error again<commit_after>/*
* Copyright 2010-2011 Research In Motion Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "stdafx.h"
#include "BuildServerManager.h"
#include "PortScanner.h"
#ifdef Q_WS_WIN
#include <windows.h>
#endif

BuildServerManager* BuildServerManager::_instance = 0;

BuildServerManager::BuildServerManager()
{
    _serverProcess = new QProcess(this);
    connect(_serverProcess, SIGNAL(started()), this, SLOT(serverStarted()));
    connect(_serverProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(onError(QProcess::ProcessError)));
    connect(_serverProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutput()));
    connect(_serverProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStdError()));
}

BuildServerManager::~BuildServerManager(void)
{
}

BuildServerManager* BuildServerManager::getInstance()
{
    if ( _instance == 0 )
        _instance = new BuildServerManager();
    return _instance;
}

unsigned short BuildServerManager::start(QString server, int port)
{
    unsigned short serverPort = 0;
    QStringList arguments = server.split(" ");
    QString portStr;

    portStr.setNum(validatePort(port));
    arguments.replaceInStrings(QString("$PORT"), portStr);

    QFile command(server);

    server = arguments[0];
    QDir dir = server;
    server = dir.absolutePath();
    arguments.removeAt(0);
    arguments.join("");
#ifdef Q_WS_WIN
    server.append(".exe");
#endif

    QString tempDir = "/tmp";

#ifdef Q_WS_WIN
    tempDir = getenv("TEMP");
#endif

    QFile pidFile(tempDir + QString("/rbd_service.pid"));

    if (pidFile.open(QIODevice::ReadWrite | QIODevice::Text))
    {
        QString s_pidInfo = pidFile.readLine();

        if (s_pidInfo.split(";").length() > 1)
            serverPort = s_pidInfo.split(";")[1].toUInt();

        unsigned int pid = s_pidInfo.split(";")[0].toUInt();
#ifdef Q_WS_WIN
        HANDLE process = OpenProcess(SYNCHRONIZE, FALSE, pid);
        CloseHandle(process);
#else
        int process = 0; // port is free, launch new proces
#endif
        if (process == 0)
        {
            _serverProcess->start(server, arguments);
            pidFile.close();
            pidFile.open(QIODevice::WriteOnly | QIODevice::Text);
            QString pidInfo = QString::number((int)_serverProcess->pid()) + ";" + portStr;
            pidFile.write(pidInfo.toAscii());
            pidFile.close();
        }
    }

    return serverPort;
}

void BuildServerManager::stop()
{
    if ( _serverProcess )
        _serverProcess->close();
    delete _instance;
    _instance = 0;
}

int BuildServerManager::validatePort(int port)
{
    PortScanner scanner;
    int usablePort = scanner.findUsablePort( (unsigned short)port);
    emit findUsablePort(usablePort);
    return usablePort;
}

void BuildServerManager::serverStarted()
{
    qDebug() << "Build Server started";
}

void BuildServerManager::onError(QProcess::ProcessError err)
{
    if ( err == QProcess::Crashed )
        qDebug() << "Server is killed by Ripple";
    else
        qDebug() << "Build Server can not be started. Error code: " << err;
}

void BuildServerManager::readStdOutput()
{
    qDebug() << _serverProcess->readAllStandardOutput();
}

void BuildServerManager::readStdError()
{
    qDebug() << _serverProcess->readAllStandardError();
}<|endoftext|>


<commit_before>//---------------------------------*-C++-*-----------------------------------//
/*!
 * \file   MC/mc/KDE_Fission_Source.cc
 * \author Gregory G. Davidson
 * \date   Mon Nov 23 15:47:23 2015
 * \brief  KDE_Fission_Source class definitions.
 * \note   Copyright (c) 2015 Oak Ridge National Laboratory, UT-Battelle, LLC.
 */
//---------------------------------------------------------------------------//

#include "KDE_Fission_Source.hh"

#include "KDE_Kernel_Resample.hh"
#include "comm/Timing.hh"
#include "mc/Global_RNG.hh"

namespace profugus
{

//---------------------------------------------------------------------------//
// CONSTRUCTOR
//---------------------------------------------------------------------------//
/*!
 * \brief Constructor.
 */
KDE_Fission_Source::KDE_Fission_Source(RCP_Std_DB     db,
                                       SP_Geometry    geometry,
                                       SP_Physics     physics,
                                       SP_RNG_Control rng_control)
    : Base(db, geometry, physics, rng_control)
{
    REQUIRE(db.is_valid_ptr());
    REQUIRE(db->isType<std::string>("kernel_type"));

    // Get the type of KDE kernel
    const std::string &kernel_type = db->get<std::string>("kernel_type");

    // Get the bandwidth coefficient
    double coeff = db->get<double>("bnd_coeff", 1.06);
    double exponent = db->get<double>("bnd_exp", -0.20);

    if (kernel_type == "resample")
    {
        // Instantiate the resample kernel
        d_kernel = std::make_shared<KDE_Kernel_Resample>(geometry, physics,
                                                         coeff, exponent);
    }
    else
    {
        VALIDATE(false, "Unrecognized kernel type " << kernel_type);
    }

    ENSURE(d_kernel);
}

//---------------------------------------------------------------------------//
// PUBLIC FUNCTIONS
//---------------------------------------------------------------------------//
/*!
 * \brief Build a source from a fission site container.
 */
void KDE_Fission_Source::build_source(SP_Fission_Sites &fission_sites)
{
    REQUIRE(d_kernel);

    // Call Base method first.  Afterwards, we must use the internal fission
    // site container
    Base::build_source(fission_sites);
    CHECK(fission_sites->empty());

    // Calculate the bandwidths
    d_kernel->calc_bandwidths(*d_fission_sites);
}

//---------------------------------------------------------------------------//
/*!
 * \brief Sample a particle.
 */
KDE_Fission_Source::SP_Particle
KDE_Fission_Source::get_particle()
{
    using def::I; using def::J; using def::K;

    REQUIRE(d_wt > 0.0);
    REQUIRE(profugus::Global_RNG::d_rng.assigned());

    // particle
    SP_Particle p;
    CHECK(!p);

    // return a null particle if no source
    if (!d_num_left)
    {
        ENSURE(d_fission_sites ? d_fission_sites->empty() : true);
        return p;
    }

    SCOPED_TIMER_2("MC::KDE_Fission_Source.get_particle");

    // make a particle
    p = std::make_shared<Particle_t>();

    // use the global rng on this domain for the random number generator
    p->set_rng(profugus::Global_RNG::d_rng);
    RNG rng = p->rng();

    // material id
    int matid = 0;

    // particle position and isotropic direction
    Space_Vector r, omega;

    // sample the angle isotropically
    Base::sample_angle(omega, rng);

    // sample flag
    bool sampled;

    // if there is a fission site container than get the particle from there;
    // otherwise assume this is an initial source
    if (!is_initial_source())
    {
        CHECK(!d_fission_sites->empty());

        // get the last element in the site container
        Fission_Site &fs = d_fission_sites->back();

        // get the location of the physics site
        r = b_physics->fission_site(fs);

        // Now, sample from the kernel
        r = d_kernel->sample_position(r, rng);

        // intialize the geometry state
        b_geometry->initialize(r, omega, p->geo_state());

        // get the material id
        matid = b_geometry->matid(p->geo_state());

        // initialize the physics state at the fission site
        sampled = b_physics->initialize_fission(fs, *p);
        CHECK(sampled);

        // pop this fission site from the list
        d_fission_sites->pop_back();
    }
    else
    {
        matid = sample_geometry(r, omega, *p, rng);
    }

    // set the material id in the particle
    p->set_matid(matid);

    // set particle weight
    p->set_wt(d_wt);

    // make particle alive
    p->live();

    // update counters
    d_num_left--;
    d_num_run++;

    ENSURE(p->matid() == matid);
    return p;
}

//---------------------------------------------------------------------------//
} // end namespace profugus

//---------------------------------------------------------------------------//
// end of MC/mc/KDE_Fission_Source.cc
//---------------------------------------------------------------------------//
<commit_msg>Removed whitespace<commit_after>//---------------------------------*-C++-*-----------------------------------//
/*!
 * \file   MC/mc/KDE_Fission_Source.cc
 * \author Gregory G. Davidson
 * \date   Mon Nov 23 15:47:23 2015
 * \brief  KDE_Fission_Source class definitions.
 * \note   Copyright (c) 2015 Oak Ridge National Laboratory, UT-Battelle, LLC.
 */
//---------------------------------------------------------------------------//

#include "KDE_Fission_Source.hh"

#include "KDE_Kernel_Resample.hh"
#include "comm/Timing.hh"
#include "mc/Global_RNG.hh"

namespace profugus
{

//---------------------------------------------------------------------------//
// CONSTRUCTOR
//---------------------------------------------------------------------------//
/*!
 * \brief Constructor.
 */
KDE_Fission_Source::KDE_Fission_Source(RCP_Std_DB     db,
                                       SP_Geometry    geometry,
                                       SP_Physics     physics,
                                       SP_RNG_Control rng_control)
    : Base(db, geometry, physics, rng_control)
{
    REQUIRE(db.is_valid_ptr());
    REQUIRE(db->isType<std::string>("kernel_type"));

    // Get the type of KDE kernel
    const std::string &kernel_type = db->get<std::string>("kernel_type");

    // Get the bandwidth coefficient
    double coeff = db->get<double>("bnd_coeff", 1.06);
    double exponent = db->get<double>("bnd_exp", -0.20);

    if (kernel_type == "resample")
    {
        // Instantiate the resample kernel
        d_kernel = std::make_shared<KDE_Kernel_Resample>(geometry, physics,
                                                         coeff, exponent);
    }
    else
    {
        VALIDATE(false, "Unrecognized kernel type " << kernel_type);
    }

    ENSURE(d_kernel);
}

//---------------------------------------------------------------------------//
// PUBLIC FUNCTIONS
//---------------------------------------------------------------------------//
/*!
 * \brief Build a source from a fission site container.
 */
void KDE_Fission_Source::build_source(SP_Fission_Sites &fission_sites)
{
    REQUIRE(d_kernel);

    // Call Base method first.  Afterwards, we must use the internal fission
    // site container
    Base::build_source(fission_sites);
    CHECK(fission_sites->empty());

    // Calculate the bandwidths
    d_kernel->calc_bandwidths(*d_fission_sites);
}

//---------------------------------------------------------------------------//
/*!
 * \brief Sample a particle.
 */
KDE_Fission_Source::SP_Particle
KDE_Fission_Source::get_particle()
{
    using def::I; using def::J; using def::K;

    REQUIRE(d_wt > 0.0);
    REQUIRE(profugus::Global_RNG::d_rng.assigned());

    // particle
    SP_Particle p;
    CHECK(!p);

    // return a null particle if no source
    if (!d_num_left)
    {
        ENSURE(d_fission_sites ? d_fission_sites->empty() : true);
        return p;
    }

    SCOPED_TIMER_2("MC::KDE_Fission_Source.get_particle");

    // make a particle
    p = std::make_shared<Particle_t>();

    // use the global rng on this domain for the random number generator
    p->set_rng(profugus::Global_RNG::d_rng);
    RNG rng = p->rng();

    // material id
    int matid = 0;

    // particle position and isotropic direction
    Space_Vector r, omega;

    // sample the angle isotropically
    Base::sample_angle(omega, rng);

    // sample flag
    bool sampled;

    // if there is a fission site container than get the particle from there;
    // otherwise assume this is an initial source
    if (!is_initial_source())
    {
        CHECK(!d_fission_sites->empty());

        // get the last element in the site container
        Fission_Site &fs = d_fission_sites->back();

        // get the location of the physics site
        r = b_physics->fission_site(fs);

        // Now, sample from the kernel
        r = d_kernel->sample_position(r, rng);

        // intialize the geometry state
        b_geometry->initialize(r, omega, p->geo_state());

        // get the material id
        matid = b_geometry->matid(p->geo_state());

        // initialize the physics state at the fission site
        sampled = b_physics->initialize_fission(fs, *p);
        CHECK(sampled);

        // pop this fission site from the list
        d_fission_sites->pop_back();
    }
    else
    {
        matid = sample_geometry(r, omega, *p, rng);
    }

    // set the material id in the particle
    p->set_matid(matid);

    // set particle weight
    p->set_wt(d_wt);

    // make particle alive
    p->live();

    // update counters
    d_num_left--;
    d_num_run++;

    ENSURE(p->matid() == matid);
    return p;
}

//---------------------------------------------------------------------------//
} // end namespace profugus

//---------------------------------------------------------------------------//
// end of MC/mc/KDE_Fission_Source.cc
//---------------------------------------------------------------------------//
<|endoftext|>


<commit_before>#include <iostream>

#include <QDir>
#include <QDebug>
#include <QFileInfo>
#include <QEventLoop>
#include <QMutexLocker>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QCoreApplication>

#include "Util.h"
#include "Downloader.h"
#include "DownloadTask.h"

Downloader::Downloader(const QUrl &url, const QString &outputDir, int conns,
                       int chunks, int chunkSize, bool confirm, bool verbose)
  : url{url}, outputDir{outputDir}, conns{conns}, chunks{chunks},
  chunkSize{chunkSize}, downloadCount{0}, rangeCount{0}, contentLen{0},
  bytesDown{0}, confirm{confirm}, verbose{verbose}, continuable{false},
  reply{nullptr}
{
  connect(&commitThread, &CommitThread::finished,
          this, &Downloader::onCommitThreadFinished);
  connect(this, &Downloader::chunkToThread,
          &commitThread, &CommitThread::enqueueChunk,
          Qt::QueuedConnection);
}

void Downloader::start() {
  // Fetch HEAD to find out the size but also if it exists.
  reply = getHead(url);
  if (!reply) {
    QCoreApplication::exit(-1);
    return;
  }
  url = reply->url();

  // Find "Content-Length".
  if (!reply->hasRawHeader("Content-Length")) {
    qCritical() << "ERROR Invalid response from server. No"
                << "'Content-Length' header present!";
    QCoreApplication::exit(-1);
    return;
  }
  bool ok;
  contentLen =
    QString::fromUtf8(reply->rawHeader("Content-Length")).toLongLong(&ok);
  if (!ok || contentLen == 0) {
    qCritical() << "ERROR Invalid content length:" << contentLen;
    QCoreApplication::exit(-1);
    return;
  }
  if (verbose) {
    qDebug() << "SIZE" << contentLen;
  }

  // Check for header "Accept-Ranges" and whether it has "bytes"
  // supported.
  continuable = false;
  if (reply->hasRawHeader("Accept-Ranges")) {
    const QString ranges = QString::fromUtf8(reply->rawHeader("Accept-Ranges"));
    continuable = ranges.toLower().contains("bytes");
  }
  if (verbose) {
    qDebug() << qPrintable(QString("%1CONTINUABLE").
                           arg(continuable ? "" : "NOT "));
  }

  // Clean reply.
  reply->close();
  reply = nullptr;

  createRanges();
  setupThreadPool();

  // Start actual download.
  download();
}

void Downloader::onDownloadTaskFinished(Range range, QByteArray *data) {
  QMutexLocker locker{&finishedMutex};
  chunksMap[range.first] = data;
  downloadCount++;
  bytesDown += data->size();
  updateProgress();
  saveChunk();
}

void Downloader::onDownloadTaskFailed(Range range, int httpCode,
                                      QNetworkReply::NetworkError error) {
  qDebug() << "failed" << range << Util::getErrorString(error);
}

void Downloader::onCommitThreadFinished() {
  qDebug(); // Write newline to end the progress line.
  emit finished();
}

QNetworkReply *Downloader::getHead(const QUrl &url) {
  if (verbose) {
    qDebug() << "HEAD" << qPrintable(url.toString());
  }

  QNetworkRequest req{url};
  auto *rep = netmgr.head(req);
  QEventLoop loop;
  connect(rep, &QNetworkReply::finished, &loop, &QEventLoop::quit);
  loop.exec();

  if (rep->error() != QNetworkReply::NoError) {
    rep->abort();
    qCritical() << "ERROR" << qPrintable(Util::getErrorString(rep->error()));
    return nullptr;
  }

  int code = rep->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
  if (verbose) {
    qDebug() << "CODE" << code;
    //qDebug() << "HEADERS" << rep->rawHeaderPairs();
  }

  static bool didRedir = false;

  if (code >= 200 && code < 300) {
    if (url != this->url) {
      qDebug() << "Resolved URL:" << qPrintable(url.toString());
    }

    if (confirm && didRedir) {
      if (!Util::askProceed(tr("Do you want to continue?") + " [y/N] ")) {
        rep->abort();
        qCritical() << "Aborting..";
        return nullptr;
      }
    }
  }

  // Handle redirect.
  if (code >= 300 && code < 400) {
    if (!rep->hasRawHeader("Location")) {
      rep->abort();
      qCritical() << "ERROR Could not resolve URL!";
      return nullptr;
    }

    QString locHdr = QString::fromUtf8(rep->rawHeader("Location"));

    QUrl loc{locHdr, QUrl::StrictMode};
    if (!loc.isValid()) {
      rep->abort();
      qCritical() << "ERROR Invalid redirection header:" <<
        qPrintable(loc.toString());
      return nullptr;
    }

    // If relative then try resolving with the previous URL.
    if (loc.isRelative()) {
      loc = url.resolved(loc);
    }

    if (verbose) {
      qDebug() << "REDIRECT" << qPrintable(loc.toString());
    }

    didRedir = true;
    rep->abort();
    rep = getHead(loc);
  }

  // Client errors.
  else if (code >= 400 && code < 500) {
    rep->abort();
    qDebug() << "CLIENT ERROR";
    return nullptr;
  }

  // Server errors.
  else if (code >= 500 && code < 600) {
    rep->abort();
    qDebug() << "SERVER ERROR";
    return nullptr;
  }

  return rep;
}

void Downloader::createRanges() {
  ranges.clear();
  chunksMap.clear();

  qint64 size = 1048576;
  if (chunkSize != -1) {
    size = chunkSize;
  }
  else if (chunks != -1) {
    size = contentLen / chunks;
  }
  else if (conns >= 8) {
    size = contentLen / conns;
    qint64 onePerc = contentLen / 100;
    if (size > onePerc) {
      size = onePerc;
    }
  }

  if (verbose) {
    qDebug() << "CHUNK SIZE" << size;
  }

  for (qint64 start = 0; start < contentLen; start += size) {
    qint64 end = start + size;
    if (end >= contentLen) {
      end = contentLen;
    }
    ranges.enqueue(Range{start, end - 1});
    chunksMap[start] = nullptr;
  }
  rangeCount = ranges.size();

  if (verbose) {
    qDebug() << "CHUNKS" << rangeCount;
  }
}

void Downloader::setupThreadPool() {
  // Cap connections to the amount of chunks to download.
  if (conns > ranges.size()) {
    int old{conns};
    conns = ranges.size();
    qDebug() << "CAP connection amount capped to amount of chunks:"
             << old << "->" << conns;
  }

  pool.setMaxThreadCount(conns);
}

void Downloader::download() {
  QFileInfo fi{url.path()};
  QDir dir = (outputDir.isEmpty() ? QDir::current() : outputDir);
  QString path{dir.absoluteFilePath(fi.baseName())};
  QString suf{fi.suffix()};
  if (!suf.isEmpty()) {
    path.append("." + fi.suffix());
  }
  qDebug() << "Saving to" << qPrintable(path);

  auto *file = new QFile{path};
  if (file->exists()) {
    QFile::remove(path);
  }
  if (!file->open(QIODevice::WriteOnly)) {
    qCritical() << "ERROR Could not open file for writing!";
    delete file;
    QCoreApplication::exit(-1);
    return;
  }
  commitThread.setFile(file);

  // Fill queue with tasks and start immediately.
  started = QDateTime::currentDateTime();
  while (!ranges.empty()) {
    auto range = ranges.dequeue();
    auto *task = new DownloadTask{url, range};
    connect(task, &DownloadTask::finished,
            this, &Downloader::onDownloadTaskFinished);
    connect(task, &DownloadTask::failed,
            this,  &Downloader::onDownloadTaskFailed);
    pool.start(task);
  }
}

void Downloader::saveChunk() {
  // Lock on chunks map is required to be acquired going into this
  // method!

  if (chunksMap.isEmpty()) {
    // Wait for commit thread to be done.
    return;
  }

  auto key = chunksMap.firstKey();
  const auto *value = chunksMap[key];
  if (value != nullptr) {
    emit chunkToThread(value, chunksMap.size() == 1);
    if (!commitThread.isRunning()) {
      commitThread.start();
    }
    chunksMap.remove(key);
  }

  // If everything has been downloaded then call method again.
  if (rangeCount == downloadCount) {
    saveChunk();
  }
}

void Downloader::updateProgress() {
  // Lock on chunks map is required to be acquired going into this
  // method!

  QDateTime now{QDateTime::currentDateTime()};
  qint64 secs{started.secsTo(now)}, bytesPrSec{0};
  if (bytesDown > 0 && secs > 0) {
    bytesPrSec = bytesDown / secs;
  }

  float perc = float(downloadCount) / float(rangeCount) * 100.0;

  // Set fixed float formatting to two decimal digits.
  using namespace std;
  cout.precision(2);
  cout.setf(ios::fixed, ios::floatfield);

  cout << "\r" // Rewind to beginning with carriage return.
       << "[ " << perc << "% | "
       << Util::sizeToString(bytesDown).toStdString() << " / "
       << Util::sizeToString(contentLen).toStdString() << " @ "
       << Util::sizeToString(bytesPrSec).toStdString() << "/s | "
       << "chunk " << downloadCount << " / " << rangeCount << " ]";
  cout.flush();
}
<commit_msg>Restarint to 1 decimal digit.<commit_after>#include <iostream>

#include <QDir>
#include <QDebug>
#include <QFileInfo>
#include <QEventLoop>
#include <QMutexLocker>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QCoreApplication>

#include "Util.h"
#include "Downloader.h"
#include "DownloadTask.h"

Downloader::Downloader(const QUrl &url, const QString &outputDir, int conns,
                       int chunks, int chunkSize, bool confirm, bool verbose)
  : url{url}, outputDir{outputDir}, conns{conns}, chunks{chunks},
  chunkSize{chunkSize}, downloadCount{0}, rangeCount{0}, contentLen{0},
  bytesDown{0}, confirm{confirm}, verbose{verbose}, continuable{false},
  reply{nullptr}
{
  connect(&commitThread, &CommitThread::finished,
          this, &Downloader::onCommitThreadFinished);
  connect(this, &Downloader::chunkToThread,
          &commitThread, &CommitThread::enqueueChunk,
          Qt::QueuedConnection);
}

void Downloader::start() {
  // Fetch HEAD to find out the size but also if it exists.
  reply = getHead(url);
  if (!reply) {
    QCoreApplication::exit(-1);
    return;
  }
  url = reply->url();

  // Find "Content-Length".
  if (!reply->hasRawHeader("Content-Length")) {
    qCritical() << "ERROR Invalid response from server. No"
                << "'Content-Length' header present!";
    QCoreApplication::exit(-1);
    return;
  }
  bool ok;
  contentLen =
    QString::fromUtf8(reply->rawHeader("Content-Length")).toLongLong(&ok);
  if (!ok || contentLen == 0) {
    qCritical() << "ERROR Invalid content length:" << contentLen;
    QCoreApplication::exit(-1);
    return;
  }
  if (verbose) {
    qDebug() << "SIZE" << contentLen;
  }

  // Check for header "Accept-Ranges" and whether it has "bytes"
  // supported.
  continuable = false;
  if (reply->hasRawHeader("Accept-Ranges")) {
    const QString ranges = QString::fromUtf8(reply->rawHeader("Accept-Ranges"));
    continuable = ranges.toLower().contains("bytes");
  }
  if (verbose) {
    qDebug() << qPrintable(QString("%1CONTINUABLE").
                           arg(continuable ? "" : "NOT "));
  }

  // Clean reply.
  reply->close();
  reply = nullptr;

  createRanges();
  setupThreadPool();

  // Start actual download.
  download();
}

void Downloader::onDownloadTaskFinished(Range range, QByteArray *data) {
  QMutexLocker locker{&finishedMutex};
  chunksMap[range.first] = data;
  downloadCount++;
  bytesDown += data->size();
  updateProgress();
  saveChunk();
}

void Downloader::onDownloadTaskFailed(Range range, int httpCode,
                                      QNetworkReply::NetworkError error) {
  qDebug() << "failed" << range << Util::getErrorString(error);
}

void Downloader::onCommitThreadFinished() {
  qDebug(); // Write newline to end the progress line.
  emit finished();
}

QNetworkReply *Downloader::getHead(const QUrl &url) {
  if (verbose) {
    qDebug() << "HEAD" << qPrintable(url.toString());
  }

  QNetworkRequest req{url};
  auto *rep = netmgr.head(req);
  QEventLoop loop;
  connect(rep, &QNetworkReply::finished, &loop, &QEventLoop::quit);
  loop.exec();

  if (rep->error() != QNetworkReply::NoError) {
    rep->abort();
    qCritical() << "ERROR" << qPrintable(Util::getErrorString(rep->error()));
    return nullptr;
  }

  int code = rep->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
  if (verbose) {
    qDebug() << "CODE" << code;
    //qDebug() << "HEADERS" << rep->rawHeaderPairs();
  }

  static bool didRedir = false;

  if (code >= 200 && code < 300) {
    if (url != this->url) {
      qDebug() << "Resolved URL:" << qPrintable(url.toString());
    }

    if (confirm && didRedir) {
      if (!Util::askProceed(tr("Do you want to continue?") + " [y/N] ")) {
        rep->abort();
        qCritical() << "Aborting..";
        return nullptr;
      }
    }
  }

  // Handle redirect.
  if (code >= 300 && code < 400) {
    if (!rep->hasRawHeader("Location")) {
      rep->abort();
      qCritical() << "ERROR Could not resolve URL!";
      return nullptr;
    }

    QString locHdr = QString::fromUtf8(rep->rawHeader("Location"));

    QUrl loc{locHdr, QUrl::StrictMode};
    if (!loc.isValid()) {
      rep->abort();
      qCritical() << "ERROR Invalid redirection header:" <<
        qPrintable(loc.toString());
      return nullptr;
    }

    // If relative then try resolving with the previous URL.
    if (loc.isRelative()) {
      loc = url.resolved(loc);
    }

    if (verbose) {
      qDebug() << "REDIRECT" << qPrintable(loc.toString());
    }

    didRedir = true;
    rep->abort();
    rep = getHead(loc);
  }

  // Client errors.
  else if (code >= 400 && code < 500) {
    rep->abort();
    qDebug() << "CLIENT ERROR";
    return nullptr;
  }

  // Server errors.
  else if (code >= 500 && code < 600) {
    rep->abort();
    qDebug() << "SERVER ERROR";
    return nullptr;
  }

  return rep;
}

void Downloader::createRanges() {
  ranges.clear();
  chunksMap.clear();

  qint64 size = 1048576;
  if (chunkSize != -1) {
    size = chunkSize;
  }
  else if (chunks != -1) {
    size = contentLen / chunks;
  }
  else if (conns >= 8) {
    size = contentLen / conns;
    qint64 onePerc = contentLen / 100;
    if (size > onePerc) {
      size = onePerc;
    }
  }

  if (verbose) {
    qDebug() << "CHUNK SIZE" << size;
  }

  for (qint64 start = 0; start < contentLen; start += size) {
    qint64 end = start + size;
    if (end >= contentLen) {
      end = contentLen;
    }
    ranges.enqueue(Range{start, end - 1});
    chunksMap[start] = nullptr;
  }
  rangeCount = ranges.size();

  if (verbose) {
    qDebug() << "CHUNKS" << rangeCount;
  }
}

void Downloader::setupThreadPool() {
  // Cap connections to the amount of chunks to download.
  if (conns > ranges.size()) {
    int old{conns};
    conns = ranges.size();
    qDebug() << "CAP connection amount capped to amount of chunks:"
             << old << "->" << conns;
  }

  pool.setMaxThreadCount(conns);
}

void Downloader::download() {
  QFileInfo fi{url.path()};
  QDir dir = (outputDir.isEmpty() ? QDir::current() : outputDir);
  QString path{dir.absoluteFilePath(fi.baseName())};
  QString suf{fi.suffix()};
  if (!suf.isEmpty()) {
    path.append("." + fi.suffix());
  }
  qDebug() << "Saving to" << qPrintable(path);

  auto *file = new QFile{path};
  if (file->exists()) {
    QFile::remove(path);
  }
  if (!file->open(QIODevice::WriteOnly)) {
    qCritical() << "ERROR Could not open file for writing!";
    delete file;
    QCoreApplication::exit(-1);
    return;
  }
  commitThread.setFile(file);

  // Fill queue with tasks and start immediately.
  started = QDateTime::currentDateTime();
  while (!ranges.empty()) {
    auto range = ranges.dequeue();
    auto *task = new DownloadTask{url, range};
    connect(task, &DownloadTask::finished,
            this, &Downloader::onDownloadTaskFinished);
    connect(task, &DownloadTask::failed,
            this,  &Downloader::onDownloadTaskFailed);
    pool.start(task);
  }
}

void Downloader::saveChunk() {
  // Lock on chunks map is required to be acquired going into this
  // method!

  if (chunksMap.isEmpty()) {
    // Wait for commit thread to be done.
    return;
  }

  auto key = chunksMap.firstKey();
  const auto *value = chunksMap[key];
  if (value != nullptr) {
    emit chunkToThread(value, chunksMap.size() == 1);
    if (!commitThread.isRunning()) {
      commitThread.start();
    }
    chunksMap.remove(key);
  }

  // If everything has been downloaded then call method again.
  if (rangeCount == downloadCount) {
    saveChunk();
  }
}

void Downloader::updateProgress() {
  // Lock on chunks map is required to be acquired going into this
  // method!

  QDateTime now{QDateTime::currentDateTime()};
  qint64 secs{started.secsTo(now)}, bytesPrSec{0};
  if (bytesDown > 0 && secs > 0) {
    bytesPrSec = bytesDown / secs;
  }

  float perc = float(downloadCount) / float(rangeCount) * 100.0;

  // Set fixed float formatting to one decimal digit.
  using namespace std;
  cout.precision(1);
  cout.setf(ios::fixed, ios::floatfield);

  cout << "\r" // Rewind to beginning with carriage return.
       << "[ " << perc << "% | "
       << Util::sizeToString(bytesDown, 1).toStdString() << " / "
       << Util::sizeToString(contentLen, 1).toStdString() << " @ "
       << Util::sizeToString(bytesPrSec, 1).toStdString() << "/s | "
       << "chunk " << downloadCount << " / " << rangeCount << " ]";
  cout.flush();
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "CppUnitTest.h"

#include "Property.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace std;
using namespace FTL;

namespace FTLTest
{
	class TestClass
	{
	public:
		// Value
		Property<TestClass, int, false, false, PropertyType::AutoGen> defaultProp;

		Property<TestClass, int, true, true, PropertyType::Manual> prop1{ [this]() { return innerI1; }, [this](int val) { innerI1 = val * val; } };
		Property<TestClass, int, false, true, PropertyType::Manual> prop2{ [this]() { return innerI2; }, [this](int val) { innerI2 = val * val; } };
		Property<TestClass, int, true, false, PropertyType::Manual> prop3{ [this]() { return innerI3; }, [this](int val) { innerI3 = val * val; } };
		Property<TestClass, int, false, false, PropertyType::Manual> prop4{ [this]() { return innerI4; }, [this](int val) { innerI4 = val * val; } };

		int innerI1, innerI2, innerI3, innerI4;

		int *pD, *p1, *p2, *p3, *p4;
		int pID, pI1, pI2, pI3, pI4;

		Property<TestClass, int*, false, false, PropertyType::AutoGen> pDefaultProp{ pD };

		Property<TestClass, int*, true, true, PropertyType::Manual> pProp1{ [this]() { return p1; }, [this](int* val) { p1 = val; } };
		Property<TestClass, int*, false, true, PropertyType::Manual> pProp2{ [this]() { return p2; }, [this](int* val) { p2 = val; } };
		Property<TestClass, int*, true, false, PropertyType::Manual> pProp3{ [this]() { return p3; }, [this](int* val) { p3 = val; } };
		Property<TestClass, int*, false, false, PropertyType::Manual> pProp4{ [this]() { return p4; }, [this](int* val) { p4 = val; } };

		// Pointer
		Property<TestClass, int*, false, false, PropertyType::AutoGen> ptrProp;

		// Smart Pointer
		Property<TestClass, shared_ptr<int>, false, false, PropertyType::AutoGen> smptrProp;

		// Getter only
		int goInnerValue;
		Property <TestClass, int, false, false, PropertyType::GetterOnly> go{ [this]() { return goInnerValue; } };

		// Setter only
		int soInnerValue;
		Property <TestClass, int, false, false, PropertyType::SetterOnly> so{ [this](int value) { soInnerValue = value; } };

		void Test()
		{
			defaultProp = 0;
			prop1 = 1;
			prop2 = 2;
			prop3 = 3;
			prop4 = 4;

			pDefaultProp = &pID;
			pProp1 = &pI1;
			pProp2 = &pI2;
			pProp3 = &pI3;
			pProp4 = &pI4;

			*pDefaultProp = 0;
			*pProp1 = 1;
			*pProp2 = 2;
			*pProp3 = 3;
			*pProp4 = 4;
		}
	};

	TEST_CLASS(PropertyTest)
	{
	public:
		TEST_METHOD(PropertyTest1)
		{
			FTLTest::TestClass cls;
			cls.Test();

			// Getter privateness
			Assert::AreEqual(false, IsGetterPrivate(cls.defaultProp, nullptr));
			Assert::AreEqual(true, IsGetterPrivate(cls.prop1, nullptr));
			Assert::AreEqual(false, IsGetterPrivate(cls.prop2, nullptr));
			Assert::AreEqual(true, IsGetterPrivate(cls.prop3, nullptr));
			Assert::AreEqual(false, IsGetterPrivate(cls.prop4, nullptr));

			Assert::AreEqual(false, IsGetterPrivate(cls.pDefaultProp, nullptr));
			Assert::AreEqual(true, IsGetterPrivate(cls.pProp1, nullptr));
			Assert::AreEqual(false, IsGetterPrivate(cls.pProp2, nullptr));
			Assert::AreEqual(true, IsGetterPrivate(cls.pProp3, nullptr));
			Assert::AreEqual(false, IsGetterPrivate(cls.pProp4, nullptr));

			// Setter privateness
			Assert::AreEqual(false, IsSetterPrivate(cls.defaultProp, nullptr));
			Assert::AreEqual(true, IsSetterPrivate(cls.prop1, nullptr));
			Assert::AreEqual(true, IsSetterPrivate(cls.prop2, nullptr));
			Assert::AreEqual(false, IsSetterPrivate(cls.prop3, nullptr));
			Assert::AreEqual(false, IsSetterPrivate(cls.prop4, nullptr));

			Assert::AreEqual(false, IsSetterPrivate(cls.pDefaultProp, nullptr));
			Assert::AreEqual(true, IsSetterPrivate(cls.pProp1, nullptr));
			Assert::AreEqual(true, IsSetterPrivate(cls.pProp2, nullptr));
			Assert::AreEqual(false, IsSetterPrivate(cls.pProp3, nullptr));
			Assert::AreEqual(false, IsSetterPrivate(cls.pProp4, nullptr));
		}

		TEST_METHOD(PropertyTest2)
		{
			FTLTest::TestClass cls;
			cls.Test();

			// Getter value
			Assert::AreEqual(0, static_cast<int>(cls.defaultProp));
			// Assert::AreEqual(1 * 1, static_cast<int>(cls.prop1)); // Compile error
			Assert::AreEqual(2 * 2, static_cast<int>(cls.prop2));
			// Assert::AreEqual(3 * 3, static_cast<int>(cls.prop3)); // Compile error
			Assert::AreEqual(4 * 4, static_cast<int>(cls.prop4));

			// Setter value
			Assert::AreEqual(1, static_cast<int>(cls.defaultProp = 1));
			// Assert::AreEqual(2 * 2, static_cast<int>(cls.prop1 = 2)); // Compile error
			// Assert::AreEqual(3 * 3, static_cast<int>(cls.prop2 = 3)); // Compile error
			Assert::AreEqual(4, static_cast<int>(cls.prop3 = 4));
			Assert::AreEqual(5, static_cast<int>(cls.prop4 = 5));

			// After set
			Assert::AreEqual(1 * 1, static_cast<int>(cls.defaultProp));
			// Assert::AreEqual(2 * 2, static_cast<int>(cls.prop1)); // Setter private, compile error
			// Assert::AreEqual(3 * 3, static_cast<int>(cls.prop2)); // Setter private
			// Assert::AreEqual(4 * 4, static_cast<int>(cls.prop3)); // Compile error
			Assert::AreEqual(5 * 5, static_cast<int>(cls.prop4));
		}

		TEST_METHOD(PropertyTest3)
		{
			FTLTest::TestClass cls;

			int dummyInt = 5555;
			int dummyInt1 = 6666;
			int dummyInt2 = 7777;
			int dummyInt3 = 8888;
			int dummyInt4 = 9999;

			Assert::AreEqual(&dummyInt, static_cast<int*>(cls.pDefaultProp = &dummyInt));
			// Assert::AreEqual(&dummyInt1, static_cast<int*>(cls.pProp1 = &dummyInt1)); // Compile error
			// Assert::AreEqual(&dummyInt2, static_cast<int*>(cls.pProp2 = &dummyInt2)); // Compile error
			Assert::AreEqual(&dummyInt3, static_cast<int*>(cls.pProp3 = &dummyInt3));
			Assert::AreEqual(&dummyInt4, static_cast<int*>(cls.pProp4 = &dummyInt4));
		}

		TEST_METHOD(PropertyTest4)
		{
			FTLTest::TestClass cls;
			cls.Test();

			// Pointer dereference(getter)
			Assert::AreEqual(0, static_cast<int>(*cls.pDefaultProp));
			// Assert::AreEqual(1, static_cast<int>(*cls.pProp1)); // Compile error
			Assert::AreEqual(2, static_cast<int>(*cls.pProp2));
			// Assert::AreEqual(3, static_cast<int>(*cls.pProp3)); // Compile error
			Assert::AreEqual(4, static_cast<int>(*cls.pProp4));

			// Pointer deference(setter)
			*cls.pDefaultProp = 10;
			// *cls.pProp1 = 11; // Compile error
			*cls.pProp2 = 12;
			// *cls.pProp3 = 13; // Compile error
			*cls.pProp4 = 14;

			Assert::AreEqual(10, static_cast<int>(*cls.pDefaultProp));
			// Assert::AreEqual(11, static_cast<int>(*cls.pProp1)); // Compile error
			Assert::AreEqual(12, static_cast<int>(*cls.pProp2));
			// Assert::AreEqual(13, static_cast<int>(*cls.pProp3)); // Compile error
			Assert::AreEqual(14, static_cast<int>(*cls.pProp4));
		}

		TEST_METHOD(PropertyTest5)
		{
			FTLTest::TestClass cls;
			cls.Test();

			// Getter only
			cls.goInnerValue = 3;
			// cls.go = 4; // Compile error
			Assert::AreEqual(3, cls.go.get());

			// Setter only
			cls.so = 6;
			Assert::AreEqual(6, cls.soInnerValue);
			// Assert::AreEqual(6, cls.so.get()); // Compile error
		}

	private:
		template <class T>
		constexpr bool IsGetterPrivate(const T&, ...) const
		{
			return true;
		}

		template <class T>
		constexpr bool IsGetterPrivate(const T&, decltype(typename declval<T>().operator T::InterfaceType())* ptr) const
		{
			return false;
		}

		template <class T>
		constexpr bool IsSetterPrivate(T&, ...) const
		{
			return true;
		}

		template <class T>
		constexpr bool IsSetterPrivate(T& val, decltype(val = typename T::InterfaceType())* ptr) const
		{
			return false;
		}

		// Sealed due to Visual Studio C++ compiler's bug.  Works well on clang.
		/*
		template <class T, class = void>
		class IsGetterPrivate : public true_type {};

		template <class T>
		class IsGetterPrivate<T, VoidTemplate<decltype(typename declval<T>().operator T::Type())>> : public false_type {};
		*/
	};
}<commit_msg>Property pointer test added<commit_after>#include "stdafx.h"
#include "CppUnitTest.h"

#include "Property.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace std;
using namespace FTL;

namespace FTLTest
{
	class TestClass
	{
	public:
		// Value
		Property<TestClass, int, false, false, PropertyType::AutoGen> defaultProp;

		Property<TestClass, int, true, true, PropertyType::Manual> prop1{ [this]() { return innerI1; }, [this](int val) { innerI1 = val * val; } };
		Property<TestClass, int, false, true, PropertyType::Manual> prop2{ [this]() { return innerI2; }, [this](int val) { innerI2 = val * val; } };
		Property<TestClass, int, true, false, PropertyType::Manual> prop3{ [this]() { return innerI3; }, [this](int val) { innerI3 = val * val; } };
		Property<TestClass, int, false, false, PropertyType::Manual> prop4{ [this]() { return innerI4; }, [this](int val) { innerI4 = val * val; } };

		int innerI1, innerI2, innerI3, innerI4;

		int *pD, *p1, *p2, *p3, *p4;
		int pID, pI1, pI2, pI3, pI4;

		Property<TestClass, int*, false, false, PropertyType::AutoGen> pDefaultProp{ pD };

		Property<TestClass, int*, true, true, PropertyType::Manual> pProp1{ [this]() { return p1; }, [this](int* val) { p1 = val; } };
		Property<TestClass, int*, false, true, PropertyType::Manual> pProp2{ [this]() { return p2; }, [this](int* val) { p2 = val; } };
		Property<TestClass, int*, true, false, PropertyType::Manual> pProp3{ [this]() { return p3; }, [this](int* val) { p3 = val; } };
		Property<TestClass, int*, false, false, PropertyType::Manual> pProp4{ [this]() { return p4; }, [this](int* val) { p4 = val; } };

		// Pointer
		Property<TestClass, int*, false, false, PropertyType::AutoGen> ptrProp;

		// Smart Pointer
		Property<TestClass, shared_ptr<int>, false, false, PropertyType::AutoGen> smptrProp;

		// Getter only
		int goInnerValue;
		Property <TestClass, int, false, false, PropertyType::GetterOnly> go{ [this]() { return goInnerValue; } };

		// Setter only
		int soInnerValue;
		Property <TestClass, int, false, false, PropertyType::SetterOnly> so{ [this](int value) { soInnerValue = value; } };

		void Test()
		{
			defaultProp = 0;
			prop1 = 1;
			prop2 = 2;
			prop3 = 3;
			prop4 = 4;

			pDefaultProp = &pID;
			pProp1 = &pI1;
			pProp2 = &pI2;
			pProp3 = &pI3;
			pProp4 = &pI4;

			*pDefaultProp = 0;
			*pProp1 = 1;
			*pProp2 = 2;
			*pProp3 = 3;
			*pProp4 = 4;
		}
	};

	TEST_CLASS(PropertyTest)
	{
	public:
		TEST_METHOD(PropertyTest1)
		{
			FTLTest::TestClass cls;
			cls.Test();

			// Getter privateness
			Assert::AreEqual(false, IsGetterPrivate(cls.defaultProp, nullptr));
			Assert::AreEqual(true, IsGetterPrivate(cls.prop1, nullptr));
			Assert::AreEqual(false, IsGetterPrivate(cls.prop2, nullptr));
			Assert::AreEqual(true, IsGetterPrivate(cls.prop3, nullptr));
			Assert::AreEqual(false, IsGetterPrivate(cls.prop4, nullptr));

			Assert::AreEqual(false, IsGetterPrivate(cls.pDefaultProp, nullptr));
			Assert::AreEqual(true, IsGetterPrivate(cls.pProp1, nullptr));
			Assert::AreEqual(false, IsGetterPrivate(cls.pProp2, nullptr));
			Assert::AreEqual(true, IsGetterPrivate(cls.pProp3, nullptr));
			Assert::AreEqual(false, IsGetterPrivate(cls.pProp4, nullptr));

			// Setter privateness
			Assert::AreEqual(false, IsSetterPrivate(cls.defaultProp, nullptr));
			Assert::AreEqual(true, IsSetterPrivate(cls.prop1, nullptr));
			Assert::AreEqual(true, IsSetterPrivate(cls.prop2, nullptr));
			Assert::AreEqual(false, IsSetterPrivate(cls.prop3, nullptr));
			Assert::AreEqual(false, IsSetterPrivate(cls.prop4, nullptr));

			Assert::AreEqual(false, IsSetterPrivate(cls.pDefaultProp, nullptr));
			Assert::AreEqual(true, IsSetterPrivate(cls.pProp1, nullptr));
			Assert::AreEqual(true, IsSetterPrivate(cls.pProp2, nullptr));
			Assert::AreEqual(false, IsSetterPrivate(cls.pProp3, nullptr));
			Assert::AreEqual(false, IsSetterPrivate(cls.pProp4, nullptr));
		}

		TEST_METHOD(PropertyTest2)
		{
			FTLTest::TestClass cls;
			cls.Test();

			// Getter value
			Assert::AreEqual(0, static_cast<int>(cls.defaultProp));
			// Assert::AreEqual(1 * 1, static_cast<int>(cls.prop1)); // Compile error
			Assert::AreEqual(2 * 2, static_cast<int>(cls.prop2));
			// Assert::AreEqual(3 * 3, static_cast<int>(cls.prop3)); // Compile error
			Assert::AreEqual(4 * 4, static_cast<int>(cls.prop4));

			// Setter value
			Assert::AreEqual(1, static_cast<int>(cls.defaultProp = 1));
			// Assert::AreEqual(2 * 2, static_cast<int>(cls.prop1 = 2)); // Compile error
			// Assert::AreEqual(3 * 3, static_cast<int>(cls.prop2 = 3)); // Compile error
			Assert::AreEqual(4, static_cast<int>(cls.prop3 = 4));
			Assert::AreEqual(5, static_cast<int>(cls.prop4 = 5));

			// After set
			Assert::AreEqual(1 * 1, static_cast<int>(cls.defaultProp));
			// Assert::AreEqual(2 * 2, static_cast<int>(cls.prop1)); // Setter private, compile error
			// Assert::AreEqual(3 * 3, static_cast<int>(cls.prop2)); // Setter private
			// Assert::AreEqual(4 * 4, static_cast<int>(cls.prop3)); // Compile error
			Assert::AreEqual(5 * 5, static_cast<int>(cls.prop4));
		}

		TEST_METHOD(PropertyTest3)
		{
			FTLTest::TestClass cls;

			int dummyInt = 5555;
			int dummyInt1 = 6666;
			int dummyInt2 = 7777;
			int dummyInt3 = 8888;
			int dummyInt4 = 9999;

			Assert::AreEqual(&dummyInt, static_cast<int*>(cls.pDefaultProp = &dummyInt));
			// Assert::AreEqual(&dummyInt1, static_cast<int*>(cls.pProp1 = &dummyInt1)); // Compile error
			// Assert::AreEqual(&dummyInt2, static_cast<int*>(cls.pProp2 = &dummyInt2)); // Compile error
			Assert::AreEqual(&dummyInt3, static_cast<int*>(cls.pProp3 = &dummyInt3));
			Assert::AreEqual(&dummyInt4, static_cast<int*>(cls.pProp4 = &dummyInt4));
		}

		TEST_METHOD(PropertyTest4)
		{
			FTLTest::TestClass cls;
			cls.Test();

			// Pointer dereference(getter)
			Assert::AreEqual(0, static_cast<int>(*cls.pDefaultProp));
			// Assert::AreEqual(1, static_cast<int>(*cls.pProp1)); // Compile error
			Assert::AreEqual(2, static_cast<int>(*cls.pProp2));
			// Assert::AreEqual(3, static_cast<int>(*cls.pProp3)); // Compile error
			Assert::AreEqual(4, static_cast<int>(*cls.pProp4));

			// Pointer deference(setter)
			*cls.pDefaultProp = 10;
			// *cls.pProp1 = 11; // Compile error
			*cls.pProp2 = 12;
			// *cls.pProp3 = 13; // Compile error
			*cls.pProp4 = 14;

			Assert::AreEqual(10, static_cast<int>(*cls.pDefaultProp));
			// Assert::AreEqual(11, static_cast<int>(*cls.pProp1)); // Compile error
			Assert::AreEqual(12, static_cast<int>(*cls.pProp2));
			// Assert::AreEqual(13, static_cast<int>(*cls.pProp3)); // Compile error
			Assert::AreEqual(14, static_cast<int>(*cls.pProp4));
		}

		TEST_METHOD(PropertyTest5)
		{
			FTLTest::TestClass cls;
			cls.Test();

			// Getter only
			cls.goInnerValue = 3;
			// cls.go = 4; // Compile error
			Assert::AreEqual(3, cls.go.get());

			// Setter only
			cls.so = 6;
			Assert::AreEqual(6, cls.soInnerValue);
			// Assert::AreEqual(6, cls.so.get()); // Compile error
		}

		TEST_METHOD(PropertyTest6)
		{
			FTLTest::TestClass cls;
			cls.Test();

			Assert::AreEqual(false, cls.defaultProp.isPointer);
			Assert::AreEqual(false, cls.prop1.isPointer);
			Assert::AreEqual(false, cls.prop2.isPointer);
			Assert::AreEqual(false, cls.prop3.isPointer);
			Assert::AreEqual(false, cls.prop4.isPointer);

			Assert::AreEqual(true, cls.pDefaultProp.isPointer);
			Assert::AreEqual(true, cls.pProp1.isPointer);
			Assert::AreEqual(true, cls.pProp2.isPointer);
			Assert::AreEqual(true, cls.pProp3.isPointer);
			Assert::AreEqual(true, cls.pProp4.isPointer);
			Assert::AreEqual(true, cls.smptrProp.isPointer);
		}

	private:
		template <class T>
		constexpr bool IsGetterPrivate(const T&, ...) const
		{
			return true;
		}

		template <class T>
		constexpr bool IsGetterPrivate(const T&, decltype(typename declval<T>().operator T::InterfaceType())* ptr) const
		{
			return false;
		}

		template <class T>
		constexpr bool IsSetterPrivate(T&, ...) const
		{
			return true;
		}

		template <class T>
		constexpr bool IsSetterPrivate(T& val, decltype(val = typename T::InterfaceType())* ptr) const
		{
			return false;
		}

		// Sealed due to Visual Studio C++ compiler's bug.  Works well on clang.
		/*
		template <class T, class = void>
		class IsGetterPrivate : public true_type {};

		template <class T>
		class IsGetterPrivate<T, VoidTemplate<decltype(typename declval<T>().operator T::Type())>> : public false_type {};
		*/
	};
}<|endoftext|>


<commit_before>// commodconverter.cc
// Implements the CommodConverter class
#include "commodconverter.h"

namespace commodconverter {

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CommodConverter::CommodConverter(cyclus::Context* ctx)
    : cyclus::Facility(ctx) {
  cyclus::Warn<cyclus::EXPERIMENTAL_WARNING>("the CommodConverter is experimental.");
    };

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// pragmas

#pragma cyclus def schema commodconverter::CommodConverter

#pragma cyclus def annotations commodconverter::CommodConverter

#pragma cyclus def initinv commodconverter::CommodConverter

#pragma cyclus def snapshotinv commodconverter::CommodConverter

#pragma cyclus def infiletodb commodconverter::CommodConverter

#pragma cyclus def snapshot commodconverter::CommodConverter

#pragma cyclus def clone commodconverter::CommodConverter

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::InitFrom(CommodConverter* m) {

  #pragma cyclus impl initfromcopy commodconverter::CommodConverter

  cyclus::toolkit::CommodityProducer::Copy(m);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::InitFrom(cyclus::QueryableBackend* b){

  #pragma cyclus impl initfromdb commodconverter::CommodConverter

  using cyclus::toolkit::Commodity;
  Commodity commod = Commodity(out_commod);
  cyclus::toolkit::CommodityProducer::Add(commod);
  cyclus::toolkit::CommodityProducer::SetCapacity(commod, capacity);
  cyclus::toolkit::CommodityProducer::SetCost(commod, cost);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::EnterNotify() {
  Facility::EnterNotify();

  using cyclus::toolkit::Commodity;
  Commodity commod = Commodity(out_commod);
  cyclus::toolkit::CommodityProducer::Add(commod);
  cyclus::toolkit::CommodityProducer::SetCapacity(commod, capacity);
  cyclus::toolkit::CommodityProducer::SetCost(commod, cost);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::string CommodConverter::str() {
  std::stringstream ss;
  std::string ans;
  if (cyclus::toolkit::CommodityProducer::
      Produces(cyclus::toolkit::Commodity(out_commod_()))){
    ans = "yes";
  } else {
    ans = "no";
  }
  ss << cyclus::Facility::str();
  ss << " has facility parameters {" << "\n"
     << "     Input Commodity = " << in_commod_() << ",\n"
     << "     Output Commodity = " << out_commod_() << ",\n"
     << "     Process Time = " << process_time_() << ",\n"
     << "     Capacity = " << capacity_() << ",\n"
     << " commod producer members: " << " produces "
     << out_commod << "?:" << ans
     << " capacity: " << cyclus::toolkit::CommodityProducer::Capacity(out_commod_())
     << " cost: " << cyclus::toolkit::CommodityProducer::Cost(out_commod_())
     << "'}";
  return ss.str();
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::Tick() {
  LOG(cyclus::LEV_INFO3, "ComCnv") << prototype() << " is ticking {";

  if (current_capacity() > cyclus::eps()) {
    LOG(cyclus::LEV_INFO4, "ComCnv") << " has capacity for " << current_capacity()
                                       << " kg of " << in_commod
                                       << " recipe: " << in_recipe << ".";
  }

  LOG(cyclus::LEV_INFO3, "ComCnv") << "}";
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::Tock() {
  LOG(cyclus::LEV_INFO3, "ComCnv") << prototype() << " is tocking {";

  if( ready() >= 0 || process_time = 0 ) {
    Convert_(capacity_()); // place processing into stocks
  }

  BeginProcessing_(); // place unprocessed inventory into processing
  LOG(cyclus::LEV_INFO3, "ComCnv") << "}";
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::set<cyclus::RequestPortfolio<cyclus::Material>::Ptr>
CommodConverter::GetMatlRequests() {
  using cyclus::CapacityConstraint;
  using cyclus::Material;
  using cyclus::RequestPortfolio;
  using cyclus::Request;

  std::set<RequestPortfolio<Material>::Ptr> ports;

  RequestPortfolio<Material>::Ptr port(new RequestPortfolio<Material>());
  Material::Ptr mat = Request_();
  double amt = mat->quantity();

  if (amt > cyclus::eps()) {
    //CapacityConstraint<Material> cc(amt);
    //port->AddConstraint(cc);

    port->AddRequest(mat, this, in_commod_());

    ports.insert(port);
  }

  return ports;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::AcceptMatlTrades(
  const std::vector< std::pair<cyclus::Trade<cyclus::Material>,
  cyclus::Material::Ptr> >& responses) {
  std::vector< std::pair<cyclus::Trade<cyclus::Material>,
      cyclus::Material::Ptr> >::const_iterator it;
  for (it = responses.begin(); it != responses.end(); ++it) {
    AddMat_(it->second);
  }
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::set<cyclus::BidPortfolio<cyclus::Material>::Ptr>
CommodConverter::GetMatlBids(cyclus::CommodMap<cyclus::Material>::type&
                          commod_requests) {
  using cyclus::BidPortfolio;
  using cyclus::Material;

  std::set<BidPortfolio<Material>::Ptr> ports;

  std::set<std::string>::const_iterator it;
  BidPortfolio<Material>::Ptr port = GetBids_(commod_requests,
                                              out_commod,
                                              &stocks);
  if (!port->bids().empty()) {
    ports.insert(port);
  }

  return ports;

}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::GetMatlTrades(
  const std::vector< cyclus::Trade<cyclus::Material> >& trades,
  std::vector<std::pair<cyclus::Trade<cyclus::Material>,
  cyclus::Material::Ptr> >& responses) {
  using cyclus::Material;
  using cyclus::Trade;

  // for each trade, respond
  std::vector< Trade<Material> >::const_iterator it;
  for (it = trades.begin(); it != trades.end(); ++it) {
    std::string commodity = it->request->commodity();
    double qty = it->amt;
    // create a material pointer representing what you can offer
    Material::Ptr response = TradeResponse_(qty, &stocks);

    responses.push_back(std::make_pair(*it, response));
    LOG(cyclus::LEV_INFO5, "ComCnv") << prototype()
                                  << " just received an order"
                                  << " for " << it->amt
                                  << " of " << commodity;
  }

}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::AddMat_(cyclus::Material::Ptr mat) {
  // Here we do not check that the recipe matches the input recipe.

  LOG(cyclus::LEV_INFO5, "ComCnv") << prototype() << " is initially holding "
                                << inventory.quantity() << " total.";

  try {
    inventory.Push(mat);
  } catch (cyclus::Error& e) {
    e.msg(Agent::InformErrorMsg(e.msg()));
    throw e;
  }

  LOG(cyclus::LEV_INFO5, "ComCnv") << prototype() << " added " << mat->quantity()
                                << " of " << in_commod_()
                                << " to its inventory, which is holding "
                                << inventory.quantity() << " total.";

}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cyclus::Material::Ptr CommodConverter::Request_() {
  double qty = std::max(0.0, current_capacity());
  LOG(cyclus::LEV_INFO5, "ComCnv") << prototype()
                                  << " just requested "
                                  << current_capacity()
                                  << " of commodity: " << in_commod
                                  << " with recipe: " << in_recipe;
  return cyclus::Material::CreateUntracked(qty,
                                        context()->GetRecipe(in_recipe));
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cyclus::BidPortfolio<cyclus::Material>::Ptr CommodConverter::GetBids_(
    cyclus::CommodMap<cyclus::Material>::type& commod_requests,
    std::string commod,
    cyclus::toolkit::ResourceBuff* buffer) {
  using cyclus::Bid;
  using cyclus::BidPortfolio;
  using cyclus::CapacityConstraint;
  using cyclus::Composition;
  using cyclus::Converter;
  using cyclus::Material;
  using cyclus::Request;
  using cyclus::ResCast;
  using cyclus::toolkit::ResourceBuff;

  BidPortfolio<Material>::Ptr port(new BidPortfolio<Material>());

  if (commod_requests.count(commod) > 0 && buffer->quantity() > 0) {
    std::vector<Request<Material>*>& requests = commod_requests.at(commod);

    // get offer composition
    Material::Ptr back = ResCast<Material>(buffer->Pop(ResourceBuff::BACK));
    Composition::Ptr comp = back->comp();
    buffer->Push(back);

    std::vector<Request<Material>*>::iterator it;
    for (it = requests.begin(); it != requests.end(); ++it) {
      Request<Material>* req = *it;
      double qty = std::min(req->target()->quantity(), buffer->quantity());
      Material::Ptr offer = Material::CreateUntracked(qty, comp);
      port->AddBid(req, offer, this);
    }

    //CapacityConstraint<Material> cc(buffer->quantity());
    //port->AddConstraint(cc);
  }

  return port;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cyclus::Material::Ptr CommodConverter::TradeResponse_(
    double qty,
    cyclus::toolkit::ResourceBuff* buffer) {
  using cyclus::Material;
  using cyclus::ResCast;

  std::vector<Material::Ptr> manifest;
  try {
    // pop amount from inventory and blob it into one material
    manifest = ResCast<Material>(buffer->PopQty(qty));
  } catch(cyclus::Error& e) {
    e.msg(Agent::InformErrorMsg(e.msg()));
    throw e;
  }

  Material::Ptr response = manifest[0];
  for (int i = 1; i < manifest.size(); i++) {
    response->Absorb(manifest[i]);
  }
  return response;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::BeginProcessing_(){
  if( inventory.count() > 0 ){
    try {
      processing[context()->time()].Push(inventory.Pop());
      LOG(cyclus::LEV_DEBUG2, "ComCnv") << "CommodConverter " << prototype()
                                      << " added resources to processing at t= "
                                      << context()->time();
    } catch (cyclus::Error& e) {
      e.msg(Agent::InformErrorMsg(e.msg()));
      throw e;
    }
  }
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::Convert_(double cap){
  using cyclus::Material;
  using cyclus::ResCast;
  using cyclus::toolkit::ResourceBuff;
  using cyclus::toolkit::Manifest;

  int t = ready();
  if ( ProcessingAmt_(t) > 0 ){
    try {
      double to_pop = std::min(cap, processing[t].quantity());
      // pop appropriate amount of material from processing
      std::vector<Material::Ptr> to_conv =
        ResCast<Material>(processing[t].PopQty(to_pop));
      // if an out_recipe was provided, transmute it
      std::vector<Material::Ptr>::iterator mat;
      if( out_recipe == "" ){
        // if no out recipe, then no transmute needed
        stocks.PushAll(to_conv);
      } else {
        // transmute each mat
        for(mat=to_conv.begin(); mat!=to_conv.end(); ++mat) {
          (*mat)->Transmute(context()->GetRecipe(out_recipe));
          // put it in the stocks
          stocks.Push(*mat);
        }
      }
      AdvanceUnconverted_(t);
      LOG(cyclus::LEV_INFO1, "ComCnv") << "CommodConverter " << prototype()
                                        << " converted quantity : " << to_pop
                                        << " from " << in_commod
                                        << " to " << out_commod;
    } catch (cyclus::Error& e) {
      e.msg(Agent::InformErrorMsg(e.msg()));
      throw e;
    }
  }
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
double CommodConverter::ProcessingAmt_(int time) {
  using cyclus::toolkit::ResourceBuff;
  double to_ret = 0;
  std::map<int, ResourceBuff>::iterator proc = processing.find(time);
  if ( proc!=processing.end() &&
      proc->second.quantity() > 0 ) {
    to_ret = proc->second.quantity();
  }
  return to_ret;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::AdvanceUnconverted_(int time){
  using cyclus::Material;
  using cyclus::ResCast;

  double to_pop = ProcessingAmt_(time);
  if ( to_pop > 0 ) {
    try {
      std::vector<Material::Ptr> to_advance =
      ResCast<Material>(processing[time].PopQty(to_pop));
      processing[time+1].PushAll(to_advance);
    } catch (cyclus::Error& e) {
      e.msg(Agent::InformErrorMsg(e.msg()));
      throw e;
    }
  }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
extern "C" cyclus::Agent* ConstructCommodConverter(cyclus::Context* ctx) {
  return new CommodConverter(ctx);
}

} // namespace commodconverter
<commit_msg>fixes process_time = 0 bug<commit_after>// commodconverter.cc
// Implements the CommodConverter class
#include "commodconverter.h"

namespace commodconverter {

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CommodConverter::CommodConverter(cyclus::Context* ctx)
    : cyclus::Facility(ctx) {
  cyclus::Warn<cyclus::EXPERIMENTAL_WARNING>("the CommodConverter is experimental.");
    };

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// pragmas

#pragma cyclus def schema commodconverter::CommodConverter

#pragma cyclus def annotations commodconverter::CommodConverter

#pragma cyclus def initinv commodconverter::CommodConverter

#pragma cyclus def snapshotinv commodconverter::CommodConverter

#pragma cyclus def infiletodb commodconverter::CommodConverter

#pragma cyclus def snapshot commodconverter::CommodConverter

#pragma cyclus def clone commodconverter::CommodConverter

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::InitFrom(CommodConverter* m) {

  #pragma cyclus impl initfromcopy commodconverter::CommodConverter

  cyclus::toolkit::CommodityProducer::Copy(m);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::InitFrom(cyclus::QueryableBackend* b){

  #pragma cyclus impl initfromdb commodconverter::CommodConverter

  using cyclus::toolkit::Commodity;
  Commodity commod = Commodity(out_commod);
  cyclus::toolkit::CommodityProducer::Add(commod);
  cyclus::toolkit::CommodityProducer::SetCapacity(commod, capacity);
  cyclus::toolkit::CommodityProducer::SetCost(commod, cost);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::EnterNotify() {
  Facility::EnterNotify();

  using cyclus::toolkit::Commodity;
  Commodity commod = Commodity(out_commod);
  cyclus::toolkit::CommodityProducer::Add(commod);
  cyclus::toolkit::CommodityProducer::SetCapacity(commod, capacity);
  cyclus::toolkit::CommodityProducer::SetCost(commod, cost);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::string CommodConverter::str() {
  std::stringstream ss;
  std::string ans;
  if (cyclus::toolkit::CommodityProducer::
      Produces(cyclus::toolkit::Commodity(out_commod_()))){
    ans = "yes";
  } else {
    ans = "no";
  }
  ss << cyclus::Facility::str();
  ss << " has facility parameters {" << "\n"
     << "     Input Commodity = " << in_commod_() << ",\n"
     << "     Output Commodity = " << out_commod_() << ",\n"
     << "     Process Time = " << process_time_() << ",\n"
     << "     Capacity = " << capacity_() << ",\n"
     << " commod producer members: " << " produces "
     << out_commod << "?:" << ans
     << " capacity: " << cyclus::toolkit::CommodityProducer::Capacity(out_commod_())
     << " cost: " << cyclus::toolkit::CommodityProducer::Cost(out_commod_())
     << "'}";
  return ss.str();
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::Tick() {
  LOG(cyclus::LEV_INFO3, "ComCnv") << prototype() << " is ticking {";

  if (current_capacity() > cyclus::eps()) {
    LOG(cyclus::LEV_INFO4, "ComCnv") << " has capacity for " << current_capacity()
                                       << " kg of " << in_commod
                                       << " recipe: " << in_recipe << ".";
  }

  LOG(cyclus::LEV_INFO3, "ComCnv") << "}";
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::Tock() {
  LOG(cyclus::LEV_INFO3, "ComCnv") << prototype() << " is tocking {";

  if( ready() >= 0 || process_time == 0 ) {
    Convert_(capacity_()); // place processing into stocks
  }

  BeginProcessing_(); // place unprocessed inventory into processing
  LOG(cyclus::LEV_INFO3, "ComCnv") << "}";
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::set<cyclus::RequestPortfolio<cyclus::Material>::Ptr>
CommodConverter::GetMatlRequests() {
  using cyclus::CapacityConstraint;
  using cyclus::Material;
  using cyclus::RequestPortfolio;
  using cyclus::Request;

  std::set<RequestPortfolio<Material>::Ptr> ports;

  RequestPortfolio<Material>::Ptr port(new RequestPortfolio<Material>());
  Material::Ptr mat = Request_();
  double amt = mat->quantity();

  if (amt > cyclus::eps()) {
    //CapacityConstraint<Material> cc(amt);
    //port->AddConstraint(cc);

    port->AddRequest(mat, this, in_commod_());

    ports.insert(port);
  }

  return ports;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::AcceptMatlTrades(
  const std::vector< std::pair<cyclus::Trade<cyclus::Material>,
  cyclus::Material::Ptr> >& responses) {
  std::vector< std::pair<cyclus::Trade<cyclus::Material>,
      cyclus::Material::Ptr> >::const_iterator it;
  for (it = responses.begin(); it != responses.end(); ++it) {
    AddMat_(it->second);
  }
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::set<cyclus::BidPortfolio<cyclus::Material>::Ptr>
CommodConverter::GetMatlBids(cyclus::CommodMap<cyclus::Material>::type&
                          commod_requests) {
  using cyclus::BidPortfolio;
  using cyclus::Material;

  std::set<BidPortfolio<Material>::Ptr> ports;

  std::set<std::string>::const_iterator it;
  BidPortfolio<Material>::Ptr port = GetBids_(commod_requests,
                                              out_commod,
                                              &stocks);
  if (!port->bids().empty()) {
    ports.insert(port);
  }

  return ports;

}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::GetMatlTrades(
  const std::vector< cyclus::Trade<cyclus::Material> >& trades,
  std::vector<std::pair<cyclus::Trade<cyclus::Material>,
  cyclus::Material::Ptr> >& responses) {
  using cyclus::Material;
  using cyclus::Trade;

  // for each trade, respond
  std::vector< Trade<Material> >::const_iterator it;
  for (it = trades.begin(); it != trades.end(); ++it) {
    std::string commodity = it->request->commodity();
    double qty = it->amt;
    // create a material pointer representing what you can offer
    Material::Ptr response = TradeResponse_(qty, &stocks);

    responses.push_back(std::make_pair(*it, response));
    LOG(cyclus::LEV_INFO5, "ComCnv") << prototype()
                                  << " just received an order"
                                  << " for " << it->amt
                                  << " of " << commodity;
  }

}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::AddMat_(cyclus::Material::Ptr mat) {
  // Here we do not check that the recipe matches the input recipe.

  LOG(cyclus::LEV_INFO5, "ComCnv") << prototype() << " is initially holding "
                                << inventory.quantity() << " total.";

  try {
    inventory.Push(mat);
  } catch (cyclus::Error& e) {
    e.msg(Agent::InformErrorMsg(e.msg()));
    throw e;
  }

  LOG(cyclus::LEV_INFO5, "ComCnv") << prototype() << " added " << mat->quantity()
                                << " of " << in_commod_()
                                << " to its inventory, which is holding "
                                << inventory.quantity() << " total.";

}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cyclus::Material::Ptr CommodConverter::Request_() {
  double qty = std::max(0.0, current_capacity());
  LOG(cyclus::LEV_INFO5, "ComCnv") << prototype()
                                  << " just requested "
                                  << current_capacity()
                                  << " of commodity: " << in_commod
                                  << " with recipe: " << in_recipe;
  return cyclus::Material::CreateUntracked(qty,
                                        context()->GetRecipe(in_recipe));
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cyclus::BidPortfolio<cyclus::Material>::Ptr CommodConverter::GetBids_(
    cyclus::CommodMap<cyclus::Material>::type& commod_requests,
    std::string commod,
    cyclus::toolkit::ResourceBuff* buffer) {
  using cyclus::Bid;
  using cyclus::BidPortfolio;
  using cyclus::CapacityConstraint;
  using cyclus::Composition;
  using cyclus::Converter;
  using cyclus::Material;
  using cyclus::Request;
  using cyclus::ResCast;
  using cyclus::toolkit::ResourceBuff;

  BidPortfolio<Material>::Ptr port(new BidPortfolio<Material>());

  if (commod_requests.count(commod) > 0 && buffer->quantity() > 0) {
    std::vector<Request<Material>*>& requests = commod_requests.at(commod);

    // get offer composition
    Material::Ptr back = ResCast<Material>(buffer->Pop(ResourceBuff::BACK));
    Composition::Ptr comp = back->comp();
    buffer->Push(back);

    std::vector<Request<Material>*>::iterator it;
    for (it = requests.begin(); it != requests.end(); ++it) {
      Request<Material>* req = *it;
      double qty = std::min(req->target()->quantity(), buffer->quantity());
      Material::Ptr offer = Material::CreateUntracked(qty, comp);
      port->AddBid(req, offer, this);
    }

    //CapacityConstraint<Material> cc(buffer->quantity());
    //port->AddConstraint(cc);
  }

  return port;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cyclus::Material::Ptr CommodConverter::TradeResponse_(
    double qty,
    cyclus::toolkit::ResourceBuff* buffer) {
  using cyclus::Material;
  using cyclus::ResCast;

  std::vector<Material::Ptr> manifest;
  try {
    // pop amount from inventory and blob it into one material
    manifest = ResCast<Material>(buffer->PopQty(qty));
  } catch(cyclus::Error& e) {
    e.msg(Agent::InformErrorMsg(e.msg()));
    throw e;
  }

  Material::Ptr response = manifest[0];
  for (int i = 1; i < manifest.size(); i++) {
    response->Absorb(manifest[i]);
  }
  return response;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::BeginProcessing_(){
  if( inventory.count() > 0 ){
    try {
      processing[context()->time()].Push(inventory.Pop());
      LOG(cyclus::LEV_DEBUG2, "ComCnv") << "CommodConverter " << prototype()
                                      << " added resources to processing at t= "
                                      << context()->time();
    } catch (cyclus::Error& e) {
      e.msg(Agent::InformErrorMsg(e.msg()));
      throw e;
    }
  }
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::Convert_(double cap){
  using cyclus::Material;
  using cyclus::ResCast;
  using cyclus::toolkit::ResourceBuff;
  using cyclus::toolkit::Manifest;

  int t = ready();
  if ( ProcessingAmt_(t) > 0 ){
    try {
      double to_pop = std::min(cap, processing[t].quantity());
      // pop appropriate amount of material from processing
      std::vector<Material::Ptr> to_conv =
        ResCast<Material>(processing[t].PopQty(to_pop));
      // if an out_recipe was provided, transmute it
      std::vector<Material::Ptr>::iterator mat;
      if( out_recipe == "" ){
        // if no out recipe, then no transmute needed
        stocks.PushAll(to_conv);
      } else {
        // transmute each mat
        for(mat=to_conv.begin(); mat!=to_conv.end(); ++mat) {
          (*mat)->Transmute(context()->GetRecipe(out_recipe));
          // put it in the stocks
          stocks.Push(*mat);
        }
      }
      AdvanceUnconverted_(t);
      LOG(cyclus::LEV_INFO1, "ComCnv") << "CommodConverter " << prototype()
                                        << " converted quantity : " << to_pop
                                        << " from " << in_commod
                                        << " to " << out_commod;
    } catch (cyclus::Error& e) {
      e.msg(Agent::InformErrorMsg(e.msg()));
      throw e;
    }
  }
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
double CommodConverter::ProcessingAmt_(int time) {
  using cyclus::toolkit::ResourceBuff;
  double to_ret = 0;
  std::map<int, ResourceBuff>::iterator proc = processing.find(time);
  if ( proc!=processing.end() &&
      proc->second.quantity() > 0 ) {
    to_ret = proc->second.quantity();
  }
  return to_ret;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CommodConverter::AdvanceUnconverted_(int time){
  using cyclus::Material;
  using cyclus::ResCast;

  double to_pop = ProcessingAmt_(time);
  if ( to_pop > 0 ) {
    try {
      std::vector<Material::Ptr> to_advance =
      ResCast<Material>(processing[time].PopQty(to_pop));
      processing[time+1].PushAll(to_advance);
    } catch (cyclus::Error& e) {
      e.msg(Agent::InformErrorMsg(e.msg()));
      throw e;
    }
  }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
extern "C" cyclus::Agent* ConstructCommodConverter(cyclus::Context* ctx) {
  return new CommodConverter(ctx);
}

} // namespace commodconverter
<|endoftext|>


<commit_before>#include <shogun/multiclass/MulticlassStrategy.h>
#include <shogun/mathematics/Math.h>

using namespace shogun;

CMulticlassStrategy::CMulticlassStrategy()
	:m_train_labels(NULL), m_orig_labels(NULL), m_train_iter(0)
{
}

CMulticlassOneVsRestStrategy::CMulticlassOneVsRestStrategy()
	:CMulticlassStrategy(), m_num_machines(0), m_rejection_strategy(NULL)
{
}

CMulticlassOneVsRestStrategy::CMulticlassOneVsRestStrategy(CRejectionStrategy *rejection_strategy)
	:CMulticlassStrategy(), m_num_machines(0), m_rejection_strategy(rejection_strategy)
{
}

SGVector<int32_t> CMulticlassOneVsRestStrategy::train_prepare_next()
{
	CMulticlassStrategy::train_prepare_next();

	for (int32_t i=0; i < m_orig_labels->get_num_labels(); ++i)
	{
		if (m_orig_labels->get_int_label(i)==m_train_iter)
			m_train_labels->set_label(i, +1.0);
		else
			m_train_labels->set_label(i, -1.0);
	}

	return SGVector<int32_t>(0);
}

int32_t CMulticlassOneVsRestStrategy::decide_label(const SGVector<float64_t> &outputs, int32_t num_classes)
{
	if (m_rejection_strategy && m_rejection_strategy->reject(outputs))
		return CLabels::REJECTION_LABEL;

	return CMath::arg_max(outputs.vector, 1, outputs.vlen);
}

CMulticlassOneVsOneStrategy::CMulticlassOneVsOneStrategy()
	:CMulticlassStrategy(), m_num_machines(0), m_num_classes(0)
{
}

SGVector<int32_t> CMulticlassOneVsOneStrategy::train_prepare_next()
{
	CMulticlassStrategy::train_prepare_next();

	SGVector<int32_t> subset(m_orig_labels->get_num_labels());
	int32_t tot=0;
	for (int32_t k=0; k < m_orig_labels->get_num_labels(); ++k)
	{
		if (m_orig_labels->get_int_label(k)==m_train_pair_idx_1)
		{
			m_train_labels->set_label(k, +1.0);
			subset[tot]=k;
			tot++;
		}
		else if (m_orig_labels->get_int_label(k)==m_train_pair_idx_2)
		{
			m_train_labels->set_label(k, -1.0);
			subset[tot]=k;
			tot++;
		}
	}

	m_train_pair_idx_2++;
	if (m_train_pair_idx_2 >= m_num_classes)
	{
		m_train_pair_idx_1++;
		m_train_pair_idx_2=m_train_pair_idx_1+1;
	}

	return SGVector<int32_t>(subset.vector, tot);
}

int32_t CMulticlassOneVsOneStrategy::decide_label(const SGVector<float64_t> &outputs, int32_t num_classes)
{
	int32_t s=0;
	SGVector<int32_t> votes(num_classes);
	votes.zero();

	for (int32_t i=0; i<num_classes; i++)
	{
		for (int32_t j=i+1; j<num_classes; j++)
		{
			if (outputs[s++]>0)
				votes[i]++;
			else
				votes[j]++;
		}
	}

	int32_t result=CMath::arg_max(votes.vector, 1, votes.vlen);
	votes.destroy_vector();

	return result;
}
<commit_msg>Use SGVector default constructor instead of normal ctor with 0-length.<commit_after>#include <shogun/multiclass/MulticlassStrategy.h>
#include <shogun/mathematics/Math.h>

using namespace shogun;

CMulticlassStrategy::CMulticlassStrategy()
	:m_train_labels(NULL), m_orig_labels(NULL), m_train_iter(0)
{
}

CMulticlassOneVsRestStrategy::CMulticlassOneVsRestStrategy()
	:CMulticlassStrategy(), m_num_machines(0), m_rejection_strategy(NULL)
{
}

CMulticlassOneVsRestStrategy::CMulticlassOneVsRestStrategy(CRejectionStrategy *rejection_strategy)
	:CMulticlassStrategy(), m_num_machines(0), m_rejection_strategy(rejection_strategy)
{
}

SGVector<int32_t> CMulticlassOneVsRestStrategy::train_prepare_next()
{
	CMulticlassStrategy::train_prepare_next();

	for (int32_t i=0; i < m_orig_labels->get_num_labels(); ++i)
	{
		if (m_orig_labels->get_int_label(i)==m_train_iter)
			m_train_labels->set_label(i, +1.0);
		else
			m_train_labels->set_label(i, -1.0);
	}

	return SGVector<int32_t>();
}

int32_t CMulticlassOneVsRestStrategy::decide_label(const SGVector<float64_t> &outputs, int32_t num_classes)
{
	if (m_rejection_strategy && m_rejection_strategy->reject(outputs))
		return CLabels::REJECTION_LABEL;

	return CMath::arg_max(outputs.vector, 1, outputs.vlen);
}

CMulticlassOneVsOneStrategy::CMulticlassOneVsOneStrategy()
	:CMulticlassStrategy(), m_num_machines(0), m_num_classes(0)
{
}

SGVector<int32_t> CMulticlassOneVsOneStrategy::train_prepare_next()
{
	CMulticlassStrategy::train_prepare_next();

	SGVector<int32_t> subset(m_orig_labels->get_num_labels());
	int32_t tot=0;
	for (int32_t k=0; k < m_orig_labels->get_num_labels(); ++k)
	{
		if (m_orig_labels->get_int_label(k)==m_train_pair_idx_1)
		{
			m_train_labels->set_label(k, +1.0);
			subset[tot]=k;
			tot++;
		}
		else if (m_orig_labels->get_int_label(k)==m_train_pair_idx_2)
		{
			m_train_labels->set_label(k, -1.0);
			subset[tot]=k;
			tot++;
		}
	}

	m_train_pair_idx_2++;
	if (m_train_pair_idx_2 >= m_num_classes)
	{
		m_train_pair_idx_1++;
		m_train_pair_idx_2=m_train_pair_idx_1+1;
	}

	return SGVector<int32_t>(subset.vector, tot);
}

int32_t CMulticlassOneVsOneStrategy::decide_label(const SGVector<float64_t> &outputs, int32_t num_classes)
{
	int32_t s=0;
	SGVector<int32_t> votes(num_classes);
	votes.zero();

	for (int32_t i=0; i<num_classes; i++)
	{
		for (int32_t j=i+1; j<num_classes; j++)
		{
			if (outputs[s++]>0)
				votes[i]++;
			else
				votes[j]++;
		}
	}

	int32_t result=CMath::arg_max(votes.vector, 1, votes.vlen);
	votes.destroy_vector();

	return result;
}
<|endoftext|>


<commit_before><commit_msg>Clean up json file input<commit_after><|endoftext|>