<commit_before>/**
    Copyright 2015 Emil Maskovsky

    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.
*/

/**
    @file

    Cookies puzzle.

    @author Emil Maskovsky

    Determine the minimum time to reach the target with different types
    of cookies generating credit.

    Git repository: https://github.com/emaskovsky/puzzles-cookies
*/

#include <map>

#include <iostream>
using namespace std;

typedef map< double, double > ValuesT;

double minTime(
    const ValuesT::const_iterator & start,
    const ValuesT::const_iterator & end,
    const double total,
    const double cps = 0)
{
    if (start == end)
    {
        return (cps > 0) ? (total / cps) : 0.0;
    }
    const double G = start->first;
    const double P = start->second;
    const double CPS = (cps > 0) ? cps : G;
    ValuesT::const_iterator next = start;
    ++next;
    // compute the minimum for the current status
    // (the result must not be worse)
    double timeMin = minTime(next, end, total, CPS);
    // time to get N factories
    double timeN = 0.0;
    for (unsigned N = 1; /* empty */; ++N)
    {
        // time to get the N-th factory from (N-1)-th is P/((N -1) * G + CPS)
        // and that is added to the total time to get N
        timeN += P / ((N - 1) * G + CPS);
        // time to get T with current N factories
        // (next sources checked recursively)
        const double timeMinNext = minTime(next, end, total, N * G + CPS);
        // and add the time to get the N factories
        const double timeTotal = timeN + timeMinNext;
        if (timeTotal >= timeMin)
        {
            // found the optimum - the time to get T with current N is greater
            // than or equat to the previous minimum
            break;
        }
        // found a new minimum
        timeMin = timeTotal;
    }
    return timeMin;
}

void testMinTime(const ValuesT & values, const double total)
{
    const double time = minTime(values.begin(), values.end(), total);
    cout << "Minimum time: " << time << " s" << endl;
}

void test_1source()
{
    ValuesT values;
    values[1] = 5;
    testMinTime(values, 100);
}

void test_2sources()
{
    ValuesT values;
    values[1] = 5;
    values[4] = 16;
    testMinTime(values, 100);
}

void test_2sources2ndExpensive()
{
    ValuesT values;
    values[1] = 5;
    values[4] = 21;
    testMinTime(values, 100);
}

void test_3sources()
{
    ValuesT values;
    values[1] = 5;
    values[4] = 16;
    values[8] = 25;
    testMinTime(values, 1000);
}

int main()
{
    test_1source();
    test_2sources();
    test_2sources2ndExpensive();
    test_3sources();
    return EXIT_SUCCESS;
}

/* EOF */
<commit_msg>Add big numbers test<commit_after>/**
    Copyright 2015 Emil Maskovsky

    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.
*/

/**
    @file

    Cookies puzzle.

    @author Emil Maskovsky

    Determine the minimum time to reach the target with different types
    of cookies generating credit.

    Git repository: https://github.com/emaskovsky/puzzles-cookies
*/

#include <map>

#include <iostream>
using namespace std;

typedef map< double, double > ValuesT;

double minTime(
    const ValuesT::const_iterator & start,
    const ValuesT::const_iterator & end,
    const double total,
    const double cps = 0)
{
    if (start == end)
    {
        return (cps > 0) ? (total / cps) : 0.0;
    }
    const double G = start->first;
    const double P = start->second;
    const double CPS = (cps > 0) ? cps : G;
    ValuesT::const_iterator next = start;
    ++next;
    // compute the minimum for the current status
    // (the result must not be worse)
    double timeMin = minTime(next, end, total, CPS);
    // time to get N factories
    double timeN = 0.0;
    for (unsigned N = 1; /* empty */; ++N)
    {
        // time to get the N-th factory from (N-1)-th is P/((N -1) * G + CPS)
        // and that is added to the total time to get N
        timeN += P / ((N - 1) * G + CPS);
        // time to get T with current N factories
        // (next sources checked recursively)
        const double timeMinNext = minTime(next, end, total, N * G + CPS);
        // and add the time to get the N factories
        const double timeTotal = timeN + timeMinNext;
        if (timeTotal >= timeMin)
        {
            // found the optimum - the time to get T with current N is greater
            // than or equat to the previous minimum
            break;
        }
        // found a new minimum
        timeMin = timeTotal;
    }
    return timeMin;
}

void testMinTime(const ValuesT & values, const double total)
{
    const double time = minTime(values.begin(), values.end(), total);
    cout << "Minimum time: " << time << " s" << endl;
}

void test_1source()
{
    ValuesT values;
    values[1] = 5;
    testMinTime(values, 100);
}

void test_2sources()
{
    ValuesT values;
    values[1] = 5;
    values[4] = 16;
    testMinTime(values, 100);
}

void test_2sources2ndExpensive()
{
    ValuesT values;
    values[1] = 5;
    values[4] = 21;
    testMinTime(values, 100);
}

void test_3sources()
{
    ValuesT values;
    values[1] = 5;
    values[4] = 16;
    values[8] = 25;
    testMinTime(values, 1000);
}

void test_3sourcesBigNumbers()
{
    ValuesT values;
    values[0.1] = 15;
    values[0.5] = 100;
    values[4.0] = 500;
    testMinTime(values, 1e6);
}

int main()
{
    test_1source();
    test_2sources();
    test_2sources2ndExpensive();
    test_3sources();
    test_3sourcesBigNumbers();
    return EXIT_SUCCESS;
}

/* EOF */
<|endoftext|>


<commit_before>#include <cwchar>
#include <cstring>
#include "ExecElem_HttpHeader.h"
#include "LowDbAccess.h"
#include <windows.h>

ExecElem_HttpHeader::ExecElem_HttpHeader(int Id) : ExecElem(Id)
{
}

// Destructor
ExecElem_HttpHeader::~ExecElem_HttpHeader()
{
}

int ExecElem_HttpHeader::Execute()
{
	wchar_t tmp_http_header[1024];

	char presented_http_header[1024];
	char* presented_http_header_ptr = presented_http_header;

	int intput_bin = 0;
	bool http_header_del = false;
	bool http_header_add = false;
	LowDbAccess::GetInstance()->GetHttpHeaderInfo(ElementId, &intput_bin, tmp_http_header);
	wcstombs(presented_http_header, tmp_http_header, 1024 - 1);
	if (intput_bin & 0x01) {
		http_header_del = true;
	}
	if (intput_bin & 0x02) {
		http_header_add = true;
	}

	char* data = (char*)GetData();
	char* data_ptr = NULL;
	char* data_end_ptr = (char*)data + GetDataLength();

	char* new_data = new char[10000000];
	char* new_data_ptr = new_data;

	if (http_header_del) {
		if (strncmp(data, "GET", 3) == 0 ||
			strncmp(data, "HEAD", 4) == 0 ||
			strncmp(data, "POST", 4) == 0 ||
			strncmp(data, "PUT", 3) == 0 ||
			strncmp(data, "DELETE", 6) == 0 ||
			strncmp(data, "CONNECT", 7) == 0 ||
			strncmp(data, "OPTIONS", 7) == 0 ||
			strncmp(data, "TRACE", 5) == 0 ||
			strncmp(data, "PATCH", 5) == 0 ||
			strncmp(data, "HTTP/", 5) == 0) {
			for (data_ptr = data; data_ptr < data_end_ptr && strncmp(data_ptr, "\r\n\r\n", 4); data_ptr++);
			if (data_ptr == data_end_ptr) {
				for (data_ptr = data; data_ptr < data_end_ptr && strncmp(data_ptr, "\n\n", 2); data_ptr++);
				if (data_ptr == data_end_ptr) {
					data_ptr = data;
				} else {
					data_ptr += 2;
				}
			} else {
				data_ptr += 4;
			}
		}
	}
	if (http_header_add) {
		char* tmp_ptr = strstr(presented_http_header_ptr, "\r\n");
		while (tmp_ptr) {
			tmp_ptr += 2;
			if (strncmp(presented_http_header_ptr, "Date: <automatically replaced>\r\n", 32) == 0) {
				strncpy(new_data_ptr, "Date: 111\r\n", 11);
				new_data_ptr += 11;
			} else if (strncmp(presented_http_header_ptr, "Content-Length: <automatically replaced>\r\n", 42) == 0) {
				strncpy(new_data_ptr, "Content-Length: 111\r\n", 21);
				new_data_ptr += 21;
			} else {
				for (char* i = presented_http_header_ptr; i < tmp_ptr; i++) {
					*new_data_ptr = *i;
					*new_data_ptr++;
				}
			}

			presented_http_header_ptr = tmp_ptr;
			tmp_ptr = strstr(presented_http_header_ptr, "\r\n");
		}
		strncpy(new_data_ptr, "\r\n", 2);
		new_data_ptr += 2;
	}
	for (char* i = (char*)data_ptr; i < data_end_ptr; i++) {
		*new_data_ptr = *i;
		new_data_ptr++;
	}
	*new_data_ptr = '\0';
	delete data;
	SetData(new_data);
	SetDataLength(new_data_ptr - new_data + 1);
	return 0;
}
<commit_msg>#41 : Actual date and content-length have been passed to http header.<commit_after>#include <cwchar>
#include <cstring>
#include "ExecElem_HttpHeader.h"
#include "LowDbAccess.h"
#include <windows.h>

ExecElem_HttpHeader::ExecElem_HttpHeader(int Id) : ExecElem(Id)
{
}

// Destructor
ExecElem_HttpHeader::~ExecElem_HttpHeader()
{
}

int ExecElem_HttpHeader::Execute()
{
	wchar_t tmp_http_header[1024];

	char presented_http_header[1024];
	char* presented_http_header_ptr = presented_http_header;

	int intput_bin = 0;
	bool http_header_del = false;
	bool http_header_add = false;
	LowDbAccess::GetInstance()->GetHttpHeaderInfo(ElementId, &intput_bin, tmp_http_header);
	wcstombs(presented_http_header, tmp_http_header, 1024 - 1);
	if (intput_bin & 0x01) {
		http_header_del = true;
	}
	if (intput_bin & 0x02) {
		http_header_add = true;
	}

	char* data = (char*)GetData();
	char* data_ptr = NULL;
	char* data_end_ptr = (char*)data + GetDataLength();

	char* new_data = new char[10000000];
	char* new_data_ptr = new_data;

	if (http_header_del) {
		if (strncmp(data, "GET", 3) == 0 ||
			strncmp(data, "HEAD", 4) == 0 ||
			strncmp(data, "POST", 4) == 0 ||
			strncmp(data, "PUT", 3) == 0 ||
			strncmp(data, "DELETE", 6) == 0 ||
			strncmp(data, "CONNECT", 7) == 0 ||
			strncmp(data, "OPTIONS", 7) == 0 ||
			strncmp(data, "TRACE", 5) == 0 ||
			strncmp(data, "PATCH", 5) == 0 ||
			strncmp(data, "HTTP/", 5) == 0) {
			for (data_ptr = data; data_ptr < data_end_ptr && strncmp(data_ptr, "\r\n\r\n", 4); data_ptr++);
			if (data_ptr == data_end_ptr) {
				for (data_ptr = data; data_ptr < data_end_ptr && strncmp(data_ptr, "\n\n", 2); data_ptr++);
				if (data_ptr == data_end_ptr) {
					data_ptr = data;
				} else {
					data_ptr += 2;
				}
			} else {
				data_ptr += 4;
			}
		}
	}
	if (http_header_add) {
		char* tmp_ptr = strstr(presented_http_header_ptr, "\r\n");
		while (tmp_ptr) {
			tmp_ptr += 2;
			if (strncmp(presented_http_header_ptr, "Date: <automatically replaced>\r\n", 32) == 0) {
				char date_work[128] = "";
				int date_work_len = 0;
				/***** Make time string begin *****/
				struct tm GmtTime;
				__int64 Ltime;
				_time64(&Ltime);
				_gmtime64_s(&GmtTime, &Ltime);
				char MonStr[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
				char WdayStr[7][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
				sprintf(date_work, "Date: %s, %02d %s %d %02d:%02d:%02d GMT\r\n",
					WdayStr[GmtTime.tm_wday],
					GmtTime.tm_mday,
					MonStr[GmtTime.tm_mon],
					GmtTime.tm_year + 1900,
					GmtTime.tm_hour,
					GmtTime.tm_min,
					GmtTime.tm_sec);
				/***** Make time string end *****/
				date_work_len = strlen(date_work);
				strncpy(new_data_ptr, date_work, date_work_len);
				new_data_ptr += date_work_len;
			} else if (strncmp(presented_http_header_ptr, "Content-Length: <automatically replaced>\r\n", 42) == 0) {
				char cont_len_work[128] = "";
				int cont_len_work_len = 0;
				sprintf(cont_len_work, "Content-Length: %d\r\n", data_end_ptr - data_ptr);
				cont_len_work_len = strlen(cont_len_work);
				strncpy(new_data_ptr, cont_len_work, cont_len_work_len);
				new_data_ptr += cont_len_work_len;
			} else {
				for (char* i = presented_http_header_ptr; i < tmp_ptr; i++) {
					*new_data_ptr = *i;
					*new_data_ptr++;
				}
			}

			presented_http_header_ptr = tmp_ptr;
			tmp_ptr = strstr(presented_http_header_ptr, "\r\n");
		}
		strncpy(new_data_ptr, "\r\n", 2);
		new_data_ptr += 2;
	}
	for (char* i = (char*)data_ptr; i < data_end_ptr; i++) {
		*new_data_ptr = *i;
		new_data_ptr++;
	}
	delete data;
	SetData(new_data);
	SetDataLength(new_data_ptr - new_data);
	return 0;
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin-server.
 *
 * libbitcoin-server is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/server/config/settings.hpp>

#include <cstdint>
#include <iostream>
#include <string>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <bitcoin/node.hpp>
#include <bitcoin/server/config/config.hpp>
#include <bitcoin/server/server_node.hpp>

// Define after boost asio, see stackoverflow.com/a/9750437/1172329.
#ifdef _MSC_VER
    #include <shlobj.h>
    #include <windows.h>
#else
    #include <pwd.h>
    #include <unistd.h>
#endif

namespace libbitcoin {
namespace server {

using boost::filesystem::path;
using namespace boost::program_options;
using namespace bc::config;
using namespace bc::network;

static std::string system_config_directory()
{
#ifdef _MSC_VER
    char directory[MAX_PATH];
    const auto result = SHGetFolderPathA(NULL, CSIDL_COMMON_APPDATA, NULL,
        SHGFP_TYPE_CURRENT, directory);
    if (SUCCEEDED(result))
        return directory;
    return "";
#else
    // This symbol must be defined at compile for this project.
    // Therefore do not move this definition into libbitcoin.
    return std::string(SYSCONFDIR);
#endif
}

static path default_config_path()
{
    // This subdirectory and file name must stay in sync with the path
    // for the sample distributed via the build.
    return path(system_config_directory()) / "libbitcoin" / "bs.cfg";
}

// TODO: localize descriptions.
const options_description config_type::load_options()
{
    options_description description("options");
    description.add_options()
    (
        BS_CONFIG_VARIABLE,
        value<path>(&settings.configuration),
        "The path to the configuration settings file."
    )
    (
        BS_HELP_VARIABLE ",h",
        value<bool>(&settings.help)->default_value(false)->zero_tokens(),
        "Get list of options for this command."
    )
    (
        "mainnet,m",
        value<bool>(&settings.mainnet)->default_value(false)->zero_tokens(),
        "Initialize mainnet in the configured directory."
    )
    (
        BS_SETTINGS_VARIABLE ",s",
        value<bool>(&settings.settings)->default_value(false)->zero_tokens(),
        "Display the loaded configuration settings."
    )
    (
        "testnet,t",
        value<bool>(&settings.testnet)->default_value(false)->zero_tokens(),
        "Initialize testnet in the configured directory."
    )
    (
        BS_VERSION_VARIABLE ",v",
        value<bool>(&settings.version)->default_value(false)->zero_tokens(),
        "Get version information."
    );

    return description;
}

const positional_options_description config_type::load_arguments()
{
    positional_options_description description;
    return description
        .add(BS_CONFIG_VARIABLE, 1);
}

// TODO: localize descriptions.
const options_description config_type::load_environment()
{
    options_description description("environment");
    description.add_options()
    (
        // For some reason po requires this to be a lower case name.
        // The case must match the other declarations for it to compose.
        // This composes with the cmdline options and inits to system path.
        BS_CONFIG_VARIABLE,
        value<path>(&settings.configuration)->composing()
            ->default_value(default_config_path()),
        "The path to the configuration settings file."
    );

    return description;
}

// TODO: localize descriptions.
const options_description config_type::load_settings()
{
    options_description description("settings");
    description.add_options()
    /* [network] */
    (
        "network.threads",
        value<uint32_t>(&settings.network.threads)->
            default_value(p2p::mainnet.threads),
        "The number of threads in the network threadpool, defaults to 4."
    )
    (
        "network.identifier",
        value<uint32_t>(&settings.network.identifier)->
        default_value(p2p::mainnet.identifier),
        "The magic number for message headers, defaults to 3652501241."
    )
    (
        "network.inbound_port",
        value<uint16_t>(&settings.network.inbound_port)->
            default_value(p2p::mainnet.inbound_port),
        "The port for incoming connections, defaults to 8333."
    )
    (
        "network.inbound_connection_limit",
        value<uint32_t>(&settings.network.inbound_connection_limit)->
            default_value(p2p::mainnet.inbound_connection_limit),
        "The maximum number of incoming network connections, defaults to 8."
    )
    (
        "network.outbound_connections",
        value<uint32_t>(&settings.network.outbound_connections)->
            default_value(p2p::mainnet.outbound_connections),
        "The maximum number of outgoing network connections, defaults to 8."
    )
    (
        "network.connect_timeout_seconds",
        value<uint32_t>(&settings.network.connect_timeout_seconds)->
            default_value(p2p::mainnet.connect_timeout_seconds),
        "The time limit for connection establishment, defaults to 5."
    )
    (
        "network.channel_handshake_seconds",
        value<uint32_t>(&settings.network.channel_handshake_seconds)->
            default_value(p2p::mainnet.channel_handshake_seconds),
        "The time limit to complete the connection handshake, defaults to 30."
    )
    (
        "network.channel_revival_minutes",
        value<uint32_t>(&settings.network.channel_revival_minutes)->
            default_value(p2p::mainnet.channel_revival_minutes),
        "The time between blocks that initiates a request, defaults to 5."
    )
    (
        "network.channel_heartbeat_minutes",
        value<uint32_t>(&settings.network.channel_heartbeat_minutes)->
            default_value(p2p::mainnet.channel_heartbeat_minutes),
        "The time between ping messages, defaults to 5."
    )
    (
        "network.channel_inactivity_minutes",
        value<uint32_t>(&settings.network.channel_inactivity_minutes)->
            default_value(p2p::mainnet.channel_inactivity_minutes),
        "The inactivity time limit for any connection, defaults to 30."
    )
    (
        "network.channel_expiration_minutes",
        value<uint32_t>(&settings.network.channel_expiration_minutes)->
            default_value(p2p::mainnet.channel_expiration_minutes),
        "The maximum age limit for an outbound connection, defaults to 90."
    )
    (
        "network.channel_germination_seconds",
        value<uint32_t>(&settings.network.channel_germination_seconds)->
            default_value(p2p::mainnet.channel_germination_seconds),
        "The maximum time limit for obtaining seed addresses, defaults to 30."
    )
    (
        "network.host_pool_capacity",
        value<uint32_t>(&settings.network.host_pool_capacity)->
            default_value(p2p::mainnet.host_pool_capacity),
        "The maximum number of peer hosts in the pool, defaults to 1000."
    )
    (
        "network.relay_transactions",
        value<bool>(&settings.network.relay_transactions)->
            default_value(p2p::mainnet.relay_transactions),
        "Request that peers relay transactions, defaults to true."
    )
    (
        "network.hosts_file",
        value<path>(&settings.network.hosts_file)->
            default_value(p2p::mainnet.hosts_file),
        "The peer hosts cache file path, defaults to 'hosts.cache'."
    )
    (
        "network.debug_file",
        value<path>(&settings.network.debug_file)->
            default_value(p2p::mainnet.debug_file),
        "The debug log file path, defaults to 'debug.log'."
    )
    (
        "network.error_file",
        value<path>(&settings.network.error_file)->
            default_value(p2p::mainnet.error_file),
        "The error log file path, defaults to 'error.log'."
    )
    (
        "network.self",
        value<config::authority>(&settings.network.self)->
            multitoken()->default_value(p2p::mainnet.self),
        "The advertised public address of this node, defaults to none."
    )
    (
        "network.seed",
        value<config::endpoint::list>(&settings.network.seeds)->
            multitoken()->default_value(p2p::mainnet.seeds),
        "A seed node for initializing the host pool, multiple entries allowed."
    )

    /* [blockchain] */
    (
        "blockchain.threads",
        value<uint32_t>(&settings.chain.threads)->
            default_value(BLOCKCHAIN_THREADS),
        "The number of threads in the blockchain threadpool, defaults to 6."
    )
    (
        "blockchain.block_pool_capacity",
        value<uint32_t>(&settings.chain.block_pool_capacity)->
            default_value(BLOCKCHAIN_BLOCK_POOL_CAPACITY),
        "The maximum number of orphan blocks in the pool, defaults to 50."
    )
    (
        "blockchain.history_start_height",
        value<uint32_t>(&settings.chain.history_start_height)->
            default_value(BLOCKCHAIN_HISTORY_START_HEIGHT),
        "The history index start height, defaults to 0."
    )
    (
        "blockchain.use_testnet_rules",
        value<bool>(&settings.chain.use_testnet_rules)->
            default_value(BLOCKCHAIN_TESTNET_RULES_MAINNET),
        "Use testnet rules for determination of work required, defaults to false."
    )
    (
        "blockchain.database_path",
        value<path>(&settings.chain.database_path)->
            default_value(BLOCKCHAIN_DATABASE_PATH),
        "The blockchain database directory, defaults to 'blockchain'."
    )
    (
        "blockchain.checkpoint",
        value<config::checkpoint::list>(&settings.chain.checkpoints)->
            multitoken()->default_value(BLOCKCHAIN_CHECKPOINTS_MAINNET),
        "A hash:height checkpoint, multiple entries allowed."
    )

    /* [node] */
    (
        "node.threads",
        value<uint32_t>(&settings.node.threads)->
            default_value(NODE_THREADS),
        "The number of threads in the node threadpool, defaults to 4."
    )
    (
        "node.transaction_pool_capacity",
        value<uint32_t>(&settings.node.transaction_pool_capacity)->
            default_value(NODE_TRANSACTION_POOL_CAPACITY),
        "The maximum number of transactions in the pool, defaults to 2000."
    )
    (
        "node.peer",
        value<config::endpoint::list>(&settings.node.peers)->
            multitoken()->default_value(NODE_PEERS),
        "Persistent host:port to augment discovered hosts, multiple entries allowed."
    )
    (
        "node.blacklist",
        value<config::authority::list>(&settings.node.blacklists)->
            multitoken()->default_value(NODE_BLACKLISTS),
        "IP address to disallow as a peer, multiple entries allowed."
    )

    /* [server] */
    (
        "server.query_endpoint",
        value<endpoint>(&settings.server.query_endpoint)->
            default_value(SERVER_QUERY_ENDPOINT),
        "The query service endpoint, defaults to 'tcp://*:9091'."
    )
    (
        "server.heartbeat_endpoint",
        value<endpoint>(&settings.server.heartbeat_endpoint)->
            default_value(SERVER_HEARTBEAT_ENDPOINT),
        "The heartbeat service endpoint, defaults to 'tcp://*:9092'."
    )
    (
        "server.block_publish_endpoint",
        value<endpoint>(&settings.server.block_publish_endpoint)->
            default_value(SERVER_BLOCK_PUBLISH_ENDPOINT),
        "The block publishing service endpoint, defaults to 'tcp://*:9093'."
    )
    (
        "server.transaction_publish_endpoint",
        value<endpoint>(&settings.server.transaction_publish_endpoint)->
            default_value(SERVER_TRANSACTION_PUBLISH_ENDPOINT),
        "The transaction publishing service endpoint, defaults to 'tcp://*:9094'."
    )
    (
        "server.publisher_enabled",
        value<bool>(&settings.server.publisher_enabled)->
            default_value(SERVER_PUBLISHER_ENABLED),
        "Enable the block and transaction publishing endpoints, defaults to true."
    )
    (
        "server.queries_enabled",
        value<bool>(&settings.server.queries_enabled)->
            default_value(SERVER_QUERIES_ENABLED),
        "Enable the query and heartbeat endpoints, defaults to true."
    )
    (
        "server.log_requests",
        value<bool>(&settings.server.log_requests)->
            default_value(SERVER_LOG_REQUESTS),
        "Write service requests to the log, defaults to false."
    )
    (
        "server.polling_interval_milliseconds",
        value<uint32_t>(&settings.server.polling_interval_milliseconds)->
            default_value(SERVER_POLLING_INTERVAL_MILLISECONDS),
        "The query polling interval in milliseconds, defaults to 1000."
    )
    (
        "server.heartbeat_interval_seconds",
        value<uint32_t>(&settings.server.heartbeat_interval_seconds)->
            default_value(SERVER_HEARTBEAT_INTERVAL_SECONDS),
        "The heartbeat interval in seconds, defaults to 5."
    )
    (
        "server.subscription_expiration_minutes",
        value<uint32_t>(&settings.server.subscription_expiration_minutes)->
            default_value(SERVER_SUBSCRIPTION_EXPIRATION_MINUTES),
        "The subscription expiration time, defaults to 10 minutes."
    )
    (
        "server.subscription_limit",
        value<uint32_t>(&settings.server.subscription_limit)->
            default_value(SERVER_SUBSCRIPTION_LIMIT),
        "The maximum number of subscriptions, defaults to 100000000."
    )
    (
        "server.certificate_file",
        value<path>(&settings.server.certificate_file)->
            default_value(SERVER_CERTIFICATE_FILE),
        "The path to the ZPL-encoded server private certificate file."
    )
    (
        "server.client_certificates_path",
        value<path>(&settings.server.client_certificates_path)->
            default_value(SERVER_CLIENT_CERTIFICATES_PATH),
        "The directory for ZPL-encoded client public certificate files, allows anonymous clients if not set."
    )
    (
        "server.whitelist",
        value<config::authority::list>(&settings.server.whitelists)->
            multitoken()->default_value(SERVER_WHITELISTS),
        "Allowed client IP address, all clients allowed if none set, multiple entries allowed."
    );

    return description;
}

} // namespace server
} // namespace libbitcoin

<commit_msg>Add missing settings.<commit_after>/**
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin-server.
 *
 * libbitcoin-server is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/server/config/settings.hpp>

#include <cstdint>
#include <iostream>
#include <string>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <bitcoin/node.hpp>
#include <bitcoin/server/config/config.hpp>
#include <bitcoin/server/server_node.hpp>

// Define after boost asio, see stackoverflow.com/a/9750437/1172329.
#ifdef _MSC_VER
    #include <shlobj.h>
    #include <windows.h>
#else
    #include <pwd.h>
    #include <unistd.h>
#endif

namespace libbitcoin {
namespace server {

using boost::filesystem::path;
using namespace boost::program_options;
using namespace bc::config;
using namespace bc::network;

static std::string system_config_directory()
{
#ifdef _MSC_VER
    char directory[MAX_PATH];
    const auto result = SHGetFolderPathA(NULL, CSIDL_COMMON_APPDATA, NULL,
        SHGFP_TYPE_CURRENT, directory);
    if (SUCCEEDED(result))
        return directory;
    return "";
#else
    // This symbol must be defined at compile for this project.
    // Therefore do not move this definition into libbitcoin.
    return std::string(SYSCONFDIR);
#endif
}

static path default_config_path()
{
    // This subdirectory and file name must stay in sync with the path
    // for the sample distributed via the build.
    return path(system_config_directory()) / "libbitcoin" / "bs.cfg";
}

// TODO: localize descriptions.
const options_description config_type::load_options()
{
    options_description description("options");
    description.add_options()
    (
        BS_CONFIG_VARIABLE,
        value<path>(&settings.configuration),
        "The path to the configuration settings file."
    )
    (
        BS_HELP_VARIABLE ",h",
        value<bool>(&settings.help)->default_value(false)->zero_tokens(),
        "Get list of options for this command."
    )
    (
        "mainnet,m",
        value<bool>(&settings.mainnet)->default_value(false)->zero_tokens(),
        "Initialize mainnet in the configured directory."
    )
    (
        BS_SETTINGS_VARIABLE ",s",
        value<bool>(&settings.settings)->default_value(false)->zero_tokens(),
        "Display the loaded configuration settings."
    )
    (
        "testnet,t",
        value<bool>(&settings.testnet)->default_value(false)->zero_tokens(),
        "Initialize testnet in the configured directory."
    )
    (
        BS_VERSION_VARIABLE ",v",
        value<bool>(&settings.version)->default_value(false)->zero_tokens(),
        "Get version information."
    );

    return description;
}

const positional_options_description config_type::load_arguments()
{
    positional_options_description description;
    return description
        .add(BS_CONFIG_VARIABLE, 1);
}

// TODO: localize descriptions.
const options_description config_type::load_environment()
{
    options_description description("environment");
    description.add_options()
    (
        // For some reason po requires this to be a lower case name.
        // The case must match the other declarations for it to compose.
        // This composes with the cmdline options and inits to system path.
        BS_CONFIG_VARIABLE,
        value<path>(&settings.configuration)->composing()
            ->default_value(default_config_path()),
        "The path to the configuration settings file."
    );

    return description;
}

// TODO: localize descriptions.
const options_description config_type::load_settings()
{
    options_description description("settings");
    description.add_options()
    /* [network] */
    (
        "network.threads",
        value<uint32_t>(&settings.network.threads)->
            default_value(p2p::mainnet.threads),
        "The number of threads in the network threadpool, defaults to 4."
    )
    (
        "network.identifier",
        value<uint32_t>(&settings.network.identifier)->
        default_value(p2p::mainnet.identifier),
        "The magic number for message headers, defaults to 3652501241."
    )
    (
        "network.inbound_port",
        value<uint16_t>(&settings.network.inbound_port)->
            default_value(p2p::mainnet.inbound_port),
        "The port for incoming connections, defaults to 8333."
    )
    (
        "network.inbound_connection_limit",
        value<uint32_t>(&settings.network.inbound_connection_limit)->
            default_value(p2p::mainnet.inbound_connection_limit),
        "The maximum number of incoming network connections, defaults to 8."
    )
    (
        "network.outbound_connections",
        value<uint32_t>(&settings.network.outbound_connections)->
            default_value(p2p::mainnet.outbound_connections),
        "The maximum number of outgoing network connections, defaults to 8."
    )
    (
        "network.connect_attempts",
        value<uint16_t>(&settings.network.connect_attempts)->
            default_value(p2p::mainnet.connect_attempts),
        "The number of times to attempt contacting a node, defaults to 0 (forever)."
    )
    (
        "network.connect_timeout_seconds",
        value<uint32_t>(&settings.network.connect_timeout_seconds)->
            default_value(p2p::mainnet.connect_timeout_seconds),
        "The time limit for connection establishment, defaults to 5."
    )
    (
        "network.channel_handshake_seconds",
        value<uint32_t>(&settings.network.channel_handshake_seconds)->
            default_value(p2p::mainnet.channel_handshake_seconds),
        "The time limit to complete the connection handshake, defaults to 30."
    )
    (
        "network.channel_revival_minutes",
        value<uint32_t>(&settings.network.channel_revival_minutes)->
            default_value(p2p::mainnet.channel_revival_minutes),
        "The time between blocks that initiates a request, defaults to 5."
    )
    (
        "network.channel_heartbeat_minutes",
        value<uint32_t>(&settings.network.channel_heartbeat_minutes)->
            default_value(p2p::mainnet.channel_heartbeat_minutes),
        "The time between ping messages, defaults to 5."
    )
    (
        "network.channel_inactivity_minutes",
        value<uint32_t>(&settings.network.channel_inactivity_minutes)->
            default_value(p2p::mainnet.channel_inactivity_minutes),
        "The inactivity time limit for any connection, defaults to 30."
    )
    (
        "network.channel_expiration_minutes",
        value<uint32_t>(&settings.network.channel_expiration_minutes)->
            default_value(p2p::mainnet.channel_expiration_minutes),
        "The maximum age limit for an outbound connection, defaults to 90."
    )
    (
        "network.channel_germination_seconds",
        value<uint32_t>(&settings.network.channel_germination_seconds)->
            default_value(p2p::mainnet.channel_germination_seconds),
        "The maximum time limit for obtaining seed addresses, defaults to 30."
    )
    (
        "network.host_pool_capacity",
        value<uint32_t>(&settings.network.host_pool_capacity)->
            default_value(p2p::mainnet.host_pool_capacity),
        "The maximum number of peer hosts in the pool, defaults to 1000."
    )
    (
        "network.relay_transactions",
        value<bool>(&settings.network.relay_transactions)->
            default_value(p2p::mainnet.relay_transactions),
        "Request that peers relay transactions, defaults to true."
    )
    (
        "network.hosts_file",
        value<path>(&settings.network.hosts_file)->
            default_value(p2p::mainnet.hosts_file),
        "The peer hosts cache file path, defaults to 'hosts.cache'."
    )
    (
        "network.debug_file",
        value<path>(&settings.network.debug_file)->
            default_value(p2p::mainnet.debug_file),
        "The debug log file path, defaults to 'debug.log'."
    )
    (
        "network.error_file",
        value<path>(&settings.network.error_file)->
            default_value(p2p::mainnet.error_file),
        "The error log file path, defaults to 'error.log'."
    )
    (
        "network.self",
        value<config::authority>(&settings.network.self)->
            multitoken()->default_value(p2p::mainnet.self),
        "The advertised public address of this node, defaults to none."
    )
    (
        "network.blacklist",
        value<config::authority::list>(&settings.network.blacklists)->
            multitoken()->default_value(p2p::mainnet.blacklists),
        "IP address to disallow as a peer, multiple entries allowed."
    )
    (
        "network.seed",
        value<config::endpoint::list>(&settings.network.seeds)->
            multitoken()->default_value(p2p::mainnet.seeds),
        "A seed node for initializing the host pool, multiple entries allowed."
    )

    /* [blockchain] */
    (
        "blockchain.threads",
        value<uint32_t>(&settings.chain.threads)->
            default_value(BLOCKCHAIN_THREADS),
        "The number of threads in the blockchain threadpool, defaults to 6."
    )
    (
        "blockchain.block_pool_capacity",
        value<uint32_t>(&settings.chain.block_pool_capacity)->
            default_value(BLOCKCHAIN_BLOCK_POOL_CAPACITY),
        "The maximum number of orphan blocks in the pool, defaults to 50."
    )
    (
        "blockchain.history_start_height",
        value<uint32_t>(&settings.chain.history_start_height)->
            default_value(BLOCKCHAIN_HISTORY_START_HEIGHT),
        "The history index start height, defaults to 0."
    )
    (
        "blockchain.use_testnet_rules",
        value<bool>(&settings.chain.use_testnet_rules)->
            default_value(BLOCKCHAIN_TESTNET_RULES_MAINNET),
        "Use testnet rules for determination of work required, defaults to false."
    )
    (
        "blockchain.database_path",
        value<path>(&settings.chain.database_path)->
            default_value(BLOCKCHAIN_DATABASE_PATH),
        "The blockchain database directory, defaults to 'blockchain'."
    )
    (
        "blockchain.checkpoint",
        value<config::checkpoint::list>(&settings.chain.checkpoints)->
            multitoken()->default_value(BLOCKCHAIN_CHECKPOINTS_MAINNET),
        "A hash:height checkpoint, multiple entries allowed."
    )

    /* [node] */
    (
        "node.threads",
        value<uint32_t>(&settings.node.threads)->
            default_value(NODE_THREADS),
        "The number of threads in the node threadpool, defaults to 4."
    )
    (
        "node.transaction_pool_capacity",
        value<uint32_t>(&settings.node.transaction_pool_capacity)->
            default_value(NODE_TRANSACTION_POOL_CAPACITY),
        "The maximum number of transactions in the pool, defaults to 2000."
    )
    (
        "node.peer",
        value<config::endpoint::list>(&settings.node.peers)->
            multitoken()->default_value(NODE_PEERS),
        "Persistent host:port to augment discovered hosts, multiple entries allowed."
    )
    (
        "node.blacklist",
        value<config::authority::list>(&settings.node.blacklists)->
            multitoken()->default_value(NODE_BLACKLISTS),
        "IP address to disallow as a peer, multiple entries allowed."
    )

    /* [server] */
    (
        "server.query_endpoint",
        value<endpoint>(&settings.server.query_endpoint)->
            default_value(SERVER_QUERY_ENDPOINT),
        "The query service endpoint, defaults to 'tcp://*:9091'."
    )
    (
        "server.heartbeat_endpoint",
        value<endpoint>(&settings.server.heartbeat_endpoint)->
            default_value(SERVER_HEARTBEAT_ENDPOINT),
        "The heartbeat service endpoint, defaults to 'tcp://*:9092'."
    )
    (
        "server.block_publish_endpoint",
        value<endpoint>(&settings.server.block_publish_endpoint)->
            default_value(SERVER_BLOCK_PUBLISH_ENDPOINT),
        "The block publishing service endpoint, defaults to 'tcp://*:9093'."
    )
    (
        "server.transaction_publish_endpoint",
        value<endpoint>(&settings.server.transaction_publish_endpoint)->
            default_value(SERVER_TRANSACTION_PUBLISH_ENDPOINT),
        "The transaction publishing service endpoint, defaults to 'tcp://*:9094'."
    )
    (
        "server.publisher_enabled",
        value<bool>(&settings.server.publisher_enabled)->
            default_value(SERVER_PUBLISHER_ENABLED),
        "Enable the block and transaction publishing endpoints, defaults to true."
    )
    (
        "server.queries_enabled",
        value<bool>(&settings.server.queries_enabled)->
            default_value(SERVER_QUERIES_ENABLED),
        "Enable the query and heartbeat endpoints, defaults to true."
    )
    (
        "server.log_requests",
        value<bool>(&settings.server.log_requests)->
            default_value(SERVER_LOG_REQUESTS),
        "Write service requests to the log, defaults to false."
    )
    (
        "server.polling_interval_milliseconds",
        value<uint32_t>(&settings.server.polling_interval_milliseconds)->
            default_value(SERVER_POLLING_INTERVAL_MILLISECONDS),
        "The query polling interval in milliseconds, defaults to 1000."
    )
    (
        "server.heartbeat_interval_seconds",
        value<uint32_t>(&settings.server.heartbeat_interval_seconds)->
            default_value(SERVER_HEARTBEAT_INTERVAL_SECONDS),
        "The heartbeat interval in seconds, defaults to 5."
    )
    (
        "server.subscription_expiration_minutes",
        value<uint32_t>(&settings.server.subscription_expiration_minutes)->
            default_value(SERVER_SUBSCRIPTION_EXPIRATION_MINUTES),
        "The subscription expiration time, defaults to 10 minutes."
    )
    (
        "server.subscription_limit",
        value<uint32_t>(&settings.server.subscription_limit)->
            default_value(SERVER_SUBSCRIPTION_LIMIT),
        "The maximum number of subscriptions, defaults to 100000000."
    )
    (
        "server.certificate_file",
        value<path>(&settings.server.certificate_file)->
            default_value(SERVER_CERTIFICATE_FILE),
        "The path to the ZPL-encoded server private certificate file."
    )
    (
        "server.client_certificates_path",
        value<path>(&settings.server.client_certificates_path)->
            default_value(SERVER_CLIENT_CERTIFICATES_PATH),
        "The directory for ZPL-encoded client public certificate files, allows anonymous clients if not set."
    )
    (
        "server.whitelist",
        value<config::authority::list>(&settings.server.whitelists)->
            multitoken()->default_value(SERVER_WHITELISTS),
        "Allowed client IP address, all clients allowed if none set, multiple entries allowed."
    );

    return description;
}

} // namespace server
} // namespace libbitcoin

<|endoftext|>


<commit_before>/**
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin-server.
 *
 * libbitcoin-server is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/server/config/settings.hpp>

#include <cstdint>
#include <iostream>
#include <string>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <bitcoin/node.hpp>
#include <bitcoin/server/config/config.hpp>
#include <bitcoin/server/server_node.hpp>

// Define after boost asio, see stackoverflow.com/a/9750437/1172329.
#ifdef _MSC_VER
    #include <shlobj.h>
    #include <windows.h>
#else
    #include <pwd.h>
    #include <unistd.h>
#endif

namespace libbitcoin {
namespace server {

using boost::filesystem::path;
using namespace boost::program_options;
using namespace libbitcoin::config;

static std::string system_config_directory()
{
#ifdef _MSC_VER
    char directory[MAX_PATH];
    const auto result = SHGetFolderPathA(NULL, CSIDL_COMMON_APPDATA, NULL,
        SHGFP_TYPE_CURRENT, directory);
    if (SUCCEEDED(result))
        return directory;
    return "";
#else
    // This symbol must be defined at compile for this project.
    // Therefore do not move this definition into libbitcoin.
    return std::string(SYSCONFDIR);
#endif
}

static path default_config_path()
{
    // This subdirectory and file name must stay in sync with the path
    // for the sample distributed via the build.
    return path(system_config_directory()) / "libbitcoin" / "bs.cfg";
}

// TODO: localize descriptions.
const options_description config_type::load_options()
{
    options_description description("options");
    description.add_options()
    (
        BS_CONFIG_VARIABLE,
        value<path>(&settings.configuration),
        "The path to the configuration settings file."
    )
    (
        BS_HELP_VARIABLE ",h",
        value<bool>(&settings.help)->default_value(false)->zero_tokens(),
        "Get list of options for this command."
    )
    (
        "initchain,i",
        value<bool>(&settings.initchain)->default_value(false)->zero_tokens(),
        "Initialize database in the configured directory."
    )
    (
        BS_SETTINGS_VARIABLE ",s",
        value<bool>(&settings.settings)->default_value(false)->zero_tokens(),
        "Display the loaded configuration settings."
    )
    (
        BS_VERSION_VARIABLE ",v",
        value<bool>(&settings.version)->default_value(false)->zero_tokens(),
        "Get version information."
    );

    return description;
}

const positional_options_description config_type::load_arguments()
{
    positional_options_description description;
    return description
        .add(BS_CONFIG_VARIABLE, 1);
}

// TODO: localize descriptions.
const options_description config_type::load_environment()
{
    options_description description("environment");
    description.add_options()
    (
        // For some reason po requires this to be a lower case name.
        // The case must match the other declarations for it to compose.
        // This composes with the cmdline options and inits to system path.
        BS_CONFIG_VARIABLE,
        value<path>(&settings.configuration)->composing()
            ->default_value(default_config_path()),
        "The path to the configuration settings file."
    );

    return description;
}

// TODO: localize descriptions.
const options_description config_type::load_settings()
{
    options_description description("settings");
    description.add_options()
    /* [network] */
    (
        "network.threads",
        value<uint32_t>(&settings.network.threads)->
            default_value(NETWORK_THREADS),
        "The number of threads in the network threadpool, defaults to 4."
    )
    (
        "network.inbound_port",
        value<uint16_t>(&settings.network.inbound_port)->
            default_value(NETWORK_INBOUND_PORT_MAINNET),
        "The port for incoming connections, defaults to 8333."
    )
    (
        "network.inbound_connection_limit",
        value<uint32_t>(&settings.network.inbound_connection_limit)->
            default_value(NETWORK_INBOUND_CONNECTION_LIMIT),
        "The maximum number of incoming network connections, defaults to 8."
    )
    (
        "network.outbound_connections",
        value<uint32_t>(&settings.network.outbound_connections)->
            default_value(NETWORK_OUTBOUND_CONNECTIONS),
        "The maximum number of outgoing network connections, defaults to 8."
    )
    (
        "network.connect_timeout_seconds",
        value<uint32_t>(&settings.network.connect_timeout_seconds)->
            default_value(NETWORK_CONNECT_TIMEOUT_SECONDS),
        "The time limit for connection establishment, defaults to 5."
    )
    (
        "network.channel_handshake_seconds",
        value<uint32_t>(&settings.network.channel_handshake_seconds)->
            default_value(NETWORK_CHANNEL_HANDSHAKE_SECONDS),
        "The time limit to complete the connection handshake, defaults to 30."
    )
    (
        "network.channel_revival_minutes",
        value<uint32_t>(&settings.network.channel_revival_minutes)->
            default_value(NETWORK_CHANNEL_REVIVAL_MINUTES),
        "The time between blocks that initiates a request, defaults to 2."
    )
    (
        "network.channel_heartbeat_minutes",
        value<uint32_t>(&settings.network.channel_heartbeat_minutes)->
            default_value(NETWORK_CHANNEL_HEARTBEAT_MINUTES),
        "The time between ping messages, defaults to 5."
    )
    (
        "network.channel_inactivity_minutes",
        value<uint32_t>(&settings.network.channel_inactivity_minutes)->
            default_value(NETWORK_CHANNEL_INACTIVITY_MINUTES),
        "The inactivity time limit for any connection, defaults to 30."
    )
    (
        "network.channel_expiration_minutes",
        value<uint32_t>(&settings.network.channel_expiration_minutes)->
            default_value(NETWORK_CHANNEL_EXPIRATION_MINUTES),
        "The maximum age limit for an outbound connection, defaults to 90."
    )
    (
        "network.channel_germination_seconds",
        value<uint32_t>(&settings.network.channel_germination_seconds)->
            default_value(NETWORK_CHANNEL_GERMINATION_SECONDS),
        "The maximum time limit for obtaining seed addresses, defaults to 30."
    )
    (
        "network.host_pool_capacity",
        value<uint32_t>(&settings.network.host_pool_capacity)->
            default_value(NETWORK_HOST_POOL_CAPACITY),
        "The maximum number of peer hosts in the pool, defaults to 1000."
    )
    (
        "network.relay_transactions",
        value<bool>(&settings.network.relay_transactions)->
            default_value(NETWORK_RELAY_TRANSACTIONS),
        "Request that peers relay transactions, defaults to true."
    )
    (
        "network.hosts_file",
        value<path>(&settings.network.hosts_file)->
            default_value(NETWORK_HOSTS_FILE),
        "The peer hosts cache file path, defaults to 'hosts'."
    )
    (
        "network.debug_file",
        value<path>(&settings.network.debug_file)->
            default_value(NETWORK_DEBUG_FILE),
        "The debug log file path, defaults to 'debug.log'."
    )
    (
        "network.error_file",
        value<path>(&settings.network.error_file)->
            default_value(NETWORK_ERROR_FILE),
        "The error log file path, defaults to 'error.log'."
    )
    (
        "network.self",
        value<config::authority>(&settings.network.self)->
        multitoken()->default_value(NETWORK_SELF),
        "The advertised public address of this node, defaults to none."
    )
    (
        "network.seed",
        value<config::endpoint::list>(&settings.network.seeds)->
        multitoken()->default_value(NETWORK_SEEDS_MAINNET),
        "A seed node for initializing the host pool, multiple entries allowed."
    )

    /* [blockchain] */
    (
        "blockchain.threads",
        value<uint32_t>(&settings.chain.threads)->
            default_value(BLOCKCHAIN_THREADS),
        "The number of threads in the blockchain threadpool, defaults to 6."
    )
    (
        "blockchain.block_pool_capacity",
        value<uint32_t>(&settings.chain.block_pool_capacity)->
            default_value(BLOCKCHAIN_BLOCK_POOL_CAPACITY),
        "The maximum number of orphan blocks in the pool, defaults to 50."
    )
    (
        "blockchain.history_start_height",
        value<uint32_t>(&settings.chain.history_start_height)->
            default_value(BLOCKCHAIN_HISTORY_START_HEIGHT),
        "The history index start height, defaults to 0."
    )
    (
        "blockchain.database_path",
        value<path>(&settings.chain.database_path)->
            default_value(BLOCKCHAIN_DATABASE_PATH),
        "The blockchain database directory, defaults to 'blockchain'."
    )
    (
        "blockchain.checkpoint",
        value<config::checkpoint::list>(&settings.chain.checkpoints)->
            multitoken()->default_value(BLOCKCHAIN_CHECKPOINTS_MAINNET),
        "A hash:height checkpoint, multiple entries allowed."
    )

    /* [node] */
    (
        "node.threads",
        value<uint32_t>(&settings.node.threads)->
            default_value(NODE_THREADS),
        "The number of threads in the node threadpool, defaults to 4."
    )
    (
        "node.transaction_pool_capacity",
        value<uint32_t>(&settings.node.transaction_pool_capacity)->
            default_value(NODE_TRANSACTION_POOL_CAPACITY),
        "The number of threads in the node threadpool, defaults to 4."
    )
    (
        "node.peer",
        value<config::endpoint::list>(&settings.node.peers)->
            multitoken()->default_value(NODE_PEERS),
        "Persistent host:port to augment discovered hosts, multiple entries allowed."
    )
    (
        "node.blacklist",
        value<config::authority::list>(&settings.node.blacklists)->
            multitoken()->default_value(NODE_BLACKLISTS),
        "IP address to disallow as a peer, multiple entries allowed."
    )

    /* [server] */
    (
        "server.query_endpoint",
        value<endpoint>(&settings.server.query_endpoint)->
            default_value(SERVER_QUERY_ENDPOINT),
        "The query service endpoint, defaults to 'tcp://*:9091'."
    )
    (
        "server.heartbeat_endpoint",
        value<endpoint>(&settings.server.heartbeat_endpoint)->
            default_value(SERVER_HEARTBEAT_ENDPOINT),
        "The heartbeat service endpoint, defaults to 'tcp://*:9092'."
    )
    (
        "server.block_publish_endpoint",
        value<endpoint>(&settings.server.block_publish_endpoint)->
            default_value(SERVER_BLOCK_PUBLISH_ENDPOINT),
        "The block publishing service endpoint, defaults to 'tcp://*:9093'."
    )
    (
        "server.transaction_publish_endpoint",
        value<endpoint>(&settings.server.transaction_publish_endpoint)->
            default_value(SERVER_TRANSACTION_PUBLISH_ENDPOINT),
        "The transaction publishing service endpoint, defaults to 'tcp://*:9094'."
    )
    (
        "server.publisher_enabled",
        value<bool>(&settings.server.publisher_enabled)->
            default_value(SERVER_PUBLISHER_ENABLED),
        "Enable the block and transaction publishing endpoints, defaults to true."
    )
    (
        "server.queries_enabled",
        value<bool>(&settings.server.queries_enabled)->
            default_value(SERVER_QUERIES_ENABLED),
        "Enable the query and heartbeat endpoints, defaults to true."
    )
    (
        "server.log_requests",
        value<bool>(&settings.server.log_requests)->
            default_value(SERVER_LOG_REQUESTS),
        "Write service requests to the log, defaults to false."
    )
    (
        "server.polling_interval_milliseconds",
        value<uint32_t>(&settings.server.polling_interval_milliseconds)->
            default_value(SERVER_POLLING_INTERVAL_MILLISECONDS),
        "The query polling interval in milliseconds, defaults to 1000."
    )
    (
        "server.heartbeat_interval_seconds",
        value<uint32_t>(&settings.server.heartbeat_interval_seconds)->
            default_value(SERVER_HEARTBEAT_INTERVAL_SECONDS),
        "The heartbeat interval in seconds, defaults to 5."
    )
    (
        "server.subscription_expiration_minutes",
        value<uint32_t>(&settings.server.subscription_expiration_minutes)->
            default_value(SERVER_SUBSCRIPTION_EXPIRATION_MINUTES),
        "The subscription expiration time, defaults to 10 minutes."
    )
    (
        "server.subscription_limit",
        value<uint32_t>(&settings.server.subscription_limit)->
            default_value(SERVER_SUBSCRIPTION_LIMIT),
        "The maximum number of subscriptions, defaults to 100000000."
    )
    (
        "server.certificate_file",
        value<path>(&settings.server.certificate_file)->
            default_value(SERVER_CERTIFICATE_FILE),
        "The path to the ZPL-encoded server private certificate file."
    )
    (
        "server.client_certificates_path",
        value<path>(&settings.server.client_certificates_path)->
            default_value(SERVER_CLIENT_CERTIFICATES_PATH),
        "The directory for ZPL-encoded client public certificate files, allows anonymous clients if not set."
    )
    (
        "server.whitelist",
        value<config::authority::list>(&settings.server.whitelists)->
            multitoken()->default_value(SERVER_WHITELISTS),
        "Allowed client IP address, all clients allowed if none set, multiple entries allowed."
    );

    return description;
}

} // namespace server
} // namespace libbitcoin

<commit_msg>Incorporate new configuration settings.<commit_after>/**
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin-server.
 *
 * libbitcoin-server is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/server/config/settings.hpp>

#include <cstdint>
#include <iostream>
#include <string>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <bitcoin/node.hpp>
#include <bitcoin/server/config/config.hpp>
#include <bitcoin/server/server_node.hpp>

// Define after boost asio, see stackoverflow.com/a/9750437/1172329.
#ifdef _MSC_VER
    #include <shlobj.h>
    #include <windows.h>
#else
    #include <pwd.h>
    #include <unistd.h>
#endif

namespace libbitcoin {
namespace server {

using boost::filesystem::path;
using namespace boost::program_options;
using namespace libbitcoin::config;

static std::string system_config_directory()
{
#ifdef _MSC_VER
    char directory[MAX_PATH];
    const auto result = SHGetFolderPathA(NULL, CSIDL_COMMON_APPDATA, NULL,
        SHGFP_TYPE_CURRENT, directory);
    if (SUCCEEDED(result))
        return directory;
    return "";
#else
    // This symbol must be defined at compile for this project.
    // Therefore do not move this definition into libbitcoin.
    return std::string(SYSCONFDIR);
#endif
}

static path default_config_path()
{
    // This subdirectory and file name must stay in sync with the path
    // for the sample distributed via the build.
    return path(system_config_directory()) / "libbitcoin" / "bs.cfg";
}

// TODO: localize descriptions.
const options_description config_type::load_options()
{
    options_description description("options");
    description.add_options()
    (
        BS_CONFIG_VARIABLE,
        value<path>(&settings.configuration),
        "The path to the configuration settings file."
    )
    (
        BS_HELP_VARIABLE ",h",
        value<bool>(&settings.help)->default_value(false)->zero_tokens(),
        "Get list of options for this command."
    )
    (
        "initchain,i",
        value<bool>(&settings.initchain)->default_value(false)->zero_tokens(),
        "Initialize database in the configured directory."
    )
    (
        BS_SETTINGS_VARIABLE ",s",
        value<bool>(&settings.settings)->default_value(false)->zero_tokens(),
        "Display the loaded configuration settings."
    )
    (
        BS_VERSION_VARIABLE ",v",
        value<bool>(&settings.version)->default_value(false)->zero_tokens(),
        "Get version information."
    );

    return description;
}

const positional_options_description config_type::load_arguments()
{
    positional_options_description description;
    return description
        .add(BS_CONFIG_VARIABLE, 1);
}

// TODO: localize descriptions.
const options_description config_type::load_environment()
{
    options_description description("environment");
    description.add_options()
    (
        // For some reason po requires this to be a lower case name.
        // The case must match the other declarations for it to compose.
        // This composes with the cmdline options and inits to system path.
        BS_CONFIG_VARIABLE,
        value<path>(&settings.configuration)->composing()
            ->default_value(default_config_path()),
        "The path to the configuration settings file."
    );

    return description;
}

// TODO: localize descriptions.
const options_description config_type::load_settings()
{
    options_description description("settings");
    description.add_options()
    /* [network] */
    (
        "network.threads",
        value<uint32_t>(&settings.network.threads)->
            default_value(NETWORK_THREADS),
        "The number of threads in the network threadpool, defaults to 4."
    )
    (
        "network.identifier",
        value<uint32_t>(&settings.network.identifier)->
            default_value(NETWORK_IDENTIFIER_MAINNET),
        "The magic number for message headers, defaults to 3652501241."
    )
    (
        "network.inbound_port",
        value<uint16_t>(&settings.network.inbound_port)->
            default_value(NETWORK_INBOUND_PORT_MAINNET),
        "The port for incoming connections, defaults to 8333."
    )
    (
        "network.inbound_connection_limit",
        value<uint32_t>(&settings.network.inbound_connection_limit)->
            default_value(NETWORK_INBOUND_CONNECTION_LIMIT),
        "The maximum number of incoming network connections, defaults to 8."
    )
    (
        "network.outbound_connections",
        value<uint32_t>(&settings.network.outbound_connections)->
            default_value(NETWORK_OUTBOUND_CONNECTIONS),
        "The maximum number of outgoing network connections, defaults to 8."
    )
    (
        "network.connect_timeout_seconds",
        value<uint32_t>(&settings.network.connect_timeout_seconds)->
            default_value(NETWORK_CONNECT_TIMEOUT_SECONDS),
        "The time limit for connection establishment, defaults to 5."
    )
    (
        "network.channel_handshake_seconds",
        value<uint32_t>(&settings.network.channel_handshake_seconds)->
            default_value(NETWORK_CHANNEL_HANDSHAKE_SECONDS),
        "The time limit to complete the connection handshake, defaults to 30."
    )
    (
        "network.channel_revival_minutes",
        value<uint32_t>(&settings.network.channel_revival_minutes)->
            default_value(NETWORK_CHANNEL_REVIVAL_MINUTES),
        "The time between blocks that initiates a request, defaults to 5."
    )
    (
        "network.channel_heartbeat_minutes",
        value<uint32_t>(&settings.network.channel_heartbeat_minutes)->
            default_value(NETWORK_CHANNEL_HEARTBEAT_MINUTES),
        "The time between ping messages, defaults to 5."
    )
    (
        "network.channel_inactivity_minutes",
        value<uint32_t>(&settings.network.channel_inactivity_minutes)->
            default_value(NETWORK_CHANNEL_INACTIVITY_MINUTES),
        "The inactivity time limit for any connection, defaults to 30."
    )
    (
        "network.channel_expiration_minutes",
        value<uint32_t>(&settings.network.channel_expiration_minutes)->
            default_value(NETWORK_CHANNEL_EXPIRATION_MINUTES),
        "The maximum age limit for an outbound connection, defaults to 90."
    )
    (
        "network.channel_germination_seconds",
        value<uint32_t>(&settings.network.channel_germination_seconds)->
            default_value(NETWORK_CHANNEL_GERMINATION_SECONDS),
        "The maximum time limit for obtaining seed addresses, defaults to 30."
    )
    (
        "network.host_pool_capacity",
        value<uint32_t>(&settings.network.host_pool_capacity)->
            default_value(NETWORK_HOST_POOL_CAPACITY),
        "The maximum number of peer hosts in the pool, defaults to 1000."
    )
    (
        "network.relay_transactions",
        value<bool>(&settings.network.relay_transactions)->
            default_value(NETWORK_RELAY_TRANSACTIONS),
        "Request that peers relay transactions, defaults to true."
    )
    (
        "network.hosts_file",
        value<path>(&settings.network.hosts_file)->
            default_value(NETWORK_HOSTS_FILE),
        "The peer hosts cache file path, defaults to 'hosts.cache'."
    )
    (
        "network.debug_file",
        value<path>(&settings.network.debug_file)->
            default_value(NETWORK_DEBUG_FILE),
        "The debug log file path, defaults to 'debug.log'."
    )
    (
        "network.error_file",
        value<path>(&settings.network.error_file)->
            default_value(NETWORK_ERROR_FILE),
        "The error log file path, defaults to 'error.log'."
    )
    (
        "network.self",
        value<config::authority>(&settings.network.self)->
        multitoken()->default_value(NETWORK_SELF),
        "The advertised public address of this node, defaults to none."
    )
    (
        "network.seed",
        value<config::endpoint::list>(&settings.network.seeds)->
        multitoken()->default_value(NETWORK_SEEDS_MAINNET),
        "A seed node for initializing the host pool, multiple entries allowed."
    )

    /* [blockchain] */
    (
        "blockchain.threads",
        value<uint32_t>(&settings.chain.threads)->
            default_value(BLOCKCHAIN_THREADS),
        "The number of threads in the blockchain threadpool, defaults to 6."
    )
    (
        "blockchain.block_pool_capacity",
        value<uint32_t>(&settings.chain.block_pool_capacity)->
            default_value(BLOCKCHAIN_BLOCK_POOL_CAPACITY),
        "The maximum number of orphan blocks in the pool, defaults to 50."
    )
    (
        "blockchain.history_start_height",
        value<uint32_t>(&settings.chain.history_start_height)->
            default_value(BLOCKCHAIN_HISTORY_START_HEIGHT),
        "The history index start height, defaults to 0."
    )
    (
        "blockchain.use_testnet_rules",
        value<bool>(&settings.chain.use_testnet_rules)->
            default_value(BLOCKCHAIN_TESTNET_RULES_MAINNET),
        "Use testnet rules for determination of work required, defaults to false."
    )
    (
        "blockchain.database_path",
        value<path>(&settings.chain.database_path)->
            default_value(BLOCKCHAIN_DATABASE_PATH),
        "The blockchain database directory, defaults to 'blockchain'."
    )
    (
        "blockchain.checkpoint",
        value<config::checkpoint::list>(&settings.chain.checkpoints)->
            multitoken()->default_value(BLOCKCHAIN_CHECKPOINTS_MAINNET),
        "A hash:height checkpoint, multiple entries allowed."
    )

    /* [node] */
    (
        "node.threads",
        value<uint32_t>(&settings.node.threads)->
            default_value(NODE_THREADS),
        "The number of threads in the node threadpool, defaults to 4."
    )
    (
        "node.transaction_pool_capacity",
        value<uint32_t>(&settings.node.transaction_pool_capacity)->
            default_value(NODE_TRANSACTION_POOL_CAPACITY),
        "The number of threads in the node threadpool, defaults to 4."
    )
    (
        "node.peer",
        value<config::endpoint::list>(&settings.node.peers)->
            multitoken()->default_value(NODE_PEERS),
        "Persistent host:port to augment discovered hosts, multiple entries allowed."
    )
    (
        "node.blacklist",
        value<config::authority::list>(&settings.node.blacklists)->
            multitoken()->default_value(NODE_BLACKLISTS),
        "IP address to disallow as a peer, multiple entries allowed."
    )

    /* [server] */
    (
        "server.query_endpoint",
        value<endpoint>(&settings.server.query_endpoint)->
            default_value(SERVER_QUERY_ENDPOINT),
        "The query service endpoint, defaults to 'tcp://*:9091'."
    )
    (
        "server.heartbeat_endpoint",
        value<endpoint>(&settings.server.heartbeat_endpoint)->
            default_value(SERVER_HEARTBEAT_ENDPOINT),
        "The heartbeat service endpoint, defaults to 'tcp://*:9092'."
    )
    (
        "server.block_publish_endpoint",
        value<endpoint>(&settings.server.block_publish_endpoint)->
            default_value(SERVER_BLOCK_PUBLISH_ENDPOINT),
        "The block publishing service endpoint, defaults to 'tcp://*:9093'."
    )
    (
        "server.transaction_publish_endpoint",
        value<endpoint>(&settings.server.transaction_publish_endpoint)->
            default_value(SERVER_TRANSACTION_PUBLISH_ENDPOINT),
        "The transaction publishing service endpoint, defaults to 'tcp://*:9094'."
    )
    (
        "server.publisher_enabled",
        value<bool>(&settings.server.publisher_enabled)->
            default_value(SERVER_PUBLISHER_ENABLED),
        "Enable the block and transaction publishing endpoints, defaults to true."
    )
    (
        "server.queries_enabled",
        value<bool>(&settings.server.queries_enabled)->
            default_value(SERVER_QUERIES_ENABLED),
        "Enable the query and heartbeat endpoints, defaults to true."
    )
    (
        "server.log_requests",
        value<bool>(&settings.server.log_requests)->
            default_value(SERVER_LOG_REQUESTS),
        "Write service requests to the log, defaults to false."
    )
    (
        "server.polling_interval_milliseconds",
        value<uint32_t>(&settings.server.polling_interval_milliseconds)->
            default_value(SERVER_POLLING_INTERVAL_MILLISECONDS),
        "The query polling interval in milliseconds, defaults to 1000."
    )
    (
        "server.heartbeat_interval_seconds",
        value<uint32_t>(&settings.server.heartbeat_interval_seconds)->
            default_value(SERVER_HEARTBEAT_INTERVAL_SECONDS),
        "The heartbeat interval in seconds, defaults to 5."
    )
    (
        "server.subscription_expiration_minutes",
        value<uint32_t>(&settings.server.subscription_expiration_minutes)->
            default_value(SERVER_SUBSCRIPTION_EXPIRATION_MINUTES),
        "The subscription expiration time, defaults to 10 minutes."
    )
    (
        "server.subscription_limit",
        value<uint32_t>(&settings.server.subscription_limit)->
            default_value(SERVER_SUBSCRIPTION_LIMIT),
        "The maximum number of subscriptions, defaults to 100000000."
    )
    (
        "server.certificate_file",
        value<path>(&settings.server.certificate_file)->
            default_value(SERVER_CERTIFICATE_FILE),
        "The path to the ZPL-encoded server private certificate file."
    )
    (
        "server.client_certificates_path",
        value<path>(&settings.server.client_certificates_path)->
            default_value(SERVER_CLIENT_CERTIFICATES_PATH),
        "The directory for ZPL-encoded client public certificate files, allows anonymous clients if not set."
    )
    (
        "server.whitelist",
        value<config::authority::list>(&settings.server.whitelists)->
            multitoken()->default_value(SERVER_WHITELISTS),
        "Allowed client IP address, all clients allowed if none set, multiple entries allowed."
    );

    return description;
}

} // namespace server
} // namespace libbitcoin

<|endoftext|>


<commit_before>/*
Stereo Vision Algorithm Framework, Copyright(c) 2016-2018, Peng Chao
þɿռת
*/

#include "MatrixMulLayer.h"
#include <sstream>

namespace svaf{

MatrixMulLayer::MatrixMulLayer(LayerParameter& layer) : StereoLayer(layer)
{
	if (layer.mxmul_param().has_col0() && layer.mxmul_param().has_col1() && layer.mxmul_param().has_col2()){
		string col[3];
		col[0] = layer.mxmul_param().col0();
		col[1] = layer.mxmul_param().col1();
		col[2] = layer.mxmul_param().col2();
		stringstream ss;
		for (int i = 0; i < 2; ++i){
			ss.clear();
			ss << col[i];
			for (int j = 0; j < 3; ++j){
				ss >> M[i][j];
			}
		}
		LOG(INFO) << "Matrix Opened From Proto.";
	} else if(layer.mxmul_param().has_filename()){
		string filename = layer.mxmul_param().filename();
		FILE *fp = fopen(filename.c_str(), "rb+");
		CHECK_NOTNULL(fp);
		fread(&M[0], 4, 4, fp);
		fread(&M[1], 4, 4, fp);
		fread(&M[2], 4, 4, fp);
		fclose(fp);
		LOG(INFO) << "Matrix Opened From File " << filename;
	} else{
		LOG(FATAL) << "Matrix Create Failed!";
		RLOG("Matrix Create Failed!");
	}

	char loginfo[160];
	string logstr;
	sprintf(loginfo, "\t%8.3f\t%8.3f\t%8.3f\t%8.3f\n", M[0][0], M[0][1], M[0][2], M[0][3]); logstr += loginfo;
	sprintf(loginfo, "\t%8.3f\t%8.3f\t%8.3f\t%8.3f\n", M[1][0], M[1][1], M[1][2], M[1][3]); logstr += loginfo;
	sprintf(loginfo, "\t%8.3f\t%8.3f\t%8.3f\t%8.3f\n", M[2][0], M[2][1], M[2][2], M[2][3]); logstr += loginfo;
	LOG(INFO) << "world = M * camera, M = \n" << logstr;
	RLOG(string("world = M * camera, M = \n") + logstr);
}

MatrixMulLayer::~MatrixMulLayer()
{
}

bool MatrixMulLayer::Run(vector<Block>& images, vector<Block>& disp, LayerParameter& layer, void* param){
	auto pWorld = (World*)param;
	pWorld->pointW.clear();
	__t.StartWatchTimer();
	for (int i = 0; i < pWorld->pointL.size(); ++i){
		Point3f point;
		point.x = pWorld->pointL[i].x * M[0][0] + pWorld->pointL[i].y * M[0][1] + pWorld->pointL[i].z * M[0][2] + M[0][3];
		point.y = pWorld->pointL[i].x * M[1][0] + pWorld->pointL[i].y * M[1][1] + pWorld->pointL[i].z * M[1][2] + M[1][3];
		point.z = pWorld->pointL[i].x * M[2][0] + pWorld->pointL[i].y * M[2][1] + pWorld->pointL[i].z * M[2][2] + M[2][3];
		pWorld->pointW.push_back(point);
	}
	__t.ReadWatchTimer("RT Transform Time");
	if (__logt){
		(*figures)[__name + "_t"][*id] = (float)__t;
	}

	if (__save){
		pcdsave(string("tmp/W_") + Circuit::time_id_ + ".pcd", pWorld->pointW); // world coord
	}

	if (Layer::task_type == PC_MULMATRIX){
		__bout = true;
	} else{
		__bout = false;
	}

	if (__bout){
		Mat im;
		Block block("Point Cloud World", im, false, false, __bout);
		block.isOutput3DPoint = true;
		block.point3d = pWorld->pointW;
		disp.push_back(block);
	}

	char loginfo[160];
	string logstr;
	for (int i = 0; i < (std::min)((int)pWorld->xl.size(), INT_MAX); ++i){
		sprintf(loginfo, "(%8.3f, %8.3f) (%8.3f, %8.3f)\t(%8.3f, %8.3f, %8.3f)\n",
			pWorld->xl[i].x, pWorld->xl[i].y, pWorld->xr[i].x, pWorld->xr[i].y,
			pWorld->pointW[i].x, pWorld->pointW[i].y, pWorld->pointW[i].z);
		logstr += loginfo;
	}
	LOG(INFO) << "Left Camera Point: \n \t xl\t\t\t xr \t\t\t pointW\n" << logstr;

	if (pWorld->xl.size() == 1){
		pWorld->x = pWorld->pointW[0].x;
		pWorld->y = pWorld->pointW[0].y;
		pWorld->z = pWorld->pointW[0].z;
		pWorld->a = 0;
		pWorld->b = 0;
		pWorld->c = 0;
		pWorld->fetchtype = 1;
	}

	return true;
}

}
<commit_msg>add Note for MatrixMulLayer<commit_after>/*
Stereo Vision Algorithm Framework, Copyright(c) 2016-2018, Peng Chao
þɿռת
*/

#include "MatrixMulLayer.h"
#include <sstream>

namespace svaf{

// ๹ʱʹļȡ任
MatrixMulLayer::MatrixMulLayer(LayerParameter& layer) : StereoLayer(layer)
{
	if (layer.mxmul_param().has_col0() && layer.mxmul_param().has_col1() && layer.mxmul_param().has_col2()){
		// ļűжȡ任
		string col[3];
		col[0] = layer.mxmul_param().col0();
		col[1] = layer.mxmul_param().col1();
		col[2] = layer.mxmul_param().col2();
		stringstream ss;
		for (int i = 0; i < 2; ++i){
			ss.clear();
			ss << col[i];
			for (int j = 0; j < 3; ++j){
				ss >> M[i][j];
			}
		}
		LOG(INFO) << "Matrix Opened From Proto.";
	} else if(layer.mxmul_param().has_filename()){
		// Ӷļжȡ任
		string filename = layer.mxmul_param().filename();
		FILE *fp = fopen(filename.c_str(), "rb+");
		CHECK_NOTNULL(fp);
		fread(&M[0], 4, 4, fp);
		fread(&M[1], 4, 4, fp);
		fread(&M[2], 4, 4, fp);
		fclose(fp);
		LOG(INFO) << "Matrix Opened From File " << filename;
	} else{
		// ޾任ʧ
		LOG(FATAL) << "Matrix Create Failed!";
		RLOG("Matrix Create Failed!");
	}

	char loginfo[160];
	string logstr;
	sprintf(loginfo, "\t%8.3f\t%8.3f\t%8.3f\t%8.3f\n", M[0][0], M[0][1], M[0][2], M[0][3]); logstr += loginfo;
	sprintf(loginfo, "\t%8.3f\t%8.3f\t%8.3f\t%8.3f\n", M[1][0], M[1][1], M[1][2], M[1][3]); logstr += loginfo;
	sprintf(loginfo, "\t%8.3f\t%8.3f\t%8.3f\t%8.3f\n", M[2][0], M[2][1], M[2][2], M[2][3]); logstr += loginfo;
	LOG(INFO) << "world = M * camera, M = \n" << logstr;
	RLOG(string("world = M * camera, M = \n") + logstr);
}

MatrixMulLayer::~MatrixMulLayer()
{
}

bool MatrixMulLayer::Run(vector<Block>& images, vector<Block>& disp, LayerParameter& layer, void* param){
	auto pWorld = (World*)param;
	// ͨ˽任Ϊ
	pWorld->pointW.clear();
	__t.StartWatchTimer();
	for (int i = 0; i < pWorld->pointL.size(); ++i){
		Point3f point;
		point.x = pWorld->pointL[i].x * M[0][0] + pWorld->pointL[i].y * M[0][1] + pWorld->pointL[i].z * M[0][2] + M[0][3];
		point.y = pWorld->pointL[i].x * M[1][0] + pWorld->pointL[i].y * M[1][1] + pWorld->pointL[i].z * M[1][2] + M[1][3];
		point.z = pWorld->pointL[i].x * M[2][0] + pWorld->pointL[i].y * M[2][1] + pWorld->pointL[i].z * M[2][2] + M[2][3];
		pWorld->pointW.push_back(point);
	}
	__t.ReadWatchTimer("RT Transform Time");
	if (__logt){
		(*figures)[__name + "_t"][*id] = (float)__t;
	}

	// ϵµĵƽ
	if (__save){
		pcdsave(string("tmp/W_") + Circuit::time_id_ + ".pcd", pWorld->pointW); // world coord
	}

	if (Layer::task_type == PC_MULMATRIX){
		__bout = true;
	} else{
		__bout = false;
	}

	if (__bout){
		Mat im;
		Block block("Point Cloud World", im, false, false, __bout);
		block.isOutput3DPoint = true;
		block.point3d = pWorld->pointW;
		disp.push_back(block);
	}

	// Ϣ¼־
	char loginfo[160];
	string logstr;
	for (int i = 0; i < (std::min)((int)pWorld->xl.size(), INT_MAX); ++i){
		sprintf(loginfo, "(%8.3f, %8.3f) (%8.3f, %8.3f)\t(%8.3f, %8.3f, %8.3f)\n",
			pWorld->xl[i].x, pWorld->xl[i].y, pWorld->xr[i].x, pWorld->xr[i].y,
			pWorld->pointW[i].x, pWorld->pointW[i].y, pWorld->pointW[i].z);
		logstr += loginfo;
	}
	LOG(INFO) << "Left Camera Point: \n \t xl\t\t\t xr \t\t\t pointW\n" << logstr;

	if (pWorld->xl.size() == 1){
		pWorld->x = pWorld->pointW[0].x;
		pWorld->y = pWorld->pointW[0].y;
		pWorld->z = pWorld->pointW[0].z;
		pWorld->a = 0;
		pWorld->b = 0;
		pWorld->c = 0;
		pWorld->fetchtype = 1;
	}

	return true;
}

}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "VoxelSystem.h"
#include "lodepng.h"
#include "TerrainGen.h"

#include "GL3DProgram.h"
#include "OS.h"

#include "GameTile.h"

#include "VoxelDrawSystem.h"
#include "InstancedVoxelRenderSystem.h"
#include "BasicVoxelRenderSystem.h"
#include <sstream>

static const int tile_width = 256;
static const int tile_height = 256;

VoxelSystem::VoxelSystem() {
	//Init Terrain Generator
	generator = new TerrainGen();
	generator->setTileSize(tile_width, tile_height);

	renderer = VoxelDrawSystem::BuildAppropriateSystem();

	//Load the tile textures
	unsigned int textureWidth, textureHeight;
	vector<unsigned char> image;

	//A smart system would have multiple res tiles and would automatically select
	//one appropriate for the system its running on
	lodepng::decode(image, textureWidth, textureHeight, "terrain/tiles-lowres.png");

	//I should have moved the png->texture into a utility library
	//later...
	glGenTextures(1, &textureId);
	glBindTexture(GL_TEXTURE_2D, textureId);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth,
		textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
		&image[0]);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);	//GL_NEAREST FOR SPEED
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);	//GL_NEAREST FOR SPEED
}
VoxelSystem::~VoxelSystem() {
	delete renderer;
}

//Attempt to load a tile from disc
bool VoxelSystem::LoadWorld(string saveName) {
	if (0) {

	}
	else {
		//todo, set seed
		GenWorld(128);

	}

	return true;
}

bool VoxelSystem::LoadTile(int seed, int x, int y) {
	stringstream s;
	s << "saves/" << seed << "-" << x << "-" << y << ".txt";
	GameTile * tileData = GameTile::LoadTileFromDisk(s.str());

	if (tileData != NULL) {
		tileData->tile_x = x;
		tileData->tile_y = y;
		world.insert(tileData);
		return true;

	}
	else {
		GenTile(x, y);
		return false;
	}

}

bool VoxelSystem::GenTile(int x, int y) {
	//Generate Terrain Tile
	unsigned char* rawTile = generator->generateTile(x, y);

	//Create and Fill Terrain Data Vector
	vector<unsigned char> tile;
	tile.assign(rawTile, rawTile + (tile_width*tile_height * 4));

	//Free Terrain Tile Memory
	free(rawTile);

	GameTile * tileData = GameTile::LoadTileFromMemory(tile, tile_width, tile_height);
	tileData->tile_x = x;
	tileData->tile_y = y;
	world.insert(tileData);
	return true;
}

bool VoxelSystem::GenWorld(int seed) {
	//todo, call set seed
	//for (int x = 0; x < 3; x++) {
	//	for (int y = 0; y < 3; y++) {
	//		LoadTile(seed, x, y);
	//	}
	//}
	LoadTile(seed, 0, 0);
	return true;
}

TileCell * VoxelSystem::GetTileCellAt(vec2 pos) {
	GameTile * tileData = NULL;

	//Check that the position is valid
	for (int j = 0; j < world.size(); j++) {
		if ((world[j])->tile_x == floor(pos.x / 256) && world[j]->tile_y == floor(pos.y / 256)) {
			tileData = world[j];
			break;
		}
	}
	//convert to relative position
	pos.x = int(pos.x) % 256;
	pos.y = int(pos.y) % 256;

	if ((pos.x < 0) || (pos.y < 0))
		return NULL;

	if ((pos.x >= tileData->Width) || (pos.y >= tileData->Height))
		return NULL;

	return tileData->GetTileCell(pos);
}

//When the voxel system calculates position height
//it will have to check which tile the position is in
//in the future. For now only one tile is loaded
float VoxelSystem::GetPositionHeight(vec2 pos) {
	//The height where there is no tiles
	//right now causes the player to fall
	//because that's fun?
	GameTile * tileData = NULL;
	static const float floorHeight = -1000.0f;

	for (int j = 0; j < world.size(); j++) {
		if ((world[j])->tile_x == floor(pos.x / 256) && world[j]->tile_y == floor(pos.y / 256)) {
			tileData = world[j];
			break;
		}
	}
	TileCell * cell = GetTileCellAt(pos);

	if (tileData != NULL){

		if (cell == NULL)
			return floorHeight;

		//Player is within the set of valid tiles

		//Now get the height of that tile
		//we add 1 because voxels have 1 height
		//so the visible floor is 1 above the corner they draw from
		return cell->height + 1.0f;
	}
	return  floorHeight;
}

//Get the stack size of a specific position
//all positions acceptable
int VoxelSystem::GetPositionStackSize(vec2 pos) {
	TileCell * cell = GetTileCellAt(pos);

	if (cell == NULL)
		return -1;

	//Player is within the set of valid tiles

	return cell->stackHeight + 1;
}

//Draw the voxels in a region
void VoxelSystem::Draw(GL3DProgram * shader, vec3 drawPos, int atx, int aty, int tox, int toy) {
	_ASSERTE(atx >= 0);
	_ASSERTE(aty >= 0);
	//_ASSERTE(tileData != NULL);

	//Enable voxel texture
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, textureId);

	vector<tile_renderinfo> tiles;
	tile_renderinfo current_tile;
	//cout << "Player Position: " << atx << " : " << tox << "," << aty << " : " << toy << endl;

	//break the view into relevant rectangles
	for (int y = aty; y <= toy; y += 256 - y % 256) {
		//start at the smallest value and get tile aligned asap
		for (int x = atx; x <= tox; x += 256 - x % 256) {
			//calculate offsets for this rectangle
			current_tile.tile_x = floor(x / 256);
			current_tile.tile_y = floor(y / 256);

			current_tile.x_start = x % 256;
			current_tile.x_end = (min(x + 256 - x % 256, tox) - 1) % 256;
			current_tile.y_start = y % 256;
			current_tile.y_end = (min(y + 256 - y % 256, toy) - 1) % 256;
			tiles.push_back(current_tile);

		}
	}
	voxelCount = 0;

	//render each viewable rectangle

	for (int i = 0; i < tiles.size(); i++) {
		current_tile = tiles[i];
		//find the tile in our world
		GameTile * tileData = NULL;
		for (int j = 0; j < world.size(); j++) {
			if ((world[j])->tile_x == current_tile.tile_x && world[j]->tile_y == current_tile.tile_y) {
				tileData = world[j];
				break;
			}
		}
		if (tileData != NULL){
			shader->Model.PushMatrix();
			shader->Model.Translate(vec3(current_tile.tile_x * 256, current_tile.tile_y * 256, 0));
			shader->Model.Apply();
			TileCell * cells = tileData->Cells;

			renderer->startDraw(shader);
			for (int y = current_tile.y_start; y <= current_tile.y_end; y++) {
				//It is important for x to be the inner loop
				//so consecutive operations access contiguous memory
				//(though performance will probably be poor anyways)
				for (int x = current_tile.x_start; x <= current_tile.x_end; x++) {
					//Lookup cell to render
					TileCell & cell = cells[tileData->Width*y + x];

					//Get position
					vec3 pos = vec3(x, y, cell.height);
					int8_t stack = (int8_t)cell.stackHeight;

					voxelCount += stack + 1;

					//For now use raw tile % 16 to map all tiles to be within the 16 valid materials
					//Note: This is a really bad place for a virtual function call
					//maybe swap this out in the future
					while (stack-- >= 0) {
						renderer->pushVoxel(shader, pos, cell.materialId % 16);
						pos.z--;
					}
				}
			}
			renderer->finishDraw(shader);
			shader->Model.PopMatrix();
		}
	}

}

void VoxelSystem::Update(vec3 player_pos){
	//check the players position, offload tiles, generate new tiles
	for (int x_offset = -1; x_offset <= 1; x_offset++) {
		for (int y_offset = -1; y_offset <= 1; y_offset++) {
			//make sure tile exists
			GameTile * tileData = NULL;
			for (int j = 0; j < world.size(); j++) {
				if ((world[j])->tile_x == floor(player_pos.x / 256) +x_offset && world[j]->tile_y == floor(player_pos.y / 256) + y_offset) {
					tileData = world[j];
					break;
				}
			}
			if (tileData == NULL) {
				cout << "Generating: " << floor(player_pos.x / 256) + x_offset << "," << floor(player_pos.y / 256) + y_offset;
				GenTile(floor(player_pos.x / 256) + x_offset, floor(player_pos.y / 256) + y_offset);
			}

		}
	}

}

//Get map width
int VoxelSystem::GetWidth() {
	return tile_width * 3; //tileData->Width*5;
}
//Get map height
int VoxelSystem::GetHeight() {
	return tile_height * 3; //tileData->Height;
}

int VoxelSystem::GetLastVoxelCount() {
	return voxelCount;
}

void VoxelSystem::Paint(vec2 pos, int newMaterial) {
	TileCell * cell = GetTileCellAt(pos);

	if (cell == NULL)
		return;

	//Player is within the set of valid tiles
	//Paint the tile material
	cell->materialId = newMaterial;
}

//Deforms a region of voxels, punching a crater into the given position
//all voxels removed are returned as positions
vector<vec4> VoxelSystem::Crater(vec3 pos, float size) {
	GameTile * tileData;

	vector<tile_renderinfo> tiles;
	tile_renderinfo current_tile;
	//get the crater sides
	int atx = (int)(pos.x - size / 2.0);
	int aty = (int)(pos.y - size / 2.0);
	int tox = (int)(pos.x + size / 2.0);
	int toy = (int)(pos.y + size / 2.0);

	//break the view into relevant rectangles
	for (int y = aty; y <= toy; y += 256 - y % 256) {
		//start at the smallest value and get tile aligned asap
		for (int x = atx; x <= tox; x += 256 - x % 256) {
			//calculate offsets for this rectangle
			current_tile.tile_x = floor(x / 256);
			current_tile.tile_y = floor(y / 256);

			current_tile.x_start = x % 256;
			current_tile.x_end = (min(x + 256 - x % 256, tox) - 1) % 256;
			current_tile.y_start = y % 256;
			current_tile.y_end = (min(y + 256 - y % 256, toy) - 1) % 256;
			tiles.push_back(current_tile);

		}
	}
	vector<vec4> removedVoxels;

	for (int i = 0; i < tiles.size(); i++) {
		current_tile = tiles[i];
		//find the tile in our world
		GameTile * tileData = NULL;
		for (int j = 0; j < world.size(); j++) {
			if ((world[j])->tile_x == current_tile.tile_x && world[j]->tile_y == current_tile.tile_y) {
				tileData = world[j];
				break;
			}
		}
		if (tileData != NULL){
			for (int y = current_tile.y_start; y <= current_tile.y_end; y++) {
				for (int x = current_tile.x_start; x <= current_tile.x_end; x++) {

					//Modify pos to be relative to the tile
					pos -= vec3((float)tileData->tile_x*tile_width, (float)tileData->tile_y*tile_height, 0.0f);
					//Build the intersection of this crater and the valid tile(s)

					//Apply this region to the valid tile
					tileData->Crater(current_tile.x_start, current_tile.y_start, current_tile.x_end, current_tile.y_end, (int)(pos.z - size / 2.0), removedVoxels);

				}
			}
		}
	}
	//Return all removed voxels
	return removedVoxels;
}<commit_msg>made the map larger<commit_after>#include "stdafx.h"
#include "VoxelSystem.h"
#include "lodepng.h"
#include "TerrainGen.h"

#include "GL3DProgram.h"
#include "OS.h"

#include "GameTile.h"

#include "VoxelDrawSystem.h"
#include "InstancedVoxelRenderSystem.h"
#include "BasicVoxelRenderSystem.h"
#include <sstream>

static const int tile_width = 256;
static const int tile_height = 256;

VoxelSystem::VoxelSystem() {
	//Init Terrain Generator
	generator = new TerrainGen();
	generator->setTileSize(tile_width, tile_height);

	renderer = VoxelDrawSystem::BuildAppropriateSystem();

	//Load the tile textures
	unsigned int textureWidth, textureHeight;
	vector<unsigned char> image;

	//A smart system would have multiple res tiles and would automatically select
	//one appropriate for the system its running on
	lodepng::decode(image, textureWidth, textureHeight, "terrain/tiles-lowres.png");

	//I should have moved the png->texture into a utility library
	//later...
	glGenTextures(1, &textureId);
	glBindTexture(GL_TEXTURE_2D, textureId);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth,
		textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
		&image[0]);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);	//GL_NEAREST FOR SPEED
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);	//GL_NEAREST FOR SPEED
}
VoxelSystem::~VoxelSystem() {
	delete renderer;
}

//Attempt to load a tile from disc
bool VoxelSystem::LoadWorld(string saveName) {
	if (0) {

	}
	else {
		//todo, set seed
		GenWorld(128);

	}

	return true;
}

bool VoxelSystem::LoadTile(int seed, int x, int y) {
	stringstream s;
	s << "saves/" << seed << "-" << x << "-" << y << ".txt";
	GameTile * tileData = GameTile::LoadTileFromDisk(s.str());

	if (tileData != NULL) {
		tileData->tile_x = x;
		tileData->tile_y = y;
		world.insert(tileData);
		return true;

	}
	else {
		GenTile(x, y);
		return false;
	}

}

bool VoxelSystem::GenTile(int x, int y) {
	//Generate Terrain Tile
	unsigned char* rawTile = generator->generateTile(x, y);

	//Create and Fill Terrain Data Vector
	vector<unsigned char> tile;
	tile.assign(rawTile, rawTile + (tile_width*tile_height * 4));

	//Free Terrain Tile Memory
	free(rawTile);

	GameTile * tileData = GameTile::LoadTileFromMemory(tile, tile_width, tile_height);
	tileData->tile_x = x;
	tileData->tile_y = y;
	world.insert(tileData);
	return true;
}

bool VoxelSystem::GenWorld(int seed) {
	//todo, call set seed
	//for (int x = 0; x < 3; x++) {
	//	for (int y = 0; y < 3; y++) {
	//		LoadTile(seed, x, y);
	//	}
	//}
	LoadTile(seed, 0, 0);
	return true;
}

TileCell * VoxelSystem::GetTileCellAt(vec2 pos) {
	GameTile * tileData = NULL;

	//Check that the position is valid
	for (int j = 0; j < world.size(); j++) {
		if ((world[j])->tile_x == floor(pos.x / 256) && world[j]->tile_y == floor(pos.y / 256)) {
			tileData = world[j];
			break;
		}
	}
	//convert to relative position
	pos.x = int(pos.x) % 256;
	pos.y = int(pos.y) % 256;

	if ((pos.x < 0) || (pos.y < 0))
		return NULL;

	if ((pos.x >= tileData->Width) || (pos.y >= tileData->Height))
		return NULL;

	return tileData->GetTileCell(pos);
}

//When the voxel system calculates position height
//it will have to check which tile the position is in
//in the future. For now only one tile is loaded
float VoxelSystem::GetPositionHeight(vec2 pos) {
	//The height where there is no tiles
	//right now causes the player to fall
	//because that's fun?
	GameTile * tileData = NULL;
	static const float floorHeight = -1000.0f;

	for (int j = 0; j < world.size(); j++) {
		if ((world[j])->tile_x == floor(pos.x / 256) && world[j]->tile_y == floor(pos.y / 256)) {
			tileData = world[j];
			break;
		}
	}
	TileCell * cell = GetTileCellAt(pos);

	if (tileData != NULL){

		if (cell == NULL)
			return floorHeight;

		//Player is within the set of valid tiles

		//Now get the height of that tile
		//we add 1 because voxels have 1 height
		//so the visible floor is 1 above the corner they draw from
		return cell->height + 1.0f;
	}
	return  floorHeight;
}

//Get the stack size of a specific position
//all positions acceptable
int VoxelSystem::GetPositionStackSize(vec2 pos) {
	TileCell * cell = GetTileCellAt(pos);

	if (cell == NULL)
		return -1;

	//Player is within the set of valid tiles

	return cell->stackHeight + 1;
}

//Draw the voxels in a region
void VoxelSystem::Draw(GL3DProgram * shader, vec3 drawPos, int atx, int aty, int tox, int toy) {
	_ASSERTE(atx >= 0);
	_ASSERTE(aty >= 0);
	//_ASSERTE(tileData != NULL);

	//Enable voxel texture
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, textureId);

	vector<tile_renderinfo> tiles;
	tile_renderinfo current_tile;
	//cout << "Player Position: " << atx << " : " << tox << "," << aty << " : " << toy << endl;

	//break the view into relevant rectangles
	for (int y = aty; y <= toy; y += 256 - y % 256) {
		//start at the smallest value and get tile aligned asap
		for (int x = atx; x <= tox; x += 256 - x % 256) {
			//calculate offsets for this rectangle
			current_tile.tile_x = floor(x / 256);
			current_tile.tile_y = floor(y / 256);

			current_tile.x_start = x % 256;
			current_tile.x_end = (min(x + 256 - x % 256, tox) - 1) % 256;
			current_tile.y_start = y % 256;
			current_tile.y_end = (min(y + 256 - y % 256, toy) - 1) % 256;
			tiles.push_back(current_tile);

		}
	}
	voxelCount = 0;

	//render each viewable rectangle

	for (int i = 0; i < tiles.size(); i++) {
		current_tile = tiles[i];
		//find the tile in our world
		GameTile * tileData = NULL;
		for (int j = 0; j < world.size(); j++) {
			if ((world[j])->tile_x == current_tile.tile_x && world[j]->tile_y == current_tile.tile_y) {
				tileData = world[j];
				break;
			}
		}
		if (tileData != NULL){
			shader->Model.PushMatrix();
			shader->Model.Translate(vec3(current_tile.tile_x * 256, current_tile.tile_y * 256, 0));
			shader->Model.Apply();
			TileCell * cells = tileData->Cells;

			renderer->startDraw(shader);
			for (int y = current_tile.y_start; y <= current_tile.y_end; y++) {
				//It is important for x to be the inner loop
				//so consecutive operations access contiguous memory
				//(though performance will probably be poor anyways)
				for (int x = current_tile.x_start; x <= current_tile.x_end; x++) {
					//Lookup cell to render
					TileCell & cell = cells[tileData->Width*y + x];

					//Get position
					vec3 pos = vec3(x, y, cell.height);
					int8_t stack = (int8_t)cell.stackHeight;

					voxelCount += stack + 1;

					//For now use raw tile % 16 to map all tiles to be within the 16 valid materials
					//Note: This is a really bad place for a virtual function call
					//maybe swap this out in the future
					while (stack-- >= 0) {
						renderer->pushVoxel(shader, pos, cell.materialId % 16);
						pos.z--;
					}
				}
			}
			renderer->finishDraw(shader);
			shader->Model.PopMatrix();
		}
	}

}

void VoxelSystem::Update(vec3 player_pos){
	//check the players position, offload tiles, generate new tiles
	for (int x_offset = -1; x_offset <= 1; x_offset++) {
		for (int y_offset = -1; y_offset <= 1; y_offset++) {
			//make sure tile exists
			GameTile * tileData = NULL;
			for (int j = 0; j < world.size(); j++) {
				if ((world[j])->tile_x == floor(player_pos.x / 256) +x_offset && world[j]->tile_y == floor(player_pos.y / 256) + y_offset) {
					tileData = world[j];
					break;
				}
			}
			if (tileData == NULL) {
				cout << "Generating: " << floor(player_pos.x / 256) + x_offset << "," << floor(player_pos.y / 256) + y_offset;
				GenTile(floor(player_pos.x / 256) + x_offset, floor(player_pos.y / 256) + y_offset);
			}

		}
	}

}

//Get map width
int VoxelSystem::GetWidth() {
	return tile_width * 255; //tileData->Width*5;
}
//Get map height
int VoxelSystem::GetHeight() {
	return tile_height * 255; //tileData->Height;
}

int VoxelSystem::GetLastVoxelCount() {
	return voxelCount;
}

void VoxelSystem::Paint(vec2 pos, int newMaterial) {
	TileCell * cell = GetTileCellAt(pos);

	if (cell == NULL)
		return;

	//Player is within the set of valid tiles
	//Paint the tile material
	cell->materialId = newMaterial;
}

//Deforms a region of voxels, punching a crater into the given position
//all voxels removed are returned as positions
vector<vec4> VoxelSystem::Crater(vec3 pos, float size) {
	GameTile * tileData;

	vector<tile_renderinfo> tiles;
	tile_renderinfo current_tile;
	//get the crater sides
	int atx = (int)(pos.x - size / 2.0);
	int aty = (int)(pos.y - size / 2.0);
	int tox = (int)(pos.x + size / 2.0);
	int toy = (int)(pos.y + size / 2.0);

	//break the view into relevant rectangles
	for (int y = aty; y <= toy; y += 256 - y % 256) {
		//start at the smallest value and get tile aligned asap
		for (int x = atx; x <= tox; x += 256 - x % 256) {
			//calculate offsets for this rectangle
			current_tile.tile_x = floor(x / 256);
			current_tile.tile_y = floor(y / 256);

			current_tile.x_start = x % 256;
			current_tile.x_end = (min(x + 256 - x % 256, tox) - 1) % 256;
			current_tile.y_start = y % 256;
			current_tile.y_end = (min(y + 256 - y % 256, toy) - 1) % 256;
			tiles.push_back(current_tile);

		}
	}
	vector<vec4> removedVoxels;

	for (int i = 0; i < tiles.size(); i++) {
		current_tile = tiles[i];
		//find the tile in our world
		GameTile * tileData = NULL;
		for (int j = 0; j < world.size(); j++) {
			if ((world[j])->tile_x == current_tile.tile_x && world[j]->tile_y == current_tile.tile_y) {
				tileData = world[j];
				break;
			}
		}
		if (tileData != NULL){
			for (int y = current_tile.y_start; y <= current_tile.y_end; y++) {
				for (int x = current_tile.x_start; x <= current_tile.x_end; x++) {

					//Modify pos to be relative to the tile
					pos -= vec3((float)tileData->tile_x*tile_width, (float)tileData->tile_y*tile_height, 0.0f);
					//Build the intersection of this crater and the valid tile(s)

					//Apply this region to the valid tile
					tileData->Crater(current_tile.x_start, current_tile.y_start, current_tile.x_end, current_tile.y_end, (int)(pos.z - size / 2.0), removedVoxels);

				}
			}
		}
	}
	//Return all removed voxels
	return removedVoxels;
}<|endoftext|>