<commit_before>#include "joystick.h"

using namespace JoystickLibrary;

constexpr int NUMBER_BUTTONS = 11;

Xbox360Service::Xbox360Service(int number_joysticks) : JoystickService(number_joysticks)
{
    this->valid_devices = {
        { 0x045E, 0x028E },	// Microsoft Xbox 360 Controller
        { 0x045E, 0x0291 }, // Microsoft Xbox 360 Wireless Controller
		{ 0x0E6F, 0x0213 }	// Afterglow AX.1 for Xbox 360
    };
}

Xbox360Service::~Xbox360Service()
{
}

bool Xbox360Service::GetLeftX(int joystickID, int& leftX)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    leftX = this->GetState(joystickID).lX;
    return true;
}

bool Xbox360Service::GetLeftY(int joystickID, int& leftY)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    leftY = -this->GetState(joystickID).lY;
    return true;
}

bool Xbox360Service::GetRightX(int joystickID, int& rightX)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    rightX = this->GetState(joystickID).lRx;
    return true;
}

bool Xbox360Service::GetRightY(int joystickID, int& rightY)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    rightY = -this->GetState(joystickID).lRy;
    return true;
}

bool Xbox360Service::GetLeftTrigger(int joystickID, int& leftTrigger)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    // triggers share the lZ field. left: [0, 100], right: [0, -100]
    int lz = this->GetState(joystickID).lZ;
    leftTrigger = (lz > 0) ? lz : 0;
    return true;
}

bool Xbox360Service::GetRightTrigger(int joystickID, int& rightTrigger)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    // triggers share the lZ field. left: [0, 100], right: [0, -100]
    int lz = this->GetState(joystickID).lZ;
    rightTrigger = (lz < 0) ? -lz : 0;
    return true;
}

bool Xbox360Service::GetDpad(int joystickID, POV& dpad)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    // POV values are done in 45 deg segments (0 is up) * 100.
    // i.e. straight right = 90 deg = 9000.
    // determine POV value by way of lookup table (divide by 4500)
    unsigned int povListIndex = jsMap[joystickID].state.rgdwPOV[0] / 4500;
    dpad = (povListIndex < povList.size()) ? povList[povListIndex] : POV::POV_NONE;
    return true;
}

bool Xbox360Service::GetButton(int joystickID, Xbox360Button button, bool& buttonVal)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    buttonVal = !!this->GetState(joystickID).rgbButtons[static_cast<int>(button)];
    return true;
}

bool Xbox360Service::GetButtons(int joystickID, std::map<Xbox360Button, bool>& buttons)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    buttons.clear();
    for (int i = 0; i < NUMBER_BUTTONS; i++)
        buttons[static_cast<Xbox360Button>(i)] = !!this->GetState(joystickID).rgbButtons[i];

    return true;
}
<commit_msg>fixed whitespace<commit_after>#include "joystick.h"

using namespace JoystickLibrary;

constexpr int NUMBER_BUTTONS = 11;

Xbox360Service::Xbox360Service(int number_joysticks) : JoystickService(number_joysticks)
{
    this->valid_devices = {
        { 0x045E, 0x028E },	// Microsoft Xbox 360 Controller
        { 0x045E, 0x0291 }, // Microsoft Xbox 360 Wireless Controller
        { 0x0E6F, 0x0213 }	// Afterglow AX.1 for Xbox 360
    };
}

Xbox360Service::~Xbox360Service()
{
}

bool Xbox360Service::GetLeftX(int joystickID, int& leftX)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    leftX = this->GetState(joystickID).lX;
    return true;
}

bool Xbox360Service::GetLeftY(int joystickID, int& leftY)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    leftY = -this->GetState(joystickID).lY;
    return true;
}

bool Xbox360Service::GetRightX(int joystickID, int& rightX)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    rightX = this->GetState(joystickID).lRx;
    return true;
}

bool Xbox360Service::GetRightY(int joystickID, int& rightY)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    rightY = -this->GetState(joystickID).lRy;
    return true;
}

bool Xbox360Service::GetLeftTrigger(int joystickID, int& leftTrigger)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    // triggers share the lZ field. left: [0, 100], right: [0, -100]
    int lz = this->GetState(joystickID).lZ;
    leftTrigger = (lz > 0) ? lz : 0;
    return true;
}

bool Xbox360Service::GetRightTrigger(int joystickID, int& rightTrigger)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    // triggers share the lZ field. left: [0, 100], right: [0, -100]
    int lz = this->GetState(joystickID).lZ;
    rightTrigger = (lz < 0) ? -lz : 0;
    return true;
}

bool Xbox360Service::GetDpad(int joystickID, POV& dpad)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    // POV values are done in 45 deg segments (0 is up) * 100.
    // i.e. straight right = 90 deg = 9000.
    // determine POV value by way of lookup table (divide by 4500)
    unsigned int povListIndex = jsMap[joystickID].state.rgdwPOV[0] / 4500;
    dpad = (povListIndex < povList.size()) ? povList[povListIndex] : POV::POV_NONE;
    return true;
}

bool Xbox360Service::GetButton(int joystickID, Xbox360Button button, bool& buttonVal)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    buttonVal = !!this->GetState(joystickID).rgbButtons[static_cast<int>(button)];
    return true;
}

bool Xbox360Service::GetButtons(int joystickID, std::map<Xbox360Button, bool>& buttons)
{
    if (!IsValidJoystickID(joystickID))
        return false;

    buttons.clear();
    for (int i = 0; i < NUMBER_BUTTONS; i++)
        buttons[static_cast<Xbox360Button>(i)] = !!this->GetState(joystickID).rgbButtons[i];

    return true;
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Vassil Vassilev <vvasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "BackendPasses.h"

#include "llvm/Analysis/InlineCost.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/InlinerPass.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/PassManager.h"

#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Frontend/CodeGenOptions.h"

using namespace cling;
using namespace clang;
using namespace llvm;

namespace {

  class InlinerKeepDeadFunc: public Inliner {
    Inliner* m_Inliner; // the actual inliner
    static char ID; // Pass identification, replacement for typeid
  public:
    InlinerKeepDeadFunc():
    Inliner(ID), m_Inliner(0) { }
    InlinerKeepDeadFunc(Pass* I):
    Inliner(ID), m_Inliner((Inliner*)I) { }

    using llvm::Pass::doInitialization;
    bool doInitialization(CallGraph &CG) override {
      // Forward out Resolver now that we are registered.
      if (!m_Inliner->getResolver())
        m_Inliner->setResolver(getResolver());
      return m_Inliner->doInitialization(CG); // no Module modification
    }

    InlineCost getInlineCost(CallSite CS) override {
      return m_Inliner->getInlineCost(CS);
    }
    void getAnalysisUsage(AnalysisUsage &AU) const override {
      m_Inliner->getAnalysisUsage(AU);
    }
    bool runOnSCC(CallGraphSCC &SCC) override {
      return m_Inliner->runOnSCC(SCC);
    }

    using llvm::Pass::doFinalization;
    // No-op: we need to keep the inlined functions for later use.
    bool doFinalization(CallGraph& /*CG*/) override {
      // Module is unchanged
      return false;
    }
  };
} // end anonymous namespace

// Pass registration. Luckily all known inliners depend on the same set
// of passes.
char InlinerKeepDeadFunc::ID = 0;

BackendPasses::BackendPasses(const CodeGenOptions &CGOpts,
                             const TargetOptions &TOpts,
                             const LangOptions &LOpts):
  m_CodeGenOptsVerifyModule(CGOpts.VerifyModule)
{
  CreatePasses(CGOpts, TOpts, LOpts);
}

BackendPasses::~BackendPasses() {}

void BackendPasses::CreatePasses(const CodeGenOptions &CGOpts,
                                 const TargetOptions &TOpts,
                                 const LangOptions &LOpts)
{
  // From BackEndUtil's clang::EmitAssemblyHelper::CreatePasses().

  unsigned OptLevel = CGOpts.OptimizationLevel;
  CodeGenOptions::InliningMethod Inlining = CGOpts.getInlining();

  // Handle disabling of LLVM optimization, where we want to preserve the
  // internal module before any optimization.
  if (CGOpts.DisableLLVMOpts) {
    OptLevel = 0;
    // Always keep at least ForceInline - NoInlining is deadly for libc++.
    // Inlining = CGOpts.NoInlining;
  }

  m_PMBuilder.reset(new PassManagerBuilder());
  m_PMBuilder->OptLevel = OptLevel;
  m_PMBuilder->SizeLevel = CGOpts.OptimizeSize;
  m_PMBuilder->BBVectorize = CGOpts.VectorizeBB;
  m_PMBuilder->SLPVectorize = CGOpts.VectorizeSLP;
  m_PMBuilder->LoopVectorize = CGOpts.VectorizeLoop;

  m_PMBuilder->DisableTailCalls = CGOpts.DisableTailCalls;
  m_PMBuilder->DisableUnitAtATime = !CGOpts.UnitAtATime;
  m_PMBuilder->DisableUnrollLoops = !CGOpts.UnrollLoops;
  m_PMBuilder->MergeFunctions = CGOpts.MergeFunctions;
  m_PMBuilder->RerollLoops = CGOpts.RerollLoops;

  switch (Inlining) {
    case CodeGenOptions::NoInlining: {
      assert(0 && "libc++ requires at least OnlyAlwaysInlining!");
      break;
    }
    case CodeGenOptions::NormalInlining: {
      m_PMBuilder->Inliner =
        new InlinerKeepDeadFunc(createFunctionInliningPass(OptLevel,
                                                          CGOpts.OptimizeSize));
      break;
    }
    case CodeGenOptions::OnlyAlwaysInlining:
      // Respect always_inline.
      if (OptLevel == 0)
        // Do not insert lifetime intrinsics at -O0.
        m_PMBuilder->Inliner
          = new InlinerKeepDeadFunc(createAlwaysInlinerPass(false));
      else
        m_PMBuilder->Inliner
          = new InlinerKeepDeadFunc(createAlwaysInlinerPass());
      break;
  }

  // Set up the per-module pass manager.
  m_MPM.reset(new PassManager());
  m_MPM->add(new DataLayoutPass());
  //m_MPM->add(createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
  //if (!CGOpts.RewriteMapFiles.empty())
  //  addSymbolRewriterPass(CGOpts, m_MPM);
  if (CGOpts.VerifyModule)
    m_MPM->add(createDebugInfoVerifierPass());

  m_PMBuilder->populateModulePassManager(*m_MPM);
}

void BackendPasses::runOnModule(Module& M) {

  // Set up the per-function pass manager.
  FunctionPassManager FPM(&M);
  FPM.add(new DataLayoutPass());
  //FPM.add(createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
  if (m_CodeGenOptsVerifyModule)
      FPM.add(createVerifierPass());
  m_PMBuilder->populateFunctionPassManager(FPM);

  // Run the per-function passes on the module.
  FPM.doInitialization();
  for (auto&& I: M.functions())
    if (!I.isDeclaration())
      FPM.run(I);
  FPM.doFinalization();

  m_MPM->run(M);
}
<commit_msg>Reduce cling leakage to 0, according to valgrind.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Vassil Vassilev <vvasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "BackendPasses.h"

#include "llvm/Analysis/InlineCost.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/InlinerPass.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/PassManager.h"

#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Frontend/CodeGenOptions.h"

using namespace cling;
using namespace clang;
using namespace llvm;

namespace {

  class InlinerKeepDeadFunc: public Inliner {
    Inliner* m_Inliner; // the actual inliner
    static char ID; // Pass identification, replacement for typeid
  public:
    InlinerKeepDeadFunc():
    Inliner(ID), m_Inliner(0) { }
    InlinerKeepDeadFunc(Pass* I):
    Inliner(ID), m_Inliner((Inliner*)I) { }

    using llvm::Pass::doInitialization;
    bool doInitialization(CallGraph &CG) override {
      // Forward out Resolver now that we are registered.
      if (!m_Inliner->getResolver())
        m_Inliner->setResolver(getResolver());
      return m_Inliner->doInitialization(CG); // no Module modification
    }

    InlineCost getInlineCost(CallSite CS) override {
      return m_Inliner->getInlineCost(CS);
    }
    void getAnalysisUsage(AnalysisUsage &AU) const override {
      m_Inliner->getAnalysisUsage(AU);
    }
    bool runOnSCC(CallGraphSCC &SCC) override {
      return m_Inliner->runOnSCC(SCC);
    }

    using llvm::Pass::doFinalization;
    // No-op: we need to keep the inlined functions for later use.
    bool doFinalization(CallGraph& /*CG*/) override {
      // Module is unchanged
      return false;
    }
  };
} // end anonymous namespace

// Pass registration. Luckily all known inliners depend on the same set
// of passes.
char InlinerKeepDeadFunc::ID = 0;

BackendPasses::BackendPasses(const CodeGenOptions &CGOpts,
                             const TargetOptions &TOpts,
                             const LangOptions &LOpts):
  m_CodeGenOptsVerifyModule(CGOpts.VerifyModule)
{
  CreatePasses(CGOpts, TOpts, LOpts);
}

BackendPasses::~BackendPasses() {
  delete m_PMBuilder->Inliner;
}

void BackendPasses::CreatePasses(const CodeGenOptions &CGOpts,
                                 const TargetOptions &TOpts,
                                 const LangOptions &LOpts)
{
  // From BackEndUtil's clang::EmitAssemblyHelper::CreatePasses().

  unsigned OptLevel = CGOpts.OptimizationLevel;
  CodeGenOptions::InliningMethod Inlining = CGOpts.getInlining();

  // Handle disabling of LLVM optimization, where we want to preserve the
  // internal module before any optimization.
  if (CGOpts.DisableLLVMOpts) {
    OptLevel = 0;
    // Always keep at least ForceInline - NoInlining is deadly for libc++.
    // Inlining = CGOpts.NoInlining;
  }

  m_PMBuilder.reset(new PassManagerBuilder());
  m_PMBuilder->OptLevel = OptLevel;
  m_PMBuilder->SizeLevel = CGOpts.OptimizeSize;
  m_PMBuilder->BBVectorize = CGOpts.VectorizeBB;
  m_PMBuilder->SLPVectorize = CGOpts.VectorizeSLP;
  m_PMBuilder->LoopVectorize = CGOpts.VectorizeLoop;

  m_PMBuilder->DisableTailCalls = CGOpts.DisableTailCalls;
  m_PMBuilder->DisableUnitAtATime = !CGOpts.UnitAtATime;
  m_PMBuilder->DisableUnrollLoops = !CGOpts.UnrollLoops;
  m_PMBuilder->MergeFunctions = CGOpts.MergeFunctions;
  m_PMBuilder->RerollLoops = CGOpts.RerollLoops;

  switch (Inlining) {
    case CodeGenOptions::NoInlining: {
      assert(0 && "libc++ requires at least OnlyAlwaysInlining!");
      break;
    }
    case CodeGenOptions::NormalInlining: {
      m_PMBuilder->Inliner =
        new InlinerKeepDeadFunc(createFunctionInliningPass(OptLevel,
                                                          CGOpts.OptimizeSize));
      break;
    }
    case CodeGenOptions::OnlyAlwaysInlining:
      // Respect always_inline.
      if (OptLevel == 0)
        // Do not insert lifetime intrinsics at -O0.
        m_PMBuilder->Inliner
          = new InlinerKeepDeadFunc(createAlwaysInlinerPass(false));
      else
        m_PMBuilder->Inliner
          = new InlinerKeepDeadFunc(createAlwaysInlinerPass());
      break;
  }

  // Set up the per-module pass manager.
  m_MPM.reset(new PassManager());
  m_MPM->add(new DataLayoutPass());
  //m_MPM->add(createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
  //if (!CGOpts.RewriteMapFiles.empty())
  //  addSymbolRewriterPass(CGOpts, m_MPM);
  if (CGOpts.VerifyModule)
    m_MPM->add(createDebugInfoVerifierPass());

  m_PMBuilder->populateModulePassManager(*m_MPM);
}

void BackendPasses::runOnModule(Module& M) {

  // Set up the per-function pass manager.
  FunctionPassManager FPM(&M);
  FPM.add(new DataLayoutPass());
  //FPM.add(createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
  if (m_CodeGenOptsVerifyModule)
      FPM.add(createVerifierPass());
  m_PMBuilder->populateFunctionPassManager(FPM);

  // Run the per-function passes on the module.
  FPM.doInitialization();
  for (auto&& I: M.functions())
    if (!I.isDeclaration())
      FPM.run(I);
  FPM.doFinalization();

  m_MPM->run(M);
}
<|endoftext|>


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

/*! \file device_malloc.inl
 *  \brief Inline file for device_malloc.h.
 */

#include <thrust/device_malloc.h>
#include <thrust/detail/device/cuda/malloc.h>

namespace thrust
{

thrust::device_ptr<void> device_malloc(const std::size_t n)
{
  return detail::device::cuda::malloc(n);
} // end device_malloc()

template<typename T>
  thrust::device_ptr<T> device_malloc(const std::size_t n)
{
  return thrust::device_malloc(n * sizeof(T));
} // end device_malloc()

} // end thrust

<commit_msg>Work around a circular inclusion problem that was keeping trivial_tests/device_malloc.cu from compiling.<commit_after>/*
 *  Copyright 2008-2009 NVIDIA Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/*! \file device_malloc.inl
 *  \brief Inline file for device_malloc.h.
 */

// workaround a recursive #inclusion problem here
// by providing a forward declaration of cuda::malloc
namespace thrust { namespace detail { namespace device { namespace cuda
{
inline device_ptr<void> malloc(const std::size_t n);
}}}}

#include <thrust/device_malloc.h>
#include <thrust/detail/device/cuda/malloc.h>

namespace thrust
{

thrust::device_ptr<void> device_malloc(const std::size_t n)
{
  return thrust::detail::device::cuda::malloc(n);
} // end device_malloc()

template<typename T>
  thrust::device_ptr<T> device_malloc(const std::size_t n)
{
  return thrust::device_malloc(n * sizeof(T));
} // end device_malloc()

} // end thrust

<|endoftext|>


<commit_before>/*************************************************************************/
/*  gdscript_highlighter.cpp                                             */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "gdscript_highlighter.h"
#include "../gdscript_tokenizer.h"
#include "editor/editor_settings.h"
#include "scene/gui/text_edit.h"

inline bool _is_symbol(CharType c) {

	return is_symbol(c);
}

static bool _is_text_char(CharType c) {

	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
}

static bool _is_char(CharType c) {

	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
}

static bool _is_number(CharType c) {
	return (c >= '0' && c <= '9');
}

static bool _is_hex_symbol(CharType c) {
	return ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
}

Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line) {
	Map<int, TextEdit::HighlighterInfo> color_map;

	Type next_type = NONE;
	Type current_type = NONE;
	Type previous_type = NONE;

	String previous_text = "";
	int previous_column = 0;

	bool prev_is_char = false;
	bool prev_is_number = false;
	bool in_keyword = false;
	bool in_word = false;
	bool in_function_name = false;
	bool in_variable_declaration = false;
	bool in_member_variable = false;
	bool in_node_path = false;
	bool is_hex_notation = false;
	bool expect_type = false;
	Color keyword_color;
	Color color;

	int in_region = text_editor->_is_line_in_region(p_line);
	int deregion = 0;

	const Map<int, TextEdit::Text::ColorRegionInfo> cri_map = text_editor->_get_line_color_region_info(p_line);
	const String &str = text_editor->get_line(p_line);
	Color prev_color;
	for (int j = 0; j < str.length(); j++) {
		TextEdit::HighlighterInfo highlighter_info;

		if (deregion > 0) {
			deregion--;
			if (deregion == 0) {
				in_region = -1;
			}
		}

		if (deregion != 0) {
			if (color != prev_color) {
				prev_color = color;
				highlighter_info.color = color;
				color_map[j] = highlighter_info;
			}
			continue;
		}

		color = font_color;

		bool is_char = _is_text_char(str[j]);
		bool is_symbol = _is_symbol(str[j]);
		bool is_number = _is_number(str[j]);

		// allow ABCDEF in hex notation
		if (is_hex_notation && (_is_hex_symbol(str[j]) || is_number)) {
			is_number = true;
		} else {
			is_hex_notation = false;
		}

		// check for dot or underscore or 'x' for hex notation in floating point number or 'e' for scientific notation
		if ((str[j] == '.' || str[j] == 'x' || str[j] == '_' || str[j] == 'e') && !in_word && prev_is_number && !is_number) {
			is_number = true;
			is_symbol = false;
			is_char = false;

			if (str[j] == 'x' && str[j - 1] == '0') {
				is_hex_notation = true;
			}
		}

		if (!in_word && _is_char(str[j]) && !is_number) {
			in_word = true;
		}

		if ((in_keyword || in_word) && !is_hex_notation) {
			is_number = false;
		}

		if (is_symbol && str[j] != '.' && in_word) {
			in_word = false;
		}

		if (is_symbol && cri_map.has(j)) {
			const TextEdit::Text::ColorRegionInfo &cri = cri_map[j];

			if (in_region == -1) {
				if (!cri.end) {
					in_region = cri.region;
				}
			} else {
				TextEdit::ColorRegion cr = text_editor->_get_color_region(cri.region);
				if (in_region == cri.region && !cr.line_only) { //ignore otherwise
					if (cri.end || cr.eq) {
						deregion = cr.eq ? cr.begin_key.length() : cr.end_key.length();
					}
				}
			}
		}

		if (!is_char) {
			in_keyword = false;
		}

		if (in_region == -1 && !in_keyword && is_char && !prev_is_char) {

			int to = j;
			while (to < str.length() && _is_text_char(str[to]))
				to++;

			String word = str.substr(j, to - j);
			Color col = Color();
			if (text_editor->has_keyword_color(word)) {
				col = text_editor->get_keyword_color(word);
			} else if (text_editor->has_member_color(word)) {
				col = text_editor->get_member_color(word);
				for (int k = j - 1; k >= 0; k--) {
					if (str[k] == '.') {
						col = Color(); //member indexing not allowed
						break;
					} else if (str[k] > 32) {
						break;
					}
				}
			}

			if (col != Color()) {
				in_keyword = true;
				keyword_color = col;
			}
		}

		if (!in_function_name && in_word && !in_keyword) {

			int k = j;
			while (k < str.length() && !_is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
				k++;
			}

			// check for space between name and bracket
			while (k < str.length() && (str[k] == '\t' || str[k] == ' ')) {
				k++;
			}

			if (str[k] == '(') {
				in_function_name = true;
			} else if (previous_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::TK_PR_VAR)) {
				in_variable_declaration = true;
			}
		}

		if (!in_function_name && !in_member_variable && !in_keyword && !is_number && in_word) {
			int k = j;
			while (k > 0 && !_is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
				k--;
			}

			if (str[k] == '.') {
				in_member_variable = true;
			}
		}

		if (is_symbol) {
			in_function_name = false;
			in_member_variable = false;

			if (expect_type && str[j] != ' ' && str[j] != '\t' && str[j] != ':') {
				expect_type = false;
			}
			if (j > 0 && str[j] == '>' && str[j - 1] == '-') {
				expect_type = true;
			}

			if (in_variable_declaration || previous_text == "(" || previous_text == ",") {
				int k = j;
				// Skip space
				while (k < str.length() && (str[k] == '\t' || str[k] == ' ')) {
					k++;
				}

				if (str[k] == ':') {
					// has type hint
					expect_type = true;
				}
			}

			in_variable_declaration = false;
		}

		if (!in_node_path && in_region == -1 && str[j] == '$') {
			in_node_path = true;
		} else if (in_region != -1 || (is_symbol && str[j] != '/')) {
			in_node_path = false;
		}

		if (in_region >= 0) {
			next_type = REGION;
			color = text_editor->_get_color_region(in_region).color;
		} else if (in_node_path) {
			next_type = NODE_PATH;
			color = node_path_color;
		} else if (in_keyword) {
			next_type = KEYWORD;
			color = keyword_color;
		} else if (in_member_variable) {
			next_type = MEMBER;
			color = member_color;
		} else if (in_function_name) {
			next_type = FUNCTION;

			if (previous_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::TK_PR_FUNCTION)) {
				color = function_definition_color;
			} else {
				color = function_color;
			}
		} else if (is_symbol) {
			next_type = SYMBOL;
			color = symbol_color;
		} else if (is_number) {
			next_type = NUMBER;
			color = number_color;
		} else if (expect_type) {
			next_type = TYPE;
			color = type_color;
		} else {
			next_type = IDENTIFIER;
		}

		if (next_type != current_type) {
			if (current_type == NONE) {
				current_type = next_type;
			} else {
				previous_type = current_type;
				current_type = next_type;

				// no need to store regions...
				if (previous_type == REGION) {
					previous_text = "";
					previous_column = j;
				} else {
					String text = str.substr(previous_column, j - previous_column).strip_edges();
					previous_column = j;

					// ignore if just whitespace
					if (text != "") {
						previous_text = text;
					}
				}
			}
		}

		prev_is_char = is_char;
		prev_is_number = is_number;

		if (color != prev_color) {
			prev_color = color;
			highlighter_info.color = color;
			color_map[j] = highlighter_info;
		}
	}
	return color_map;
}

String GDScriptSyntaxHighlighter::get_name() {
	return "GDScript";
}

List<String> GDScriptSyntaxHighlighter::get_supported_languages() {
	List<String> languages;
	languages.push_back("GDScript");
	return languages;
}

void GDScriptSyntaxHighlighter::_update_cache() {
	font_color = text_editor->get_color("font_color");
	symbol_color = text_editor->get_color("symbol_color");
	function_color = text_editor->get_color("function_color");
	number_color = text_editor->get_color("number_color");
	member_color = text_editor->get_color("member_variable_color");

	EditorSettings *settings = EditorSettings::get_singleton();
	String text_editor_color_theme = settings->get("text_editor/theme/color_theme");

	bool default_theme = text_editor_color_theme == "Default";
	bool dark_theme = settings->is_dark_theme();

	function_definition_color = Color::html(default_theme ? "#01e1ff" : dark_theme ? "#01e1ff" : "#00a5ba");
	node_path_color = Color::html(default_theme ? "#64c15a" : dark_theme ? "64c15a" : "#518b4b");

	EDITOR_DEF("text_editor/highlighting/gdscript/function_definition_color", function_definition_color);
	EDITOR_DEF("text_editor/highlighting/gdscript/node_path_color", node_path_color);
	if (text_editor_color_theme == "Adaptive" || default_theme) {
		settings->set_initial_value("text_editor/highlighting/gdscript/function_definition_color", function_definition_color, true);
		settings->set_initial_value("text_editor/highlighting/gdscript/node_path_color", node_path_color, true);
	}

	function_definition_color = EDITOR_GET("text_editor/highlighting/gdscript/function_definition_color");
	node_path_color = EDITOR_GET("text_editor/highlighting/gdscript/node_path_color");
	type_color = EDITOR_GET("text_editor/highlighting/base_type_color");
}

SyntaxHighlighter *GDScriptSyntaxHighlighter::create() {
	return memnew(GDScriptSyntaxHighlighter);
}
<commit_msg>Fix types highlighting outside of function args and var declarations, issues 22029,21638<commit_after>/*************************************************************************/
/*  gdscript_highlighter.cpp                                             */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "gdscript_highlighter.h"
#include "../gdscript_tokenizer.h"
#include "editor/editor_settings.h"
#include "scene/gui/text_edit.h"

inline bool _is_symbol(CharType c) {

	return is_symbol(c);
}

static bool _is_text_char(CharType c) {

	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
}

static bool _is_char(CharType c) {

	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
}

static bool _is_number(CharType c) {
	return (c >= '0' && c <= '9');
}

static bool _is_hex_symbol(CharType c) {
	return ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
}

Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line) {
	Map<int, TextEdit::HighlighterInfo> color_map;

	Type next_type = NONE;
	Type current_type = NONE;
	Type previous_type = NONE;

	String previous_text = "";
	int previous_column = 0;

	bool prev_is_char = false;
	bool prev_is_number = false;
	bool in_keyword = false;
	bool in_word = false;
	bool in_function_name = false;
	bool in_variable_declaration = false;
	bool in_function_args = false;
	bool in_member_variable = false;
	bool in_node_path = false;
	bool is_hex_notation = false;
	bool expect_type = false;
	Color keyword_color;
	Color color;

	int in_region = text_editor->_is_line_in_region(p_line);
	int deregion = 0;

	const Map<int, TextEdit::Text::ColorRegionInfo> cri_map = text_editor->_get_line_color_region_info(p_line);
	const String &str = text_editor->get_line(p_line);
	Color prev_color;
	for (int j = 0; j < str.length(); j++) {
		TextEdit::HighlighterInfo highlighter_info;

		if (deregion > 0) {
			deregion--;
			if (deregion == 0) {
				in_region = -1;
			}
		}

		if (deregion != 0) {
			if (color != prev_color) {
				prev_color = color;
				highlighter_info.color = color;
				color_map[j] = highlighter_info;
			}
			continue;
		}

		color = font_color;

		bool is_char = _is_text_char(str[j]);
		bool is_symbol = _is_symbol(str[j]);
		bool is_number = _is_number(str[j]);

		// allow ABCDEF in hex notation
		if (is_hex_notation && (_is_hex_symbol(str[j]) || is_number)) {
			is_number = true;
		} else {
			is_hex_notation = false;
		}

		// check for dot or underscore or 'x' for hex notation in floating point number or 'e' for scientific notation
		if ((str[j] == '.' || str[j] == 'x' || str[j] == '_' || str[j] == 'e') && !in_word && prev_is_number && !is_number) {
			is_number = true;
			is_symbol = false;
			is_char = false;

			if (str[j] == 'x' && str[j - 1] == '0') {
				is_hex_notation = true;
			}
		}

		if (!in_word && _is_char(str[j]) && !is_number) {
			in_word = true;
		}

		if ((in_keyword || in_word) && !is_hex_notation) {
			is_number = false;
		}

		if (is_symbol && str[j] != '.' && in_word) {
			in_word = false;
		}

		if (is_symbol && cri_map.has(j)) {
			const TextEdit::Text::ColorRegionInfo &cri = cri_map[j];

			if (in_region == -1) {
				if (!cri.end) {
					in_region = cri.region;
				}
			} else {
				TextEdit::ColorRegion cr = text_editor->_get_color_region(cri.region);
				if (in_region == cri.region && !cr.line_only) { //ignore otherwise
					if (cri.end || cr.eq) {
						deregion = cr.eq ? cr.begin_key.length() : cr.end_key.length();
					}
				}
			}
		}

		if (!is_char) {
			in_keyword = false;
		}

		if (in_region == -1 && !in_keyword && is_char && !prev_is_char) {

			int to = j;
			while (to < str.length() && _is_text_char(str[to]))
				to++;

			String word = str.substr(j, to - j);
			Color col = Color();
			if (text_editor->has_keyword_color(word)) {
				col = text_editor->get_keyword_color(word);
			} else if (text_editor->has_member_color(word)) {
				col = text_editor->get_member_color(word);
				for (int k = j - 1; k >= 0; k--) {
					if (str[k] == '.') {
						col = Color(); //member indexing not allowed
						break;
					} else if (str[k] > 32) {
						break;
					}
				}
			}

			if (col != Color()) {
				in_keyword = true;
				keyword_color = col;
			}
		}

		if (!in_function_name && in_word && !in_keyword) {

			int k = j;
			while (k < str.length() && !_is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
				k++;
			}

			// check for space between name and bracket
			while (k < str.length() && (str[k] == '\t' || str[k] == ' ')) {
				k++;
			}

			if (str[k] == '(') {
				in_function_name = true;
			} else if (previous_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::TK_PR_VAR)) {
				in_variable_declaration = true;
			}
		}

		if (!in_function_name && !in_member_variable && !in_keyword && !is_number && in_word) {
			int k = j;
			while (k > 0 && !_is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
				k--;
			}

			if (str[k] == '.') {
				in_member_variable = true;
			}
		}

		if (is_symbol) {

			if (in_function_name) {
				in_function_args = true;
			}

			if (in_function_args && str[j] == ')') {
				in_function_args = false;
			}

			if (expect_type && prev_is_char) {
				expect_type = false;
			}

			if (j > 0 && str[j] == '>' && str[j - 1] == '-') {
				expect_type = true;
			}

			if (in_variable_declaration || in_function_args) {
				int k = j;
				// Skip space
				while (k < str.length() && (str[k] == '\t' || str[k] == ' ')) {
					k++;
				}

				if (str[k] == ':') {
					// has type hint
					expect_type = true;
				}
			}

			in_variable_declaration = false;
			in_function_name = false;
			in_member_variable = false;
		}

		if (!in_node_path && in_region == -1 && str[j] == '$') {
			in_node_path = true;
		} else if (in_region != -1 || (is_symbol && str[j] != '/')) {
			in_node_path = false;
		}

		if (in_region >= 0) {
			next_type = REGION;
			color = text_editor->_get_color_region(in_region).color;
		} else if (in_node_path) {
			next_type = NODE_PATH;
			color = node_path_color;
		} else if (in_keyword) {
			next_type = KEYWORD;
			color = keyword_color;
		} else if (in_member_variable) {
			next_type = MEMBER;
			color = member_color;
		} else if (in_function_name) {
			next_type = FUNCTION;

			if (previous_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::TK_PR_FUNCTION)) {
				color = function_definition_color;
			} else {
				color = function_color;
			}
		} else if (is_symbol) {
			next_type = SYMBOL;
			color = symbol_color;
		} else if (is_number) {
			next_type = NUMBER;
			color = number_color;
		} else if (expect_type) {
			next_type = TYPE;
			color = type_color;
		} else {
			next_type = IDENTIFIER;
		}

		if (next_type != current_type) {
			if (current_type == NONE) {
				current_type = next_type;
			} else {
				previous_type = current_type;
				current_type = next_type;

				// no need to store regions...
				if (previous_type == REGION) {
					previous_text = "";
					previous_column = j;
				} else {
					String text = str.substr(previous_column, j - previous_column).strip_edges();
					previous_column = j;

					// ignore if just whitespace
					if (text != "") {
						previous_text = text;
					}
				}
			}
		}

		prev_is_char = is_char;
		prev_is_number = is_number;

		if (color != prev_color) {
			prev_color = color;
			highlighter_info.color = color;
			color_map[j] = highlighter_info;
		}
	}
	return color_map;
}

String GDScriptSyntaxHighlighter::get_name() {
	return "GDScript";
}

List<String> GDScriptSyntaxHighlighter::get_supported_languages() {
	List<String> languages;
	languages.push_back("GDScript");
	return languages;
}

void GDScriptSyntaxHighlighter::_update_cache() {
	font_color = text_editor->get_color("font_color");
	symbol_color = text_editor->get_color("symbol_color");
	function_color = text_editor->get_color("function_color");
	number_color = text_editor->get_color("number_color");
	member_color = text_editor->get_color("member_variable_color");

	EditorSettings *settings = EditorSettings::get_singleton();
	String text_editor_color_theme = settings->get("text_editor/theme/color_theme");

	bool default_theme = text_editor_color_theme == "Default";
	bool dark_theme = settings->is_dark_theme();

	function_definition_color = Color::html(default_theme ? "#01e1ff" : dark_theme ? "#01e1ff" : "#00a5ba");
	node_path_color = Color::html(default_theme ? "#64c15a" : dark_theme ? "64c15a" : "#518b4b");

	EDITOR_DEF("text_editor/highlighting/gdscript/function_definition_color", function_definition_color);
	EDITOR_DEF("text_editor/highlighting/gdscript/node_path_color", node_path_color);
	if (text_editor_color_theme == "Adaptive" || default_theme) {
		settings->set_initial_value("text_editor/highlighting/gdscript/function_definition_color", function_definition_color, true);
		settings->set_initial_value("text_editor/highlighting/gdscript/node_path_color", node_path_color, true);
	}

	function_definition_color = EDITOR_GET("text_editor/highlighting/gdscript/function_definition_color");
	node_path_color = EDITOR_GET("text_editor/highlighting/gdscript/node_path_color");
	type_color = EDITOR_GET("text_editor/highlighting/base_type_color");
}

SyntaxHighlighter *GDScriptSyntaxHighlighter::create() {
	return memnew(GDScriptSyntaxHighlighter);
}
<|endoftext|>


<commit_before>#include "ug_sampling_bias.h"
#include <iostream>
#include <boost/foreach.hpp>

#ifdef HAVE_CURLPP
#include <curlpp/Options.hpp>
#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#endif

namespace Moses
{
  namespace bitext
  {
    using ugdiss::id_type;

    std::string
    query_bias_server(std::string const& url, std::string const& text)
    {
      // communicate with the bias server; resuts will be in ...
      std::ostringstream os;
      curlpp::Easy myRequest;
      std::string query = url+curlpp::escape(text);
      myRequest.setOpt(new curlpp::options::Url(query));
      curlpp::options::WriteStream ws(&os);
      myRequest.setOpt(ws); // Give it to your request
      myRequest.perform();  // This will output to os
      return os.str();
    }

    DocumentBias
    ::DocumentBias
    ( std::vector<id_type> const& sid2doc,
      std::map<std::string,id_type> const& docname2docid,
      std::string const& server_url, std::string const& text,
      std::ostream* log)
      : m_sid2docid(sid2doc)
      , m_bias(docname2docid.size(), 0)
    {
      std::string json = query_bias_server(server_url, text);
      init_from_json(json, docname2docid, log);
    }

    void
    DocumentBias
    ::init_from_json
    ( std::string const& json, std::map<std::string,id_type> const& docname2docid,
      std::ostream* log)
    { // poor man's special purpose json parser for responses from the
      // MMT bias server

      std::string d; float total = 0; std::map<std::string,float> bias;
      size_t i = 0; while (i < json.size() && json[i] != '"') ++i;
      while (++i < json.size())
	{
	  size_t  k = i; while (i < json.size() && json[i] != '"') ++i;
	  if (i >= json.size())  break;
	  float& f = bias[json.substr(k,i-k)];
	  while (++i < json.size() && json[i] != ':');
	  k = ++i;
	  while (++i < json.size() && json[i] != ',' && json[i] != '}');
	  total += (f = atof(json.substr(k, i-k).c_str()));
	  k = ++i; while (i < json.size() && json[i] != '"') ++i;
	}

      typedef std::pair<std::string const,float> item;
      if (total) { BOOST_FOREACH(item& x, bias) { x.second /= total; } }
      if (log)
	{
	  BOOST_FOREACH(item& x, bias)
	    {
	      std::map<std::string,id_type>::const_iterator m;
	      m = docname2docid.find(x.first);
	      int docid = m != docname2docid.end() ? m->second : -1;
	      *log << "CONTEXT SERVER RESPONSE "
		   << "[" << docid << "] "
		   << x.first << " " << x.second << std::endl;
	    }
	}
      init(bias, docname2docid);

      // using xmlrpc_parse_json didn't always work (parser errors)
      // xmlrpc_value* b = xmlrpc_parse_json(env ,buf.str().c_str());
      // std::cerr << "|" << buf.str() << "|" << std::endl;
      // // if (b == NULL) std::cerr << "OOpS" << std::endl;
      // xmlrpc_c::value_struct v(b); //  = *b;
      // std::map<std::string, xmlrpc_c::value> const
      // 	bmap = static_cast<map<std::string, xmlrpc_c::value> >(v);
      // std::map<std::string, float> bias;
      // typedef std::map<std::string, xmlrpc_c::value>::value_type item;
      // float total = 0;
      // BOOST_FOREACH(item const& x, bmap)
      // 	{
      // 	  total += bias[x.first] = xmlrpc_c::value_double(x.second);
      // 	}
      // typedef std::map<std::string, float>::value_type fitem;
      // BOOST_FOREACH(fitem const& x, bias)
      // 	std::cerr << x.first << " " << x.second/total << std::endl;
      // // delete b;
    }

    void
    DocumentBias
    ::init(std::map<std::string,float> const& biasmap,
	   std::map<std::string,id_type> const& docname2docid)
    {
      typedef std::map<std::string, id_type>::value_type doc_record;
      float total = 0;
      BOOST_FOREACH(doc_record const& d, docname2docid)
	{
	  std::map<std::string, float>::const_iterator m = biasmap.find(d.first);
	  if (m != biasmap.end()) total += (m_bias[d.second] = m->second);
	  }
      if (total) { BOOST_FOREACH(float& f, m_bias) f /= total; }
      BOOST_FOREACH(doc_record const& d, docname2docid)
	std::cerr << "BIAS " << d.first << " " << m_bias[d.second] << std::endl;
    }

    id_type
    DocumentBias
    ::GetClass(id_type const idx) const
    {
      return m_sid2docid.at(idx);
    }

    float
    DocumentBias
    ::operator[](id_type const idx) const
    {
      UTIL_THROW_IF2(idx >= m_sid2docid.size(),
		     "Out of bounds: " << idx << "/" << m_sid2docid.size());
      return m_bias[m_sid2docid[idx]];
    }

    size_t
    DocumentBias
    ::size() const
    { return m_sid2docid.size(); }

    SentenceBias
    ::SentenceBias(std::vector<float> const& bias)
      : m_bias(bias) { }

    SentenceBias
    ::SentenceBias(size_t const s) : m_bias(s) { }

    id_type
    SentenceBias
    ::GetClass(id_type idx) const { return idx; }

    float&
    SentenceBias
    ::operator[](id_type const idx)
    {
      UTIL_THROW_IF2(idx >= m_bias.size(), "Out of bounds");
      return m_bias[idx];
    }

    float
    SentenceBias
    ::operator[](id_type const idx) const
    {
      UTIL_THROW_IF2(idx >= m_bias.size(), "Out of bounds");
      return m_bias[idx];
    }

    size_t
    SentenceBias
    ::size() const { return m_bias.size(); }

  }
}
<commit_msg>Make sure things work when curl-based biasing is disabled.<commit_after>#include "ug_sampling_bias.h"
#include <iostream>
#include <boost/foreach.hpp>

#ifdef HAVE_CURLPP
#include <curlpp/Options.hpp>
#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#endif

namespace Moses
{
  namespace bitext
  {
    using ugdiss::id_type;

#ifdef HAVE_CURLPP
    std::string
    query_bias_server(std::string const& url, std::string const& text)
    {
      // communicate with the bias server; resuts will be in ...
      std::ostringstream os;
      curlpp::Easy myRequest;
      std::string query = url+curlpp::escape(text);
      myRequest.setOpt(new curlpp::options::Url(query));
      curlpp::options::WriteStream ws(&os);
      myRequest.setOpt(ws); // Give it to your request
      myRequest.perform();  // This will output to os
      return os.str();
    }
#endif

    DocumentBias
    ::DocumentBias
    ( std::vector<id_type> const& sid2doc,
      std::map<std::string,id_type> const& docname2docid,
      std::string const& server_url, std::string const& text,
      std::ostream* log)
      : m_sid2docid(sid2doc)
      , m_bias(docname2docid.size(), 0)
    {
#ifdef HAVE_CURLPP
      std::string json = query_bias_server(server_url, text);
      init_from_json(json, docname2docid, log);
#endif
    }

    void
    DocumentBias
    ::init_from_json
    ( std::string const& json, std::map<std::string,id_type> const& docname2docid,
      std::ostream* log)
    { // poor man's special purpose json parser for responses from the
      // MMT bias server

      std::string d; float total = 0; std::map<std::string,float> bias;
      size_t i = 0; while (i < json.size() && json[i] != '"') ++i;
      while (++i < json.size())
	{
	  size_t  k = i; while (i < json.size() && json[i] != '"') ++i;
	  if (i >= json.size())  break;
	  float& f = bias[json.substr(k,i-k)];
	  while (++i < json.size() && json[i] != ':');
	  k = ++i;
	  while (++i < json.size() && json[i] != ',' && json[i] != '}');
	  total += (f = atof(json.substr(k, i-k).c_str()));
	  k = ++i; while (i < json.size() && json[i] != '"') ++i;
	}

      typedef std::pair<std::string const,float> item;
      if (total) { BOOST_FOREACH(item& x, bias) { x.second /= total; } }
      if (log)
	{
	  BOOST_FOREACH(item& x, bias)
	    {
	      std::map<std::string,id_type>::const_iterator m;
	      m = docname2docid.find(x.first);
	      int docid = m != docname2docid.end() ? m->second : -1;
	      *log << "CONTEXT SERVER RESPONSE "
		   << "[" << docid << "] "
		   << x.first << " " << x.second << std::endl;
	    }
	}
      init(bias, docname2docid);

      // using xmlrpc_parse_json didn't always work (parser errors)
      // xmlrpc_value* b = xmlrpc_parse_json(env ,buf.str().c_str());
      // std::cerr << "|" << buf.str() << "|" << std::endl;
      // // if (b == NULL) std::cerr << "OOpS" << std::endl;
      // xmlrpc_c::value_struct v(b); //  = *b;
      // std::map<std::string, xmlrpc_c::value> const
      // 	bmap = static_cast<map<std::string, xmlrpc_c::value> >(v);
      // std::map<std::string, float> bias;
      // typedef std::map<std::string, xmlrpc_c::value>::value_type item;
      // float total = 0;
      // BOOST_FOREACH(item const& x, bmap)
      // 	{
      // 	  total += bias[x.first] = xmlrpc_c::value_double(x.second);
      // 	}
      // typedef std::map<std::string, float>::value_type fitem;
      // BOOST_FOREACH(fitem const& x, bias)
      // 	std::cerr << x.first << " " << x.second/total << std::endl;
      // // delete b;
    }

    void
    DocumentBias
    ::init(std::map<std::string,float> const& biasmap,
	   std::map<std::string,id_type> const& docname2docid)
    {
      typedef std::map<std::string, id_type>::value_type doc_record;
      float total = 0;
      BOOST_FOREACH(doc_record const& d, docname2docid)
	{
	  std::map<std::string, float>::const_iterator m = biasmap.find(d.first);
	  if (m != biasmap.end()) total += (m_bias[d.second] = m->second);
	  }
      if (total) { BOOST_FOREACH(float& f, m_bias) f /= total; }
      BOOST_FOREACH(doc_record const& d, docname2docid)
	std::cerr << "BIAS " << d.first << " " << m_bias[d.second] << std::endl;
    }

    id_type
    DocumentBias
    ::GetClass(id_type const idx) const
    {
      return m_sid2docid.at(idx);
    }

    float
    DocumentBias
    ::operator[](id_type const idx) const
    {
      UTIL_THROW_IF2(idx >= m_sid2docid.size(),
		     "Out of bounds: " << idx << "/" << m_sid2docid.size());
      return m_bias[m_sid2docid[idx]];
    }

    size_t
    DocumentBias
    ::size() const
    { return m_sid2docid.size(); }

    SentenceBias
    ::SentenceBias(std::vector<float> const& bias)
      : m_bias(bias) { }

    SentenceBias
    ::SentenceBias(size_t const s) : m_bias(s) { }

    id_type
    SentenceBias
    ::GetClass(id_type idx) const { return idx; }

    float&
    SentenceBias
    ::operator[](id_type const idx)
    {
      UTIL_THROW_IF2(idx >= m_bias.size(), "Out of bounds");
      return m_bias[idx];
    }

    float
    SentenceBias
    ::operator[](id_type const idx) const
    {
      UTIL_THROW_IF2(idx >= m_bias.size(), "Out of bounds");
      return m_bias[idx];
    }

    size_t
    SentenceBias
    ::size() const { return m_bias.size(); }

  }
}
<|endoftext|>


<commit_before>#include <string>
#include <vector>
#include <fstream>
#include <algorithm>
#include <iostream>
#include <stdlib.h>

#include "Note.h"
#include "VoiceProp.h"
#include "Oto.h"

#define DEBUG true
#define DEBUG_FULL false // enables debug output on every oto line, may result in a LOT of output

using namespace std;

Oto::Oto(std::string path) {
	filePath = path;
	openFile();
}

Oto::~Oto() { }

void Oto::openFile() {
	std::ifstream otoStream;
	otoStream.open(filePath + "/oto.ini");

	if (!otoStream) {
		//TODO: fallback to default from config file
		cout << "Error: Voicebank \"" << filePath << "\" not found or format unsupported. Stop." << std::endl;
		exit(EXIT_FAILURE);
	}

	if (otoStream.is_open()) {
		std::string otoItem;
		unsigned int index = 0;
		voices.resize(8192);

		// This was mostly ported from FVSS, there probably will be errors
		// Also needs error handling
		while (getline(otoStream, otoItem)) {
			VoiceProp *vp = new VoiceProp();

			// needed because of newline fix
			std::string item = otoItem;
#if DEBUG_FULL
			clog << "DEBUG_FULL: oto line " << std::to_string(index) << ":" << std::endl;
			clog << "	" << item << std::endl;
#endif
			try {
				//TODO: maybe remove newlines that get left behind

				// Get indexes from line
				int index1 = item.find('=');
                int index2 = item.find(",", index1 + 1);
                int index3 = item.find(",", index2 + 1);
                int index4 = item.find(",", index3 + 1);
                int index5 = item.find(",", index4 + 1);
                int index6 = item.find(",", index5 + 1);
#if DEBUG_FULL
				clog << "DEBUG_FULL: Printing all OTO content indexes" << std::endl;
				clog << "	" << std::to_string(index1) << std::endl;
				clog << "	" << std::to_string(index2) << std::endl;
				clog << "	" << std::to_string(index3) << std::endl;
				clog << "	" << std::to_string(index4) << std::endl;
				clog << "	" << std::to_string(index5) << std::endl;
#endif
				// Chop up line into individual properties and add them to vp
				vp->fileName = item.substr(0, index1);
				vp->sampleName = item.substr(index1 + 1, index2 - index1 - 1);
#if DEBUG_FULL
				clog << "DEBUG_FULL: OTO fileName: " << vp->fileName << std::endl;
				clog << "DEBUG_FULL: OTO sampleName: " << vp->sampleName << std::endl;
#endif
				vp->start = std::stoi(item.substr(index2 + 1, index3 - index2 - 1));
                vp->consonant = std::stoi(item.substr(index3 + 1, index4 - index3 - 1));
                vp->end = std::stoi(item.substr(index4 + 1, index5 - index4 - 1));
                vp->preutterance = std::stoi(item.substr(index5 + 1, index6 - index5 - 1));
                vp->overlap = std::stoi(item.substr(index6 + 1));
#if DEBUG_FULL
				clog << "DEBUG_FULL: Printing all parsed OTO properties:" << std::endl;
				clog << "	" << std::to_string(vp->start) << std::endl;
				clog << "	" << std::to_string(vp->consonant) << std::endl;
				clog << "	" << std::to_string(vp->end) << std::endl;
				clog << "	" << std::to_string(vp->preutterance) << std::endl;
				clog << "	" << std::to_string(vp->overlap) << std::endl;
#endif
				//TODO: might need to remove newlines from FileName property

				if (voices.size() <= index) voices.resize(index + 129);
				voices[index] = vp;
#if DEBUG
				//print the first 2 oto property lists
				if (index < 2) {
					clog << "DEBUG: OTO data from entry " << std::to_string(index);
					clog << "fileName = " << voices[index]->fileName << std::endl;
					clog << "sampleName = " << voices[index]->sampleName << std::endl;
					clog << "start = " << std::to_string(voices[index]->start) << std::endl;
					clog << "consonant = " << std::to_string(voices[index]->consonant) << std::endl;
					clog << "end = " << std::to_string(voices[index]->end) << std::endl;
					clog << "preutterance = " << std::to_string(voices[index]->preutterance) << std::endl;
					clog << "overlap = " << std::to_string(voices[index]->overlap) << std::endl;
				}
#endif
			}
			catch (...) { }

			index++;
		}
		voices.resize(index + 1);
	}
}

// This is broken...
void Oto::getVPfromName(std::string smpName, VoiceProp *vp) {
	for (int i = 0; i < voices.size(); i++) {
		if (voices[i]->sampleName == smpName || voices[i]->sampleName == smpName + ".wav")
			vp = voices[i];
	}
#if DEBUG
	clog << "DEBUG: Note with content \"" << smpName << "\" doesn't exist in voicebank;"
		<< " using empty VoiceProp." << std::endl;
#endif
	vp = new VoiceProp();
}<commit_msg>Fixed VoiceProperties being stored as integers<commit_after>#include <string>
#include <vector>
#include <fstream>
#include <algorithm>
#include <iostream>
#include <stdlib.h>

#include "Note.h"
#include "VoiceProp.h"
#include "Oto.h"

#define DEBUG true
#define DEBUG_FULL false // enables debug output on every oto line, may result in a LOT of output

using namespace std;

Oto::Oto(std::string path) {
	filePath = path;
	openFile();
}

Oto::~Oto() { }

void Oto::openFile() {
	std::ifstream otoStream;
	otoStream.open(filePath + "/oto.ini");

	if (!otoStream) {
		//TODO: fallback to default from config file
		cout << "Error: Voicebank \"" << filePath << "\" not found or format unsupported. Stop." << std::endl;
		exit(EXIT_FAILURE);
	}

	if (otoStream.is_open()) {
		std::string otoItem;
		unsigned int index = 0;
		voices.resize(8192);

		// This was mostly ported from FVSS, there probably will be errors
		// Also needs error handling
		while (getline(otoStream, otoItem)) {
			VoiceProp *vp = new VoiceProp();

			// needed because of newline fix
			std::string item = otoItem;
#if DEBUG_FULL
			clog << "DEBUG_FULL: oto line " << std::to_string(index) << ":" << std::endl;
			clog << "	" << item << std::endl;
#endif
			try {
				//TODO: maybe remove newlines that get left behind

				// Get indexes from line
				int index1 = item.find('=');
                int index2 = item.find(",", index1 + 1);
                int index3 = item.find(",", index2 + 1);
                int index4 = item.find(",", index3 + 1);
                int index5 = item.find(",", index4 + 1);
                int index6 = item.find(",", index5 + 1);
#if DEBUG_FULL
				clog << "DEBUG_FULL: Printing all OTO content indexes" << std::endl;
				clog << "	" << std::to_string(index1) << std::endl;
				clog << "	" << std::to_string(index2) << std::endl;
				clog << "	" << std::to_string(index3) << std::endl;
				clog << "	" << std::to_string(index4) << std::endl;
				clog << "	" << std::to_string(index5) << std::endl;
#endif
				// Chop up line into individual properties and add them to vp
				vp->fileName = item.substr(0, index1);
				vp->sampleName = item.substr(index1 + 1, index2 - index1 - 1);
#if DEBUG_FULL
				clog << "DEBUG_FULL: OTO fileName: " << vp->fileName << std::endl;
				clog << "DEBUG_FULL: OTO sampleName: " << vp->sampleName << std::endl;
#endif
				vp->start = std::stod(item.substr(index2 + 1, index3 - index2 - 1));
                vp->consonant = std::stod(item.substr(index3 + 1, index4 - index3 - 1));
                vp->end = std::stod(item.substr(index4 + 1, index5 - index4 - 1));
                vp->preutterance = std::stod(item.substr(index5 + 1, index6 - index5 - 1));
                vp->overlap = std::stod(item.substr(index6 + 1));
#if DEBUG_FULL
				clog << "DEBUG_FULL: Printing all parsed OTO properties:" << std::endl;
				clog << "	" << std::to_string(vp->start) << std::endl;
				clog << "	" << std::to_string(vp->consonant) << std::endl;
				clog << "	" << std::to_string(vp->end) << std::endl;
				clog << "	" << std::to_string(vp->preutterance) << std::endl;
				clog << "	" << std::to_string(vp->overlap) << std::endl;
#endif
				//TODO: might need to remove newlines from FileName property

				if (voices.size() <= index) voices.resize(index + 129);
				voices[index] = vp;
#if DEBUG
				//print the first 2 oto property lists
				if (index < 2) {
					clog << "DEBUG: OTO data from entry " << std::to_string(index);
					clog << "fileName = " << voices[index]->fileName << std::endl;
					clog << "sampleName = " << voices[index]->sampleName << std::endl;
					clog << "start = " << std::to_string(voices[index]->start) << std::endl;
					clog << "consonant = " << std::to_string(voices[index]->consonant) << std::endl;
					clog << "end = " << std::to_string(voices[index]->end) << std::endl;
					clog << "preutterance = " << std::to_string(voices[index]->preutterance) << std::endl;
					clog << "overlap = " << std::to_string(voices[index]->overlap) << std::endl;
				}
#endif
			}
			catch (...) { }

			index++;
		}
		voices.resize(index + 1);
	}
}

// This is broken...
void Oto::getVPfromName(std::string smpName, VoiceProp *vp) {
	for (int i = 0; i < voices.size(); i++) {
		if (voices[i]->sampleName == smpName || voices[i]->sampleName == smpName + ".wav")
			vp = voices[i];
	}
#if DEBUG
	clog << "DEBUG: Note with content \"" << smpName << "\" doesn't exist in voicebank;"
		<< " using empty VoiceProp." << std::endl;
#endif
	vp = new VoiceProp();
}<|endoftext|>


<commit_before>#include "org/xtreemfs/client/proxy.h"
#include "policy_container.h"
using namespace org::xtreemfs::client;

#include "org/xtreemfs/interfaces/constants.h"

#include <errno.h>
#ifdef _WIN32
#include "yield/ipc/sockets.h"
#define ETIMEDOUT WSAETIMEDOUT
#endif

Proxy::Proxy( const YIELD::URI& uri, uint16_t default_oncrpc_port, uint16_t default_oncrpcs_port ) : uri( uri )
{
  if ( strcmp( uri.getScheme(), org::xtreemfs::interfaces::ONCRPC_SCHEME ) == 0 || strcmp( uri.getScheme(), org::xtreemfs::interfaces::ONCRPCS_SCHEME ) == 0 )
  {
    if ( this->uri.getPort() == 0 )
    {
      if ( strcmp( this->uri.getScheme(), org::xtreemfs::interfaces::ONCRPC_SCHEME ) == 0 )
        this->uri.setPort( default_oncrpc_port );
      else if ( strcmp( this->uri.getScheme(), org::xtreemfs::interfaces::ONCRPCS_SCHEME ) == 0 )
        this->uri.setPort( default_oncrpcs_port );
      else
        YIELD::DebugBreak();
    }

    this->reconnect_tries_max = PROXY_DEFAULT_RECONNECT_TRIES_MAX;
    this->flags = PROXY_DEFAULT_FLAGS;
    this->peer_ip = 0;
    this->conn = 0;

    org::xtreemfs::interfaces::Exceptions().registerSerializableFactories( serializable_factories );
  }
  else
    throw YIELD::Exception( "unknown URI scheme" );
}

Proxy::~Proxy()
{
  delete conn;
}

void Proxy::handleEvent( YIELD::Event& ev )
{
  switch ( ev.getTypeId() )
  {
    case TYPE_ID( YIELD::StageStartupEvent ):
    case TYPE_ID( YIELD::StageShutdownEvent ): YIELD::SharedObject::decRef( ev ); break;

    default:
    {
      switch ( ev.getGeneralType() )
      {
        case YIELD::RTTI::REQUEST:
        {
          YIELD::Request& req = static_cast<YIELD::Request&>( ev );
          if ( ( flags & PROXY_FLAG_PRINT_OPERATIONS ) == PROXY_FLAG_PRINT_OPERATIONS )
          {
            YIELD::PrettyPrintOutputStream pretty_print_output_stream( std::cout );
            pretty_print_output_stream.writeSerializable( YIELD::PrettyPrintOutputStream::Declaration( req.getTypeName() ), req );
          }

          try
          {
            YIELD::auto_SharedObject<org::xtreemfs::interfaces::UserCredentials> user_credentials = get_user_credentials();
            YIELD::ONCRPCRequest oncrpc_req( YIELD::SharedObject::incRef( req ), serializable_factories, user_credentials.get() ? org::xtreemfs::interfaces::ONCRPC_AUTH_FLAVOR : YIELD::ONCRPCRequest::AUTH_NONE, user_credentials.get() );

            uint64_t timeout_ms = req.getResponseTimeoutMS();
            uint64_t original_timeout_ms = timeout_ms;
            uint8_t reconnect_tries_left = reconnect_tries_max;

            if ( conn == NULL )
              reconnect_tries_left = reconnect( original_timeout_ms, reconnect_tries_left );

            if ( timeout_ms == static_cast<uint64_t>( -1 ) ) // Blocking
            {
              YIELD::SocketLib::setBlocking( conn->getSocket() );

              for ( uint8_t serialize_tries = 0; serialize_tries < 2; serialize_tries++ ) // Try, allow for one reconnect, then try again
              {
                oncrpc_req.serialize( *conn );
                if ( conn->getStatus() == YIELD::SocketConnection::SCS_READY )
                {
                  for ( uint8_t deserialize_tries = 0; deserialize_tries < 2; deserialize_tries++ )
                  {
                    oncrpc_req.deserialize( *conn );
                    if ( conn->getStatus() == YIELD::SocketConnection::SCS_READY )
                    {
                      req.respond( static_cast<YIELD::Event&>( YIELD::SharedObject::incRef( *oncrpc_req.getInBody() ) ) );
                      YIELD::SharedObject::decRef( req );
                      return;
                    }
                    else if ( conn->getStatus() == YIELD::SocketConnection::SCS_CLOSED )
                      reconnect_tries_left = reconnect( original_timeout_ms, reconnect_tries_left );
                    else
                      YIELD::DebugBreak();
                  }
                }
                else if ( conn->getStatus() == YIELD::SocketConnection::SCS_CLOSED )
                  reconnect_tries_left = reconnect( original_timeout_ms, reconnect_tries_left );
                else
                  YIELD::DebugBreak();
              }
            }
            else // Non-blocking/timed
            {
              YIELD::SocketLib::setNonBlocking( conn->getSocket() );

              bool have_written = false; // Use the variable so the read and write attempt loops can be combined and eliminate some code duplication

              while ( true ) // Loop for read and write attempts
              {
                if ( !have_written )
                  oncrpc_req.serialize( *conn );
                else
                  oncrpc_req.deserialize( *conn );

                // Use if statements instead of a switch so the break after a successful read will exit the loop
                if ( conn->getStatus() == YIELD::SocketConnection::SCS_READY )
                {
                  if ( !have_written )
                    have_written = true;
                  else
                    break;
                }
                else if ( conn->getStatus() == YIELD::SocketConnection::SCS_CLOSED )
                  reconnect_tries_left = reconnect( original_timeout_ms, reconnect_tries_left );
                else if ( timeout_ms > 0 )
                {
                  bool enable_read = conn->getStatus() == YIELD::SocketConnection::SCS_BLOCKED_ON_READ;
                  fd_event_queue.toggleSocketEvent( conn->getSocket(), conn, enable_read, !enable_read );
                  double start_epoch_time_ms = YIELD::Time::getCurrentEpochTimeMS();
                  YIELD::FDEvent* fd_event = static_cast<YIELD::FDEvent*>( fd_event_queue.timed_dequeue( static_cast<YIELD::timeout_ns_t>( timeout_ms ) * NS_IN_MS ) );
                  if ( fd_event )
                  {
                    if ( fd_event->error_code == 0 )
                      timeout_ms -= std::min( static_cast<uint64_t>( YIELD::Time::getCurrentEpochTimeMS() - start_epoch_time_ms ), timeout_ms );
                    else
                      reconnect_tries_left = reconnect( original_timeout_ms, reconnect_tries_left );
                  }
                  else
                    throwExceptionEvent( new YIELD::PlatformExceptionEvent( ETIMEDOUT ) );
                }
                else
                  throwExceptionEvent( new YIELD::PlatformExceptionEvent( ETIMEDOUT ) );
              }
            }
          }
          catch ( YIELD::ExceptionEvent* exc_ev )
          {
            req.respond( *exc_ev );
            YIELD::SharedObject::decRef( req );
          }
        }
        break;

        default: YIELD::DebugBreak(); break;
      }
    }
    break;
  }
}

uint8_t Proxy::reconnect( uint64_t timeout_ms, uint8_t reconnect_tries_left )
{
  if ( peer_ip == 0 )
  {
    peer_ip = YIELD::SocketLib::resolveHost( uri.getHost() );
    if ( peer_ip == 0 && ( strcmp( uri.getHost(), "localhost" ) == 0 || strcmp( uri.getHost(), "127.0.0.1" ) == 0 ) )
      peer_ip = YIELD::SocketLib::resolveHost( YIELD::SocketLib::getLocalHostFQDN() );
    if ( peer_ip == 0 )
      throw new YIELD::PlatformExceptionEvent();
  }

  if ( conn != NULL ) // This is a reconnect, not the first connect
  {
    fd_event_queue.detachSocket( conn->getSocket(), conn );
    conn->close();
    delete conn;
    conn = NULL;
  }

  while ( reconnect_tries_left > 0 )
  {
    reconnect_tries_left--;

    // Create the conn object based on the URI type
    if ( strcmp( uri.getScheme(), "oncrpc" ) == 0 )
      conn = new YIELD::TCPConnection( peer_ip, uri.getPort(), NULL );
    else
      YIELD::DebugBreak();

    // Attach the socket to the fd_event_queue even if we're doing a blocking connect, in case a later read/write is non-blocking
    fd_event_queue.attachSocket( conn->getSocket(), conn, false, false ); // Attach without read or write notifications enabled

    // Now try the actual connect
    if ( timeout_ms == static_cast<uint64_t>( -1 ) ) // Blocking
    {
      YIELD::SocketLib::setBlocking( conn->getSocket() );

      if ( conn->connect() == YIELD::SocketConnection::SCS_READY )
        return reconnect_tries_left;
    }
    else // Non-blocking/timed
    {
      YIELD::SocketLib::setNonBlocking( conn->getSocket() );

      switch ( conn->connect() )
      {
        case YIELD::SocketConnection::SCS_READY: break;
        case YIELD::SocketConnection::SCS_BLOCKED_ON_WRITE:
        {
          fd_event_queue.toggleSocketEvent( conn->getSocket(), conn, false, true ); // Write readiness = the connect() operation is complete
          double start_epoch_time_ms = YIELD::Time::getCurrentEpochTimeMS();
          YIELD::FDEvent* fd_event = static_cast<YIELD::FDEvent*>( fd_event_queue.timed_dequeue( static_cast<YIELD::timeout_ns_t>( timeout_ms ) * NS_IN_MS ) );
          if ( fd_event && fd_event->error_code == 0 &&
               conn->connect() == YIELD::SocketConnection::SCS_READY )
          {
            fd_event_queue.toggleSocketEvent( conn->getSocket(), conn, false, false );
            return reconnect_tries_left;
          }
          else
          {
            timeout_ms -= std::min( static_cast<uint64_t>( YIELD::Time::getCurrentEpochTimeMS() - start_epoch_time_ms ), timeout_ms );
            if ( timeout_ms == 0 ) { reconnect_tries_left = 0; break; }
          }
        }
      }
    }

    // Clear the connection state for the next try
    fd_event_queue.detachSocket( conn->getSocket(), conn );
    conn->close();
    delete conn;
    conn = NULL;
  }

  unsigned long error_code = YIELD::PlatformException::errno_();
  if ( error_code == 0 )
    error_code = ETIMEDOUT;
  throw new YIELD::PlatformExceptionEvent( error_code );
}

void Proxy::throwExceptionEvent( YIELD::ExceptionEvent* exc_ev )
{
  if ( conn )
  {
    fd_event_queue.detachSocket( conn->getSocket(), conn );
    conn->close();
    delete conn;
    conn = NULL;
  }

  throw exc_ev;
}
<commit_msg>Proxy: Linux fix<commit_after>#include "org/xtreemfs/client/proxy.h"
#include "policy_container.h"
using namespace org::xtreemfs::client;

#include "org/xtreemfs/interfaces/constants.h"

#include <errno.h>
#ifdef _WIN32
#include "yield/ipc/sockets.h"
#define ETIMEDOUT WSAETIMEDOUT
#endif

Proxy::Proxy( const YIELD::URI& uri, uint16_t default_oncrpc_port, uint16_t default_oncrpcs_port ) : uri( uri )
{
  if ( strcmp( uri.getScheme(), org::xtreemfs::interfaces::ONCRPC_SCHEME ) == 0 || strcmp( uri.getScheme(), org::xtreemfs::interfaces::ONCRPCS_SCHEME ) == 0 )
  {
    if ( this->uri.getPort() == 0 )
    {
      if ( strcmp( this->uri.getScheme(), org::xtreemfs::interfaces::ONCRPC_SCHEME ) == 0 )
        this->uri.setPort( default_oncrpc_port );
      else if ( strcmp( this->uri.getScheme(), org::xtreemfs::interfaces::ONCRPCS_SCHEME ) == 0 )
        this->uri.setPort( default_oncrpcs_port );
      else
        YIELD::DebugBreak();
    }

    this->reconnect_tries_max = PROXY_DEFAULT_RECONNECT_TRIES_MAX;
    this->flags = PROXY_DEFAULT_FLAGS;
    this->peer_ip = 0;
    this->conn = 0;

    org::xtreemfs::interfaces::Exceptions().registerSerializableFactories( serializable_factories );
  }
  else
    throw YIELD::Exception( "unknown URI scheme" );
}

Proxy::~Proxy()
{
  delete conn;
}

void Proxy::handleEvent( YIELD::Event& ev )
{
  switch ( ev.getTypeId() )
  {
    case TYPE_ID( YIELD::StageStartupEvent ):
    case TYPE_ID( YIELD::StageShutdownEvent ): YIELD::SharedObject::decRef( ev ); break;

    default:
    {
      switch ( ev.getGeneralType() )
      {
        case YIELD::RTTI::REQUEST:
        {
          YIELD::Request& req = static_cast<YIELD::Request&>( ev );
          if ( ( flags & PROXY_FLAG_PRINT_OPERATIONS ) == PROXY_FLAG_PRINT_OPERATIONS )
          {
            YIELD::PrettyPrintOutputStream pretty_print_output_stream( std::cout );
            pretty_print_output_stream.writeSerializable( YIELD::PrettyPrintOutputStream::Declaration( req.getTypeName() ), req );
          }

          try
          {
            YIELD::auto_SharedObject<org::xtreemfs::interfaces::UserCredentials> user_credentials = get_user_credentials();
            YIELD::ONCRPCRequest oncrpc_req( YIELD::SharedObject::incRef( req ), serializable_factories, user_credentials.get() ? org::xtreemfs::interfaces::ONCRPC_AUTH_FLAVOR : 0, user_credentials.get() );

            uint64_t timeout_ms = req.getResponseTimeoutMS();
            uint64_t original_timeout_ms = timeout_ms;
            uint8_t reconnect_tries_left = reconnect_tries_max;

            if ( conn == NULL )
              reconnect_tries_left = reconnect( original_timeout_ms, reconnect_tries_left );

            if ( timeout_ms == static_cast<uint64_t>( -1 ) ) // Blocking
            {
              YIELD::SocketLib::setBlocking( conn->getSocket() );

              for ( uint8_t serialize_tries = 0; serialize_tries < 2; serialize_tries++ ) // Try, allow for one reconnect, then try again
              {
                oncrpc_req.serialize( *conn );
                if ( conn->getStatus() == YIELD::SocketConnection::SCS_READY )
                {
                  for ( uint8_t deserialize_tries = 0; deserialize_tries < 2; deserialize_tries++ )
                  {
                    oncrpc_req.deserialize( *conn );
                    if ( conn->getStatus() == YIELD::SocketConnection::SCS_READY )
                    {
                      req.respond( static_cast<YIELD::Event&>( YIELD::SharedObject::incRef( *oncrpc_req.getInBody() ) ) );
                      YIELD::SharedObject::decRef( req );
                      return;
                    }
                    else if ( conn->getStatus() == YIELD::SocketConnection::SCS_CLOSED )
                      reconnect_tries_left = reconnect( original_timeout_ms, reconnect_tries_left );
                    else
                      YIELD::DebugBreak();
                  }
                }
                else if ( conn->getStatus() == YIELD::SocketConnection::SCS_CLOSED )
                  reconnect_tries_left = reconnect( original_timeout_ms, reconnect_tries_left );
                else
                  YIELD::DebugBreak();
              }
            }
            else // Non-blocking/timed
            {
              YIELD::SocketLib::setNonBlocking( conn->getSocket() );

              bool have_written = false; // Use the variable so the read and write attempt loops can be combined and eliminate some code duplication

              while ( true ) // Loop for read and write attempts
              {
                if ( !have_written )
                  oncrpc_req.serialize( *conn );
                else
                  oncrpc_req.deserialize( *conn );

                // Use if statements instead of a switch so the break after a successful read will exit the loop
                if ( conn->getStatus() == YIELD::SocketConnection::SCS_READY )
                {
                  if ( !have_written )
                    have_written = true;
                  else
                    break;
                }
                else if ( conn->getStatus() == YIELD::SocketConnection::SCS_CLOSED )
                  reconnect_tries_left = reconnect( original_timeout_ms, reconnect_tries_left );
                else if ( timeout_ms > 0 )
                {
                  bool enable_read = conn->getStatus() == YIELD::SocketConnection::SCS_BLOCKED_ON_READ;
                  fd_event_queue.toggleSocketEvent( conn->getSocket(), conn, enable_read, !enable_read );
                  double start_epoch_time_ms = YIELD::Time::getCurrentEpochTimeMS();
                  YIELD::FDEvent* fd_event = static_cast<YIELD::FDEvent*>( fd_event_queue.timed_dequeue( static_cast<YIELD::timeout_ns_t>( timeout_ms ) * NS_IN_MS ) );
                  if ( fd_event )
                  {
                    if ( fd_event->error_code == 0 )
                      timeout_ms -= std::min( static_cast<uint64_t>( YIELD::Time::getCurrentEpochTimeMS() - start_epoch_time_ms ), timeout_ms );
                    else
                      reconnect_tries_left = reconnect( original_timeout_ms, reconnect_tries_left );
                  }
                  else
                    throwExceptionEvent( new YIELD::PlatformExceptionEvent( ETIMEDOUT ) );
                }
                else
                  throwExceptionEvent( new YIELD::PlatformExceptionEvent( ETIMEDOUT ) );
              }
            }
          }
          catch ( YIELD::ExceptionEvent* exc_ev )
          {
            req.respond( *exc_ev );
            YIELD::SharedObject::decRef( req );
          }
        }
        break;

        default: YIELD::DebugBreak(); break;
      }
    }
    break;
  }
}

uint8_t Proxy::reconnect( uint64_t timeout_ms, uint8_t reconnect_tries_left )
{
  if ( peer_ip == 0 )
  {
    peer_ip = YIELD::SocketLib::resolveHost( uri.getHost() );
    if ( peer_ip == 0 && ( strcmp( uri.getHost(), "localhost" ) == 0 || strcmp( uri.getHost(), "127.0.0.1" ) == 0 ) )
      peer_ip = YIELD::SocketLib::resolveHost( YIELD::SocketLib::getLocalHostFQDN() );
    if ( peer_ip == 0 )
      throw new YIELD::PlatformExceptionEvent();
  }

  if ( conn != NULL ) // This is a reconnect, not the first connect
  {
    fd_event_queue.detachSocket( conn->getSocket(), conn );
    conn->close();
    delete conn;
    conn = NULL;
  }

  while ( reconnect_tries_left > 0 )
  {
    reconnect_tries_left--;

    // Create the conn object based on the URI type
    if ( strcmp( uri.getScheme(), "oncrpc" ) == 0 )
      conn = new YIELD::TCPConnection( peer_ip, uri.getPort(), NULL );
    else
      YIELD::DebugBreak();

    // Attach the socket to the fd_event_queue even if we're doing a blocking connect, in case a later read/write is non-blocking
    fd_event_queue.attachSocket( conn->getSocket(), conn, false, false ); // Attach without read or write notifications enabled

    // Now try the actual connect
    if ( timeout_ms == static_cast<uint64_t>( -1 ) ) // Blocking
    {
      YIELD::SocketLib::setBlocking( conn->getSocket() );

      if ( conn->connect() == YIELD::SocketConnection::SCS_READY )
        return reconnect_tries_left;
    }
    else // Non-blocking/timed
    {
      YIELD::SocketLib::setNonBlocking( conn->getSocket() );

      switch ( conn->connect() )
      {
        case YIELD::SocketConnection::SCS_READY: break;
        case YIELD::SocketConnection::SCS_BLOCKED_ON_WRITE:
        {
          fd_event_queue.toggleSocketEvent( conn->getSocket(), conn, false, true ); // Write readiness = the connect() operation is complete
          double start_epoch_time_ms = YIELD::Time::getCurrentEpochTimeMS();
          YIELD::FDEvent* fd_event = static_cast<YIELD::FDEvent*>( fd_event_queue.timed_dequeue( static_cast<YIELD::timeout_ns_t>( timeout_ms ) * NS_IN_MS ) );
          if ( fd_event && fd_event->error_code == 0 &&
               conn->connect() == YIELD::SocketConnection::SCS_READY )
          {
            fd_event_queue.toggleSocketEvent( conn->getSocket(), conn, false, false );
            return reconnect_tries_left;
          }
          else
          {
            timeout_ms -= std::min( static_cast<uint64_t>( YIELD::Time::getCurrentEpochTimeMS() - start_epoch_time_ms ), timeout_ms );
            if ( timeout_ms == 0 ) { reconnect_tries_left = 0; break; }
          }
        }
      }
    }

    // Clear the connection state for the next try
    fd_event_queue.detachSocket( conn->getSocket(), conn );
    conn->close();
    delete conn;
    conn = NULL;
  }

  unsigned long error_code = YIELD::PlatformException::errno_();
  if ( error_code == 0 )
    error_code = ETIMEDOUT;
  throw new YIELD::PlatformExceptionEvent( error_code );
}

void Proxy::throwExceptionEvent( YIELD::ExceptionEvent* exc_ev )
{
  if ( conn )
  {
    fd_event_queue.detachSocket( conn->getSocket(), conn );
    conn->close();
    delete conn;
    conn = NULL;
  }

  throw exc_ev;
}
<|endoftext|>


<commit_before>#include <cmath>
#include <cassert>
#include <cstdlib>
#include <iostream>
#include "World.H"
#include "Unit.H"

//May not need this inclusion
#include "World2.C"

using namespace std;

/* helper that you need to implement

 - move unit by current_speed * heading

 - units only collide with the map border

 - when units hit a wall they stop at the collision point (current_speed=0)
   and collision_hook is called with the previous speed and a vector of bools
   encoding the walls that were hit. This vector is used in collision_hook to
   implement bouncing by only changing the unit's heading, i.e. even when
   bouncing the unit stays at the collision location for the remainder of the
   simulation frame and only starts moving again in the following frame.

 - it is essential that units are located inside the map at all times. There
   can be no overlap. Ensure this property by clipping coordinates after
   moving.

*/

void World::move_unit(Unit &u)
{
  //Take unit speed multiply by heading to get new position
  double futureX = u.pos.x + (u.current_speed*u.heading.x);
  double futureY = u.pos.y + (u.current_speed*u.heading.y);
  //Extra space to leave for a collision. Compensates for rounding errors.
  double buffer = 0.1;
  //Collision occured flag
  bool collision = false;
  bool collisions[4] = {false, false, false, false};
    //double prev_speed = u.current_speed;

  //Check to see if movement would result in a collision
  if(futureX+u.radius+buffer >= width) {
    //Collision with Right wall
    futureX = width - u.radius - buffer;
    collision = true;
    collisions[1] = true;
  }
  if(futureX-u.radius-buffer <= 0) {
    //Collision with Left wall
    futureX = u.radius + buffer;
    collision = true;
    collisions[3] = true;
  }
  if(futureY+u.radius+buffer >= height) {
    //Collision with Bottom wall
    futureX = height - u.radius - buffer;
    collision = true;
    collisions[2] = true;
  }
  if(futureY-u.radius-buffer >= 0) {
    //Collision with Top wall
    futureX = u.radius + buffer;
    collision = true;
    collisions[0] = true;
  }

  if(collision) {
    u.collision_hook(u.current_speed, collisions);
    u.current_speed = 0;
  }

  //Update unit's position to new position
  u.pos = Vec2(futureX, futureY);

}

// returns policy name
const char *apol2str(AttackPolicy pol)
{
  switch (pol) {
    case ATTACK_WEAKEST:
      return "attack-weakest";
    case ATTACK_CLOSEST:
      return "attack-closest";
    case ATTACK_MOST_DANGEROUS:
      return "attack-most-dangerous";
  }
  return "?";
}

World::~World()
{
  // clean up

  // ... implement
}

// deducts hit points and calls attack_hook

void World::attack(Unit &attacker, Unit &attacked)
{
  //Reduce attacked unit's health by attack strength of attacker
  attacked.hp -= (int)attacker.damage;

  //Remove dead is handled by step in World2.C
}

// return a random position at which a circle of that radius fits

Vec2 World::rnd_pos(double radius) const
{
  double slack = radius * 2;

  Vec2 p((width  - 2*slack) * rnd01() + slack,
         (height - 2*slack) * rnd01() + slack);

  // assert circle in rectangle
  assert(p.x > radius && p.x < width - radius);
  assert(p.y > radius && p.y < height - radius);
  return p;
}

// return uniform random heading
// length of vector = 1
Vec2 World::rnd_heading() const
{
  // Generate random value between (0 and 2)*pi
  // This should preserve a uniform distribution as the 2*rnd01
  // transforms from an infinite set of points
  double angle = (this->rnd01())*2;

  // create Vec2 object with x = cos(angle), y = sin(angle)
  return Vec2(cos(angle), sin(angle));
}

// mirror position with respect to map mid-point
Vec2 World::mirror(const Vec2 &pos) const
{
  //Create Mid-point coordinates
  double midX = width/2;
  double midY = height/2;
  double newX;
  double newY;
  double diff;

  //Set new coordinate to position same distance from midpoint
  //but on the other side of said midpoint
  if(pos.x >= midX) {
    diff = pos.x - midX;
    newX = midX - diff;
  } else {
    diff = midX - pos.x;
    newX = midX + diff;
  }
  if(pos.y >= midY){
    diff = pos.y - midY;
    newY = midY - diff;
  } else {
    diff = midY - pos.y;
    newY = midY + diff;
  }

  //Create vector with new values and return it
  return Vec2(newX, newY);
}

// return squared distance between two unit centers
double World::distance2(const Unit &u, const Unit &v)
{
  return pow((v.pos.x - u.pos.x), 2) + pow((v.pos.y - u.pos.y), 2);
}

// return true iff u can attack v, i.e. distance of u's and v's centers is
// less than u's attack distance plus v's radius
bool World::can_attack(const Unit &u, const Unit &v)
{
  double dist = sqrt(distance2(u, v));

  if(dist <= u.attack_radius + v.radius){
    return true;
  } else {
    return false;
  }
}

// populate a vector with enemy units that can be attacked by u;
// clears vector first
void World::enemies_within_attack_range(const Unit &u,
                                        vector<Unit*> &targets) const
{
  targets.clear();

  //Append all units to vector
  for(auto &unit : units) {
    if(can_attack(u, *unit)) {
      if(unit->team != u.team){
        targets.push_back(unit);
      }
    }
  }
}

// return a random unit that can be attacked by u with minimal hp_old value,
// or 0 if none exists
Unit *World::random_weakest_target(Unit &u) const
{
  //Create list of possible targets
  vector<Unit*> targets;
  enemies_within_attack_range(u, targets);

  //If there are no available targets
  if(targets.size() ==0) {return 0;}

  //Search for unit with lowest hp
  Unit * lowest = targets[0];
  for(auto &unit: targets) {
    if(unit->hp < lowest->hp){
      lowest = unit;
    }
  }

  return lowest;
}

// return a random unit that can be attacked by u with minimal distance to
// u, or 0 if none exists

Unit *World::random_closest_target(Unit &u) const
{
  //Create list of possible targets
  vector<Unit*> targets;
  enemies_within_attack_range(u, targets);

  //If there are no available targets
  if(targets.size() == 0) {return 0;}

  //Search for unit with lowest distance
  Unit * closest = targets[0];
  for(auto &unit: targets) {
    if(distance2(u, *unit) < distance2(u, *closest)){
      closest = unit;
    }
  }

  return closest;
}

// return a random unit that can be attacked by u with maximal damage/hp_old
// ratio, or 0 if none exists
Unit *World::random_most_dangerous_target(Unit &u) const
{
  //Create list of possible targets
  vector<Unit*> targets;
  enemies_within_attack_range(u, targets);

  //If there are no available targets
  if(targets.size() ==0) {return 0;}

  //Search for unit with highest damage
  Unit * baddest = targets[0];
  for(auto &unit: targets) {
    if(unit->damage < baddest->damage){
      baddest = unit;
    }
  }

  return baddest;
}

// return score for red: 2 for win, 0 for loss, 1 for draw, -1 for game not
// over yet
int World::red_score() const
{
  //Flags for if red or blue units still exist
  bool red = false;
  bool blue = false;

  if (units.empty()) {
    return 1;
  }

  //Check all remaining units for team affiliations
  for(auto &unit : units){
    if(unit->team == Team::BLUE){
      blue = true;
    }
    if(unit->team == Team::RED){
      red = true;
    }
    //If there are at least one unit of each team game continues
    if(red && blue){return -1;}
  }

  //If in all the remaining units, none are red loss
  if(!red) {
    return 0;
  } else {
    return 2; //Otherwise return win!
  }

}

<commit_msg>Removed extra include of World2.C<commit_after>#include <cmath>
#include <cassert>
#include <cstdlib>
#include <iostream>
#include "World.H"
#include "Unit.H"

using namespace std;

/* helper that you need to implement

 - move unit by current_speed * heading

 - units only collide with the map border

 - when units hit a wall they stop at the collision point (current_speed=0)
   and collision_hook is called with the previous speed and a vector of bools
   encoding the walls that were hit. This vector is used in collision_hook to
   implement bouncing by only changing the unit's heading, i.e. even when
   bouncing the unit stays at the collision location for the remainder of the
   simulation frame and only starts moving again in the following frame.

 - it is essential that units are located inside the map at all times. There
   can be no overlap. Ensure this property by clipping coordinates after
   moving.

*/

void World::move_unit(Unit &u)
{
  //Take unit speed multiply by heading to get new position
  double futureX = u.pos.x + (u.current_speed*u.heading.x);
  double futureY = u.pos.y + (u.current_speed*u.heading.y);
  //Extra space to leave for a collision. Compensates for rounding errors.
  double buffer = 0.1;
  //Collision occured flag
  bool collision = false;
  bool collisions[4] = {false, false, false, false};
    //double prev_speed = u.current_speed;

  //Check to see if movement would result in a collision
  if(futureX+u.radius+buffer >= width) {
    //Collision with Right wall
    futureX = width - u.radius - buffer;
    collision = true;
    collisions[1] = true;
  }
  if(futureX-u.radius-buffer <= 0) {
    //Collision with Left wall
    futureX = u.radius + buffer;
    collision = true;
    collisions[3] = true;
  }
  if(futureY+u.radius+buffer >= height) {
    //Collision with Bottom wall
    futureX = height - u.radius - buffer;
    collision = true;
    collisions[2] = true;
  }
  if(futureY-u.radius-buffer >= 0) {
    //Collision with Top wall
    futureX = u.radius + buffer;
    collision = true;
    collisions[0] = true;
  }

  if(collision) {
    u.collision_hook(u.current_speed, collisions);
    u.current_speed = 0;
  }

  //Update unit's position to new position
  u.pos = Vec2(futureX, futureY);

}

// returns policy name
const char *apol2str(AttackPolicy pol)
{
  switch (pol) {
    case ATTACK_WEAKEST:
      return "attack-weakest";
    case ATTACK_CLOSEST:
      return "attack-closest";
    case ATTACK_MOST_DANGEROUS:
      return "attack-most-dangerous";
  }
  return "?";
}

World::~World()
{
  // clean up

  // ... implement
}

// deducts hit points and calls attack_hook

void World::attack(Unit &attacker, Unit &attacked)
{
  //Reduce attacked unit's health by attack strength of attacker
  attacked.hp -= (int)attacker.damage;

  //Remove dead is handled by step in World2.C
}

// return a random position at which a circle of that radius fits

Vec2 World::rnd_pos(double radius) const
{
  double slack = radius * 2;

  Vec2 p((width  - 2*slack) * rnd01() + slack,
         (height - 2*slack) * rnd01() + slack);

  // assert circle in rectangle
  assert(p.x > radius && p.x < width - radius);
  assert(p.y > radius && p.y < height - radius);
  return p;
}

// return uniform random heading
// length of vector = 1
Vec2 World::rnd_heading() const
{
  // Generate random value between (0 and 2)*pi
  // This should preserve a uniform distribution as the 2*rnd01
  // transforms from an infinite set of points
  double angle = (this->rnd01())*2;

  // create Vec2 object with x = cos(angle), y = sin(angle)
  return Vec2(cos(angle), sin(angle));
}

// mirror position with respect to map mid-point
Vec2 World::mirror(const Vec2 &pos) const
{
  //Create Mid-point coordinates
  double midX = width/2;
  double midY = height/2;
  double newX;
  double newY;
  double diff;

  //Set new coordinate to position same distance from midpoint
  //but on the other side of said midpoint
  if(pos.x >= midX) {
    diff = pos.x - midX;
    newX = midX - diff;
  } else {
    diff = midX - pos.x;
    newX = midX + diff;
  }
  if(pos.y >= midY){
    diff = pos.y - midY;
    newY = midY - diff;
  } else {
    diff = midY - pos.y;
    newY = midY + diff;
  }

  //Create vector with new values and return it
  return Vec2(newX, newY);
}

// return squared distance between two unit centers
double World::distance2(const Unit &u, const Unit &v)
{
  return pow((v.pos.x - u.pos.x), 2) + pow((v.pos.y - u.pos.y), 2);
}

// return true iff u can attack v, i.e. distance of u's and v's centers is
// less than u's attack distance plus v's radius
bool World::can_attack(const Unit &u, const Unit &v)
{
  double dist = sqrt(distance2(u, v));

  if(dist <= u.attack_radius + v.radius){
    return true;
  } else {
    return false;
  }
}

// populate a vector with enemy units that can be attacked by u;
// clears vector first
void World::enemies_within_attack_range(const Unit &u,
                                        vector<Unit*> &targets) const
{
  targets.clear();

  //Append all units to vector
  for(auto &unit : units) {
    if(can_attack(u, *unit)) {
      if(unit->team != u.team){
        targets.push_back(unit);
      }
    }
  }
}

// return a random unit that can be attacked by u with minimal hp_old value,
// or 0 if none exists
Unit *World::random_weakest_target(Unit &u) const
{
  //Create list of possible targets
  vector<Unit*> targets;
  enemies_within_attack_range(u, targets);

  //If there are no available targets
  if(targets.size() ==0) {return 0;}

  //Search for unit with lowest hp
  Unit * lowest = targets[0];
  for(auto &unit: targets) {
    if(unit->hp < lowest->hp){
      lowest = unit;
    }
  }

  return lowest;
}

// return a random unit that can be attacked by u with minimal distance to
// u, or 0 if none exists

Unit *World::random_closest_target(Unit &u) const
{
  //Create list of possible targets
  vector<Unit*> targets;
  enemies_within_attack_range(u, targets);

  //If there are no available targets
  if(targets.size() == 0) {return 0;}

  //Search for unit with lowest distance
  Unit * closest = targets[0];
  for(auto &unit: targets) {
    if(distance2(u, *unit) < distance2(u, *closest)){
      closest = unit;
    }
  }

  return closest;
}

// return a random unit that can be attacked by u with maximal damage/hp_old
// ratio, or 0 if none exists
Unit *World::random_most_dangerous_target(Unit &u) const
{
  //Create list of possible targets
  vector<Unit*> targets;
  enemies_within_attack_range(u, targets);

  //If there are no available targets
  if(targets.size() ==0) {return 0;}

  //Search for unit with highest damage
  Unit * baddest = targets[0];
  for(auto &unit: targets) {
    if(unit->damage < baddest->damage){
      baddest = unit;
    }
  }

  return baddest;
}

// return score for red: 2 for win, 0 for loss, 1 for draw, -1 for game not
// over yet
int World::red_score() const
{
  //Flags for if red or blue units still exist
  bool red = false;
  bool blue = false;

  if (units.empty()) {
    return 1;
  }

  //Check all remaining units for team affiliations
  for(auto &unit : units){
    if(unit->team == Team::BLUE){
      blue = true;
    }
    if(unit->team == Team::RED){
      red = true;
    }
    //If there are at least one unit of each team game continues
    if(red && blue){return -1;}
  }

  //If in all the remaining units, none are red loss
  if(!red) {
    return 0;
  } else {
    return 2; //Otherwise return win!
  }

}

<|endoftext|>