<commit_before>#include "GrsApi.h"
#include "amount.h"
#include "chainparams.h"
#include "main.h"
#include "util.h"

#include <iostream>
#include <sstream>

#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
#include <curlpp/Infos.hpp>

#include "json/json_spirit_value.h"
#include "json/json_spirit_reader_template.h"

#include <boost/thread.hpp>

CGrsApi::CGrsApi(const std::string& baseUrl)
  : baseApiUrl(baseUrl)
{
    curlpp::initialize();
}

CGrsApi::~CGrsApi()
{
    curlpp::terminate();
}

CAmount CGrsApi::GetPrice(unsigned int time)
{
    LogPrintf("CGrsApi::GetPrice: time = %d\n", time);

    // projected prices for before-the-trading era

    if (time >= block_0_t && time < block_128002_t) {
        // genesis reward zone
        return 656 * USD1 + 35 * USCENT1;
    } else if (time >= block_128002_t && time < block_193536_t) {
        // decreasing reward zone
        return 10 * USCENT1;
    } else if (time >= block_193536_t && time < Params().LiveFeedSwitchTime()) {
        return 10 * USCENT1;
    }

    // TODO(dmc): check cached price

    // get price from the live feed
    while (true) {  //TODO(dmc): !!!
        try {
            boost::this_thread::interruption_point();
            unsigned int timestamp = 0; //TODO(dmc): must be 'time'
            CAmount price = GetGrsApiPrice(timestamp);
            LogPrintf("GRS price for timestamp: time = %d, price = %d\n", time, price);
            return price;
        } catch (const std::runtime_error& e) {
            error("Can't get GRS price for timestamp: %s\n", e.what());
        } catch (const boost::thread_interrupted& e) {
            LogPrintf("CGrsApi::GetPrice thread terminated\n");
            throw;
        }
    }
}

CAmount CGrsApi::GetLatestPrice()
{
    return 10 * USCENT1;   // STUB: 0.1USD, TODO(dmc): get actual coin price
}

CAmount CGrsApi::GetGrsApiPrice(unsigned int timestamp)
{
    LogPrintf("Getting GRS price for timestamp: time = %d\n", timestamp);
    std::ostringstream reqArgs;
    if (timestamp != 0) {
        reqArgs << timestamp;
    }
    return DoApiPriceRequest("price", reqArgs.str());
}

CAmount CGrsApi::DoApiPriceRequest(const std::string& reqName,
                                   const std::string& args)
{
    CAmount price = 0;
    int apiResponseCode = 200;

    std::ostringstream apiUrl;
    apiUrl << baseApiUrl << reqName << "/" << args;

    std::ostringstream rawResponse;
    try {
        apiResponseCode = DoApiRequest(apiUrl.str(), rawResponse);
        std::clog << "GRS API response: " << rawResponse.str() << std::endl;
    } catch (const curlpp::RuntimeError& e) {
        throw std::runtime_error(std::string(e.what())
                                 + "; url = '" + apiUrl.str() + "'"
                                 + "; response = '" + rawResponse.str() + "'");
    } catch (const curlpp::LogicError& e) {
        throw std::runtime_error(std::string(e.what())
                                 + "; url = '" + apiUrl.str() + "'"
                                 + "; response = '" + rawResponse.str() + "'");
    } catch (const std::invalid_argument& e) {
        throw std::runtime_error(std::string(e.what())
                                + "; url = '" + apiUrl.str() + "'"
                                + "; response = '" + rawResponse.str() + "'");
    } catch (const std::domain_error& e) {
        throw std::runtime_error(std::string(e.what())
                                 + "; url = '" + apiUrl.str() + "'"
                                 + "; response = '" + rawResponse.str() + "'");
    }

    if (apiResponseCode != 200) {
        std::ostringstream oss;
        oss << "apiResponseCode != 200; code = "
            << apiResponseCode
            << "; url = '" + apiUrl.str() + "'"
             + "; response = '" + rawResponse.str() + "'";
        throw std::runtime_error(oss.str());
    }

    try {
        json_spirit::Value value;
        json_spirit::read_string(rawResponse.str(), value);
        json_spirit::Object obj(value.get_obj());

        bool price_read = false;
        for(json_spirit::Object::size_type i = 0; i != obj.size(); ++i) {
            const json_spirit::Pair& pair = obj[i];
            if (pair.name_ == "price") {
                price = pair.value_.get_int();
                price_read = true;
            }
        }
        if (!price_read) {
            throw std::domain_error("No price field found");
        }
    } catch (const std::invalid_argument& e) {
        throw std::runtime_error(std::string(e.what())
                                + "; url = '" + apiUrl.str() + "'"
                                + "; response = '" + rawResponse.str() + "'");
    } catch (const std::domain_error& e) {
        throw std::runtime_error(std::string(e.what())
                                 + "; url = '" + apiUrl.str() + "'"
                                 + "; response = '" + rawResponse.str() + "'");
    }

    return price;
}

int CGrsApi::DoApiRequest(const std::string& url, std::ostringstream& oss)
{
    LogPrintf("CGrsApi::DoApiRequest: url=%s, oss.str()=%s\n", url, oss.str());
    // std::clog << "GRS API url: " << url << std::endl;

    curlpp::options::Url reqUrl(url);
    curlpp::Easy request;
    request.setOpt(curlpp::options::NoSignal(false));
    request.setOpt(reqUrl);

    curlpp::options::WriteStream ws(&oss);
    request.setOpt(ws);
    request.perform();

    return curlpp::infos::ResponseCode::get(request);
}

CDmcSystem::CDmcSystem(const std::string& apiUrl)
    : grsApi(apiUrl)
{
    genesisReward = 65535 * COIN;
    minReward = 1 * COIN;
    maxReward = 100000 * COIN;
    minTargetPrice = 1 * USD1 + 1 * USCENT1;    // 1.01USD
}

bool CDmcSystem::CheckBlockReward(const CBlock& block, CAmount nFees, CValidationState& state, CBlockIndex* pindex)
{
    LogPrintf("CDmcSystem::CheckBlockReward: block.nTime=%d, fees=%d, hash=%s, height=%d, time=%d\n", block.nTime, nFees, pindex->phashBlock ? pindex->GetBlockHash().ToString() : "null", pindex->nHeight, pindex->nTime);

    CAmount blockOutput = block.vtx[0].GetValueOut();
    if (!blockOutput || blockOutput <= nFees) {
        return state.DoS(100,
                     error("CDmcSystem::CheckBlockReward() : coinbase pays zero or <= fees (coinbase=%d, fees=%d)",
                           blockOutput, nFees),
                           REJECT_INVALID, "bad-cb-amount");
    }
    CAmount blockReward = blockOutput - nFees;

    //TODO(dmc): temporary simplification – one GetBlockReward result comparison check
    //            should be enough in the future (the second case of "if" construction)
    if (pindex->nTime > Params().LiveFeedSwitchTime()) {
        // simplified reward checks
        CAmount prevReward = pindex->pprev ? pindex->pprev->nReward : genesisReward;
        CAmount rewDiff = std::abs(blockReward - prevReward);
        if ((rewDiff == 0 || rewDiff == 1 * COIN) &&
            (blockReward >= minReward && blockReward <= maxReward)) {
            return true;
        }
        return state.DoS(100,
                         error("CDmcSystem::CheckBlockReward() : coinbase pays wrong (actual=%d vs mustbe=%d)",
                               blockOutput, GetBlockReward(pindex) + nFees),
                               REJECT_INVALID, "bad-cb-amount");
    }

    if (blockReward != GetBlockReward(pindex)) {
        return state.DoS(100,
                     error("CDmcSystem::CheckBlockReward() : coinbase pays wrong reward (actual=%d vs mustbe=%d, fees=%d)",
                           blockReward, GetBlockReward(pindex), nFees),
                           REJECT_INVALID, "bad-cb-amount");
    }
    return true;
}

CAmount CDmcSystem::GetBlockReward(const CBlockIndex* pindex)
{
    LogPrintf("CDmcSystem::GetBlockReward: hash=%s, height=%d, time=%d\n", pindex->phashBlock ? pindex->GetBlockHash().ToString() : "null", pindex->nHeight, pindex->nTime);

    CAmount nSubsidy = 1 * COIN;

    int nHeight = pindex->nHeight;

    if (pindex->nTime > Params().LiveFeedSwitchTime()) {
        CAmount prevReward = pindex->pprev ? pindex->pprev->nReward : genesisReward;
        CAmount reward     = prevReward;
        unsigned int price = GetPrice(pindex->nTime);
        CAmount target     = GetTargetPrice(prevReward);

        if (price < target) {
            reward -= 1 * COIN;
        } else if (price > target) {
            reward += 1 * COIN;
        }
        nSubsidy = std::max(minReward, std::min(reward, maxReward));
    } else {
        if (Params().NetworkID() == CBaseChainParams::MAIN) {
            const int kGenesisRewardZone    = 128000;
            const int kGenesisReward        = 65535;
            const int kDecreasingRewardZone = kGenesisRewardZone + 1 + kGenesisReward;

            if (nHeight >= 0 && nHeight <= kGenesisRewardZone) {
                nSubsidy = kGenesisReward * COIN;
            } else if (nHeight > kGenesisRewardZone && nHeight < kDecreasingRewardZone) {
                nSubsidy = (kDecreasingRewardZone - nHeight) * COIN;
            }
        } else {
            nSubsidy = 1024 * COIN;
        }
    }

    return nSubsidy;
}

CAmount CDmcSystem::GetBlockRewardForNewTip(unsigned int time)
{
    LogPrintf("CDmcSystem::GetBlockRewardForNewTip: time=%d\n", time);
    const CBlockIndex* tip = chainActive.Tip();

    if (!tip) {
        return genesisReward;
    }

    CAmount nSubsidy = 1 * COIN;

    int nHeight = tip->nHeight + 1;

    if (tip->nTime > Params().LiveFeedSwitchTime()) {
        CAmount prevReward = tip->nReward;
        CAmount reward     = prevReward;
        unsigned int price = GetPrice(time);
        CAmount target     = GetTargetPrice(prevReward);

        if (price < target) {
            reward -= 1 * COIN;
        } else if (price > target) {
            reward += 1 * COIN;
        }
        nSubsidy = std::max(minReward, std::min(reward, maxReward));
    } else {
        if (Params().NetworkID() == CBaseChainParams::MAIN) {
            const int kGenesisRewardZone       = 128000;
            const int kGenesisReward           = 65535;
            const int kDecreasingRewardZone = kGenesisRewardZone + 1 + kGenesisReward;

            if (nHeight >= 0 && nHeight <= kGenesisRewardZone) {
                nSubsidy = kGenesisReward * COIN;
            } else if (nHeight > kGenesisRewardZone && nHeight < kDecreasingRewardZone) {
                nSubsidy = (kDecreasingRewardZone - nHeight) * COIN;
            }
        } else {
            nSubsidy = 1024 * COIN;
        }
    }

    LogPrintf("CDmcSystem::GetBlockRewardForNewTip: time=%d, nSubsidy=%d\n", time, nSubsidy);
    return nSubsidy;
}

CAmount CDmcSystem::GetBlockReward() const
{
    LOCK(cs_main);
    return chainActive.Tip()->nReward;
}

CAmount CDmcSystem::GetPrice()
{
    LOCK(cs_main);
    return grsApi.GetPrice(chainActive.Tip()->nTime);
}

CAmount CDmcSystem::GetTargetPrice() const
{
    LOCK(cs_main);
    return GetTargetPrice(chainActive.Tip()->nReward);
}

CAmount CDmcSystem::GetTotalCoins() const
{
    LOCK(cs_main);
    return chainActive.Tip()->nChainReward;
}

CAmount CDmcSystem::GetMarketCap()
{
    return (GetTotalCoins() / COIN) * GetPrice();
}

CAmount CDmcSystem::GetPrice(unsigned int time)
{
    return grsApi.GetPrice(time);
}

CAmount CDmcSystem::GetTargetPrice(unsigned int time) const
{
    //TODO(dmc): temporary simplification
//    const CBlockIndex* pindex;  // TODO(dmc): get block for time
//    return GetTargetPrice(pindex->nReward);
    return 10 * USCENT1;
}

CAmount CDmcSystem::GetTargetPrice(CAmount reward) const
{
    CAmount targetPrice = 1 * USD1 + (reward * USD1) / (100 * COIN);

    return std::max(minTargetPrice, targetPrice);
}
<commit_msg>Raise max block reward<commit_after>#include "GrsApi.h"
#include "amount.h"
#include "chainparams.h"
#include "main.h"
#include "util.h"

#include <iostream>
#include <sstream>

#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
#include <curlpp/Infos.hpp>

#include "json/json_spirit_value.h"
#include "json/json_spirit_reader_template.h"

#include <boost/thread.hpp>

CGrsApi::CGrsApi(const std::string& baseUrl)
  : baseApiUrl(baseUrl)
{
    curlpp::initialize();
}

CGrsApi::~CGrsApi()
{
    curlpp::terminate();
}

CAmount CGrsApi::GetPrice(unsigned int time)
{
    LogPrintf("CGrsApi::GetPrice: time = %d\n", time);

    // projected prices for before-the-trading era

    if (time >= block_0_t && time < block_128002_t) {
        // genesis reward zone
        return 656 * USD1 + 35 * USCENT1;
    } else if (time >= block_128002_t && time < block_193536_t) {
        // decreasing reward zone
        return 10 * USCENT1;
    } else if (time >= block_193536_t && time < Params().LiveFeedSwitchTime()) {
        return 10 * USCENT1;
    }

    // TODO(dmc): check cached price

    // get price from the live feed
    while (true) {  //TODO(dmc): !!!
        try {
            boost::this_thread::interruption_point();
            unsigned int timestamp = 0; //TODO(dmc): must be 'time'
            CAmount price = GetGrsApiPrice(timestamp);
            LogPrintf("GRS price for timestamp: time = %d, price = %d\n", time, price);
            return price;
        } catch (const std::runtime_error& e) {
            error("Can't get GRS price for timestamp: %s\n", e.what());
        } catch (const boost::thread_interrupted& e) {
            LogPrintf("CGrsApi::GetPrice thread terminated\n");
            throw;
        }
    }
}

CAmount CGrsApi::GetLatestPrice()
{
    return 10 * USCENT1;   // STUB: 0.1USD, TODO(dmc): get actual coin price
}

CAmount CGrsApi::GetGrsApiPrice(unsigned int timestamp)
{
    LogPrintf("Getting GRS price for timestamp: time = %d\n", timestamp);
    std::ostringstream reqArgs;
    if (timestamp != 0) {
        reqArgs << timestamp;
    }
    return DoApiPriceRequest("price", reqArgs.str());
}

CAmount CGrsApi::DoApiPriceRequest(const std::string& reqName,
                                   const std::string& args)
{
    CAmount price = 0;
    int apiResponseCode = 200;

    std::ostringstream apiUrl;
    apiUrl << baseApiUrl << reqName << "/" << args;

    std::ostringstream rawResponse;
    try {
        apiResponseCode = DoApiRequest(apiUrl.str(), rawResponse);
        std::clog << "GRS API response: " << rawResponse.str() << std::endl;
    } catch (const curlpp::RuntimeError& e) {
        throw std::runtime_error(std::string(e.what())
                                 + "; url = '" + apiUrl.str() + "'"
                                 + "; response = '" + rawResponse.str() + "'");
    } catch (const curlpp::LogicError& e) {
        throw std::runtime_error(std::string(e.what())
                                 + "; url = '" + apiUrl.str() + "'"
                                 + "; response = '" + rawResponse.str() + "'");
    } catch (const std::invalid_argument& e) {
        throw std::runtime_error(std::string(e.what())
                                + "; url = '" + apiUrl.str() + "'"
                                + "; response = '" + rawResponse.str() + "'");
    } catch (const std::domain_error& e) {
        throw std::runtime_error(std::string(e.what())
                                 + "; url = '" + apiUrl.str() + "'"
                                 + "; response = '" + rawResponse.str() + "'");
    }

    if (apiResponseCode != 200) {
        std::ostringstream oss;
        oss << "apiResponseCode != 200; code = "
            << apiResponseCode
            << "; url = '" + apiUrl.str() + "'"
             + "; response = '" + rawResponse.str() + "'";
        throw std::runtime_error(oss.str());
    }

    try {
        json_spirit::Value value;
        json_spirit::read_string(rawResponse.str(), value);
        json_spirit::Object obj(value.get_obj());

        bool price_read = false;
        for(json_spirit::Object::size_type i = 0; i != obj.size(); ++i) {
            const json_spirit::Pair& pair = obj[i];
            if (pair.name_ == "price") {
                price = pair.value_.get_int();
                price_read = true;
            }
        }
        if (!price_read) {
            throw std::domain_error("No price field found");
        }
    } catch (const std::invalid_argument& e) {
        throw std::runtime_error(std::string(e.what())
                                + "; url = '" + apiUrl.str() + "'"
                                + "; response = '" + rawResponse.str() + "'");
    } catch (const std::domain_error& e) {
        throw std::runtime_error(std::string(e.what())
                                 + "; url = '" + apiUrl.str() + "'"
                                 + "; response = '" + rawResponse.str() + "'");
    }

    return price;
}

int CGrsApi::DoApiRequest(const std::string& url, std::ostringstream& oss)
{
    LogPrintf("CGrsApi::DoApiRequest: url=%s, oss.str()=%s\n", url, oss.str());
    // std::clog << "GRS API url: " << url << std::endl;

    curlpp::options::Url reqUrl(url);
    curlpp::Easy request;
    request.setOpt(curlpp::options::NoSignal(false));
    request.setOpt(reqUrl);

    curlpp::options::WriteStream ws(&oss);
    request.setOpt(ws);
    request.perform();

    return curlpp::infos::ResponseCode::get(request);
}

CDmcSystem::CDmcSystem(const std::string& apiUrl)
    : grsApi(apiUrl)
{
    genesisReward = 65535 * COIN;
    minReward = 1 * COIN;
    maxReward = 1000000 * COIN;
    minTargetPrice = 1 * USD1 + 1 * USCENT1;    // 1.01USD
}

bool CDmcSystem::CheckBlockReward(const CBlock& block, CAmount nFees, CValidationState& state, CBlockIndex* pindex)
{
    LogPrintf("CDmcSystem::CheckBlockReward: block.nTime=%d, fees=%d, hash=%s, height=%d, time=%d\n", block.nTime, nFees, pindex->phashBlock ? pindex->GetBlockHash().ToString() : "null", pindex->nHeight, pindex->nTime);

    CAmount blockOutput = block.vtx[0].GetValueOut();
    if (!blockOutput || blockOutput <= nFees) {
        return state.DoS(100,
                     error("CDmcSystem::CheckBlockReward() : coinbase pays zero or <= fees (coinbase=%d, fees=%d)",
                           blockOutput, nFees),
                           REJECT_INVALID, "bad-cb-amount");
    }
    CAmount blockReward = blockOutput - nFees;

    //TODO(dmc): temporary simplification – one GetBlockReward result comparison check
    //            should be enough in the future (the second case of "if" construction)
    if (pindex->nTime > Params().LiveFeedSwitchTime()) {
        // simplified reward checks
        CAmount prevReward = pindex->pprev ? pindex->pprev->nReward : genesisReward;
        CAmount rewDiff = std::abs(blockReward - prevReward);
        if ((rewDiff == 0 || rewDiff == 1 * COIN) &&
            (blockReward >= minReward && blockReward <= maxReward)) {
            return true;
        }
        return state.DoS(100,
                         error("CDmcSystem::CheckBlockReward() : coinbase pays wrong (actual=%d vs mustbe=%d)",
                               blockOutput, GetBlockReward(pindex) + nFees),
                               REJECT_INVALID, "bad-cb-amount");
    }

    if (blockReward != GetBlockReward(pindex)) {
        return state.DoS(100,
                     error("CDmcSystem::CheckBlockReward() : coinbase pays wrong reward (actual=%d vs mustbe=%d, fees=%d)",
                           blockReward, GetBlockReward(pindex), nFees),
                           REJECT_INVALID, "bad-cb-amount");
    }
    return true;
}

CAmount CDmcSystem::GetBlockReward(const CBlockIndex* pindex)
{
    LogPrintf("CDmcSystem::GetBlockReward: hash=%s, height=%d, time=%d\n", pindex->phashBlock ? pindex->GetBlockHash().ToString() : "null", pindex->nHeight, pindex->nTime);

    CAmount nSubsidy = 1 * COIN;

    int nHeight = pindex->nHeight;

    if (pindex->nTime > Params().LiveFeedSwitchTime()) {
        CAmount prevReward = pindex->pprev ? pindex->pprev->nReward : genesisReward;
        CAmount reward     = prevReward;
        unsigned int price = GetPrice(pindex->nTime);
        CAmount target     = GetTargetPrice(prevReward);

        if (price < target) {
            reward -= 1 * COIN;
        } else if (price > target) {
            reward += 1 * COIN;
        }
        nSubsidy = std::max(minReward, std::min(reward, maxReward));
    } else {
        if (Params().NetworkID() == CBaseChainParams::MAIN) {
            const int kGenesisRewardZone    = 128000;
            const int kGenesisReward        = 65535;
            const int kDecreasingRewardZone = kGenesisRewardZone + 1 + kGenesisReward;

            if (nHeight >= 0 && nHeight <= kGenesisRewardZone) {
                nSubsidy = kGenesisReward * COIN;
            } else if (nHeight > kGenesisRewardZone && nHeight < kDecreasingRewardZone) {
                nSubsidy = (kDecreasingRewardZone - nHeight) * COIN;
            }
        } else {
            nSubsidy = 1024 * COIN;
        }
    }

    return nSubsidy;
}

CAmount CDmcSystem::GetBlockRewardForNewTip(unsigned int time)
{
    LogPrintf("CDmcSystem::GetBlockRewardForNewTip: time=%d\n", time);
    const CBlockIndex* tip = chainActive.Tip();

    if (!tip) {
        return genesisReward;
    }

    CAmount nSubsidy = 1 * COIN;

    int nHeight = tip->nHeight + 1;

    if (tip->nTime > Params().LiveFeedSwitchTime()) {
        CAmount prevReward = tip->nReward;
        CAmount reward     = prevReward;
        unsigned int price = GetPrice(time);
        CAmount target     = GetTargetPrice(prevReward);

        if (price < target) {
            reward -= 1 * COIN;
        } else if (price > target) {
            reward += 1 * COIN;
        }
        nSubsidy = std::max(minReward, std::min(reward, maxReward));
    } else {
        if (Params().NetworkID() == CBaseChainParams::MAIN) {
            const int kGenesisRewardZone       = 128000;
            const int kGenesisReward           = 65535;
            const int kDecreasingRewardZone = kGenesisRewardZone + 1 + kGenesisReward;

            if (nHeight >= 0 && nHeight <= kGenesisRewardZone) {
                nSubsidy = kGenesisReward * COIN;
            } else if (nHeight > kGenesisRewardZone && nHeight < kDecreasingRewardZone) {
                nSubsidy = (kDecreasingRewardZone - nHeight) * COIN;
            }
        } else {
            nSubsidy = 1024 * COIN;
        }
    }

    LogPrintf("CDmcSystem::GetBlockRewardForNewTip: time=%d, nSubsidy=%d\n", time, nSubsidy);
    return nSubsidy;
}

CAmount CDmcSystem::GetBlockReward() const
{
    LOCK(cs_main);
    return chainActive.Tip()->nReward;
}

CAmount CDmcSystem::GetPrice()
{
    LOCK(cs_main);
    return grsApi.GetPrice(chainActive.Tip()->nTime);
}

CAmount CDmcSystem::GetTargetPrice() const
{
    LOCK(cs_main);
    return GetTargetPrice(chainActive.Tip()->nReward);
}

CAmount CDmcSystem::GetTotalCoins() const
{
    LOCK(cs_main);
    return chainActive.Tip()->nChainReward;
}

CAmount CDmcSystem::GetMarketCap()
{
    return (GetTotalCoins() / COIN) * GetPrice();
}

CAmount CDmcSystem::GetPrice(unsigned int time)
{
    return grsApi.GetPrice(time);
}

CAmount CDmcSystem::GetTargetPrice(unsigned int time) const
{
    //TODO(dmc): temporary simplification
//    const CBlockIndex* pindex;  // TODO(dmc): get block for time
//    return GetTargetPrice(pindex->nReward);
    return 10 * USCENT1;
}

CAmount CDmcSystem::GetTargetPrice(CAmount reward) const
{
    CAmount targetPrice = 1 * USD1 + (reward * USD1) / (100 * COIN);

    return std::max(minTargetPrice, targetPrice);
}
<|endoftext|>


<commit_before>#include "InGame.h"
#include <sstream>

InGame::InGame(Configuration& newConfig, std::unique_ptr<StartInfo> startInfo) :
	config(newConfig)
{
	loadGame(startInfo);
}

InGame::~InGame()
{
	delete interfacePtr;
	delete networkPtr;
	delete systemPtr;
}

void InGame::run()
{
	sf::RenderWindow& window = config.window;
	window.setFramerateLimit(60);

	while (window.isOpen())
	{
		//input & update phase
		systemPtr->updateQuadTree();
		networkPtr->update();

		sf::Event event;
		while (window.pollEvent(event))
		{
			if (event.type == sf::Event::Closed)
				window.close();

			if (event.type == sf::Event::KeyPressed)
			{
				if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space))
					systemPtr->interact();
			}

			interfacePtr->updateGUI(event);
		}

		//handle keyboard input, move character, interact...etc
		handleKeyboardInput();

		//if this is server, send status update to client
		if (networkPtr->isServer())
		{
			server_sendUpdate();
		}
		else //if this is client, send status update to server
		{
			client_sendUpdate();
		}

		config.cursor.update();

		//rendering phase
		window.clear();
		interfacePtr->draw();
		//window.draw(config.cursor);
		window.display();
	}
}

void InGame::loadGame(std::unique_ptr<StartInfo>& startInfo)
{
	//graphics in loading screen
	sf::RenderWindow& window = config.window;
	tgui::Gui gui;
	gui.setWindow(window);

	gui.setFont(tgui::Font(config.fontMan.get("Carlito-Bold.ttf")));

	tgui::Picture::Ptr background = std::make_shared<tgui::Picture>();
	background->setTexture(config.texMan.get("Book.png"));
	background->setSize(gui.getSize());
	gui.add(background);

	tgui::ProgressBar::Ptr progressBar = std::make_shared<tgui::ProgressBar>();
	gui.add(progressBar);
	progressBar->setPosition(50, 700);
	progressBar->setSize(930, 20);
	progressBar->setMinimum(0);
	progressBar->setMaximum(100);
	progressBar->setText("loading...0%");
	unsigned int percent = 0;

	tgui::Panel::Ptr panel = std::make_shared<tgui::Panel>();
	gui.add(panel);
	panel->setSize(820, 200);
	panel->setPosition(100, 450);
	panel->setBackgroundColor(tgui::Color(192, 192, 192, 150));

	tgui::Label::Ptr tips = std::make_shared<tgui::Label>();
	panel->add(tips);
	tips->setPosition(20, 20);
	tips->setTextSize(24);
	tips->setText("This is testing. Click cross button to leave.");

	//*************************************************************************
	//the render loop
	bool loading_complete = false;	//leave the loop when loading completed
	Connection* temp_networkPtr = new Connection;
	if (!temp_networkPtr)
	{
		throw "Failed to create network module!";
	}

	while (window.isOpen() && !loading_complete)
	{
		sf::Event event;
		while (window.pollEvent(event))
		{
			if (event.type == sf::Event::Closed)
				window.close();

			gui.handleEvent(event);
		}

		config.cursor.update();

		//if still loading, update percent
		if (percent < 0)
		{
			if (clock.getElapsedTime() > sf::seconds(0.05))
			{
				percent++;
				std::stringstream ss;
				ss << percent;
				progressBar->setText(sf::String("loading...") + sf::String(ss.str()) + sf::String("%"));
				progressBar->setValue(percent);
				clock.restart();
			}
		}
		else	//else, client: send "ready" signal to server for every 5s; server: start anyway
		{
			progressBar->setText(sf::String("waiting for server..."));
			loading_complete = waitForStart(startInfo, temp_networkPtr);
		}

		window.clear();
		gui.draw();
		window.draw(config.cursor);
		window.display();
	}
	delete temp_networkPtr;
	//*************************************************************************
	//if it is server, start server system...
	if (startInfo->type == StartInfo::TYPE::Server)
	{
		systemPtr = new Gameplay::ServerSystem(config, startInfo);
	}
	else //else it is client, start client system
	{
		systemPtr = new Gameplay::ClientSystem(config, startInfo);
	}

	//create network and interface which is pointing to the game system
	networkPtr = new Gameplay::GameNetwork(systemPtr, startInfo);

	systemPtr->setNetworkPtr(networkPtr);

	interfacePtr = new Gameplay::GameInterface(systemPtr);

	systemPtr->setInterfacePtr(interfacePtr);

	if (startInfo->type == StartInfo::TYPE::Server)
	{
		//send ready signal to every player
		//...
	}
	else //if it is a client
	{
		//wait for server's signal
	}
}

bool InGame::waitForStart(std::unique_ptr<StartInfo>& startInfoPtr, Connection * connectionPtr)
{
	if (startInfoPtr->type == StartInfo::TYPE::Server)
	{
		return true;
	}
	else
	{
		//if recevied somthing, if that's from server and the signal if "start", return true
		if (!connectionPtr->empty())
		{
			Package& package = connectionPtr->front();
			std::string signal;
			package.packet >> signal;
			if (package.ip == startInfoPtr->serverIP && signal == "start")
			{
				connectionPtr->pop();
				return true;
			}
		}
		else //else, send "ready" signal to server for every 2s
		{
			if (clock.getElapsedTime() > sf::seconds(2))
			{
				sf::Packet packet;
				packet << "ready";
				connectionPtr->send(startInfoPtr->serverIP, packet);
			}
		}
	}
	return false;
}

void InGame::handleKeyboardInput()
{
	if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Left))
	{
		systemPtr->movePlayer(config.player_name, Gameplay::Character::Direction::left);

        sf::Packet packet;
		packet << config.player_name;
        packet << "move";
        packet << "left";

		if (networkPtr->isServer())
            networkPtr->boardCast(packet);
        else
            networkPtr->send(networkPtr->getServerIP(), packet);
	}
	else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Right))
	{
		systemPtr->movePlayer(config.player_name, Gameplay::Character::Direction::right);

        sf::Packet packet;
		packet << config.player_name;
        packet << "move";
        packet << "right";

        if (networkPtr->isServer())
            networkPtr->boardCast(packet);
        else
            networkPtr->send(networkPtr->getServerIP(), packet);
	}
	else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Down))
	{
		systemPtr->movePlayer(config.player_name, Gameplay::Character::Direction::down);
        sf::Packet packet;
		packet << config.player_name;
        packet << "move";
        packet << "down";

        if (networkPtr->isServer())
            networkPtr->boardCast(packet);
        else
            networkPtr->send(networkPtr->getServerIP(), packet);
	}
	else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Up))
	{
		systemPtr->movePlayer(config.player_name, Gameplay::Character::Direction::up);

        sf::Packet packet;
		packet << config.player_name;
        packet << "move";
        packet << "up";
        if (networkPtr->isServer())
            networkPtr->boardCast(packet);
        else
            networkPtr->send(networkPtr->getServerIP(), packet);
	}
}

void InGame::client_sendUpdate()
{
	if (updateClock.getElapsedTime() > sf::seconds(2))
	{
		//update the position
		sf::Packet packet;
		packet << "setPosition";
		float x = systemPtr->getPlayerPosition().x;
		float y = systemPtr->getPlayerPosition().y;
		packet << x << y;
		networkPtr->send(networkPtr->getServerIP(), packet);
		updateClock.restart();
	}
}

void InGame::server_sendUpdate()
{

}

<commit_msg>moving function 2<commit_after>#include "InGame.h"
#include <sstream>

InGame::InGame(Configuration& newConfig, std::unique_ptr<StartInfo> startInfo) :
	config(newConfig)
{
	loadGame(startInfo);
}

InGame::~InGame()
{
	delete interfacePtr;
	delete networkPtr;
	delete systemPtr;
}

void InGame::run()
{
	sf::RenderWindow& window = config.window;
	window.setFramerateLimit(60);

	while (window.isOpen())
	{
		//input & update phase
		systemPtr->updateQuadTree();
		networkPtr->update();

		sf::Event event;
		while (window.pollEvent(event))
		{
			if (event.type == sf::Event::Closed)
				window.close();

			if (event.type == sf::Event::KeyPressed)
			{
				if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space))
					systemPtr->interact();
			}

			interfacePtr->updateGUI(event);
		}

		//handle keyboard input, move character, interact...etc
		handleKeyboardInput();

		//if this is server, send status update to client
		if (networkPtr->isServer())
		{
			server_sendUpdate();
		}
		else //if this is client, send status update to server
		{
			client_sendUpdate();
		}

		config.cursor.update();

		//rendering phase
		window.clear();
		interfacePtr->draw();
		//window.draw(config.cursor);
		window.display();
	}
}

void InGame::loadGame(std::unique_ptr<StartInfo>& startInfo)
{
	//graphics in loading screen
	sf::RenderWindow& window = config.window;
	tgui::Gui gui;
	gui.setWindow(window);

	gui.setFont(tgui::Font(config.fontMan.get("Carlito-Bold.ttf")));

	tgui::Picture::Ptr background = std::make_shared<tgui::Picture>();
	background->setTexture(config.texMan.get("Book.png"));
	background->setSize(gui.getSize());
	gui.add(background);

	tgui::ProgressBar::Ptr progressBar = std::make_shared<tgui::ProgressBar>();
	gui.add(progressBar);
	progressBar->setPosition(50, 700);
	progressBar->setSize(930, 20);
	progressBar->setMinimum(0);
	progressBar->setMaximum(100);
	progressBar->setText("loading...0%");
	unsigned int percent = 0;

	tgui::Panel::Ptr panel = std::make_shared<tgui::Panel>();
	gui.add(panel);
	panel->setSize(820, 200);
	panel->setPosition(100, 450);
	panel->setBackgroundColor(tgui::Color(192, 192, 192, 150));

	tgui::Label::Ptr tips = std::make_shared<tgui::Label>();
	panel->add(tips);
	tips->setPosition(20, 20);
	tips->setTextSize(24);
	tips->setText("This is testing. Click cross button to leave.");

	//*************************************************************************
	//the render loop
	bool loading_complete = false;	//leave the loop when loading completed
	Connection* temp_networkPtr = new Connection;
	if (!temp_networkPtr)
	{
		throw "Failed to create network module!";
	}

	while (window.isOpen() && !loading_complete)
	{
		sf::Event event;
		while (window.pollEvent(event))
		{
			if (event.type == sf::Event::Closed)
				window.close();

			gui.handleEvent(event);
		}

		config.cursor.update();

		//if still loading, update percent
		if (percent < 0)
		{
			if (clock.getElapsedTime() > sf::seconds(0.05))
			{
				percent++;
				std::stringstream ss;
				ss << percent;
				progressBar->setText(sf::String("loading...") + sf::String(ss.str()) + sf::String("%"));
				progressBar->setValue(percent);
				clock.restart();
			}
		}
		else	//else, client: send "ready" signal to server for every 5s; server: start anyway
		{
			progressBar->setText(sf::String("waiting for server..."));
			loading_complete = waitForStart(startInfo, temp_networkPtr);
		}

		window.clear();
		gui.draw();
		window.draw(config.cursor);
		window.display();
	}
	delete temp_networkPtr;
	//*************************************************************************
	//if it is server, start server system...
	if (startInfo->type == StartInfo::TYPE::Server)
	{
		systemPtr = new Gameplay::ServerSystem(config, startInfo);
	}
	else //else it is client, start client system
	{
		systemPtr = new Gameplay::ClientSystem(config, startInfo);
	}

	//create network and interface which is pointing to the game system
	networkPtr = new Gameplay::GameNetwork(systemPtr, startInfo);

	systemPtr->setNetworkPtr(networkPtr);

	interfacePtr = new Gameplay::GameInterface(systemPtr);

	systemPtr->setInterfacePtr(interfacePtr);

	if (startInfo->type == StartInfo::TYPE::Server)
	{
		//send ready signal to every player
		//...
	}
	else //if it is a client
	{
		//wait for server's signal
	}
}

bool InGame::waitForStart(std::unique_ptr<StartInfo>& startInfoPtr, Connection * connectionPtr)
{
	if (startInfoPtr->type == StartInfo::TYPE::Server)
	{
		return true;
	}
	else
	{
		//if recevied somthing, if that's from server and the signal if "start", return true
		if (!connectionPtr->empty())
		{
			Package& package = connectionPtr->front();
			std::string signal;
			package.packet >> signal;
			if (package.ip == startInfoPtr->serverIP && signal == "start")
			{
				connectionPtr->pop();
				return true;
			}
		}
		else //else, send "ready" signal to server for every 2s
		{
			if (clock.getElapsedTime() > sf::seconds(2))
			{
				sf::Packet packet;
				packet << "ready";
				connectionPtr->send(startInfoPtr->serverIP, packet);
			}
		}
	}
	return false;
}

void InGame::handleKeyboardInput()
{
	if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Left))
	{
		systemPtr->movePlayer(config.player_name, Gameplay::Character::Direction::left);

        sf::Packet packet;
        packet << "move";
		packet << config.player_name;
        packet << "left";

		if (networkPtr->isServer())
            networkPtr->boardCast(packet);
        else
            networkPtr->send(networkPtr->getServerIP(), packet);
	}
	else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Right))
	{
		systemPtr->movePlayer(config.player_name, Gameplay::Character::Direction::right);

        sf::Packet packet;
        packet << "move";
		packet << config.player_name;
        packet << "right";

        if (networkPtr->isServer())
            networkPtr->boardCast(packet);
        else
            networkPtr->send(networkPtr->getServerIP(), packet);
	}
	else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Down))
	{
		systemPtr->movePlayer(config.player_name, Gameplay::Character::Direction::down);
        sf::Packet packet;
        packet << "move";
		packet << config.player_name;
        packet << "down";

        if (networkPtr->isServer())
            networkPtr->boardCast(packet);
        else
            networkPtr->send(networkPtr->getServerIP(), packet);
	}
	else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Up))
	{
		systemPtr->movePlayer(config.player_name, Gameplay::Character::Direction::up);

        sf::Packet packet;
        packet << "move";
		packet << config.player_name;
        packet << "up";
        if (networkPtr->isServer())
            networkPtr->boardCast(packet);
        else
            networkPtr->send(networkPtr->getServerIP(), packet);
	}
}

void InGame::client_sendUpdate()
{
	if (updateClock.getElapsedTime() > sf::seconds(2))
	{
		//update the position
		sf::Packet packet;
		packet << "setPosition";
		float x = systemPtr->getPlayerPosition().x;
		float y = systemPtr->getPlayerPosition().y;
		packet << x << y;
		networkPtr->send(networkPtr->getServerIP(), packet);
		updateClock.restart();
	}
}

void InGame::server_sendUpdate()
{

}

<|endoftext|>


<commit_before>// Copyright (C) 2014 Matteo Agostini <matteo.agostini@ph.tum.de>

// This is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This software is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

// c++ libs
#include <iostream>
#include <limits>
#include <cmath>
#include <vector>

// ROOT libs
#include <TMath.h>

// m-stats libs
#include "MSMath.h"

namespace mst {

double MSMath::LogGaus(double x, double mean, double sigma) {
   // sigma must be positive
   if (sigma <= 0.0) {
      std::cerr << "MSMath::LogGaus >> error: sigma must be positive\n";
      return 0;
   }
   const double dx = (x - mean) / sigma;
   return -0.5*dx*dx - 0.5*log(2*M_PI) - log(sigma);
}

double MSMath::LogPoisson(double x, double lambda) {

   // If the parameters are negative the Poission probability is not defined
   if (lambda < 0.0 || x < 0.0) {
      std::cerr << "MSMath::LogPoisson >> error: "
                << "function not defined for negative parameters\n";
      return std::numeric_limits<double>::quiet_NaN();
   }

   // The expectation must be positive. Empty bins in the PSD should be avoided
   else if (lambda == 0.0) {
      if (x == 0) return 0;
      else        return std::numeric_limits<double>::quiet_NaN();
   }

   // Copute Poission probability for positive lambda values
   else {
      if      (x == 0)       return -lambda;
      else if (lambda < 899) return x*log(lambda)-lambda-TMath::LnGamma(x+1.);
      else                   return LogGaus(x, lambda, sqrt(lambda));
   }
}

double MSMath::LogExp (double x, double limit, double quantile, double offset) {
   // the expoential function should be normalized in the range [offset, inf] and
   // have the quantile corresponding to the desidered probablity at the limit
   // value.
   //
   // Starting from the standard exp function normalized betweeen 0 and inf:
   //
   //    f(x) = a*exp(-a*x)
   //
   // the parameter a is hence fixed by:
   //
   //    int _0 ^limit f(x) dx = quantile
   //    => a = -ln(1-quantile)/limit
   //
   // and final the frame must be changed such that 0->offset
   //
   //   => a = -ln(1-quantile)/(limit-offset)
   //   f(x) = a * exp(-a* (x-offset))

   // Check that the quantile is in the range ]0,1[
   if (quantile <= 0.0 && quantile >= 1.0) {
      std::cerr << "MSMath::Logexp >> error: "
                << "quantile must be >0 && <1\n";
      return std::numeric_limits<double>::quiet_NaN();

   // Check that the limit is above the offset
   } else if (limit <= offset) {
      std::cerr << "MSModelPullExp >> error: "
                << "the limit must be larger than the offset\n";
      return std::numeric_limits<double>::quiet_NaN();

   // Check that the parameter is in the physical range
   } else if (x < offset) {
      std::cerr << "MSMath::Logexp >> error: "
                << "parameter must be larger than the offset\n";
      return std::numeric_limits<double>::quiet_NaN();

   // compute LogExp
   } else {
      const double a = -log(1.0-quantile)/(limit-offset);
      return  log(a)-a*(x-offset);
   }
}
}
<commit_msg>changed returned values when the likelhood is not defined to push minuit away<commit_after>// Copyright (C) 2014 Matteo Agostini <matteo.agostini@ph.tum.de>

// This is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This software is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

// c++ libs
#include <iostream>
#include <limits>
#include <cmath>
#include <vector>

// ROOT libs
#include <TMath.h>

// m-stats libs
#include "MSMath.h"

namespace mst {

double MSMath::LogGaus(double x, double mean, double sigma) {
   // sigma must be positive
   if (sigma <= 0.0) {
      std::cerr << "MSMath::LogGaus >> error: sigma must be positive\n";
      return 0;
   }
   const double dx = (x - mean) / sigma;
   return -0.5*dx*dx - 0.5*log(2*M_PI) - log(sigma);
}

double MSMath::LogPoisson(double x, double lambda) {

   // If the parameters are negative the Poission probability is not defined
   if (lambda < 0.0 || x < 0.0) {
      std::cerr << "MSMath::LogPoisson >> error: "
                << "function not defined for negative parameters\n";
      return -std::numeric_limits<double>::infinity();
   }

   // The expectation must be positive. Empty bins in the PSD should be avoided
   else if (lambda == 0.0) {
      if (x == 0) return 0;
      else        return -std::numeric_limits<double>::infinity();
   }

   // Copute Poission probability for positive lambda values
   else {
      if      (x == 0)       return -lambda;
      else if (lambda < 899) return x*log(lambda)-lambda-TMath::LnGamma(x+1.);
      else                   return LogGaus(x, lambda, sqrt(lambda));
   }
}

double MSMath::LogExp (double x, double limit, double quantile, double offset) {
   // the expoential function should be normalized in the range [offset, inf] and
   // have the quantile corresponding to the desidered probablity at the limit
   // value.
   //
   // Starting from the standard exp function normalized betweeen 0 and inf:
   //
   //    f(x) = a*exp(-a*x)
   //
   // the parameter a is hence fixed by:
   //
   //    int _0 ^limit f(x) dx = quantile
   //    => a = -ln(1-quantile)/limit
   //
   // and final the frame must be changed such that 0->offset
   //
   //   => a = -ln(1-quantile)/(limit-offset)
   //   f(x) = a * exp(-a* (x-offset))

   // Check that the quantile is in the range ]0,1[
   if (quantile <= 0.0 && quantile >= 1.0) {
      std::cerr << "MSMath::Logexp >> error: "
                << "quantile must be >0 && <1\n";
      return std::numeric_limits<double>::quiet_NaN();

   // Check that the limit is above the offset
   } else if (limit <= offset) {
      std::cerr << "MSModelPullExp >> error: "
                << "the limit must be larger than the offset\n";
      return std::numeric_limits<double>::quiet_NaN();

   // Check that the parameter is in the physical range
   } else if (x < offset) {
      std::cerr << "MSMath::Logexp >> error: "
                << "parameter must be larger than the offset\n";
      return std::numeric_limits<double>::quiet_NaN();

   // compute LogExp
   } else {
      const double a = -log(1.0-quantile)/(limit-offset);
      return  log(a)-a*(x-offset);
   }
}
}
<|endoftext|>


<commit_before>//
// Matirx.hpp
// ~~~~~~~~~~
//
// Copyright (c) 2014 Rick Yang (rick68 at gmail dot com)
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

#ifndef EIGENJS_MATRIX_HPP
#define EIGENJS_MATRIX_HPP

#include <node.h>
#include <v8.h>

#include <nan.h>

#include <eigen3/Eigen/Eigen>

#include <sstream>

namespace EigenJS {

class Matrix : public node::ObjectWrap {
 public:
  static void Init(v8::Handle<v8::Object> exports) {
    NanScope();

    v8::Local<v8::FunctionTemplate> tpl = NanNew<v8::FunctionTemplate>(New);
    tpl->SetClassName(NanNew("Matrix"));
    tpl->InstanceTemplate()->SetInternalFieldCount(1);

    NODE_SET_PROTOTYPE_METHOD(tpl, "rows", rows);
    NODE_SET_PROTOTYPE_METHOD(tpl, "cols", cols);
    NODE_SET_PROTOTYPE_METHOD(tpl, "set", set);
    NODE_SET_PROTOTYPE_METHOD(tpl, "get", get);
    NODE_SET_PROTOTYPE_METHOD(tpl, "toString", toString);

    NanAssignPersistent(constructor, tpl->GetFunction());
    exports->Set(NanNew("Matrix"), tpl->GetFunction());
  }

  static NAN_METHOD(rows) {
    const Matrix* obj = node::ObjectWrap::Unwrap<Matrix>(args.This());
    NanScope();

    NanReturnValue(NanNew<v8::Integer>(obj->matrix_.rows()));
  }

  static NAN_METHOD(cols) {
    const Matrix* obj = node::ObjectWrap::Unwrap<Matrix>(args.This());
    NanScope();

    NanReturnValue(NanNew<v8::Integer>(obj->matrix_.cols()));
  }

  static NAN_METHOD(set) {
    NanScope();

    if (args.Length() == 3 &&
        args[0]->IsNumber() &&
        args[1]->IsNumber() &&
        args[2]->IsNumber()) {
      matrix_type::Index row = args[0]->Uint32Value();
      matrix_type::Index col = args[1]->Uint32Value();
      element_type value = args[2]->NumberValue();

      Matrix* obj = node::ObjectWrap::Unwrap<Matrix>(args.This());
      if (is_out_of_range(obj->matrix_, row, col))
        NanReturnUndefined();
      obj->matrix_(row, col) = value;
    }

    NanReturnValue(NanNew(args.This()));
  }

  static NAN_METHOD(get) {
    const Matrix* obj = node::ObjectWrap::Unwrap<Matrix>(args.This());
    NanScope();

    if (args.Length() == 2 &&
        args[0]->IsNumber() &&
        args[1]->IsNumber()) {
      matrix_type::Index row = args[0]->Uint32Value();
      matrix_type::Index col = args[1]->Uint32Value();
      if (is_out_of_range(obj->matrix_, row, col))
        NanReturnUndefined();
      element_type value = obj->matrix_(row, col);
      NanReturnValue(NanNew(value));
    }

    NanReturnUndefined();
  }

  static NAN_METHOD(toString) {
    const Matrix* obj = node::ObjectWrap::Unwrap<Matrix>(args.This());
    NanScope();

    std::ostringstream result;
    result << obj->matrix_;

    NanReturnValue(NanNew(result.str().c_str()));
  }

 private:
  typedef double element_type;
  typedef Eigen::Matrix<
      element_type
    , Eigen::Dynamic
    , Eigen::Dynamic
  > matrix_type;

  Matrix(matrix_type::Index rows, matrix_type::Index cols)
    : matrix_(matrix_type::Zero(rows, cols))
  {}
  ~Matrix() {}

  static NAN_METHOD(New) {
    NanScope();

    if (args.Length() < 2) {
      NanThrowError("Tried creating matrix without rows and columns arguments");
      NanReturnUndefined();
    }

    if (args.IsConstructCall()) {
      matrix_type::Index rows = args[0]->Uint32Value();
      matrix_type::Index columns = args[1]->Uint32Value();
      Matrix* obj = new Matrix(rows, columns);
      obj->Wrap(args.This());
      NanReturnValue(args.This());
    } else {
      v8::Local<v8::Function> ctr = NanNew(constructor);
      v8::Local<v8::Value> argv[] = {args[0], args[1]};
      NanReturnValue(
          ctr->NewInstance(
              sizeof(argv)/sizeof(v8::Local<v8::Value>)
            , argv
          )
      );
    }
  }

  static v8::Persistent<v8::Function> constructor;

 private:
  static bool is_out_of_range(
      const matrix_type& matrix
    , const matrix_type::Index& row
    , const matrix_type::Index& col) {
    return row < 0 || row >= matrix.rows() || col < 0 || col >= matrix.cols()
      ? NanThrowError("Row or column numbers are out of range"), true
      : false;
  }

 private:
  matrix_type matrix_;
};

v8::Persistent<v8::Function> Matrix::constructor;

}  // namespace EigenJS

#endif  // EIGENJS_MATRIX_HPP
<commit_msg>src: add 'Matrix.set()' to support Array argument<commit_after>//
// Matirx.hpp
// ~~~~~~~~~~
//
// Copyright (c) 2014 Rick Yang (rick68 at gmail dot com)
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

#ifndef EIGENJS_MATRIX_HPP
#define EIGENJS_MATRIX_HPP

#include <node.h>
#include <v8.h>

#include <nan.h>

#include <eigen3/Eigen/Eigen>

#include <sstream>

namespace EigenJS {

class Matrix : public node::ObjectWrap {
 public:
  static void Init(v8::Handle<v8::Object> exports) {
    NanScope();

    v8::Local<v8::FunctionTemplate> tpl = NanNew<v8::FunctionTemplate>(New);
    tpl->SetClassName(NanNew("Matrix"));
    tpl->InstanceTemplate()->SetInternalFieldCount(1);

    NODE_SET_PROTOTYPE_METHOD(tpl, "rows", rows);
    NODE_SET_PROTOTYPE_METHOD(tpl, "cols", cols);
    NODE_SET_PROTOTYPE_METHOD(tpl, "set", set);
    NODE_SET_PROTOTYPE_METHOD(tpl, "get", get);
    NODE_SET_PROTOTYPE_METHOD(tpl, "toString", toString);

    NanAssignPersistent(constructor, tpl->GetFunction());
    exports->Set(NanNew("Matrix"), tpl->GetFunction());
  }

  static NAN_METHOD(rows) {
    const Matrix* obj = node::ObjectWrap::Unwrap<Matrix>(args.This());
    NanScope();

    NanReturnValue(NanNew<v8::Integer>(obj->matrix_.rows()));
  }

  static NAN_METHOD(cols) {
    const Matrix* obj = node::ObjectWrap::Unwrap<Matrix>(args.This());
    NanScope();

    NanReturnValue(NanNew<v8::Integer>(obj->matrix_.cols()));
  }

  static NAN_METHOD(set) {
    Matrix* obj = node::ObjectWrap::Unwrap<Matrix>(args.This());
    NanScope();

    if (args.Length() == 1 && args[0]->IsArray()) {
      v8::Local<v8::Array> array = args[0].As<v8::Array>();
      uint32_t len = array->Length();
      const matrix_type::Index& rows = obj->matrix_.rows();

      for (uint32_t i = 0; i < len; ++i) {
        v8::Local<v8::Value> elem = array->Get(i);
        obj->matrix_(i / rows, i % rows) = elem->NumberValue();
      }
    } else if (
        args.Length() == 3 &&
        args[0]->IsNumber() &&
        args[1]->IsNumber() &&
        args[2]->IsNumber()) {
      matrix_type::Index row = args[0]->Uint32Value();
      matrix_type::Index col = args[1]->Uint32Value();
      element_type value = args[2]->NumberValue();

      if (is_out_of_range(obj->matrix_, row, col))
        NanReturnUndefined();

      obj->matrix_(row, col) = value;
    }

    NanReturnValue(NanNew(args.This()));
  }

  static NAN_METHOD(get) {
    const Matrix* obj = node::ObjectWrap::Unwrap<Matrix>(args.This());
    NanScope();

    if (args.Length() == 2 &&
        args[0]->IsNumber() &&
        args[1]->IsNumber()) {
      matrix_type::Index row = args[0]->Uint32Value();
      matrix_type::Index col = args[1]->Uint32Value();
      if (is_out_of_range(obj->matrix_, row, col))
        NanReturnUndefined();
      element_type value = obj->matrix_(row, col);
      NanReturnValue(NanNew(value));
    }

    NanReturnUndefined();
  }

  static NAN_METHOD(toString) {
    const Matrix* obj = node::ObjectWrap::Unwrap<Matrix>(args.This());
    NanScope();

    std::ostringstream result;
    result << obj->matrix_;

    NanReturnValue(NanNew(result.str().c_str()));
  }

 private:
  typedef double element_type;
  typedef Eigen::Matrix<
      element_type
    , Eigen::Dynamic
    , Eigen::Dynamic
  > matrix_type;

  Matrix(matrix_type::Index rows, matrix_type::Index cols)
    : matrix_(matrix_type::Zero(rows, cols))
  {}
  ~Matrix() {}

  static NAN_METHOD(New) {
    NanScope();

    if (args.Length() < 2) {
      NanThrowError("Tried creating matrix without rows and columns arguments");
      NanReturnUndefined();
    }

    if (args.IsConstructCall()) {
      matrix_type::Index rows = args[0]->Uint32Value();
      matrix_type::Index columns = args[1]->Uint32Value();
      Matrix* obj = new Matrix(rows, columns);
      obj->Wrap(args.This());
      NanReturnValue(args.This());
    } else {
      v8::Local<v8::Function> ctr = NanNew(constructor);
      v8::Local<v8::Value> argv[] = {args[0], args[1]};
      NanReturnValue(
          ctr->NewInstance(
              sizeof(argv)/sizeof(v8::Local<v8::Value>)
            , argv
          )
      );
    }
  }

  static v8::Persistent<v8::Function> constructor;

 private:
  static bool is_out_of_range(
      const matrix_type& matrix
    , const matrix_type::Index& row
    , const matrix_type::Index& col) {
    return row < 0 || row >= matrix.rows() || col < 0 || col >= matrix.cols()
      ? NanThrowError("Row or column numbers are out of range"), true
      : false;
  }

 private:
  matrix_type matrix_;
};

v8::Persistent<v8::Function> Matrix::constructor;

}  // namespace EigenJS

#endif  // EIGENJS_MATRIX_HPP
<|endoftext|>


<commit_before>// [[Rcpp::depends(BH)]]

#include "Random.h"

#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_01.hpp>
#include <boost/random/uniform_real_distribution.hpp>
#include <boost/random/normal_distribution.hpp>
#include <boost/random/poisson_distribution.hpp>
#include <boost/random/exponential_distribution.hpp>

#include <boost/math/distributions/gamma.hpp>
#include <boost/math/distributions/normal.hpp>
#include <boost/math/distributions/exponential.hpp>

#include <stdint.h>

#define Q_GAMMA_THRESHOLD 1E-6
#define Q_GAMMA_MIN_VALUE 0.0

typedef boost::random::mt19937 RNGType;
//typedef boost::random::mt11213b RNGType; // should be faster
static RNGType rng;

void gaps::random::setSeed(uint32_t seed)
{
    rng.seed(seed);
}

double gaps::random::normal(double mean, double var)
{
    boost::random::normal_distribution<double> dist(mean, var);
    return dist(rng);
}

int gaps::random::poisson(double lambda)
{
    boost::random::poisson_distribution<> dist(lambda);
    return dist(rng);
}

double gaps::random::exponential(double lambda)
{
    boost::random::exponential_distribution<> dist(lambda);
    return dist(rng);
}

double gaps::random::uniform()
{
    boost::random::uniform_01<RNGType&> dist(rng); // could be moved out
    return dist();
}

double gaps::random::uniform(double a, double b)
{
    if (a == b)
    {
        return a;
    }
    else if (a < b)
    {
        boost::random::uniform_real_distribution<> dist(a,b);
        return dist(rng);
    }
}

uint64_t gaps::random::uniform64()
{
    boost::random::uniform_int_distribution<uint64_t> dist(0,
        std::numeric_limits<uint64_t>::max());
    return dist(rng);
}

uint64_t gaps::random::uniform64(uint64_t a, uint64_t b)
{
    if (a == b)
    {
        return a;
    }
    else if (a < b)
    {
        boost::random::uniform_int_distribution<uint64_t> dist(a,b);
        return dist(rng);
    }
}

double gaps::random::d_gamma(double d, double shape, double scale)
{
    boost::math::gamma_distribution<> gam(shape, scale);
    return pdf(gam, d);
}

double gaps::random::p_gamma(double p, double shape, double scale)
{
    boost::math::gamma_distribution<> gam(shape, scale);
    return cdf(gam, p);
}

double gaps::random::q_gamma(double q, double shape, double scale)
{
    if (q < Q_GAMMA_THRESHOLD)
    {
        return Q_GAMMA_MIN_VALUE;
    }
    else
    {
        boost::math::gamma_distribution<> gam(shape, scale);
        return quantile(gam, q);
    }
}

double gaps::random::d_norm(double d, double mean, double sd)
{
    boost::math::normal_distribution<> norm(mean, sd);
    return pdf(norm, d);
}

double gaps::random::q_norm(double q, double mean, double sd)
{
    boost::math::normal_distribution<> norm(mean, sd);
    return quantile(norm, q);
}

double gaps::random::p_norm(double p, double mean, double sd)
{
    boost::math::normal_distribution<> norm(mean, sd);
    return cdf(norm, p);
}

<commit_msg>disable optimization around boost - needed for valgrind<commit_after>// [[Rcpp::depends(BH)]]

// needed to run in valgrind
#pragma GCC push_options
#pragma GCC optimize ("O0")

#include "Random.h"

#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_01.hpp>
#include <boost/random/uniform_real_distribution.hpp>
#include <boost/random/normal_distribution.hpp>
#include <boost/random/poisson_distribution.hpp>
#include <boost/random/exponential_distribution.hpp>

#include <boost/math/distributions/gamma.hpp>
#include <boost/math/distributions/normal.hpp>
#include <boost/math/distributions/exponential.hpp>

#include <stdint.h>

#define Q_GAMMA_THRESHOLD 1E-6
#define Q_GAMMA_MIN_VALUE 0.0

typedef boost::random::mt19937 RNGType;
//typedef boost::random::mt11213b RNGType; // should be faster
static RNGType rng;

void gaps::random::setSeed(uint32_t seed)
{
    rng.seed(seed);
}

double gaps::random::normal(double mean, double var)
{
    boost::random::normal_distribution<double> dist(mean, var);
    return dist(rng);
}

int gaps::random::poisson(double lambda)
{
    boost::random::poisson_distribution<> dist(lambda);
    return dist(rng);
}

double gaps::random::exponential(double lambda)
{
    boost::random::exponential_distribution<> dist(lambda);
    return dist(rng);
}

double gaps::random::uniform()
{
    boost::random::uniform_01<RNGType&> dist(rng); // could be moved out
    return dist();
}

double gaps::random::uniform(double a, double b)
{
    if (a == b)
    {
        return a;
    }
    else if (a < b)
    {
        boost::random::uniform_real_distribution<> dist(a,b);
        return dist(rng);
    }
}

uint64_t gaps::random::uniform64()
{
    boost::random::uniform_int_distribution<uint64_t> dist(0,
        std::numeric_limits<uint64_t>::max());
    return dist(rng);
}

uint64_t gaps::random::uniform64(uint64_t a, uint64_t b)
{
    if (a == b)
    {
        return a;
    }
    else if (a < b)
    {
        boost::random::uniform_int_distribution<uint64_t> dist(a,b);
        return dist(rng);
    }
}

double gaps::random::d_gamma(double d, double shape, double scale)
{
    boost::math::gamma_distribution<> gam(shape, scale);
    return pdf(gam, d);
}

double gaps::random::p_gamma(double p, double shape, double scale)
{
    boost::math::gamma_distribution<> gam(shape, scale);
    return cdf(gam, p);
}

double gaps::random::q_gamma(double q, double shape, double scale)
{
    if (q < Q_GAMMA_THRESHOLD)
    {
        return Q_GAMMA_MIN_VALUE;
    }
    else
    {
        boost::math::gamma_distribution<> gam(shape, scale);
        return quantile(gam, q);
    }
}

double gaps::random::d_norm(double d, double mean, double sd)
{
    boost::math::normal_distribution<> norm(mean, sd);
    return pdf(norm, d);
}

double gaps::random::q_norm(double q, double mean, double sd)
{
    boost::math::normal_distribution<> norm(mean, sd);
    return quantile(norm, q);
}

double gaps::random::p_norm(double p, double mean, double sd)
{
    boost::math::normal_distribution<> norm(mean, sd);
    return cdf(norm, p);
}

#pragma GCC pop_options<|endoftext|>


<commit_before>#include <SDL.h>
#include <iostream>
#include "SnakeEngine.h"
#include <vector>

const int SCREEN_WIDTH = 1920;
const int SCREEN_HEIGHT = 1200;

//const int SCREEN_WIDTH = 1366;
//const int SCREEN_HEIGHT = 768;

const int SNAKE_GRID_WIDTH = BOARD_WIDTH;
const int SNAKE_GRID_HEIGHT = BOARD_HEIGHT;

const int SNAKE_CELL_W_PX = SCREEN_WIDTH/SNAKE_GRID_WIDTH;
const int SNAKE_CELL_H_PX = SCREEN_HEIGHT/SNAKE_GRID_HEIGHT;

// Fixed game logic step
const Uint32 TICK_STEP = 60; // ms

void updateRects(std::vector<SDL_Rect>* rectVec, std::vector<SnakeEngine::BoardPos*>* snakeVec)
{
	int numRects = rectVec->size();
	int numSnakeSquares = snakeVec->size();

	// Just fill rectVec with sufficient rectangles at first
	while (numSnakeSquares > numRects) {
		SDL_Rect fillerRect;
		fillerRect.w = SNAKE_CELL_W_PX;
		fillerRect.h = SNAKE_CELL_H_PX;

		rectVec->insert(rectVec->begin(), fillerRect);
		numRects = rectVec->size();
	}

	int rectVecIndex = 0;
	for (auto& pos : *snakeVec) {
		int gridX = pos->x;
		int gridY = pos->y;

		int screenX = gridX*SNAKE_CELL_W_PX;
		int screenY = gridY*SNAKE_CELL_H_PX;

		rectVec->at(rectVecIndex).x = screenX;
		rectVec->at(rectVecIndex).y = screenY;

		rectVecIndex++;
	}
}

int main(int arc, char* argv[])
{
	// Create SnakeEngine object, which is responsible for all game logic
	SnakeEngine engine(SnakeEngine::NORTH);

	///////////////////////////////////////////////////////
	// Init a bunch of SDL stuff (graphics and user input)
	///////////////////////////////////////////////////////

	// INIT engine
	if (SDL_Init(SDL_INIT_EVERYTHING) == -1) {
		std::cout << SDL_GetError() << std::endl;
		return 1;
	}

	// Make the window
	SDL_Window *screen = nullptr;
	screen = SDL_CreateWindow("MaxGFX Extreme",
		0,
		0,
		SCREEN_WIDTH,
		SCREEN_HEIGHT,
		SDL_WINDOW_FULLSCREEN);

	if (screen == nullptr) {
		std::cout << SDL_GetError() << std::endl;
		return 1;
	}

	// Make the renderer
	SDL_Renderer *renderer = nullptr;
	renderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED);
	if (renderer == nullptr) {
		std::cout << SDL_GetError() << std::endl;
		return 1;
	}

	// Make event object to receive input events
	SDL_Event event;

	// Set background to black
	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
	SDL_RenderClear(renderer);

	// Create a vector for holding all SDL_Rects needed to draw snake
	std::vector<SDL_Rect> snakeRects;

	// Fill it
	updateRects(&snakeRects, engine.getSnakeVector());

	// Create a rect for an apple
	SDL_Rect appleRect;
	appleRect.w = SNAKE_CELL_W_PX;
	appleRect.h = SNAKE_CELL_H_PX;
	appleRect.x = engine.getAppleX()*SNAKE_CELL_W_PX;
	appleRect.y = engine.getAppleY()*SNAKE_CELL_H_PX;

	// Remove the cursor and set a delay for the startup
	SDL_ShowCursor(0);
	SDL_Delay(500);

	///////////////////////////////////////////////////////
	// GAME LOOP
	///////////////////////////////////////////////////////
	bool running = true;
	Uint32 lastTick = SDL_GetTicks()-100;
	bool doTick = true;
	while (running)
	{
		// Checks for input events, such as clicking "X"/close on the window or keyboard input
		if (SDL_PollEvent(&event))
		{
			if (event.type == SDL_QUIT)
			{
				running = false;
			}
			if (event.type == SDL_KEYDOWN)
			{
				switch(event.key.keysym.sym) {
				case SDLK_ESCAPE:
					running = false;
					break;
				case SDLK_w:
					engine.setDirection(SnakeEngine::NORTH);
					break;
				case SDLK_a:
					engine.setDirection(SnakeEngine::WEST);
					break;
				case SDLK_s:
					engine.setDirection(SnakeEngine::SOUTH);
					break;
				case SDLK_d:
					engine.setDirection(SnakeEngine::EAST);
					break;
				}

			}

		}

		// Game logic
		if (!doTick) {
			if ((SDL_GetTicks() - lastTick) > TICK_STEP) {
				doTick = true;
				lastTick = SDL_GetTicks();
			}
		}

		if (doTick) {
			engine.tick();
			doTick = false;

			if (engine.hasCrashed()) {
				running = false;
				SDL_Delay(1000);
			}
		}

		// Rendering
		updateRects(&snakeRects, engine.getSnakeVector());

		appleRect.x = engine.getAppleX()*SNAKE_CELL_W_PX;
		appleRect.y = engine.getAppleY()*SNAKE_CELL_H_PX;

		// Set background to black and clear
		SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
		SDL_RenderClear(renderer);

		// Draw snake
		SDL_SetRenderDrawColor(renderer, 12, 172, 12, 255);
		for (auto& rect : snakeRects) {
			SDL_RenderFillRect(renderer, &rect);
		}

		// Draw an apple
		SDL_SetRenderDrawColor(renderer, 202, 3, 3, 255);
		SDL_RenderFillRect(renderer, &appleRect);

		SDL_RenderPresent(renderer);
	}

	SDL_DestroyRenderer(renderer);
	SDL_DestroyWindow(screen);

	SDL_Quit();

	return 0;
}<commit_msg>No longer needed Source.cpp, now main.cpp<commit_after><|endoftext|>


<commit_before>// Vaca - Visual Application Components Abstraction
// Copyright (c) 2005-2009 David Capello
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in
//   the documentation and/or other materials provided with the
//   distribution.
// * Neither the name of the author nor the names of its contributors
//   may be used to endorse or promote products derived from this
//   software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

#include "Vaca/System.h"
#include "Vaca/Rect.h"
#include "Vaca/Point.h"
#include "Vaca/Size.h"
#include "Vaca/Color.h"
#include "Vaca/Debug.h"
#include "Vaca/ImageList.h"
#include "Vaca/Mutex.h"
#include "Vaca/ScopedLock.h"

#include <lmcons.h>

using namespace Vaca;

/// Returns the parameters in the command line.
///
/// @c System::getArgs()[0] is the name of the executable file.
///
std::vector<String> System::getArgs()
{
  // Convert the command-line to a vector of arguments...
  std::vector<String> args;

  Char* cmdline = wcsdup(GetCommandLine());
  Char quote;

  for (int i = 0; cmdline[i] != 0; ) {
    // eat spaces
    while (cmdline[i] != 0 && iswspace(cmdline[i]))
      ++i;

    // string with quotes?
    if (cmdline[i] == '\"' || cmdline[i] == '\'')
      quote = cmdline[i++];
    else if (cmdline[i] == 0)
      break;
    else
      quote = 0;

    // read the string
    String arg;

    for (; cmdline[i] != 0; ++i) {
      // with quotes
      if (quote != 0) {
	if (cmdline[i] == quote) {
	  ++i;
	  break;
	}
	else if (cmdline[i] == '\\' && cmdline[i+1] == quote)
	  ++i;
      }
      // without quotes
      else if (iswspace(cmdline[i]))
	break;

      arg.push_back(cmdline[i]);
    }

    args.push_back(arg);
  }

  std::free(cmdline);
  return args;
}

/// Prints a line in the console.
///
void System::println(String line)
{
#ifdef _UNICODE
  _putws(line.c_str());
#else
  puts(line.c_str());
#endif
}

void System::printf(LPCTSTR fmt, ...)
{
  Char buf[1024];		// TODO: overflow
  va_list ap;

  va_start(ap, fmt);
#ifdef UNICODE
  vswprintf(buf, fmt, ap);
#else
  vsprintf(buf, fmt, ap);
#endif
  va_end(ap);

#ifdef UNICODE
  fputws(buf, stdout);
#else
  fputs(buf, stdout);
#endif
}

void System::print(String buf)
{
#ifdef UNICODE
  fputws(buf.c_str(), stdout);
#else
  fputs(buf.c_str(), stdout);
#endif
}

String System::getCurrentDirectory()
{
  Char* buf = new Char[MAX_PATH];

  if (GetCurrentDirectory(MAX_PATH, buf) > 0)
    return String(buf);
  else
    return L"";
}

String System::getWindowsDirectory()
{
  Char* buf = new Char[MAX_PATH];

  if (GetWindowsDirectory(buf, MAX_PATH) > 0)
    return String(buf);
  else
    return L"";
}

///
/// TODO folderCsidl can't be a virtual folder
///
/// CSIDL_ADMINTOOLS
/// CSIDL_ALTSTARTUP
/// CSIDL_APPDATA
/// CSIDL_BITBUCKET
/// CSIDL_CDBURN_AREA
/// CSIDL_COMMON_ADMINTOOLS
/// CSIDL_COMMON_ALTSTARTUP
/// CSIDL_COMMON_APPDATA
/// CSIDL_COMMON_DESKTOPDIRECTORY
/// CSIDL_COMMON_DOCUMENTS
/// CSIDL_COMMON_FAVORITES
/// CSIDL_COMMON_MUSIC
/// CSIDL_COMMON_OEM_LINKS
/// CSIDL_COMMON_PICTURES
/// CSIDL_COMMON_PROGRAMS
/// CSIDL_COMMON_STARTMENU
/// CSIDL_COMMON_STARTUP
/// CSIDL_COMMON_TEMPLATES
/// CSIDL_COMMON_VIDEO
/// CSIDL_COMPUTERSNEARME
/// CSIDL_CONNECTIONS
/// CSIDL_CONTROLS
/// CSIDL_COOKIES
/// CSIDL_DESKTOP
/// CSIDL_DESKTOPDIRECTORY
/// CSIDL_DRIVES
/// CSIDL_FAVORITES
/// CSIDL_FONTS
/// CSIDL_HISTORY
/// CSIDL_INTERNET
/// CSIDL_INTERNET_CACHE
/// CSIDL_LOCAL_APPDATA
/// CSIDL_MYPICTURES
/// CSIDL_NETHOOD
/// CSIDL_NETWORK
/// CSIDL_PERSONAL
/// CSIDL_PRINTERS
/// CSIDL_PRINTHOOD
/// CSIDL_PROFILE
/// CSIDL_PROGRAMS
/// CSIDL_PROGRAM_FILES
/// CSIDL_PROGRAM_FILESX86
/// CSIDL_PROGRAM_FILES_COMMON
/// CSIDL_PROGRAM_FILES_COMMONX86
/// CSIDL_RECENT
/// CSIDL_RESOURCES
/// CSIDL_RESOURCES_LOCALIZED
/// CSIDL_SENDTO
/// CSIDL_STARTMENU
/// CSIDL_STARTUP
/// CSIDL_SYSTEM
/// CSIDL_SYSTEMX86
/// CSIDL_TEMPLATES
/// CSIDL_WINDOWS
///
String System::getShellFolderPath(int folderCsidl, bool create)
{
  Char* buf = new Char[MAX_PATH];

  if (SHGetSpecialFolderPath(NULL, buf, folderCsidl, create))
    return String(buf);
  else
    return L"";
}

ImageList System::getImageList(bool smallImage)
{
  HIMAGELIST himl;
  SHFILEINFO shfi;

  himl = reinterpret_cast<HIMAGELIST>
    (SHGetFileInfo(L"",
		   0, &shfi, sizeof(shfi),
		   SHGFI_SYSICONINDEX |
		   (smallImage ? SHGFI_SMALLICON:
				 SHGFI_LARGEICON)));

  return ImageList(himl); // TODO this can't be delete!!!
}

int System::getFileImageIndex(const String& fileName, bool smallImage)
{
  SHFILEINFO shfi;

  SHGetFileInfo(fileName.c_str(), 0, &shfi, sizeof(shfi),
		SHGFI_SYSICONINDEX |
		(smallImage ? SHGFI_SMALLICON:
			      SHGFI_LARGEICON));

  return shfi.iIcon;
}

/// Returns the screen size.
///
Size System::getScreenSize()
{
  return Size(GetSystemMetrics(SM_CXFULLSCREEN),
	      GetSystemMetrics(SM_CYFULLSCREEN));
}

/// Returns the work-area of the screen, it is like the desktop area,
/// that is not overlapped by the task-bar.
///
/// @warning
///   Win32: It is a call to @msdn{SystemParametersInfo} using
///   @msdn{SPI_GETWORKAREA}.
///
Rect System::getWorkAreaBounds()
{
  RECT rc;

  // returns the work-area rectangle
  if (SystemParametersInfo(SPI_GETWORKAREA, 0, reinterpret_cast<PVOID>(&rc), 0))
    return Rect(&rc);
  // returns the full-screen rectangle
  else
    return Rect(Point(0, 0), System::getScreenSize());
}

/// Returns color from the system. It's a wrapper for the Win32's GetSysColor.
///
/// @param index
///     Can be one of the following values:
///     @li COLOR_3DDKSHADOW
///     @li COLOR_3DFACE
///     @li COLOR_3DHILIGHT
///     @li COLOR_3DHIGHLIGHT
///     @li COLOR_3DLIGHT
///     @li COLOR_BTNHILIGHT
///     @li COLOR_3DSHADOW
///     @li COLOR_ACTIVEBORDER
///     @li COLOR_ACTIVECAPTION
///     @li COLOR_APPWORKSPACE
///     @li COLOR_BACKGROUND
///     @li COLOR_DESKTOP
///     @li COLOR_BTNFACE
///     @li COLOR_BTNHIGHLIGHT
///     @li COLOR_BTNSHADOW
///     @li COLOR_BTNTEXT
///     @li COLOR_CAPTIONTEXT
///     @li COLOR_GRAYTEXT
///     @li COLOR_HIGHLIGHT
///     @li COLOR_HIGHLIGHTTEXT
///     @li COLOR_INACTIVEBORDER
///     @li COLOR_INACTIVECAPTION
///     @li COLOR_INACTIVECAPTIONTEXT
///     @li COLOR_INFOBK
///     @li COLOR_INFOTEXT
///     @li COLOR_MENU
///     @li COLOR_MENUTEXT
///     @li COLOR_SCROLLBAR
///     @li COLOR_WINDOW
///     @li COLOR_WINDOWFRAME
///     @li COLOR_WINDOWTEXT
///     @li COLOR_HOTLIGHT
///     @li COLOR_GRADIENTACTIVECAPTION
///     @li COLOR_GRADIENTINACTIVECAPTION
///
/// @todo make the index a Enum
///
Color System::getColor(int index)
{
  return Color(GetSysColor(index));
}

bool System::getKeyState(Keys::Type keyCode)
{
  // you can't use getKeyState for modifiers
  assert((keyCode & Keys::Modifiers) == 0);

  return (GetKeyState(keyCode) & 0x8000) != 0;
}

/// Returns the cursor position in the screen.
///
Point System::getCursorPos()
{
  POINT pt;
  GetCursorPos(&pt);
  return Point(pt.x, pt.y);
}

void System::setCursorPos(const Point& pt)
{
  SetCursorPos(pt.x, pt.y);
}

String System::getUserName()
{
  Char buf[UNLEN+1];
  // char buf[UNLEN+1];
  DWORD len = UNLEN+1;

  if (GetUserName(buf, &len))
    return String(buf);
  else
    return String();
}

// Prototypes for Win2000/XP API
// typedef BOOLEAN (*GUNEProc)(EXTENDED_NAME_FORMAT NameFormat, LPTSTR lpNameBuffer, PULONG nSize);

String System::getFriendlyUserName()
{
#if 0				// TODO
#if (_WIN32_WINNT >= 0x0500)
  HMODULE hSecur32 = GetModuleHandle(L"SECUR32.DLL");
  if (!hSecur32)
    hSecur32 = LoadLibrary(L"SECUR32.DLL");
  GUNEProc pGUNE = (GUNEProc)GetProcAddress(hSecur32, "GetUserNameExW");

  if (pGUNE != NULL) {
    Char buf[UNLEN+1];
    ULONG len = UNLEN+1;

    if (pGUNE(NameDisplay, buf, &len))
      return String(buf);
  }
#endif
#endif
  return getUserName();
}

// int System::getWheelScrollLines()
// {
//   UINT pulScrollLines = 0;
//   return SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &pulScrollLines, 0);
// }

int System::getOS()
{
  static Mutex mutex;
  static volatile OS::Type cached = OS::Unknown;

  ScopedLock hold(mutex);

  if (cached != OS::Unknown)
    return cached;

  OSVERSIONINFOEX osvi;
  BOOL bOsVersionInfoEx;

  ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

  if (!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*)&osvi))) {
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    if (!GetVersionEx((OSVERSIONINFO*)&osvi))
      return OS::Unknown;
  }

  switch (osvi.dwPlatformId) {

    case VER_PLATFORM_WIN32_NT:
      if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
	return cached = OS::WinServer2003;
      else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
	return cached = OS::WinXP;
      else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
	return cached = OS::Win2K;
      else if (osvi.dwMajorVersion <= 4)
	return cached = OS::WinNT;
      break;

    case VER_PLATFORM_WIN32_WINDOWS:
      if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) {
	if (osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B')
	  return cached = OS::Win95R2;
	else
	  return cached = OS::Win95;
      }
      else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) {
	if (osvi.szCSDVersion[1] == 'A')
	  return cached = OS::Win98SE;
	else
	  return cached = OS::Win98;
      }
      else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
	return cached = OS::WinMe;
      break;

    case VER_PLATFORM_WIN32s:
      return cached = OS::Win32s;
  }

  return cached = OS::Unknown;
}

bool System::isWin95_98_Me()
{
  return (getOS() & (OS::Win95 | OS::Win98 | OS::WinMe)) != 0;
}

bool System::isWinNT_2K_XP()
{
  return (getOS() & (OS::WinNT | OS::Win2K | OS::WinXP | OS::WinServer2003)) != 0;
}

bool System::isWin2K_XP()
{
  return (getOS() & (OS::Win2K | OS::WinXP | OS::WinServer2003)) != 0;
}

bool System::isWinXP()
{
  return (getOS() & OS::WinXP) != 0;
}
<commit_msg>Fixed System::getWorkAreaBounds() documentation.<commit_after>// Vaca - Visual Application Components Abstraction
// Copyright (c) 2005-2009 David Capello
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in
//   the documentation and/or other materials provided with the
//   distribution.
// * Neither the name of the author nor the names of its contributors
//   may be used to endorse or promote products derived from this
//   software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

#include "Vaca/System.h"
#include "Vaca/Rect.h"
#include "Vaca/Point.h"
#include "Vaca/Size.h"
#include "Vaca/Color.h"
#include "Vaca/Debug.h"
#include "Vaca/ImageList.h"
#include "Vaca/Mutex.h"
#include "Vaca/ScopedLock.h"

#include <lmcons.h>

using namespace Vaca;

/// Returns the parameters in the command line.
///
/// @c System::getArgs()[0] is the name of the executable file.
///
std::vector<String> System::getArgs()
{
  // Convert the command-line to a vector of arguments...
  std::vector<String> args;

  Char* cmdline = wcsdup(GetCommandLine());
  Char quote;

  for (int i = 0; cmdline[i] != 0; ) {
    // eat spaces
    while (cmdline[i] != 0 && iswspace(cmdline[i]))
      ++i;

    // string with quotes?
    if (cmdline[i] == '\"' || cmdline[i] == '\'')
      quote = cmdline[i++];
    else if (cmdline[i] == 0)
      break;
    else
      quote = 0;

    // read the string
    String arg;

    for (; cmdline[i] != 0; ++i) {
      // with quotes
      if (quote != 0) {
	if (cmdline[i] == quote) {
	  ++i;
	  break;
	}
	else if (cmdline[i] == '\\' && cmdline[i+1] == quote)
	  ++i;
      }
      // without quotes
      else if (iswspace(cmdline[i]))
	break;

      arg.push_back(cmdline[i]);
    }

    args.push_back(arg);
  }

  std::free(cmdline);
  return args;
}

/// Prints a line in the console.
///
void System::println(String line)
{
#ifdef _UNICODE
  _putws(line.c_str());
#else
  puts(line.c_str());
#endif
}

void System::printf(LPCTSTR fmt, ...)
{
  Char buf[1024];		// TODO: overflow
  va_list ap;

  va_start(ap, fmt);
#ifdef UNICODE
  vswprintf(buf, fmt, ap);
#else
  vsprintf(buf, fmt, ap);
#endif
  va_end(ap);

#ifdef UNICODE
  fputws(buf, stdout);
#else
  fputs(buf, stdout);
#endif
}

void System::print(String buf)
{
#ifdef UNICODE
  fputws(buf.c_str(), stdout);
#else
  fputs(buf.c_str(), stdout);
#endif
}

String System::getCurrentDirectory()
{
  Char* buf = new Char[MAX_PATH];

  if (GetCurrentDirectory(MAX_PATH, buf) > 0)
    return String(buf);
  else
    return L"";
}

String System::getWindowsDirectory()
{
  Char* buf = new Char[MAX_PATH];

  if (GetWindowsDirectory(buf, MAX_PATH) > 0)
    return String(buf);
  else
    return L"";
}

///
/// TODO folderCsidl can't be a virtual folder
///
/// CSIDL_ADMINTOOLS
/// CSIDL_ALTSTARTUP
/// CSIDL_APPDATA
/// CSIDL_BITBUCKET
/// CSIDL_CDBURN_AREA
/// CSIDL_COMMON_ADMINTOOLS
/// CSIDL_COMMON_ALTSTARTUP
/// CSIDL_COMMON_APPDATA
/// CSIDL_COMMON_DESKTOPDIRECTORY
/// CSIDL_COMMON_DOCUMENTS
/// CSIDL_COMMON_FAVORITES
/// CSIDL_COMMON_MUSIC
/// CSIDL_COMMON_OEM_LINKS
/// CSIDL_COMMON_PICTURES
/// CSIDL_COMMON_PROGRAMS
/// CSIDL_COMMON_STARTMENU
/// CSIDL_COMMON_STARTUP
/// CSIDL_COMMON_TEMPLATES
/// CSIDL_COMMON_VIDEO
/// CSIDL_COMPUTERSNEARME
/// CSIDL_CONNECTIONS
/// CSIDL_CONTROLS
/// CSIDL_COOKIES
/// CSIDL_DESKTOP
/// CSIDL_DESKTOPDIRECTORY
/// CSIDL_DRIVES
/// CSIDL_FAVORITES
/// CSIDL_FONTS
/// CSIDL_HISTORY
/// CSIDL_INTERNET
/// CSIDL_INTERNET_CACHE
/// CSIDL_LOCAL_APPDATA
/// CSIDL_MYPICTURES
/// CSIDL_NETHOOD
/// CSIDL_NETWORK
/// CSIDL_PERSONAL
/// CSIDL_PRINTERS
/// CSIDL_PRINTHOOD
/// CSIDL_PROFILE
/// CSIDL_PROGRAMS
/// CSIDL_PROGRAM_FILES
/// CSIDL_PROGRAM_FILESX86
/// CSIDL_PROGRAM_FILES_COMMON
/// CSIDL_PROGRAM_FILES_COMMONX86
/// CSIDL_RECENT
/// CSIDL_RESOURCES
/// CSIDL_RESOURCES_LOCALIZED
/// CSIDL_SENDTO
/// CSIDL_STARTMENU
/// CSIDL_STARTUP
/// CSIDL_SYSTEM
/// CSIDL_SYSTEMX86
/// CSIDL_TEMPLATES
/// CSIDL_WINDOWS
///
String System::getShellFolderPath(int folderCsidl, bool create)
{
  Char* buf = new Char[MAX_PATH];

  if (SHGetSpecialFolderPath(NULL, buf, folderCsidl, create))
    return String(buf);
  else
    return L"";
}

ImageList System::getImageList(bool smallImage)
{
  HIMAGELIST himl;
  SHFILEINFO shfi;

  himl = reinterpret_cast<HIMAGELIST>
    (SHGetFileInfo(L"",
		   0, &shfi, sizeof(shfi),
		   SHGFI_SYSICONINDEX |
		   (smallImage ? SHGFI_SMALLICON:
				 SHGFI_LARGEICON)));

  return ImageList(himl); // TODO this can't be delete!!!
}

int System::getFileImageIndex(const String& fileName, bool smallImage)
{
  SHFILEINFO shfi;

  SHGetFileInfo(fileName.c_str(), 0, &shfi, sizeof(shfi),
		SHGFI_SYSICONINDEX |
		(smallImage ? SHGFI_SMALLICON:
			      SHGFI_LARGEICON));

  return shfi.iIcon;
}

/// Returns the screen size.
///
Size System::getScreenSize()
{
  return Size(GetSystemMetrics(SM_CXFULLSCREEN),
	      GetSystemMetrics(SM_CYFULLSCREEN));
}

/// Returns the work-area of the screen, it is like the desktop area,
/// that is not overlapped by the task-bar.
///
/// @win32
///   It is a call to @msdn{SystemParametersInfo} using @msdn{SPI_GETWORKAREA}.
/// @endwin32
///
Rect System::getWorkAreaBounds()
{
  RECT rc;

  // returns the work-area rectangle
  if (SystemParametersInfo(SPI_GETWORKAREA, 0, reinterpret_cast<PVOID>(&rc), 0))
    return Rect(&rc);
  // returns the full-screen rectangle
  else
    return Rect(Point(0, 0), System::getScreenSize());
}

/// Returns color from the system. It's a wrapper for the Win32's GetSysColor.
///
/// @param index
///     Can be one of the following values:
///     @li COLOR_3DDKSHADOW
///     @li COLOR_3DFACE
///     @li COLOR_3DHILIGHT
///     @li COLOR_3DHIGHLIGHT
///     @li COLOR_3DLIGHT
///     @li COLOR_BTNHILIGHT
///     @li COLOR_3DSHADOW
///     @li COLOR_ACTIVEBORDER
///     @li COLOR_ACTIVECAPTION
///     @li COLOR_APPWORKSPACE
///     @li COLOR_BACKGROUND
///     @li COLOR_DESKTOP
///     @li COLOR_BTNFACE
///     @li COLOR_BTNHIGHLIGHT
///     @li COLOR_BTNSHADOW
///     @li COLOR_BTNTEXT
///     @li COLOR_CAPTIONTEXT
///     @li COLOR_GRAYTEXT
///     @li COLOR_HIGHLIGHT
///     @li COLOR_HIGHLIGHTTEXT
///     @li COLOR_INACTIVEBORDER
///     @li COLOR_INACTIVECAPTION
///     @li COLOR_INACTIVECAPTIONTEXT
///     @li COLOR_INFOBK
///     @li COLOR_INFOTEXT
///     @li COLOR_MENU
///     @li COLOR_MENUTEXT
///     @li COLOR_SCROLLBAR
///     @li COLOR_WINDOW
///     @li COLOR_WINDOWFRAME
///     @li COLOR_WINDOWTEXT
///     @li COLOR_HOTLIGHT
///     @li COLOR_GRADIENTACTIVECAPTION
///     @li COLOR_GRADIENTINACTIVECAPTION
///
/// @todo make the index a Enum
///
Color System::getColor(int index)
{
  return Color(GetSysColor(index));
}

bool System::getKeyState(Keys::Type keyCode)
{
  // you can't use getKeyState for modifiers
  assert((keyCode & Keys::Modifiers) == 0);

  return (GetKeyState(keyCode) & 0x8000) != 0;
}

/// Returns the cursor position in the screen.
///
Point System::getCursorPos()
{
  POINT pt;
  GetCursorPos(&pt);
  return Point(pt.x, pt.y);
}

void System::setCursorPos(const Point& pt)
{
  SetCursorPos(pt.x, pt.y);
}

String System::getUserName()
{
  Char buf[UNLEN+1];
  // char buf[UNLEN+1];
  DWORD len = UNLEN+1;

  if (GetUserName(buf, &len))
    return String(buf);
  else
    return String();
}

// Prototypes for Win2000/XP API
// typedef BOOLEAN (*GUNEProc)(EXTENDED_NAME_FORMAT NameFormat, LPTSTR lpNameBuffer, PULONG nSize);

String System::getFriendlyUserName()
{
#if 0				// TODO
#if (_WIN32_WINNT >= 0x0500)
  HMODULE hSecur32 = GetModuleHandle(L"SECUR32.DLL");
  if (!hSecur32)
    hSecur32 = LoadLibrary(L"SECUR32.DLL");
  GUNEProc pGUNE = (GUNEProc)GetProcAddress(hSecur32, "GetUserNameExW");

  if (pGUNE != NULL) {
    Char buf[UNLEN+1];
    ULONG len = UNLEN+1;

    if (pGUNE(NameDisplay, buf, &len))
      return String(buf);
  }
#endif
#endif
  return getUserName();
}

// int System::getWheelScrollLines()
// {
//   UINT pulScrollLines = 0;
//   return SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &pulScrollLines, 0);
// }

int System::getOS()
{
  static Mutex mutex;
  static volatile OS::Type cached = OS::Unknown;

  ScopedLock hold(mutex);

  if (cached != OS::Unknown)
    return cached;

  OSVERSIONINFOEX osvi;
  BOOL bOsVersionInfoEx;

  ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

  if (!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*)&osvi))) {
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    if (!GetVersionEx((OSVERSIONINFO*)&osvi))
      return OS::Unknown;
  }

  switch (osvi.dwPlatformId) {

    case VER_PLATFORM_WIN32_NT:
      if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
	return cached = OS::WinServer2003;
      else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
	return cached = OS::WinXP;
      else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
	return cached = OS::Win2K;
      else if (osvi.dwMajorVersion <= 4)
	return cached = OS::WinNT;
      break;

    case VER_PLATFORM_WIN32_WINDOWS:
      if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) {
	if (osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B')
	  return cached = OS::Win95R2;
	else
	  return cached = OS::Win95;
      }
      else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) {
	if (osvi.szCSDVersion[1] == 'A')
	  return cached = OS::Win98SE;
	else
	  return cached = OS::Win98;
      }
      else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
	return cached = OS::WinMe;
      break;

    case VER_PLATFORM_WIN32s:
      return cached = OS::Win32s;
  }

  return cached = OS::Unknown;
}

bool System::isWin95_98_Me()
{
  return (getOS() & (OS::Win95 | OS::Win98 | OS::WinMe)) != 0;
}

bool System::isWinNT_2K_XP()
{
  return (getOS() & (OS::WinNT | OS::Win2K | OS::WinXP | OS::WinServer2003)) != 0;
}

bool System::isWin2K_XP()
{
  return (getOS() & (OS::Win2K | OS::WinXP | OS::WinServer2003)) != 0;
}

bool System::isWinXP()
{
  return (getOS() & OS::WinXP) != 0;
}
<|endoftext|>