<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/mbox/ipcSp.C $                                        */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2013,2014              */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include <mbox/ipc_msg_types.H>
#include "ipcSp.H"
#include <runtime/runtime.H>
#include <vfs/vfs.H>
#include <mbox/ipc_reasoncodes.H>
#include <mbox/mboxif.H>
#include <errl/errlmanager.H>
#include <mbox/mbox_reasoncodes.H>
#include <intr/interrupt.H>

namespace START_PAYLOAD
{
    extern errlHndl_t callShutdown ( uint64_t i_hbInstance,
                                     bool i_masterInstance );
};

trace_desc_t* g_trac_ipc = NULL;
TRAC_INIT(&g_trac_ipc, IPC_TRACE_NAME, KILOBYTE);

using namespace IPC;
using namespace ERRORLOG;

IpcSp::IpcSp()
    :
        iv_msgQ()
{
}

IpcSp::~IpcSp()
{
    msg_q_destroy(iv_msgQ);
}

void IpcSp::init(errlHndl_t & o_errl)
{
    o_errl = Singleton<IpcSp>::instance()._init();
}

void* IpcSp::msg_handler(void *unused)
{
    Singleton<IpcSp>::instance().msgHandler();
    return NULL;
}

errlHndl_t IpcSp::_init()
{
    errlHndl_t err = NULL;

    iv_msgQ = msg_q_create();
    err = MBOX::msgq_register(MBOX::HB_IPC_MSGQ,iv_msgQ);

    if(!err)
    {
        task_create(IpcSp::msg_handler, NULL);
    }

    return err;
}

void IpcSp::msgHandler()
{
    errlHndl_t err = NULL;
    bool mod_loaded = false;

    while(1)
    {
        msg_t* msg = msg_wait(iv_msgQ);

        switch(msg->type)
        {
            case IPC_POPULATE_ATTRIBUTES:
                // make sure runtime module is loaded
                if ( !VFS::module_is_loaded( "libruntime.so" ) )
                {
                    err = VFS::module_load( "libruntime.so" );

                    if ( err )
                    {
                        TRACFCOMP( g_trac_ipc,
                                   "Could not load runtime module" );
                    }
                    else
                    {
                        mod_loaded = true;
                    }
                }
                if(!err)
                {
                    RUNTIME::setPayloadBaseAddress
                        (reinterpret_cast<uint64_t>(msg->extra_data));

                    err = RUNTIME::populate_node_attributes( msg->data[0] );
                }

                if (err)
                {
                    errlCommit(err, IPC_COMP_ID);
                }

                if(mod_loaded)
                {
                    err = VFS::module_unload( "libruntime.so" );

                    if (err)
                    {
                        errlCommit(err, IPC_COMP_ID);
                    }
                    mod_loaded = false;
                }

                // Respond
                err = MBOX::send(MBOX::HB_POP_ATTR_MSGQ, msg, msg->data[1] );
                if (err)
                {
                    errlCommit(err,IPC_COMP_ID);
                }

                break;

            case IPC_TEST_CONNECTION:

                TRACFCOMP( g_trac_ipc,
                           "IPC received the test connection msg - %d:%d",
                            msg->data[0], msg->data[1] );

                // Tell this HB node about the other HB node
                err = INTR::addHbNode(msg->data[1]);
                if( err)
                {
                    errlCommit(err,IPC_COMP_ID);
                }

                //Send a response to indicate the connection has been
                //established
                err = MBOX::send(MBOX::HB_COALESCE_MSGQ, msg, msg->data[1] );

                if (err)
                {
                    errlCommit(err,IPC_COMP_ID);
                }
                break;

            case IPC_START_PAYLOAD:

                if ( !VFS::module_is_loaded( "libstart_payload.so" ) )
                {
                    err = VFS::module_load( "libstart_payload.so" );

                    if ( err )
                    {
                        TRACFCOMP( g_trac_ipc,
                                   "Could not load runtime module" );
                    }
                    else
                    {
                        mod_loaded = true;
                    }
                }

                if(!err)
                {
                    //  Function will not return unless error
                    err = START_PAYLOAD::callShutdown(msg->data[0],false);
                }

                if(err)
                {
                    errlCommit(err, IPC_COMP_ID);
                }

                if(mod_loaded)
                {
                    err = VFS::module_unload( "libstart_payload.so" );

                    if (err)
                    {
                        errlCommit(err, IPC_COMP_ID);
                    }
                    mod_loaded = false;
                }

                msg_free(msg);

                break;

            default:

                TRACFCOMP( g_trac_ipc,
                           "IPC received an unexpected message type of %d",
                           msg->type);

                /*@ errorlog tag
                 * @errortype  ERRL_SEV_INFORMATIONAL
                 * @moduleid   IPC::MOD_IPCSP_MSGHDLR
                 * @reasoncode IPC::RC_INVALID_MSG_TYPE
                 * @userdata1  Message type
                 * @userdata2  Data word 0 of message
                 *
                 * @devdesc    IPC service provider received an unexpected
                 *             message.
                 *
                 */
                err = new ERRORLOG::ErrlEntry
                    (
                     ERRORLOG::ERRL_SEV_INFORMATIONAL,    // severity
                     IPC::MOD_IPCSP_MSGHDLR,              // moduleid
                     IPC::RC_INVALID_MSG_TYPE,            // reason code
                     msg->type,
                     msg->data[0],
                     true //Add HB Software Callout
                    );
                //@todo: RTC:93750 Create real parseable FFDC class
                err->addFFDC(MBOX_COMP_ID,
                             msg,
                             sizeof(msg_t),
                             1,//version
                             MBOX::MBOX_UDT_MSG_DATA);//subsect

                err->collectTrace(MBOXMSG_TRACE_NAME);
                err->collectTrace(IPC_TRACE_NAME);

                errlCommit(err, IPC_COMP_ID);

                msg_free(msg);

                break;
        }
    }
}

<commit_msg>Stop IPLing in IpcSp::messageHandler if there is an error<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/mbox/ipcSp.C $                                        */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2013,2014                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include <mbox/ipc_msg_types.H>
#include "ipcSp.H"
#include <runtime/runtime.H>
#include <vfs/vfs.H>
#include <mbox/ipc_reasoncodes.H>
#include <mbox/mboxif.H>
#include <errl/errlmanager.H>
#include <mbox/mbox_reasoncodes.H>
#include <intr/interrupt.H>
#include <initservice/initserviceif.H>

namespace START_PAYLOAD
{
    extern errlHndl_t callShutdown ( uint64_t i_hbInstance,
                                     bool i_masterInstance );
};

trace_desc_t* g_trac_ipc = NULL;
TRAC_INIT(&g_trac_ipc, IPC_TRACE_NAME, KILOBYTE);

using namespace IPC;
using namespace ERRORLOG;

IpcSp::IpcSp()
    :
        iv_msgQ()
{
}

IpcSp::~IpcSp()
{
    msg_q_destroy(iv_msgQ);
}

void IpcSp::init(errlHndl_t & o_errl)
{
    o_errl = Singleton<IpcSp>::instance()._init();
}

void* IpcSp::msg_handler(void *unused)
{
    Singleton<IpcSp>::instance().msgHandler();
    return NULL;
}

errlHndl_t IpcSp::_init()
{
    errlHndl_t err = NULL;

    iv_msgQ = msg_q_create();
    err = MBOX::msgq_register(MBOX::HB_IPC_MSGQ,iv_msgQ);

    if(!err)
    {
        task_create(IpcSp::msg_handler, NULL);
    }

    return err;
}

void IpcSp::msgHandler()
{
    errlHndl_t err = NULL;
    bool mod_loaded = false;

    while(1)
    {
        msg_t* msg = msg_wait(iv_msgQ);

        switch(msg->type)
        {
            case IPC_POPULATE_ATTRIBUTES:
                // make sure runtime module is loaded
                if ( !VFS::module_is_loaded( "libruntime.so" ) )
                {
                    err = VFS::module_load( "libruntime.so" );

                    if ( err )
                    {
                        TRACFCOMP( g_trac_ipc,
                                   "Could not load runtime module" );
                    }
                    else
                    {
                        mod_loaded = true;
                    }
                }
                if(!err)
                {
                    RUNTIME::setPayloadBaseAddress
                        (reinterpret_cast<uint64_t>(msg->extra_data));

                    err = RUNTIME::populate_node_attributes( msg->data[0] );
                }

                if (err)
                {
                    TRACFCOMP( g_trac_ipc, "In ipcSp: populate_node_attribute errored - must shutdown now!!!");
                    uint32_t l_errPlid = err->plid();
                    errlCommit(err, IPC_COMP_ID);
                    INITSERVICE::doShutdown(l_errPlid, true);
                }

                if(mod_loaded)
                {
                    err = VFS::module_unload( "libruntime.so" );

                    if (err)
                    {
                        errlCommit(err, IPC_COMP_ID);
                    }
                    mod_loaded = false;
                }

                // Respond
                err = MBOX::send(MBOX::HB_POP_ATTR_MSGQ, msg, msg->data[1] );
                if (err)
                {
                    uint32_t l_errPlid = err->plid();
                    errlCommit(err,IPC_COMP_ID);
                    INITSERVICE::doShutdown(l_errPlid, true);
                }
                break;

            case IPC_TEST_CONNECTION:

                TRACFCOMP( g_trac_ipc,
                           "IPC received the test connection msg - %d:%d",
                            msg->data[0], msg->data[1] );

                // Tell this HB node about the other HB node
                err = INTR::addHbNode(msg->data[1]);
                if( err)
                {
                    errlCommit(err,IPC_COMP_ID);
                }

                //Send a response to indicate the connection has been
                //established
                err = MBOX::send(MBOX::HB_COALESCE_MSGQ, msg, msg->data[1] );

                if (err)
                {
                    errlCommit(err,IPC_COMP_ID);
                }
                break;

            case IPC_START_PAYLOAD:

                if ( !VFS::module_is_loaded( "libstart_payload.so" ) )
                {
                    err = VFS::module_load( "libstart_payload.so" );

                    if ( err )
                    {
                        TRACFCOMP( g_trac_ipc,
                                   "Could not load runtime module" );
                    }
                    else
                    {
                        mod_loaded = true;
                    }
                }

                if(!err)
                {
                    //  Function will not return unless error
                    err = START_PAYLOAD::callShutdown(msg->data[0],false);
                }

                if(err)
                {
                    uint32_t l_errPlid = err->plid();
                    errlCommit(err, IPC_COMP_ID);
                    INITSERVICE::doShutdown(l_errPlid, true);
                }

                if(mod_loaded)
                {
                    err = VFS::module_unload( "libstart_payload.so" );

                    if (err)
                    {
                        errlCommit(err, IPC_COMP_ID);
                    }
                    mod_loaded = false;
                }

                msg_free(msg);

                break;

            default:

                TRACFCOMP( g_trac_ipc,
                           "IPC received an unexpected message type of %d",
                           msg->type);

                /*@ errorlog tag
                 * @errortype  ERRL_SEV_INFORMATIONAL
                 * @moduleid   IPC::MOD_IPCSP_MSGHDLR
                 * @reasoncode IPC::RC_INVALID_MSG_TYPE
                 * @userdata1  Message type
                 * @userdata2  Data word 0 of message
                 *
                 * @devdesc    IPC service provider received an unexpected
                 *             message.
                 *
                 */
                err = new ERRORLOG::ErrlEntry
                    (
                     ERRORLOG::ERRL_SEV_INFORMATIONAL,    // severity
                     IPC::MOD_IPCSP_MSGHDLR,              // moduleid
                     IPC::RC_INVALID_MSG_TYPE,            // reason code
                     msg->type,
                     msg->data[0],
                     true //Add HB Software Callout
                    );
                //@todo: RTC:93750 Create real parseable FFDC class
                err->addFFDC(MBOX_COMP_ID,
                             msg,
                             sizeof(msg_t),
                             1,//version
                             MBOX::MBOX_UDT_MSG_DATA);//subsect

                err->collectTrace(MBOXMSG_TRACE_NAME);
                err->collectTrace(IPC_TRACE_NAME);

                errlCommit(err, IPC_COMP_ID);

                msg_free(msg);

                break;
        }
    }
}

<|endoftext|>


<commit_before>// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <core_io.h>

#include <consensus/consensus.h>
#include <consensus/validation.h>
#include <key_io.h>
#include <script/script.h>
#include <script/standard.h>
#include <serialize.h>
#include <streams.h>
#include <univalue.h>
#include <util/system.h>
#include <util/strencodings.h>

UniValue ValueFromAmount(const CAmount& amount)
{
    bool sign = amount < 0;
    int64_t n_abs = (sign ? -amount : amount);
    int64_t quotient = n_abs / COIN;
    int64_t remainder = n_abs % COIN;
    return UniValue(UniValue::VNUM,
            strprintf("%s%d.%08d", sign ? "-" : "", quotient, remainder));
}

std::string FormatScript(const CScript& script)
{
    std::string ret;
    CScript::const_iterator it = script.begin();
    opcodetype op;
    while (it != script.end()) {
        CScript::const_iterator it2 = it;
        std::vector<unsigned char> vch;
        if (script.GetOp(it, op, vch)) {
            if (op == OP_0) {
                ret += "0 ";
                continue;
            } else if ((op >= OP_1 && op <= OP_16) || op == OP_1NEGATE) {
                ret += strprintf("%i ", op - OP_1NEGATE - 1);
                continue;
            } else if (op >= OP_NOP && op <= OP_NOP10) {
                std::string str(GetOpName(op));
                if (str.substr(0, 3) == std::string("OP_")) {
                    ret += str.substr(3, std::string::npos) + " ";
                    continue;
                }
            }
            if (vch.size() > 0) {
                ret += strprintf("0x%x 0x%x ", HexStr(std::vector<uint8_t>(it2, it - vch.size())),
                                               HexStr(std::vector<uint8_t>(it - vch.size(), it)));
            } else {
                ret += strprintf("0x%x ", HexStr(std::vector<uint8_t>(it2, it)));
            }
            continue;
        }
        ret += strprintf("0x%x ", HexStr(std::vector<uint8_t>(it2, script.end())));
        break;
    }
    return ret.substr(0, ret.size() - 1);
}

const std::map<unsigned char, std::string> mapSigHashTypes = {
    {static_cast<unsigned char>(SIGHASH_ALL), std::string("ALL")},
    {static_cast<unsigned char>(SIGHASH_ALL|SIGHASH_ANYONECANPAY), std::string("ALL|ANYONECANPAY")},
    {static_cast<unsigned char>(SIGHASH_NONE), std::string("NONE")},
    {static_cast<unsigned char>(SIGHASH_NONE|SIGHASH_ANYONECANPAY), std::string("NONE|ANYONECANPAY")},
    {static_cast<unsigned char>(SIGHASH_SINGLE), std::string("SINGLE")},
    {static_cast<unsigned char>(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY), std::string("SINGLE|ANYONECANPAY")},
};

std::string SighashToStr(unsigned char sighash_type)
{
    const auto& it = mapSigHashTypes.find(sighash_type);
    if (it == mapSigHashTypes.end()) return "";
    return it->second;
}

/**
 * Create the assembly string representation of a CScript object.
 * @param[in] script    CScript object to convert into the asm string representation.
 * @param[in] fAttemptSighashDecode    Whether to attempt to decode sighash types on data within the script that matches the format
 *                                     of a signature. Only pass true for scripts you believe could contain signatures. For example,
 *                                     pass false, or omit the this argument (defaults to false), for scriptPubKeys.
 */
std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode)
{
    std::string str;
    opcodetype opcode;
    std::vector<unsigned char> vch;
    CScript::const_iterator pc = script.begin();
    while (pc < script.end()) {
        if (!str.empty()) {
            str += " ";
        }
        if (!script.GetOp(pc, opcode, vch)) {
            str += "[error]";
            return str;
        }
        if (0 <= opcode && opcode <= OP_PUSHDATA4) {
            if (vch.size() <= static_cast<std::vector<unsigned char>::size_type>(4)) {
                str += strprintf("%d", CScriptNum(vch, false).getint());
            } else {
                // the IsUnspendable check makes sure not to try to decode OP_RETURN data that may match the format of a signature
                if (fAttemptSighashDecode && !script.IsUnspendable()) {
                    std::string strSigHashDecode;
                    // goal: only attempt to decode a defined sighash type from data that looks like a signature within a scriptSig.
                    // this won't decode correctly formatted public keys in Pubkey or Multisig scripts due to
                    // the restrictions on the pubkey formats (see IsCompressedOrUncompressedPubKey) being incongruous with the
                    // checks in CheckSignatureEncoding.
                    if (CheckSignatureEncoding(vch, SCRIPT_VERIFY_STRICTENC, nullptr)) {
                        const unsigned char chSigHashType = vch.back();
                        if (mapSigHashTypes.count(chSigHashType)) {
                            strSigHashDecode = "[" + mapSigHashTypes.find(chSigHashType)->second + "]";
                            vch.pop_back(); // remove the sighash type byte. it will be replaced by the decode.
                        }
                    }
                    str += HexStr(vch) + strSigHashDecode;
                } else {
                    str += HexStr(vch);
                }
            }
        } else {
            str += GetOpName(opcode);
        }
    }
    return str;
}

std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags)
{
    CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | serializeFlags);
    ssTx << tx;
    return HexStr(ssTx);
}

void ScriptToUniv(const CScript& script, UniValue& out, bool include_address)
{
    out.pushKV("asm", ScriptToAsmStr(script));
    out.pushKV("hex", HexStr(script));

    std::vector<std::vector<unsigned char>> solns;
    TxoutType type = Solver(script, solns);
    out.pushKV("type", GetTxnOutputType(type));

    CTxDestination address;
    if (include_address && ExtractDestination(script, address) && type != TxoutType::PUBKEY) {
        out.pushKV("address", EncodeDestination(address));
    }
}

void ScriptPubKeyToUniv(const CScript& scriptPubKey,
                        UniValue& out, bool fIncludeHex)
{
    TxoutType type;
    std::vector<CTxDestination> addresses;
    int nRequired;

    out.pushKV("asm", ScriptToAsmStr(scriptPubKey));
    if (fIncludeHex)
        out.pushKV("hex", HexStr(scriptPubKey));

    if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired) || type == TxoutType::PUBKEY) {
        out.pushKV("type", GetTxnOutputType(type));
        return;
    }

    out.pushKV("reqSigs", nRequired);
    out.pushKV("type", GetTxnOutputType(type));

    UniValue a(UniValue::VARR);
    for (const CTxDestination& addr : addresses) {
        a.push_back(EncodeDestination(addr));
    }
    out.pushKV("addresses", a);
}

void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex, int serialize_flags)
{
    entry.pushKV("txid", tx.GetHash().GetHex());
    entry.pushKV("hash", tx.GetWitnessHash().GetHex());
    // Transaction version is actually unsigned in consensus checks, just signed in memory,
    // so cast to unsigned before giving it to the user.
    entry.pushKV("version", static_cast<int64_t>(static_cast<uint32_t>(tx.nVersion)));
    entry.pushKV("size", (int)::GetSerializeSize(tx, PROTOCOL_VERSION));
    entry.pushKV("vsize", (GetTransactionWeight(tx) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR);
    entry.pushKV("weight", GetTransactionWeight(tx));
    entry.pushKV("locktime", (int64_t)tx.nLockTime);

    UniValue vin(UniValue::VARR);
    for (unsigned int i = 0; i < tx.vin.size(); i++) {
        const CTxIn& txin = tx.vin[i];
        UniValue in(UniValue::VOBJ);
        if (tx.IsCoinBase())
            in.pushKV("coinbase", HexStr(txin.scriptSig));
        else {
            in.pushKV("txid", txin.prevout.hash.GetHex());
            in.pushKV("vout", (int64_t)txin.prevout.n);
            UniValue o(UniValue::VOBJ);
            o.pushKV("asm", ScriptToAsmStr(txin.scriptSig, true));
            o.pushKV("hex", HexStr(txin.scriptSig));
            in.pushKV("scriptSig", o);
        }
        if (!tx.vin[i].scriptWitness.IsNull()) {
            UniValue txinwitness(UniValue::VARR);
            for (const auto& item : tx.vin[i].scriptWitness.stack) {
                txinwitness.push_back(HexStr(item));
            }
            in.pushKV("txinwitness", txinwitness);
        }
        in.pushKV("sequence", (int64_t)txin.nSequence);
        vin.push_back(in);
    }
    entry.pushKV("vin", vin);

    UniValue vout(UniValue::VARR);
    for (unsigned int i = 0; i < tx.vout.size(); i++) {
        const CTxOut& txout = tx.vout[i];

        UniValue out(UniValue::VOBJ);

        out.pushKV("value", ValueFromAmount(txout.nValue));
        out.pushKV("n", (int64_t)i);

        UniValue o(UniValue::VOBJ);
        ScriptPubKeyToUniv(txout.scriptPubKey, o, true);
        out.pushKV("scriptPubKey", o);
        vout.push_back(out);
    }
    entry.pushKV("vout", vout);

    if (!hashBlock.IsNull())
        entry.pushKV("blockhash", hashBlock.GetHex());

    if (include_hex) {
        entry.pushKV("hex", EncodeHexTx(tx, serialize_flags)); // The hex-encoded transaction. Used the name "hex" to be consistent with the verbose output of "getrawtransaction".
    }
}
<commit_msg>refactor: Avoid duplicate map lookup in ScriptToAsmStr<commit_after>// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <core_io.h>

#include <consensus/consensus.h>
#include <consensus/validation.h>
#include <key_io.h>
#include <script/script.h>
#include <script/standard.h>
#include <serialize.h>
#include <streams.h>
#include <univalue.h>
#include <util/system.h>
#include <util/strencodings.h>

UniValue ValueFromAmount(const CAmount& amount)
{
    bool sign = amount < 0;
    int64_t n_abs = (sign ? -amount : amount);
    int64_t quotient = n_abs / COIN;
    int64_t remainder = n_abs % COIN;
    return UniValue(UniValue::VNUM,
            strprintf("%s%d.%08d", sign ? "-" : "", quotient, remainder));
}

std::string FormatScript(const CScript& script)
{
    std::string ret;
    CScript::const_iterator it = script.begin();
    opcodetype op;
    while (it != script.end()) {
        CScript::const_iterator it2 = it;
        std::vector<unsigned char> vch;
        if (script.GetOp(it, op, vch)) {
            if (op == OP_0) {
                ret += "0 ";
                continue;
            } else if ((op >= OP_1 && op <= OP_16) || op == OP_1NEGATE) {
                ret += strprintf("%i ", op - OP_1NEGATE - 1);
                continue;
            } else if (op >= OP_NOP && op <= OP_NOP10) {
                std::string str(GetOpName(op));
                if (str.substr(0, 3) == std::string("OP_")) {
                    ret += str.substr(3, std::string::npos) + " ";
                    continue;
                }
            }
            if (vch.size() > 0) {
                ret += strprintf("0x%x 0x%x ", HexStr(std::vector<uint8_t>(it2, it - vch.size())),
                                               HexStr(std::vector<uint8_t>(it - vch.size(), it)));
            } else {
                ret += strprintf("0x%x ", HexStr(std::vector<uint8_t>(it2, it)));
            }
            continue;
        }
        ret += strprintf("0x%x ", HexStr(std::vector<uint8_t>(it2, script.end())));
        break;
    }
    return ret.substr(0, ret.size() - 1);
}

const std::map<unsigned char, std::string> mapSigHashTypes = {
    {static_cast<unsigned char>(SIGHASH_ALL), std::string("ALL")},
    {static_cast<unsigned char>(SIGHASH_ALL|SIGHASH_ANYONECANPAY), std::string("ALL|ANYONECANPAY")},
    {static_cast<unsigned char>(SIGHASH_NONE), std::string("NONE")},
    {static_cast<unsigned char>(SIGHASH_NONE|SIGHASH_ANYONECANPAY), std::string("NONE|ANYONECANPAY")},
    {static_cast<unsigned char>(SIGHASH_SINGLE), std::string("SINGLE")},
    {static_cast<unsigned char>(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY), std::string("SINGLE|ANYONECANPAY")},
};

std::string SighashToStr(unsigned char sighash_type)
{
    const auto& it = mapSigHashTypes.find(sighash_type);
    if (it == mapSigHashTypes.end()) return "";
    return it->second;
}

/**
 * Create the assembly string representation of a CScript object.
 * @param[in] script    CScript object to convert into the asm string representation.
 * @param[in] fAttemptSighashDecode    Whether to attempt to decode sighash types on data within the script that matches the format
 *                                     of a signature. Only pass true for scripts you believe could contain signatures. For example,
 *                                     pass false, or omit the this argument (defaults to false), for scriptPubKeys.
 */
std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode)
{
    std::string str;
    opcodetype opcode;
    std::vector<unsigned char> vch;
    CScript::const_iterator pc = script.begin();
    while (pc < script.end()) {
        if (!str.empty()) {
            str += " ";
        }
        if (!script.GetOp(pc, opcode, vch)) {
            str += "[error]";
            return str;
        }
        if (0 <= opcode && opcode <= OP_PUSHDATA4) {
            if (vch.size() <= static_cast<std::vector<unsigned char>::size_type>(4)) {
                str += strprintf("%d", CScriptNum(vch, false).getint());
            } else {
                // the IsUnspendable check makes sure not to try to decode OP_RETURN data that may match the format of a signature
                if (fAttemptSighashDecode && !script.IsUnspendable()) {
                    std::string strSigHashDecode;
                    // goal: only attempt to decode a defined sighash type from data that looks like a signature within a scriptSig.
                    // this won't decode correctly formatted public keys in Pubkey or Multisig scripts due to
                    // the restrictions on the pubkey formats (see IsCompressedOrUncompressedPubKey) being incongruous with the
                    // checks in CheckSignatureEncoding.
                    if (CheckSignatureEncoding(vch, SCRIPT_VERIFY_STRICTENC, nullptr)) {
                        const unsigned char chSigHashType = vch.back();
                        const auto it = mapSigHashTypes.find(chSigHashType);
                        if (it != mapSigHashTypes.end()) {
                            strSigHashDecode = "[" + it->second + "]";
                            vch.pop_back(); // remove the sighash type byte. it will be replaced by the decode.
                        }
                    }
                    str += HexStr(vch) + strSigHashDecode;
                } else {
                    str += HexStr(vch);
                }
            }
        } else {
            str += GetOpName(opcode);
        }
    }
    return str;
}

std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags)
{
    CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | serializeFlags);
    ssTx << tx;
    return HexStr(ssTx);
}

void ScriptToUniv(const CScript& script, UniValue& out, bool include_address)
{
    out.pushKV("asm", ScriptToAsmStr(script));
    out.pushKV("hex", HexStr(script));

    std::vector<std::vector<unsigned char>> solns;
    TxoutType type = Solver(script, solns);
    out.pushKV("type", GetTxnOutputType(type));

    CTxDestination address;
    if (include_address && ExtractDestination(script, address) && type != TxoutType::PUBKEY) {
        out.pushKV("address", EncodeDestination(address));
    }
}

void ScriptPubKeyToUniv(const CScript& scriptPubKey,
                        UniValue& out, bool fIncludeHex)
{
    TxoutType type;
    std::vector<CTxDestination> addresses;
    int nRequired;

    out.pushKV("asm", ScriptToAsmStr(scriptPubKey));
    if (fIncludeHex)
        out.pushKV("hex", HexStr(scriptPubKey));

    if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired) || type == TxoutType::PUBKEY) {
        out.pushKV("type", GetTxnOutputType(type));
        return;
    }

    out.pushKV("reqSigs", nRequired);
    out.pushKV("type", GetTxnOutputType(type));

    UniValue a(UniValue::VARR);
    for (const CTxDestination& addr : addresses) {
        a.push_back(EncodeDestination(addr));
    }
    out.pushKV("addresses", a);
}

void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex, int serialize_flags)
{
    entry.pushKV("txid", tx.GetHash().GetHex());
    entry.pushKV("hash", tx.GetWitnessHash().GetHex());
    // Transaction version is actually unsigned in consensus checks, just signed in memory,
    // so cast to unsigned before giving it to the user.
    entry.pushKV("version", static_cast<int64_t>(static_cast<uint32_t>(tx.nVersion)));
    entry.pushKV("size", (int)::GetSerializeSize(tx, PROTOCOL_VERSION));
    entry.pushKV("vsize", (GetTransactionWeight(tx) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR);
    entry.pushKV("weight", GetTransactionWeight(tx));
    entry.pushKV("locktime", (int64_t)tx.nLockTime);

    UniValue vin(UniValue::VARR);
    for (unsigned int i = 0; i < tx.vin.size(); i++) {
        const CTxIn& txin = tx.vin[i];
        UniValue in(UniValue::VOBJ);
        if (tx.IsCoinBase())
            in.pushKV("coinbase", HexStr(txin.scriptSig));
        else {
            in.pushKV("txid", txin.prevout.hash.GetHex());
            in.pushKV("vout", (int64_t)txin.prevout.n);
            UniValue o(UniValue::VOBJ);
            o.pushKV("asm", ScriptToAsmStr(txin.scriptSig, true));
            o.pushKV("hex", HexStr(txin.scriptSig));
            in.pushKV("scriptSig", o);
        }
        if (!tx.vin[i].scriptWitness.IsNull()) {
            UniValue txinwitness(UniValue::VARR);
            for (const auto& item : tx.vin[i].scriptWitness.stack) {
                txinwitness.push_back(HexStr(item));
            }
            in.pushKV("txinwitness", txinwitness);
        }
        in.pushKV("sequence", (int64_t)txin.nSequence);
        vin.push_back(in);
    }
    entry.pushKV("vin", vin);

    UniValue vout(UniValue::VARR);
    for (unsigned int i = 0; i < tx.vout.size(); i++) {
        const CTxOut& txout = tx.vout[i];

        UniValue out(UniValue::VOBJ);

        out.pushKV("value", ValueFromAmount(txout.nValue));
        out.pushKV("n", (int64_t)i);

        UniValue o(UniValue::VOBJ);
        ScriptPubKeyToUniv(txout.scriptPubKey, o, true);
        out.pushKV("scriptPubKey", o);
        vout.push_back(out);
    }
    entry.pushKV("vout", vout);

    if (!hashBlock.IsNull())
        entry.pushKV("blockhash", hashBlock.GetHex());

    if (include_hex) {
        entry.pushKV("hex", EncodeHexTx(tx, serialize_flags)); // The hex-encoded transaction. Used the name "hex" to be consistent with the verbose output of "getrawtransaction".
    }
}
<|endoftext|>


<commit_before>#include <iostream>
#include <cstdio>
#include <cassert>
#include <ctime>

#include "driver_program.h"
#include "fast_random.h"

void Populate(pqxx::connection &conn, const DriverConfig &config) {

  size_t table_size = config.default_table_size_ * config.scale_factor_;

  std::cout << ">>>>> Populate table \'employee\'. " << std::endl
            << "   -- Build index? : " << config.with_index_ << std::endl
            << "   -- Table size   : " << table_size << std::endl;

  pqxx::work txn(conn);

  txn.exec("DROP TABLE IF EXISTS employee;");
  txn.exec("CREATE TABLE employee(id INT, name VARCHAR(100));");

  if (config.with_index_ == true) {
    txn.exec("CREATE INDEX emp_index ON employee(id)");
  }

  for (size_t i = 0; i < table_size; ++i) {
    txn.exec("INSERT INTO employee VALUES (" + std::to_string(i) + ", 'a');");
  }
  txn.commit();
}

void ProcessClient(pqxx::connection &conn, const DriverConfig &config) {

  srand(time(NULL));

  size_t table_size = config.default_table_size_ * config.scale_factor_;

  FastRandom fast_rand;

  ZipfDistribution zipf(table_size, config.zipf_theta_);

  std::cout << ">>>>> Process transactions via client interface. " << std::endl
            << "   -- With prepared statement? : " << config.with_prep_stmt_ << std::endl
            << "   -- Table size               : " << table_size << std::endl
            << "   -- Operation count          : " << config.operation_count_ << std::endl
            << "   -- Update ratio             : " << config.update_ratio_ << std::endl
            << "   -- Zipf theta               : " << config.zipf_theta_ << std::endl;

  pqxx::work txn(conn);

  if (config.with_prep_stmt_ == true) {

    conn.prepare("read", "SELECT name FROM employee WHERE id=$1");
    conn.prepare("write", "UPDATE employee SET name = 'z' WHERE id=$1");

    for (size_t i = 0; i < config.operation_count_; ++i) {

      size_t key = zipf.GetNextNumber() - 1;

      if (fast_rand.next_uniform() < config.update_ratio_) {
        // update
        txn.prepared("write")(key).exec();
      } else {
        // select
        pqxx::result R = txn.prepared("read")(key).exec();
        printf("key = %lu, txn result set size = %lu\n", key, R.size());
      }
    }
  } else {
    for (size_t i = 0; i < config.operation_count_; ++i) {

      size_t key = zipf.GetNextNumber() - 1;

      if (fast_rand.next_uniform() < config.update_ratio_) {
        // update
        txn.exec("UPDATE employee SET name = 'z' WHERE id=" + std::to_string(key) + ";");
      } else {
        // select
        pqxx::result R = txn.exec("SELECT name FROM employee WHERE id=" + std::to_string(key) + ";");
        printf("key = %lu, txn result set size = %lu\n", key, R.size());
      }
    }
  }
  txn.commit();
}

void ProcessProcedure(pqxx::connection &conn, const DriverConfig &config) {

  srand(time(NULL));

  size_t table_size = config.default_table_size_ * config.scale_factor_;

  std::cout << ">>>>> Process transactions via stored procedure. "
            << "   -- Table size      : " << table_size << std::endl
            << "   -- Operation count : " << config.operation_count_ << std::endl
            << "   -- Update ratio    : " << config.update_ratio_ << std::endl
            << "   -- Zipf theta      : " << config.zipf_theta_ << std::endl;

  FastRandom fast_rand;

  size_t read_count = 0;
  bool *is_update = new bool[config.operation_count_];
  for (size_t i = 0; i < config.operation_count_; ++i) {
    if (fast_rand.next_uniform() < config.update_ratio_) {
      is_update[i] = true;
    } else {
      is_update[i] = false;
      ++read_count;
    }
  }

  ZipfDistribution zipf(table_size, config.zipf_theta_);

  std::string func_str("CREATE OR REPLACE FUNCTION ycsb(");

  if (read_count == 0) {
    for (size_t i = 0; i < config.operation_count_ - 1; ++i) {
      func_str += "val" + std::to_string(i) + " integer, ";
    }
    func_str +=  "val" + std::to_string(config.operation_count_ - 1) + " integer) ";
  } else {
    for (size_t i = 0; i < config.operation_count_; ++i) {
      func_str += "val" + std::to_string(i) + " integer, ";
    }
    for (size_t i = 0; i < read_count - 1; ++i) {
      func_str += "ref" + std::to_string(i) + " refcursor, ";
    }
    func_str += "ref" + std::to_string(read_count - 1) + " refcursor) ";
  }

  func_str += "RETURNS ";

  if (read_count == 0) {
    func_str += "void ";
  } else if (read_count == 1) {
    func_str += "refcursor ";
  } else {
    func_str += "SETOF refcursor ";
  }

  func_str += "AS $$ ";

  func_str += "BEGIN ";

  size_t curr_read_count = 0;
  for (size_t i = 0; i < config.operation_count_; ++i) {
    if (is_update[i] == true) {
      // is update
      func_str += "UPDATE employee SET name = 'z' WHERE id=val" + std::to_string(i) + ";";
    } else {
      // is read
      if (read_count == 1) {
        func_str += "OPEN ref" + std::to_string(curr_read_count) + " FOR SELECT name FROM employee where id = val" + std::to_string(i) + "; RETURN ref" + std::to_string(curr_read_count) + ";";
        ++curr_read_count;
      } else {
        func_str += "OPEN ref" + std::to_string(curr_read_count) + " FOR SELECT name FROM employee where id = val" + std::to_string(i) + "; RETURN NEXT ref" + std::to_string(curr_read_count) + ";";
        ++curr_read_count;
      }
    }
  }
  func_str += " END; $$ LANGUAGE PLPGSQL;";

  std::cout << ">>>>>>>>>>>>>>>" << std::endl;
  std::cout << func_str << std::endl;
  std::cout << "<<<<<<<<<<<<<<<" << std::endl;

  pqxx::nontransaction nontxn(conn);

  nontxn.exec(func_str.c_str());

  nontxn.commit();

  pqxx::work txn(conn);

  std::string txn_str = "SELECT ycsb(";
  if (read_count == 0) {
    for (size_t i = 0; i < config.operation_count_ - 1; ++i) {
      size_t key = zipf.GetNextNumber() - 1;
      txn_str += std::to_string(key) + ", ";
    }
    size_t key = zipf.GetNextNumber() - 1;
    txn_str += std::to_string(key) + ");";
  } else {
    for (size_t i = 0; i < config.operation_count_; ++i) {
      size_t key = zipf.GetNextNumber() - 1;
      txn_str += std::to_string(key) + ", ";
    }
    for (size_t i = 0; i < read_count - 1; ++i) {
      txn_str += "'ref" + std::to_string(i) + "', ";
    }
    txn_str += "'ref" + std::to_string(read_count - 1) + "') ";
  }

  std::cout << txn_str << std::endl;

  txn.exec(txn_str.c_str());

  txn.commit();

  pqxx::nontransaction nontxn1(conn);

  nontxn1.exec("DROP FUNCTION ycsb;");

  nontxn1.commit();

  delete[] is_update;
  is_update = nullptr;

}

void Scan(pqxx::connection &conn) {

  pqxx::work txn(conn);

  std::cout << ">>>>> Scan table." << std::endl;

  pqxx::result R = txn.exec("SELECT * FROM employee;");

  printf("txn result set size = %lu\n", R.size());

  for (size_t i = 0; i < R.size(); ++i) {
    int id = R[i][0].as<int>();
    std::string name = R[i][1].as<std::string>();
    std::cout << "id = " << id << ", " << name << std::endl;
  }

  txn.commit();
}

<commit_msg>rename<commit_after>#include <iostream>
#include <cstdio>
#include <cassert>
#include <ctime>

#include "driver_program.h"
#include "fast_random.h"

void Populate(pqxx::connection &conn, const DriverConfig &config) {

  size_t table_size = config.default_table_size_ * config.scale_factor_;

  std::cout << ">>>>> Populate table \'employee\'. " << std::endl
            << "   -- Build index? : " << config.with_index_ << std::endl
            << "   -- Table size   : " << table_size << std::endl;

  pqxx::work txn(conn);

  txn.exec("DROP TABLE IF EXISTS employee;");
  txn.exec("CREATE TABLE employee(id INT, name VARCHAR(100));");

  if (config.with_index_ == true) {
    txn.exec("CREATE INDEX emp_index ON employee(id)");
  }

  for (size_t i = 0; i < table_size; ++i) {
    txn.exec("INSERT INTO employee VALUES (" + std::to_string(i) + ", 'a');");
  }
  txn.commit();
}

void ProcessClient(pqxx::connection &conn, const DriverConfig &config) {

  srand(time(NULL));

  size_t table_size = config.default_table_size_ * config.scale_factor_;

  FastRandom fast_rand;

  ZipfDistribution zipf(table_size, config.zipf_theta_);

  std::cout << ">>>>> Process transactions via client interface. " << std::endl
            << "   -- With prepared statement? : " << config.with_prep_stmt_ << std::endl
            << "   -- Table size               : " << table_size << std::endl
            << "   -- Operation count          : " << config.operation_count_ << std::endl
            << "   -- Update ratio             : " << config.update_ratio_ << std::endl
            << "   -- Zipf theta               : " << config.zipf_theta_ << std::endl;

  pqxx::work txn(conn);

  if (config.with_prep_stmt_ == true) {

    conn.prepare("read", "SELECT name FROM employee WHERE id=$1");
    conn.prepare("write", "UPDATE employee SET name = 'z' WHERE id=$1");

    for (size_t i = 0; i < config.operation_count_; ++i) {

      size_t key = zipf.GetNextNumber() - 1;

      if (fast_rand.next_uniform() < config.update_ratio_) {
        // update
        txn.prepared("write")(key).exec();
      } else {
        // select
        pqxx::result R = txn.prepared("read")(key).exec();
        printf("key = %lu, txn result set size = %lu\n", key, R.size());
      }
    }
  } else {
    for (size_t i = 0; i < config.operation_count_; ++i) {

      size_t key = zipf.GetNextNumber() - 1;

      if (fast_rand.next_uniform() < config.update_ratio_) {
        // update
        txn.exec("UPDATE employee SET name = 'z' WHERE id=" + std::to_string(key) + ";");
      } else {
        // select
        pqxx::result R = txn.exec("SELECT name FROM employee WHERE id=" + std::to_string(key) + ";");
        printf("key = %lu, txn result set size = %lu\n", key, R.size());
      }
    }
  }
  txn.commit();
}

void ProcessProcedure(pqxx::connection &conn, const DriverConfig &config) {

  srand(time(NULL));

  size_t table_size = config.default_table_size_ * config.scale_factor_;

  std::cout << ">>>>> Process transactions via stored procedure. "
            << "   -- Table size      : " << table_size << std::endl
            << "   -- Operation count : " << config.operation_count_ << std::endl
            << "   -- Update ratio    : " << config.update_ratio_ << std::endl
            << "   -- Zipf theta      : " << config.zipf_theta_ << std::endl;

  FastRandom fast_rand;

  size_t read_count = 0;
  bool *is_update = new bool[config.operation_count_];
  for (size_t i = 0; i < config.operation_count_; ++i) {
    if (fast_rand.next_uniform() < config.update_ratio_) {
      is_update[i] = true;
    } else {
      is_update[i] = false;
      ++read_count;
    }
  }

  ZipfDistribution zipf(table_size, config.zipf_theta_);

  std::string func_str("CREATE OR REPLACE FUNCTION ycsb(");

  if (read_count == 0) {
    for (size_t i = 0; i < config.operation_count_ - 1; ++i) {
      func_str += "val" + std::to_string(i) + " integer, ";
    }
    func_str +=  "val" + std::to_string(config.operation_count_ - 1) + " integer) ";
  } else {
    for (size_t i = 0; i < config.operation_count_; ++i) {
      func_str += "val" + std::to_string(i) + " integer, ";
    }
    for (size_t i = 0; i < read_count - 1; ++i) {
      func_str += "ref" + std::to_string(i) + " refcursor, ";
    }
    func_str += "ref" + std::to_string(read_count - 1) + " refcursor) ";
  }

  func_str += "RETURNS ";

  if (read_count == 0) {
    func_str += "void ";
  } else if (read_count == 1) {
    func_str += "refcursor ";
  } else {
    func_str += "SETOF refcursor ";
  }

  func_str += "AS $$ ";

  func_str += "BEGIN ";

  size_t curr_read_count = 0;
  for (size_t i = 0; i < config.operation_count_; ++i) {
    if (is_update[i] == true) {
      // is update
      func_str += "UPDATE employee SET name = 'z' WHERE id=val" + std::to_string(i) + ";";
    } else {
      // is read
      if (read_count == 1) {
        func_str += "OPEN ref" + std::to_string(curr_read_count) + " FOR SELECT name FROM employee where id = val" + std::to_string(i) + "; RETURN ref" + std::to_string(curr_read_count) + ";";
        ++curr_read_count;
      } else {
        func_str += "OPEN ref" + std::to_string(curr_read_count) + " FOR SELECT name FROM employee where id = val" + std::to_string(i) + "; RETURN NEXT ref" + std::to_string(curr_read_count) + ";";
        ++curr_read_count;
      }
    }
  }
  func_str += " END; $$ LANGUAGE PLPGSQL;";

  std::cout << ">>>>>>>>>>>>>>>" << std::endl;
  std::cout << func_str << std::endl;
  std::cout << "<<<<<<<<<<<<<<<" << std::endl;

  pqxx::nontransaction nontxn0(conn);

  nontxn0.exec(func_str.c_str());

  nontxn0.commit();

  pqxx::work txn(conn);

  std::string txn_str = "SELECT ycsb(";
  if (read_count == 0) {
    for (size_t i = 0; i < config.operation_count_ - 1; ++i) {
      size_t key = zipf.GetNextNumber() - 1;
      txn_str += std::to_string(key) + ", ";
    }
    size_t key = zipf.GetNextNumber() - 1;
    txn_str += std::to_string(key) + ");";
  } else {
    for (size_t i = 0; i < config.operation_count_; ++i) {
      size_t key = zipf.GetNextNumber() - 1;
      txn_str += std::to_string(key) + ", ";
    }
    for (size_t i = 0; i < read_count - 1; ++i) {
      txn_str += "'ref" + std::to_string(i) + "', ";
    }
    txn_str += "'ref" + std::to_string(read_count - 1) + "') ";
  }

  std::cout << txn_str << std::endl;

  txn.exec(txn_str.c_str());

  txn.commit();

  pqxx::nontransaction nontxn1(conn);

  nontxn1.exec("DROP FUNCTION ycsb;");

  nontxn1.commit();

  delete[] is_update;
  is_update = nullptr;

}

void Scan(pqxx::connection &conn) {

  pqxx::work txn(conn);

  std::cout << ">>>>> Scan table." << std::endl;

  pqxx::result R = txn.exec("SELECT * FROM employee;");

  printf("txn result set size = %lu\n", R.size());

  for (size_t i = 0; i < R.size(); ++i) {
    int id = R[i][0].as<int>();
    std::string name = R[i][1].as<std::string>();
    std::cout << "id = " << id << ", " << name << std::endl;
  }

  txn.commit();
}

<|endoftext|>


<commit_before>// File:  ebdpConfigFile.cpp
// Date:  9/27/2017
// Auth:  K. Loux
// Desc:  Configuration file object.

// Local headers
#include "ebdpConfigFile.h"

void EBDPConfigFile::BuildConfigItems()
{
	AddConfigItem("OBS_DATA_FILE", config.dataFileName);
	AddConfigItem("OUTPUT_FILE", config.outputFileName);

	AddConfigItem("COUNTRY", config.countryFilter);
	AddConfigItem("STATE", config.stateFilter);
	AddConfigItem("COUNTY", config.countyFilter);
	AddConfigItem("LOCATION", config.locationFilter);

	AddConfigItem("LIST_TYPE", config.listType);

	AddConfigItem("SCORE_RARITIES", config.generateRarityScores);
	AddConfigItem("SPECIES_COUNT_ONLY", config.speciesCountOnly);
	AddConfigItem("INCLUDE_PARTIAL_IDS", config.includePartialIDs);

	AddConfigItem("PHOTO_FILE", config.photoFileName);
	AddConfigItem("SHOW_PHOTO_NEEDS", config.showOnlyPhotoNeeds);

	AddConfigItem("YEAR", config.yearFilter);
	AddConfigItem("MONTH", config.monthFilter);
	AddConfigItem("WEEK", config.weekFilter);
	AddConfigItem("DAY", config.dayFilter);

	AddConfigItem("SORT_FIRST", config.primarySort);
	AddConfigItem("SORT_SECOND", config.secondarySort);

	AddConfigItem("SHOW_UNIQUE_OBS", config.uniqueObservations);

	AddConfigItem("CALENDAR", config.generateTargetCalendar);
	AddConfigItem("TARGET_AREA", config.targetNeedArea);
	AddConfigItem("HARVEST_FREQUENCY", config.harvestFrequencyData);
	AddConfigItem("BULK_FREQUENCY_UPDATE", config.bulkFrequencyUpdate);
	AddConfigItem("AUDIT_FREQUENCY_DATA", config.auditFrequencyData);
	AddConfigItem("FIPS_START", config.fipsStart);
	AddConfigItem("TOP_COUNT", config.topBirdCount);
	AddConfigItem("FREQUENCY_FILES", config.frequencyFilePath);
	AddConfigItem("TARGET_INFO_FILE_NAME", config.targetInfoFileName);
	AddConfigItem("RECENT_PERIOD", config.recentObservationPeriod);

	AddConfigItem("GOOGLE_MAPS_KEY", config.googleMapsAPIKey);
	AddConfigItem("HOME_LOCATION", config.homeLocation);
	AddConfigItem("EBIRD_API_KEY", config.eBirdApiKey);

	AddConfigItem("FIND_MAX_NEEDS", config.findMaxNeedsLocations);

	AddConfigItem("OAUTH_CLIENT_ID", config.oAuthClientId);
	AddConfigItem("OAUTH_CLIENT_SECRET", config.oAuthClientSecret);
}

void EBDPConfigFile::AssignDefaults()
{
	config.listType = EBDPConfig::ListType::Life;
	config.speciesCountOnly = false;
	config.includePartialIDs = false;

	config.yearFilter = 0;
	config.monthFilter = 0;
	config.weekFilter = 0;
	config.dayFilter = 0;

	config.primarySort = EBDPConfig::SortBy::None;
	config.secondarySort = EBDPConfig::SortBy::None;

	config.uniqueObservations = EBDPConfig::UniquenessType::None;

	config.targetNeedArea = EBDPConfig::TargetNeedArea::None;
	config.harvestFrequencyData = false;
	config.generateTargetCalendar = false;
	config.generateRarityScores = false;
	config.topBirdCount = false;
	config.recentObservationPeriod = 15;

	config.showOnlyPhotoNeeds = false;

	config.auditFrequencyData = false;
	config.bulkFrequencyUpdate = false;
	config.harvestFrequencyData = false;

	config.fipsStart = 0;
}

bool EBDPConfigFile::ConfigIsOK()
{
	bool configurationOK(true);
	if (config.dataFileName.empty())
	{
		std::cerr << "Must specify '" << GetKey(config.dataFileName) << "'\n";
		configurationOK = false;
	}

	if (!config.countryFilter.empty() &&
		config.countryFilter.length() != 2)
	{
		std::cerr << "Country (" << GetKey(config.countryFilter) << ") must be specified using 2-digit abbreviation\n";
		configurationOK = false;
	}

	if (!config.stateFilter.empty() &&
		config.stateFilter.length() != 2)
	{
		std::cerr << "State/providence (" << GetKey(config.stateFilter) << ") must be specified using 2-digit abbreviation\n";
		configurationOK = false;
	}

	if (config.dayFilter > 31)
	{
		std::cerr << "Day (" << GetKey(config.dayFilter) << ") must be in the range 0 - 31\n";
		configurationOK = false;
	}

	if (config.monthFilter > 12)
	{
		std::cerr << "Month (" << GetKey(config.monthFilter) << ") must be in the range 0 - 12\n";
		configurationOK = false;
	}

	if (config.weekFilter > 53)
	{
		std::cerr << "Week (" << GetKey(config.weekFilter) << ") must be in the range 0 - 53\n";
		configurationOK = false;
	}

/*	if (!config.googleMapsAPIKey.empty() && config.homeLocation.empty())
	{
		std::cerr << "Must specify " << GetKey(config.homeLocation) << " when using " << GetKey(config.googleMapsAPIKey) << '\n';
		configurationOK = false;
	}*/

	if (config.recentObservationPeriod < 1 || config.recentObservationPeriod > 30)
	{
		std::cerr << GetKey(config.recentObservationPeriod) << " must be between 1 and 30\n";
		configurationOK = false;
	}

	if (config.harvestFrequencyData && config.countryFilter.empty())
	{
		std::cerr << "Must specify " << GetKey(config.countryFilter) << " when using " << GetKey(config.harvestFrequencyData) << '\n';
		configurationOK = false;
	}

	if (config.bulkFrequencyUpdate && config.harvestFrequencyData)
	{
		std::cerr << "Cannot specify both " << GetKey(config.bulkFrequencyUpdate) << " and " << GetKey(config.harvestFrequencyData) << '\n';
		configurationOK = false;
	}

	if (config.bulkFrequencyUpdate && config.countryFilter.empty())
	{
		std::cerr << "Must specify " << GetKey(config.countryFilter) << " when using " << GetKey(config.bulkFrequencyUpdate) << '\n';
		configurationOK = false;
	}

	if (config.bulkFrequencyUpdate && config.stateFilter.empty())
	{
		std::cerr << "Must specify " << GetKey(config.stateFilter) << " when using " << GetKey(config.bulkFrequencyUpdate) << '\n';
		configurationOK = false;
	}

	if (config.generateRarityScores && config.frequencyFilePath.empty())
	{
		std::cerr << "Must specify " << GetKey(config.frequencyFilePath) << " when using " << GetKey(config.generateRarityScores) << '\n';
		configurationOK = false;
	}

	if (config.bulkFrequencyUpdate && config.frequencyFilePath.empty())
	{
		std::cerr << "Must specify " << GetKey(config.frequencyFilePath) << " when using " << GetKey(config.bulkFrequencyUpdate) << '\n';
		configurationOK = false;
	}

	if (config.auditFrequencyData && config.frequencyFilePath.empty())
	{
		std::cerr << "Must specify " << GetKey(config.frequencyFilePath) << " when using " << GetKey(config.auditFrequencyData) << '\n';
		configurationOK = false;
	}

	if (config.findMaxNeedsLocations && config.frequencyFilePath.empty())
	{
		std::cerr << "Must specify " << GetKey(config.frequencyFilePath) << " when using " << GetKey(config.findMaxNeedsLocations) << '\n';
		configurationOK = false;
	}

	if (config.generateRarityScores && config.generateTargetCalendar)
	{
		std::cerr << "Cannot specify both " << GetKey(config.generateRarityScores) << " and " << GetKey(config.generateTargetCalendar) << '\n';
		configurationOK = false;
	}

	if (config.generateRarityScores && config.uniqueObservations != EBDPConfig::UniquenessType::None)
	{
		std::cerr << "Cannot specify both " << GetKey(config.generateRarityScores) << " and " << GetKey(config.uniqueObservations) << '\n';
		configurationOK = false;
	}

	if (config.generateTargetCalendar && config.uniqueObservations != EBDPConfig::UniquenessType::None)
	{
		std::cerr << "Cannot specify both " << GetKey(config.generateTargetCalendar) << " and " << GetKey(config.uniqueObservations) << '\n';
		configurationOK = false;
	}

	if (config.uniqueObservations != EBDPConfig::UniquenessType::None && !config.countryFilter.empty())
	{
		std::cerr << "Cannot specify both " << GetKey(config.countryFilter) << " and " << GetKey(config.uniqueObservations) << '\n';
		configurationOK = false;
	}

	if (config.showOnlyPhotoNeeds && config.photoFileName.empty())
	{
		std::cerr << "Must specify " << GetKey(config.photoFileName) << " when using " << GetKey(config.showOnlyPhotoNeeds) << '\n';
		configurationOK = false;
	}

	if (config.findMaxNeedsLocations &&
		(config.oAuthClientId.empty() || config.oAuthClientSecret.empty()))
	{
		std::cerr << GetKey(config.findMaxNeedsLocations) << " requires "
			<< GetKey(config.oAuthClientId) << " and " << GetKey(config.oAuthClientSecret) << '\n';
		configurationOK = false;
	}

	if (config.fipsStart > 0 && !config.bulkFrequencyUpdate)
	{
		std::cerr << GetKey(config.fipsStart) << " requires " << GetKey(config.bulkFrequencyUpdate) << '\n';
		configurationOK = false;
	}

	return configurationOK;
}
<commit_msg>Fixed initialization of config items<commit_after>// File:  ebdpConfigFile.cpp
// Date:  9/27/2017
// Auth:  K. Loux
// Desc:  Configuration file object.

// Local headers
#include "ebdpConfigFile.h"

void EBDPConfigFile::BuildConfigItems()
{
	AddConfigItem("OBS_DATA_FILE", config.dataFileName);
	AddConfigItem("OUTPUT_FILE", config.outputFileName);

	AddConfigItem("COUNTRY", config.countryFilter);
	AddConfigItem("STATE", config.stateFilter);
	AddConfigItem("COUNTY", config.countyFilter);
	AddConfigItem("LOCATION", config.locationFilter);

	AddConfigItem("LIST_TYPE", config.listType);

	AddConfigItem("SCORE_RARITIES", config.generateRarityScores);
	AddConfigItem("SPECIES_COUNT_ONLY", config.speciesCountOnly);
	AddConfigItem("INCLUDE_PARTIAL_IDS", config.includePartialIDs);

	AddConfigItem("PHOTO_FILE", config.photoFileName);
	AddConfigItem("SHOW_PHOTO_NEEDS", config.showOnlyPhotoNeeds);

	AddConfigItem("YEAR", config.yearFilter);
	AddConfigItem("MONTH", config.monthFilter);
	AddConfigItem("WEEK", config.weekFilter);
	AddConfigItem("DAY", config.dayFilter);

	AddConfigItem("SORT_FIRST", config.primarySort);
	AddConfigItem("SORT_SECOND", config.secondarySort);

	AddConfigItem("SHOW_UNIQUE_OBS", config.uniqueObservations);

	AddConfigItem("CALENDAR", config.generateTargetCalendar);
	AddConfigItem("TARGET_AREA", config.targetNeedArea);
	AddConfigItem("HARVEST_FREQUENCY", config.harvestFrequencyData);
	AddConfigItem("BULK_FREQUENCY_UPDATE", config.bulkFrequencyUpdate);
	AddConfigItem("AUDIT_FREQUENCY_DATA", config.auditFrequencyData);
	AddConfigItem("FIPS_START", config.fipsStart);
	AddConfigItem("TOP_COUNT", config.topBirdCount);
	AddConfigItem("FREQUENCY_FILES", config.frequencyFilePath);
	AddConfigItem("TARGET_INFO_FILE_NAME", config.targetInfoFileName);
	AddConfigItem("RECENT_PERIOD", config.recentObservationPeriod);

	AddConfigItem("GOOGLE_MAPS_KEY", config.googleMapsAPIKey);
	AddConfigItem("HOME_LOCATION", config.homeLocation);
	AddConfigItem("EBIRD_API_KEY", config.eBirdApiKey);

	AddConfigItem("FIND_MAX_NEEDS", config.findMaxNeedsLocations);

	AddConfigItem("OAUTH_CLIENT_ID", config.oAuthClientId);
	AddConfigItem("OAUTH_CLIENT_SECRET", config.oAuthClientSecret);
}

void EBDPConfigFile::AssignDefaults()
{
	config.listType = EBDPConfig::ListType::Life;
	config.speciesCountOnly = false;
	config.includePartialIDs = false;

	config.yearFilter = 0;
	config.monthFilter = 0;
	config.weekFilter = 0;
	config.dayFilter = 0;

	config.primarySort = EBDPConfig::SortBy::None;
	config.secondarySort = EBDPConfig::SortBy::None;

	config.uniqueObservations = EBDPConfig::UniquenessType::None;

	config.targetNeedArea = EBDPConfig::TargetNeedArea::None;
	config.generateTargetCalendar = false;
	config.generateRarityScores = false;
	config.topBirdCount = 20;
	config.recentObservationPeriod = 15;

	config.showOnlyPhotoNeeds = false;

	config.auditFrequencyData = false;
	config.bulkFrequencyUpdate = false;
	config.harvestFrequencyData = false;
	config.findMaxNeedsLocations = false;

	config.fipsStart = 0;
}

bool EBDPConfigFile::ConfigIsOK()
{
	bool configurationOK(true);
	if (config.dataFileName.empty())
	{
		std::cerr << "Must specify '" << GetKey(config.dataFileName) << "'\n";
		configurationOK = false;
	}

	if (!config.countryFilter.empty() &&
		config.countryFilter.length() != 2)
	{
		std::cerr << "Country (" << GetKey(config.countryFilter) << ") must be specified using 2-digit abbreviation\n";
		configurationOK = false;
	}

	if (!config.stateFilter.empty() &&
		config.stateFilter.length() != 2)
	{
		std::cerr << "State/providence (" << GetKey(config.stateFilter) << ") must be specified using 2-digit abbreviation\n";
		configurationOK = false;
	}

	if (config.dayFilter > 31)
	{
		std::cerr << "Day (" << GetKey(config.dayFilter) << ") must be in the range 0 - 31\n";
		configurationOK = false;
	}

	if (config.monthFilter > 12)
	{
		std::cerr << "Month (" << GetKey(config.monthFilter) << ") must be in the range 0 - 12\n";
		configurationOK = false;
	}

	if (config.weekFilter > 53)
	{
		std::cerr << "Week (" << GetKey(config.weekFilter) << ") must be in the range 0 - 53\n";
		configurationOK = false;
	}

/*	if (!config.googleMapsAPIKey.empty() && config.homeLocation.empty())
	{
		std::cerr << "Must specify " << GetKey(config.homeLocation) << " when using " << GetKey(config.googleMapsAPIKey) << '\n';
		configurationOK = false;
	}*/

	if (config.recentObservationPeriod < 1 || config.recentObservationPeriod > 30)
	{
		std::cerr << GetKey(config.recentObservationPeriod) << " must be between 1 and 30\n";
		configurationOK = false;
	}

	if (config.harvestFrequencyData && config.countryFilter.empty())
	{
		std::cerr << "Must specify " << GetKey(config.countryFilter) << " when using " << GetKey(config.harvestFrequencyData) << '\n';
		configurationOK = false;
	}

	if (config.bulkFrequencyUpdate && config.harvestFrequencyData)
	{
		std::cerr << "Cannot specify both " << GetKey(config.bulkFrequencyUpdate) << " and " << GetKey(config.harvestFrequencyData) << '\n';
		configurationOK = false;
	}

	if (config.bulkFrequencyUpdate && config.countryFilter.empty())
	{
		std::cerr << "Must specify " << GetKey(config.countryFilter) << " when using " << GetKey(config.bulkFrequencyUpdate) << '\n';
		configurationOK = false;
	}

	if (config.bulkFrequencyUpdate && config.stateFilter.empty())
	{
		std::cerr << "Must specify " << GetKey(config.stateFilter) << " when using " << GetKey(config.bulkFrequencyUpdate) << '\n';
		configurationOK = false;
	}

	if (config.generateRarityScores && config.frequencyFilePath.empty())
	{
		std::cerr << "Must specify " << GetKey(config.frequencyFilePath) << " when using " << GetKey(config.generateRarityScores) << '\n';
		configurationOK = false;
	}

	if (config.bulkFrequencyUpdate && config.frequencyFilePath.empty())
	{
		std::cerr << "Must specify " << GetKey(config.frequencyFilePath) << " when using " << GetKey(config.bulkFrequencyUpdate) << '\n';
		configurationOK = false;
	}

	if (config.auditFrequencyData && config.frequencyFilePath.empty())
	{
		std::cerr << "Must specify " << GetKey(config.frequencyFilePath) << " when using " << GetKey(config.auditFrequencyData) << '\n';
		configurationOK = false;
	}

	if (config.findMaxNeedsLocations && config.frequencyFilePath.empty())
	{
		std::cerr << "Must specify " << GetKey(config.frequencyFilePath) << " when using " << GetKey(config.findMaxNeedsLocations) << '\n';
		configurationOK = false;
	}

	if (config.generateRarityScores && config.generateTargetCalendar)
	{
		std::cerr << "Cannot specify both " << GetKey(config.generateRarityScores) << " and " << GetKey(config.generateTargetCalendar) << '\n';
		configurationOK = false;
	}

	if (config.generateRarityScores && config.uniqueObservations != EBDPConfig::UniquenessType::None)
	{
		std::cerr << "Cannot specify both " << GetKey(config.generateRarityScores) << " and " << GetKey(config.uniqueObservations) << '\n';
		configurationOK = false;
	}

	if (config.generateTargetCalendar && config.uniqueObservations != EBDPConfig::UniquenessType::None)
	{
		std::cerr << "Cannot specify both " << GetKey(config.generateTargetCalendar) << " and " << GetKey(config.uniqueObservations) << '\n';
		configurationOK = false;
	}

	if (config.uniqueObservations != EBDPConfig::UniquenessType::None && !config.countryFilter.empty())
	{
		std::cerr << "Cannot specify both " << GetKey(config.countryFilter) << " and " << GetKey(config.uniqueObservations) << '\n';
		configurationOK = false;
	}

	if (config.showOnlyPhotoNeeds && config.photoFileName.empty())
	{
		std::cerr << "Must specify " << GetKey(config.photoFileName) << " when using " << GetKey(config.showOnlyPhotoNeeds) << '\n';
		configurationOK = false;
	}

	if (config.findMaxNeedsLocations &&
		(config.oAuthClientId.empty() || config.oAuthClientSecret.empty()))
	{
		std::cerr << GetKey(config.findMaxNeedsLocations) << " requires "
			<< GetKey(config.oAuthClientId) << " and " << GetKey(config.oAuthClientSecret) << '\n';
		configurationOK = false;
	}

	if (config.fipsStart > 0 && !config.bulkFrequencyUpdate)
	{
		std::cerr << GetKey(config.fipsStart) << " requires " << GetKey(config.bulkFrequencyUpdate) << '\n';
		configurationOK = false;
	}

	return configurationOK;
}
<|endoftext|>


<commit_before>#include "debug_draw.h"
#include "vertex_buffer.h"

static const char vertex_shader[]=
    "#version 120\n"
    "attribute vec2 a_position;\n"
    "uniform mat4 u_projTrans;\n"
    "uniform float ratio;\n"
    "void main()\n"
    "{\n"
    "gl_Position = u_projTrans * vec4(ratio * a_position.x, ratio * a_position.y, 0, 1);\n"
    "}\n";

static const char fragment_shader[] =
    "#version 120\n"
    "uniform vec4 u_color;\n"
    "void main()\n"
    "{\n"
    "gl_FragColor = u_color;\n"
    "}\n";

b2DebugDraw::b2DebugDraw(float ratio) : mRatio(ratio), mShader(NULL)
{
    SetFlags( b2Draw::e_shapeBit );

    ev_shader *vs = ev_shader_create();

    if( ev_shader_compile(vs, GL_VERTEX_SHADER, vertex_shader) ) {
        ev_error("vertex shader failed to compile");
        assert(true);
    }

    ev_shader *fs = ev_shader_create();
    if( ev_shader_compile(fs, GL_FRAGMENT_SHADER, fragment_shader) ) {
        ev_error("fragment shader failed to compile");
        assert(true);
    }

    mShader = ev_program_create();
    ev_program_set_shader(mShader, vs, GL_VERTEX_SHADER);
    ev_program_set_shader(mShader, fs, GL_FRAGMENT_SHADER);
    if( ev_program_compile(mShader) ) {
        ev_error("shader failed to compile");
        assert(true);
    }
    vbuff = ev_vbuff_create();
    ev_vbuff_set_capacity(vbuff, 2*2048);
    CHECK_GL();
}

b2DebugDraw::~b2DebugDraw()
{
    ev_program_destroy(mShader);
    ev_vbuff_destroy(vbuff);
}

void b2DebugDraw::DrawPolygon(const b2Vec2* vertices, int cnt, const b2Color& color)
{
    ev_program_use(mShader);

    glUniformMatrix4fv( ev_program_get_uniform_loc(mShader, "u_projTrans"),
                        1, GL_FALSE, mMatrix.m);

    glUniform4f(ev_program_get_uniform_loc(mShader, "u_color"),
                color.r, color.g, color.b, 1.0f);

    glUniform1f(ev_program_get_uniform_loc(mShader, "ratio"),
                mRatio);

    glVertexAttribPointer(ev_program_get_attrib_loc(mShader, "a_position"),
                          2, GL_FLOAT, GL_FALSE, 0, vertices);

    glDrawArrays(GL_LINE_LOOP, 0, cnt);
}

void b2DebugDraw::DrawSolidPolygon(const b2Vec2* vertices, int cnt, const b2Color& color)
{
    ev_log("how about here?");
    ev_program_use(mShader);

    glUniformMatrix4fv( ev_program_get_uniform_loc(mShader, "u_projTrans"),
                        1, GL_FALSE, mMatrix.m);

    glUniform4f(ev_program_get_uniform_loc(mShader, "u_color"),
                color.r*.5f, color.g*.5f, color.b*.5f, 0.5f);

    glUniform1f(ev_program_get_uniform_loc(mShader, "ratio"), mRatio);

    glVertexAttribPointer(ev_program_get_attrib_loc(mShader, "a_position"),
                          2, GL_FLOAT, GL_FALSE, 0,vertices);

    glDrawArrays(GL_TRIANGLE_FAN, 0, cnt);

    glUniform4f(ev_program_get_uniform_loc(mShader, "u_color"),
                color.r, color.g, color.b, 1.0f);

    glDrawArrays(GL_LINE_LOOP, 0, cnt);

    CHECK_GL();
}

void b2DebugDraw::DrawCircle(const b2Vec2& center, float radius,  const b2Color& color )
{
    DrawSolidCircle(center, radius, b2Vec2(0,0), color);
}

void b2DebugDraw::DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color)
{
    const float k_segments = 16.0f;
    const int vertex_cnt = 16;
    const float k_inc = 2.0f * b2_pi / k_segments;
    float theta = 0.0f;
    int i;
    GLfloat *verts = (GLfloat*)ev_vbuff_map(vbuff);

    for( i = 0 ; i < vertex_cnt ; ++i ) {
        b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));
        verts[i*2] = v.x;
        verts[i*2+1] = v.y;
        theta += k_inc;
    }

    ev_vbuff_unmap(vbuff);

    ev_program_use(mShader);
    ev_vbuff_bind(vbuff);

    glEnableVertexAttribArray(ev_program_get_attrib_loc(mShader, "a_position"));
    CHECK_GL();
    glUniformMatrix4fv( ev_program_get_uniform_loc(mShader, "u_projTrans"),
                        1, GL_FALSE, mMatrix.m);

    glUniform4f(ev_program_get_uniform_loc(mShader, "u_color"),
                color.r*.5f, color.g*.5f, color.b*.5f, 0.5f);

    glUniform1f(ev_program_get_uniform_loc(mShader, "ratio"),
                mRatio);

    glVertexAttribPointer(ev_program_get_attrib_loc(mShader, "a_position"),
                           2, GL_FLOAT, GL_FALSE, 0, 0);

    glDrawArrays(GL_TRIANGLE_FAN, 0, vertex_cnt);

    glUniform4f(ev_program_get_uniform_loc(mShader, "u_color"),
                color.r, color.g, color.b, 1.0f);

    glDrawArrays(GL_LINE_LOOP, 0, vertex_cnt);

    DrawSegment(center, center + radius * axis, color );
}

void b2DebugDraw::SetOrtho(float w, float h)
{
    ev_matrix4_set_ortho(&mMatrix, 0, w, h, 1, -1, 1);
}

void b2DebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
{
    ev_program_use(mShader);
    SetColor(color);
    GLfloat *verts = (GLfloat*)ev_vbuff_map(vbuff);

    verts[0] = p1.x;
    verts[1] = p1.y;
    verts[2] = p2.x;
    verts[3] = p2.y;

    ev_vbuff_unmap(vbuff);

    ev_vbuff_bind(vbuff);

    glUniformMatrix4fv( ev_program_get_uniform_loc(mShader, "u_projTrans"),
                        1, GL_FALSE, mMatrix.m);

    glUniform1f( ev_program_get_uniform_loc(mShader, "ratio"),
                 mRatio);

    glVertexAttribPointer(ev_program_get_attrib_loc(mShader, "a_position"),
                          2, GL_FLOAT, GL_FALSE, 0, 0);
    glDrawArrays(GL_LINES, 0, 2);
}

void b2DebugDraw::SetColor(const b2Color& c, float ratio)
{
    glUniform4f(ev_program_get_uniform_loc(mShader, "u_color"),
                c.r * ratio, c.g * ratio, c.b * ratio, ratio);
}

void b2DebugDraw::DrawTransform(const b2Transform& xf)
{
}
<commit_msg>draw polygon<commit_after>#include "debug_draw.h"
#include "vertex_buffer.h"

static const char vertex_shader[]=
    "#version 120\n"
    "attribute vec2 a_position;\n"
    "uniform mat4 u_projTrans;\n"
    "uniform float ratio;\n"
    "void main()\n"
    "{\n"
    "gl_Position = u_projTrans * vec4(ratio * a_position.x, ratio * a_position.y, 0, 1);\n"
    "}\n";

static const char fragment_shader[] =
    "#version 120\n"
    "uniform vec4 u_color;\n"
    "void main()\n"
    "{\n"
    "gl_FragColor = u_color;\n"
    "}\n";

b2DebugDraw::b2DebugDraw(float ratio) : mRatio(ratio), mShader(NULL)
{
    SetFlags( b2Draw::e_shapeBit | b2Draw::e_centerOfMassBit);

    ev_shader *vs = ev_shader_create();

    if( ev_shader_compile(vs, GL_VERTEX_SHADER, vertex_shader) ) {
        ev_error("vertex shader failed to compile");
        assert(true);
    }

    ev_shader *fs = ev_shader_create();
    if( ev_shader_compile(fs, GL_FRAGMENT_SHADER, fragment_shader) ) {
        ev_error("fragment shader failed to compile");
        assert(true);
    }

    mShader = ev_program_create();
    ev_program_set_shader(mShader, vs, GL_VERTEX_SHADER);
    ev_program_set_shader(mShader, fs, GL_FRAGMENT_SHADER);
    if( ev_program_compile(mShader) ) {
        ev_error("shader failed to compile");
        assert(true);
    }
    vbuff = ev_vbuff_create();
    ev_vbuff_set_capacity(vbuff, 2*2048);
    CHECK_GL();
}

b2DebugDraw::~b2DebugDraw()
{
    ev_program_destroy(mShader);
    ev_vbuff_destroy(vbuff);
}

void b2DebugDraw::DrawPolygon(const b2Vec2* vertices, int cnt, const b2Color& color)
{
    GLfloat *verts = (GLfloat*)ev_vbuff_map(vbuff);
    memcpy(verts, vertices, cnt * sizeof(b2Vec2));
    ev_vbuff_unmap(vbuff);

    ev_program_use(mShader);
    ev_vbuff_bind(vbuff);

    glUniformMatrix4fv( ev_program_get_uniform_loc(mShader, "u_projTrans"),
                        1, GL_FALSE, mMatrix.m);

    glUniform4f(ev_program_get_uniform_loc(mShader, "u_color"),
                color.r, color.g, color.b, 1.0f);

    glUniform1f(ev_program_get_uniform_loc(mShader, "ratio"),
                mRatio);

    glVertexAttribPointer(ev_program_get_attrib_loc(mShader, "a_position"),
                          2, GL_FLOAT, GL_FALSE, 0, 0);

    glDrawArrays(GL_LINE_LOOP, 0, cnt);
}

void b2DebugDraw::DrawSolidPolygon(const b2Vec2* vertices, int cnt, const b2Color& color)
{
    GLfloat *verts = (GLfloat*)ev_vbuff_map(vbuff);
    memcpy(verts, vertices, cnt * sizeof(b2Vec2));
    ev_vbuff_unmap(vbuff);

    ev_program_use(mShader);
    ev_vbuff_bind(vbuff);

    glUniformMatrix4fv( ev_program_get_uniform_loc(mShader, "u_projTrans"),
                        1, GL_FALSE, mMatrix.m);

    glUniform4f(ev_program_get_uniform_loc(mShader, "u_color"),
                color.r*.5f, color.g*.5f, color.b*.5f, 0.5f);

    glUniform1f(ev_program_get_uniform_loc(mShader, "ratio"), mRatio);

    glVertexAttribPointer(ev_program_get_attrib_loc(mShader, "a_position"),
                          2, GL_FLOAT, GL_FALSE, 0,0);

    glDrawArrays(GL_TRIANGLE_FAN, 0, cnt);

    glUniform4f(ev_program_get_uniform_loc(mShader, "u_color"),
                color.r, color.g, color.b, 1.0f);

    glDrawArrays(GL_LINE_LOOP, 0, cnt);

    CHECK_GL();
}

void b2DebugDraw::DrawCircle(const b2Vec2& center, float radius,  const b2Color& color )
{
    DrawSolidCircle(center, radius, b2Vec2(0,0), color);
}

void b2DebugDraw::DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color)
{
    const float k_segments = 16.0f;
    const int vertex_cnt = 16;
    const float k_inc = 2.0f * b2_pi / k_segments;
    float theta = 0.0f;
    int i;
    GLfloat *verts = (GLfloat*)ev_vbuff_map(vbuff);

    for( i = 0 ; i < vertex_cnt ; ++i ) {
        b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));
        verts[i*2] = v.x;
        verts[i*2+1] = v.y;
        theta += k_inc;
    }

    ev_vbuff_unmap(vbuff);

    ev_program_use(mShader);
    ev_vbuff_bind(vbuff);

    glEnableVertexAttribArray(ev_program_get_attrib_loc(mShader, "a_position"));
    CHECK_GL();
    glUniformMatrix4fv( ev_program_get_uniform_loc(mShader, "u_projTrans"),
                        1, GL_FALSE, mMatrix.m);

    glUniform4f(ev_program_get_uniform_loc(mShader, "u_color"),
                color.r*.5f, color.g*.5f, color.b*.5f, 0.5f);

    glUniform1f(ev_program_get_uniform_loc(mShader, "ratio"),
                mRatio);

    glVertexAttribPointer(ev_program_get_attrib_loc(mShader, "a_position"),
                           2, GL_FLOAT, GL_FALSE, 0, 0);

    glDrawArrays(GL_TRIANGLE_FAN, 0, vertex_cnt);

    glUniform4f(ev_program_get_uniform_loc(mShader, "u_color"),
                color.r, color.g, color.b, 1.0f);

    glDrawArrays(GL_LINE_LOOP, 0, vertex_cnt);

    DrawSegment(center, center + radius * axis, color );
}

void b2DebugDraw::SetOrtho(float w, float h)
{
    ev_matrix4_set_ortho(&mMatrix, 0, w, h, 1, -1, 1);
}

void b2DebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
{
    ev_program_use(mShader);
    SetColor(color);
    GLfloat *verts = (GLfloat*)ev_vbuff_map(vbuff);

    verts[0] = p1.x;
    verts[1] = p1.y;
    verts[2] = p2.x;
    verts[3] = p2.y;

    ev_vbuff_unmap(vbuff);

    ev_vbuff_bind(vbuff);

    glUniformMatrix4fv( ev_program_get_uniform_loc(mShader, "u_projTrans"),
                        1, GL_FALSE, mMatrix.m);

    glUniform1f( ev_program_get_uniform_loc(mShader, "ratio"),
                 mRatio);

    glVertexAttribPointer(ev_program_get_attrib_loc(mShader, "a_position"),
                          2, GL_FLOAT, GL_FALSE, 0, 0);
    glDrawArrays(GL_LINES, 0, 2);
}

void b2DebugDraw::SetColor(const b2Color& c, float ratio)
{
    glUniform4f(ev_program_get_uniform_loc(mShader, "u_color"),
                c.r * ratio, c.g * ratio, c.b * ratio, ratio);
}

void b2DebugDraw::DrawTransform(const b2Transform& xf)
{
}
<|endoftext|>


<commit_before>#include "dialogs.h"
#include "singletons.h"

#undef NTDDI_VERSION
#define NTDDI_VERSION NTDDI_VISTA
#undef _WIN32_WINNT
#define _WIN32_WINNT _WIN32_WINNT_VISTA

#include <windows.h>
#include <shobjidl.h>
#include <vector>

#include <iostream> //TODO: remove
using namespace std; //TODO: remove

class CommonDialog {
public:
  CommonDialog(CLSID type);
  ~CommonDialog() {
    if(dialog!=nullptr)
      dialog->Release();
  }
  /** available options are listed at https://msdn.microsoft.com/en-gb/library/windows/desktop/dn457282(v=vs.85).aspx */
  void add_option(unsigned option);
  void set_title(const std::wstring &title);
  /** Sets the extensions the browser can find */
  void set_default_file_extension(const std::wstring &file_extension);
  /** Sets the directory to start browsing */
  void set_folder(const std::wstring &directory_path);
  /** Returns the selected item's path as a string */
  std::string show();

protected:
  IFileDialog *dialog=nullptr;
  DWORD options;
  bool error=false;
};

class OpenDialog : public CommonDialog {
public:
  OpenDialog(const std::wstring &title, unsigned option=0);
};

class SaveDialog : public CommonDialog {
public:
  SaveDialog(const std::wstring &title, const boost::filesystem::path &file_path="", unsigned option=0);
private:
  std::vector<COMDLG_FILTERSPEC> extensions;
};

CommonDialog::CommonDialog(CLSID type) {
  if(CoCreateInstance(type, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&dialog))!=S_OK) {
    error=true;
    return;
  }
  if(dialog->GetOptions(&options)!=S_OK)
    error=true;
}

void CommonDialog::set_title(const std::wstring &title) {
  if(error) return;
  if(dialog->SetTitle(title.c_str())!=S_OK)
    error=true;
}

void CommonDialog::add_option(unsigned option) {
  if(error) return;
  if(dialog->SetOptions(options | option)!=S_OK)
    error=true;
}

void CommonDialog::set_default_file_extension(const std::wstring &file_extension) {
  if(error) return;
  if(dialog->SetDefaultExtension(file_extension.c_str())!=S_OK)
    error=true;
}

void CommonDialog::set_folder(const std::wstring &directory_path) {
  if(error) return;

  std::wstring path=directory_path;
  size_t pos=0;
  while((pos=path.find(L'/', pos))!=std::wstring::npos) {//TODO: issue bug report on boost::filesystem::path::native on MSYS2
    path.replace(pos, 1, L"\\");
    pos++;
  }

  IShellItem * folder = nullptr;
  if(SHCreateItemFromParsingName(path.c_str(), nullptr, IID_PPV_ARGS(&folder))!=S_OK) {
    error=true;
    return;
  }
  auto hresult=dialog->SetFolder(folder);
  folder->Release();
  if(hresult!=S_OK)
    error=true;
}

std::string CommonDialog::show() {
  if(error) return "";
  if(dialog->Show(nullptr)!=S_OK) {
    return "";
  }
  IShellItem *result = nullptr;
  if(dialog->GetResult(&result)!=S_OK) {
    result->Release();
    return "";
  }
  LPWSTR str = nullptr;
  auto hresult=result->GetDisplayName(SIGDN_FILESYSPATH, &str);
  result->Release();
  if(hresult!=S_OK)
    return "";
  std::wstring wstr(str);
  std::string res(wstr.begin(), wstr.end());
  CoTaskMemFree(str);
  return res;
}

OpenDialog::OpenDialog(const std::wstring &title, unsigned option) : CommonDialog(CLSID_FileOpenDialog) {
  set_title(title);
  add_option(option);
  auto dirs = Singleton::directories->current_path;
  set_folder(dirs.empty() ? boost::filesystem::current_path().native() : dirs.native());
}

SaveDialog::SaveDialog(const std::wstring &title, const boost::filesystem::path &file_path, unsigned option) : CommonDialog(CLSID_FileSaveDialog) {
  set_title(title);
  add_option(option);
  if(!file_path.empty()) {
    set_folder(file_path.parent_path().native());
    if(file_path.has_extension() && file_path.filename()!=file_path.extension()) {
      auto extension=(L"*"+file_path.extension().native()).c_str();
      extensions.emplace_back(COMDLG_FILTERSPEC{extension, extension});
      set_default_file_extension(extension);
    }
  }
  else {
    auto dirs = Singleton::directories->current_path;
    set_folder(dirs.empty() ? boost::filesystem::current_path().native() : dirs.native());
  }
  extensions.emplace_back(COMDLG_FILTERSPEC{L"All files", L"*.*"});
  if(dialog->SetFileTypes(extensions.size(), extensions.data())!=S_OK) {
    error=true;
    return;
  }
}

std::string Dialog::open_folder() {
  return (OpenDialog(L"Open Folder", FOS_PICKFOLDERS)).show();
}

std::string Dialog::new_file() {
  return (SaveDialog(L"New File")).show();
}

std::string Dialog::new_folder() {
  return (OpenDialog(L"New Folder", FOS_PICKFOLDERS)).show();
}

std::string Dialog::open_file() {
  return (OpenDialog(L"Open File")).show();
}

std::string Dialog::save_file_as(const boost::filesystem::path &file_path) {
  return (SaveDialog(L"Save File As", file_path)).show();
}
<commit_msg>Finished cleanup of dialogs_win.cc<commit_after>#include "dialogs.h"
#include "singletons.h"

#undef NTDDI_VERSION
#define NTDDI_VERSION NTDDI_VISTA
#undef _WIN32_WINNT
#define _WIN32_WINNT _WIN32_WINNT_VISTA

#include <windows.h>
#include <shobjidl.h>
#include <vector>

#include <iostream> //TODO: remove
using namespace std; //TODO: remove

class Win32Dialog {
public:
  Win32Dialog() {};

  bool init(CLSID type) {
    if(CoCreateInstance(type, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&dialog))!=S_OK)
      return false;
    if(dialog->GetOptions(&options)!=S_OK)
      return false;
    return true;
  }

  ~Win32Dialog() {
    if(dialog!=nullptr)
      dialog->Release();
  }

  /** available options are listed at https://msdn.microsoft.com/en-gb/library/windows/desktop/dn457282(v=vs.85).aspx */
  bool add_option(unsigned option) {
    if(dialog->SetOptions(options | option)!=S_OK)
      return false;
    return true;
  }

  bool set_title(const std::wstring &title) {
    if(dialog->SetTitle(title.c_str())!=S_OK)
      return false;
    return true;
  }

  /** Sets the extensions the browser can find */
  bool set_default_file_extension(const std::wstring &file_extension) {
    if(dialog->SetDefaultExtension(file_extension.c_str())!=S_OK)
      return false;
    return true;
  }
  /** Sets the directory to start browsing */
  bool set_folder(const std::wstring &directory_path) {
    std::wstring path=directory_path;
    size_t pos=0;
    while((pos=path.find(L'/', pos))!=std::wstring::npos) {//TODO: issue bug report on boost::filesystem::path::native on MSYS2
      path.replace(pos, 1, L"\\");
      pos++;
    }

    IShellItem *folder = nullptr;
    if(SHCreateItemFromParsingName(path.c_str(), nullptr, IID_PPV_ARGS(&folder))!=S_OK)
      return false;
    if(dialog->SetFolder(folder)!=S_OK)
      return false;
    folder->Release();
    return true;
  }

  /** Returns the selected item's path as a string */
  std::string open(const std::wstring &title, unsigned option=0) {
    if(!init(CLSID_FileOpenDialog))
      return "";

    if(!set_title(title) || !add_option(option))
      return "";
    auto dirs = Singleton::directories->current_path;
    if(!set_folder(dirs.empty() ? boost::filesystem::current_path().native() : dirs.native()))
      return "";

    return show();
  }

  std::string save(const std::wstring &title, const boost::filesystem::path &file_path="", unsigned option=0) {
    if(!init(CLSID_FileSaveDialog))
      return "";

    if(!set_title(title) || !add_option(option))
      return "";
    std::vector<COMDLG_FILTERSPEC> extensions;
    if(!file_path.empty()) {
      if(!set_folder(file_path.parent_path().native()))
        return "";
      if(file_path.has_extension() && file_path.filename()!=file_path.extension()) {
        auto extension=(L"*"+file_path.extension().native()).c_str();
        extensions.emplace_back(COMDLG_FILTERSPEC{extension, extension});
        if(!set_default_file_extension(extension))
          return "";
      }
    }
    else {
      auto dirs = Singleton::directories->current_path;
      if(!set_folder(dirs.empty() ? boost::filesystem::current_path().native() : dirs.native()))
        return "";
    }
    extensions.emplace_back(COMDLG_FILTERSPEC{L"All files", L"*.*"});
    if(dialog->SetFileTypes(extensions.size(), extensions.data())!=S_OK)
      return "";

    return show();
  }

private:
  std::string show() {
    if(dialog->Show(nullptr)!=S_OK)
      return "";
    IShellItem *result = nullptr;
    if(dialog->GetResult(&result)!=S_OK)
      return "";
    LPWSTR file_path = nullptr;
    auto hresult=result->GetDisplayName(SIGDN_FILESYSPATH, &file_path);
    result->Release();
    if(hresult!=S_OK)
      return "";
    std::wstring file_path_wstring(file_path);
    std::string file_path_string(file_path_wstring.begin(), file_path_wstring.end());
    CoTaskMemFree(file_path);
    return file_path_string;
  }

  IFileDialog *dialog=nullptr;
  DWORD options;
};

std::string Dialog::open_folder() {
  return Win32Dialog().open(L"Open Folder", FOS_PICKFOLDERS);
}

std::string Dialog::new_file() {
  return Win32Dialog().save(L"New File");
}

std::string Dialog::new_folder() {
  return  Win32Dialog().open(L"New Folder", FOS_PICKFOLDERS); //TODO: this is not working correctly yet
}

std::string Dialog::open_file() {
  return  Win32Dialog().open(L"Open File");
}

std::string Dialog::save_file_as(const boost::filesystem::path &file_path) {
  return Win32Dialog().save(L"Save File As", file_path);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2013 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin 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/utility/hash.hpp>

#include <boost/detail/endian.hpp>
#include <bitcoin/utility/external/ripemd160.h>
#include <bitcoin/utility/external/sha256.h>
#include <bitcoin/format.hpp>

namespace libbitcoin {

short_hash generate_short_hash(const data_chunk& chunk)
{
    hash_digest sha_hash;
    SHA256__(chunk.data(), static_cast<uint32_t>(chunk.size()),
        sha_hash.data());

    short_hash ripemd_hash;
    RMD160(sha_hash.data(), static_cast<uint32_t>(ripemd_hash.size()),
        ripemd_hash.data());

    return ripemd_hash;
}

hash_digest generate_hash(const data_chunk& chunk)
{
    hash_digest first_hash;
    SHA256__(chunk.data(), static_cast<uint32_t>(chunk.size()),
        first_hash.data());

    hash_digest second_hash;
    SHA256__(first_hash.data(), static_cast<uint32_t>(first_hash.size()),
        second_hash.data());

    // SSL gives us the hash backwards
    std::reverse(second_hash.begin(), second_hash.end());
    return second_hash;
}

uint32_t generate_checksum(const data_chunk& chunk)
{
    hash_digest hash = generate_hash(chunk);
    data_chunk begin_bytes(hash.rbegin(), hash.rbegin() + 4);
    return cast_chunk<uint32_t>(begin_bytes);
}

} // namespace libbitcoin

<commit_msg>bugfix: ripemd was being passed wrong size. now generates correct hashes.<commit_after>/*
 * Copyright (c) 2011-2013 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin 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/utility/hash.hpp>

#include <boost/detail/endian.hpp>
#include <bitcoin/utility/external/ripemd160.h>
#include <bitcoin/utility/external/sha256.h>
#include <bitcoin/format.hpp>

namespace libbitcoin {

short_hash generate_short_hash(const data_chunk& chunk)
{
    hash_digest sha_hash;
    SHA256__(chunk.data(), static_cast<uint32_t>(chunk.size()),
        sha_hash.data());

    short_hash ripemd_hash;
    RMD160(sha_hash.data(), hash_digest_size, ripemd_hash.data());

    return ripemd_hash;
}

hash_digest generate_hash(const data_chunk& chunk)
{
    hash_digest first_hash;
    SHA256__(chunk.data(), static_cast<uint32_t>(chunk.size()),
        first_hash.data());

    hash_digest second_hash;
    SHA256__(first_hash.data(), static_cast<uint32_t>(first_hash.size()),
        second_hash.data());

    // SSL gives us the hash backwards
    std::reverse(second_hash.begin(), second_hash.end());
    return second_hash;
}

uint32_t generate_checksum(const data_chunk& chunk)
{
    hash_digest hash = generate_hash(chunk);
    data_chunk begin_bytes(hash.rbegin(), hash.rbegin() + 4);
    return cast_chunk<uint32_t>(begin_bytes);
}

} // namespace libbitcoin

<|endoftext|>


<commit_before>#include <stdlib.h>
#include <ncurses.h>

#include "../global/Global.h"

#include "../game.h"
#include "Actor.h"
#include "Enemy.h"

// Who is my enemy?
Enemy::Enemy(Actor &a) : Actor() {
    setChar('X');
    setType("Enemy");
    setName("Xarg");
    attr.HP = 30;
    attr.ACT = 1;
    init_pair(1, COLOR_RED, -1);
    disp_colo = COLOR_PAIR(1);

    target = &a;
    computeAggro();
    setPosRand();
}

void Enemy::computeAggro() {
    switch(g->getDifficulty()) {
        case CHEAT:
            aggro = 0;
            break;
        case EASY:
            aggro = 20;
            break;
        case MEDIUM:
            aggro = 30;
            break;
        case HARD:
            aggro = 50;
            break;
        case NIGHTMARE:
            aggro = 100;
            break;
    }
}

void Enemy::move() {
    // NB: `modifier' in `pool' chance of being `lucky'

    int modifier = (100 - getDistance(target->getPos()) * 4.2);
    if (modifier < 0) modifier = 0;  // Clamp

    int pool     = (100 + target->getChance() - g->getDifficulty());
    int roll     = (rand() % pool);
    bool lucky   = (roll < modifier);

    // Check if target is within range
    if (getDistance(target->getPos()) <= 1) {
        if (lucky) {
            if (target->getHP() <= 0) setPos(target->getPos());
            else attack(*target);
        }
    } else if (getDistance(target->getPos()) <= aggro) {
        // If target unlucky, seek
        if (lucky) seek();
    } else {
        mill();
    }
}

void Enemy::mill() {
    switch(rand() % 20) {
        case 1:
            moveNorth();
            break;
        case 2:
            moveNorthEast();
            break;
        case 3:
            moveEast();
            break;
        case 4:
            moveSouthEast();
            break;
        case 5:
            moveSouth();
            break;
        case 6:
            moveSouthWest();
            break;
        case 7:
            moveWest();
            break;
        case 8:
            moveNorthWest();
            break;
        default:
            break;
    }
}

vec2ui Enemy::seek() {

    // Target above, below, left, or right of me
    if (isSouth(*target)) {
        this->moveSouth();
    } else if (isNorth(*target)) {
        this->moveNorth();
    } else if (isEast(*target)) {
        this->moveEast();
    } else if (isWest(*target)) {
        this->moveWest();
    }

    // Target diagonal to me
    else if(isNorthEast(*target)) {
        this->moveNorthEast();
    } else if(isSouthEast(*target)) {
        this->moveSouthEast();
    } else if(isSouthWest(*target)) {
        this->moveSouthWest();
    } else {
        this->moveNorthWest();
    }

    return this->getPos();
}

<commit_msg>Add crucial logging to enemy attack rolls<commit_after>#include <stdlib.h>
#include <ncurses.h>

#include "../global/Global.h"
#include "../spdlog/spdlog.h"
#include "../game.h"
#include "Actor.h"
#include "Enemy.h"

// Who is my enemy?
Enemy::Enemy(Actor &a) : Actor() {
    setChar('X');
    setType("Enemy");
    setName("Xarg");
    attr.HP = 30;
    attr.ACT = 1;
    init_pair(1, COLOR_RED, -1);
    disp_colo = COLOR_PAIR(1);

    target = &a;
    computeAggro();
    setPosRand();
}

void Enemy::computeAggro() {
    switch(g->getDifficulty()) {
        case CHEAT:
            aggro = 0;
            break;
        case EASY:
            aggro = 20;
            break;
        case MEDIUM:
            aggro = 30;
            break;
        case HARD:
            aggro = 50;
            break;
        case NIGHTMARE:
            aggro = 100;
            break;
    }
}

void Enemy::move() {
    // NB: `modifier' in `pool' chance of being `lucky'

    int modifier = (100 - getDistance(target->getPos()) * 4.2);
    if (modifier < 0) modifier = 0;  // Clamp

    int pool     = (100 + target->getChance() - g->getDifficulty());
    int roll     = (rand() % pool);
    bool lucky   = (roll < modifier);

    // Check if target is within range
    if (getDistance(target->getPos()) <= 1) {
        if (lucky) {
            if (target->getHP() <= 0) setPos(target->getPos());
            else attack(*target);

            spdlog::get("termq")->info("{} attack odds {}/{}, rolled a {} ({})"
                , getName(), modifier, pool, roll, (lucky ? "success!" : "failure"));
        }
    } else if (getDistance(target->getPos()) <= aggro) {
        // If target unlucky, seek
        if (lucky) seek();
    } else {
        mill();
    }
}

void Enemy::mill() {
    switch(rand() % 20) {
        case 1:
            moveNorth();
            break;
        case 2:
            moveNorthEast();
            break;
        case 3:
            moveEast();
            break;
        case 4:
            moveSouthEast();
            break;
        case 5:
            moveSouth();
            break;
        case 6:
            moveSouthWest();
            break;
        case 7:
            moveWest();
            break;
        case 8:
            moveNorthWest();
            break;
        default:
            break;
    }
}

vec2ui Enemy::seek() {

    // Target above, below, left, or right of me
    if (isSouth(*target)) {
        this->moveSouth();
    } else if (isNorth(*target)) {
        this->moveNorth();
    } else if (isEast(*target)) {
        this->moveEast();
    } else if (isWest(*target)) {
        this->moveWest();
    }

    // Target diagonal to me
    else if(isNorthEast(*target)) {
        this->moveNorthEast();
    } else if(isSouthEast(*target)) {
        this->moveSouthEast();
    } else if(isSouthWest(*target)) {
        this->moveSouthWest();
    } else {
        this->moveNorthWest();
    }

    return this->getPos();
}

<|endoftext|>