<commit_before>//===--- SwiftRemoteMirror.cpp - C wrapper for Reflection API -------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/Reflection/ReflectionContext.h"
#include "swift/Reflection/TypeLowering.h"
#include "swift/Remote/CMemoryReader.h"
#include "swift/Runtime/Unreachable.h"
#include "swift/SwiftRemoteMirror/SwiftRemoteMirror.h"
#include "swift/SwiftRemoteMirror/SwiftRemoteMirrorLegacyInterop.h"

#ifdef __APPLE__
#include <mach-o/getsect.h>
#endif

using namespace swift;
using namespace swift::reflection;
using namespace swift::remote;

using NativeReflectionContext
  = ReflectionContext<External<RuntimeTarget<sizeof(uintptr_t)>>>;

struct SwiftReflectionContext {
  NativeReflectionContext *nativeContext;

  SwiftReflectionContext(MemoryReaderImpl impl) {
    auto Reader = std::make_shared<CMemoryReader>(impl);
    nativeContext = new NativeReflectionContext(Reader);
  }

  ~SwiftReflectionContext() {
    delete nativeContext;
  }
};

uint16_t
swift_reflection_getSupportedMetadataVersion() {
  return SWIFT_REFLECTION_METADATA_VERSION;
}

SwiftReflectionContextRef
swift_reflection_createReflectionContext(void *ReaderContext,
                                         PointerSizeFunction getPointerSize,
                                         SizeSizeFunction getSizeSize,
                                         ReadBytesFunction readBytes,
                                         GetStringLengthFunction getStringLength,
                                         GetSymbolAddressFunction getSymbolAddress) {
  MemoryReaderImpl ReaderImpl {
    ReaderContext,
    getPointerSize,
    getSizeSize,
    readBytes,
    getStringLength,
    getSymbolAddress
  };

  return new SwiftReflectionContext(ReaderImpl);
}

void swift_reflection_destroyReflectionContext(SwiftReflectionContextRef ContextRef) {
  delete ContextRef;
}

void
swift_reflection_addReflectionInfo(SwiftReflectionContextRef ContextRef,
                                   swift_reflection_info_t Info) {
  auto Context = ContextRef->nativeContext;

  Context->addReflectionInfo(*reinterpret_cast<ReflectionInfo *>(&Info));
}

#ifdef __APPLE__
#ifndef __LP64__
typedef const struct mach_header MachHeader;
#else
typedef const struct mach_header_64 MachHeader;
#endif

template <typename Section>
static bool findSection(MachHeader *Header, const char *Name,
                        Section &Sect) {
  unsigned long Size;
  auto Address = getsectiondata(Header, "__TEXT", Name, &Size);
  if (!Address)
    return false;

  Sect.section.Begin = Address;
  auto End = reinterpret_cast<uintptr_t>(Address) + Size;
  Sect.section.End = reinterpret_cast<void *>(End);
  Sect.offset = 0;

  return true;
}

int
swift_reflection_addImage(SwiftReflectionContextRef ContextRef,
                          swift_addr_t imageStart, uint64_t imageLength) {
  auto Context = ContextRef->nativeContext;

  if (imageLength < sizeof(MachHeader)) {
    return 0;
  }

  auto Buf = malloc(imageLength);
  Context->getReader().readBytes(RemoteAddress(imageStart),
                                 reinterpret_cast<uint8_t *>(Buf),
                                 imageLength);

  auto Header = reinterpret_cast<MachHeader *>(Buf);
  if (Header->magic != MH_MAGIC && Header->magic != MH_MAGIC_64) {
    return 0;
  }

  swift_reflection_info_t info = {};

  // The docs say "not all sections may be present." We'll succeed if ANY of them are
  // present. Not sure if that's the right thing to do.
  bool success = false;
  success = findSection(Header, "__swift5_fieldmd", info.field) || success;
  success = findSection(Header, "__swift5_assocty", info.associated_types) || success;
  success = findSection(Header, "__swift5_builtin", info.builtin_types) || success;
  success = findSection(Header, "__swift5_capture", info.capture) || success;
  success = findSection(Header, "__swift5_typeref", info.type_references) || success;
  success = findSection(Header, "__swift5_reflstr", info.reflection_strings) || success;

  if (!success)
    return 0;

  info.LocalStartAddress = reinterpret_cast<uintptr_t>(Buf);
  info.RemoteStartAddress = imageStart;
  swift_reflection_addReflectionInfo(ContextRef, info);
  return 1;
}
#endif

int
swift_reflection_readIsaMask(SwiftReflectionContextRef ContextRef,
                             uintptr_t *outIsaMask) {
  auto Context = ContextRef->nativeContext;
  auto isaMask = Context->readIsaMask();
  if (isaMask) {
    *outIsaMask = *isaMask;
    return true;
  }
  *outIsaMask = 0;
  return false;
}

swift_typeref_t
swift_reflection_typeRefForMetadata(SwiftReflectionContextRef ContextRef,
                                    uintptr_t Metadata) {
  auto Context = ContextRef->nativeContext;
  auto TR = Context->readTypeFromMetadata(Metadata);
  return reinterpret_cast<swift_typeref_t>(TR);
}

swift_typeref_t
swift_reflection_typeRefForInstance(SwiftReflectionContextRef ContextRef,
                                    uintptr_t Object) {
  auto Context = ContextRef->nativeContext;
  auto MetadataAddress = Context->readMetadataFromInstance(Object);
  if (!MetadataAddress)
    return 0;
  auto TR = Context->readTypeFromMetadata(*MetadataAddress);
  return reinterpret_cast<swift_typeref_t>(TR);
}

swift_typeref_t
swift_reflection_typeRefForMangledTypeName(SwiftReflectionContextRef ContextRef,
                                           const char *MangledTypeName,
                                           uint64_t Length) {
  auto Context = ContextRef->nativeContext;
  auto TR = Context->readTypeFromMangledName(MangledTypeName, Length);
  return reinterpret_cast<swift_typeref_t>(TR);
}

swift_typeref_t
swift_reflection_genericArgumentOfTypeRef(swift_typeref_t OpaqueTypeRef,
                                          unsigned Index) {
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);

  if (auto BG = dyn_cast<BoundGenericTypeRef>(TR)) {
    auto &Params = BG->getGenericParams();
    assert(Index < Params.size());
    return reinterpret_cast<swift_typeref_t>(Params[Index]);
  }
  return 0;
}

unsigned
swift_reflection_genericArgumentCountOfTypeRef(swift_typeref_t OpaqueTypeRef) {
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);

  if (auto BG = dyn_cast<BoundGenericTypeRef>(TR)) {
    auto &Params = BG->getGenericParams();
    return Params.size();
  }
  return 0;
}

swift_layout_kind_t getTypeInfoKind(const TypeInfo &TI) {
  switch (TI.getKind()) {
  case TypeInfoKind::Builtin: {
    auto &BuiltinTI = cast<BuiltinTypeInfo>(TI);
    if (BuiltinTI.getMangledTypeName() == "Bp")
      return SWIFT_RAW_POINTER;
    return SWIFT_BUILTIN;
  }
  case TypeInfoKind::Record: {
    auto &RecordTI = cast<RecordTypeInfo>(TI);
    switch (RecordTI.getRecordKind()) {
    case RecordKind::Invalid:
      return SWIFT_UNKNOWN;
    case RecordKind::Tuple:
      return SWIFT_TUPLE;
    case RecordKind::Struct:
      return SWIFT_STRUCT;
    case RecordKind::NoPayloadEnum:
      return SWIFT_NO_PAYLOAD_ENUM;
    case RecordKind::SinglePayloadEnum:
      return SWIFT_SINGLE_PAYLOAD_ENUM;
    case RecordKind::MultiPayloadEnum:
      return SWIFT_MULTI_PAYLOAD_ENUM;
    case RecordKind::ThickFunction:
      return SWIFT_THICK_FUNCTION;
    case RecordKind::OpaqueExistential:
      return SWIFT_OPAQUE_EXISTENTIAL;
    case RecordKind::ClassExistential:
      return SWIFT_CLASS_EXISTENTIAL;
    case RecordKind::ErrorExistential:
      return SWIFT_ERROR_EXISTENTIAL;
    case RecordKind::ExistentialMetatype:
      return SWIFT_EXISTENTIAL_METATYPE;
    case RecordKind::ClassInstance:
      return SWIFT_CLASS_INSTANCE;
    case RecordKind::ClosureContext:
      return SWIFT_CLOSURE_CONTEXT;
    }
  }
  case TypeInfoKind::Reference: {
    auto &ReferenceTI = cast<ReferenceTypeInfo>(TI);
    switch (ReferenceTI.getReferenceKind()) {
    case ReferenceKind::Strong:
      return SWIFT_STRONG_REFERENCE;
    case ReferenceKind::Unowned:
      return SWIFT_UNOWNED_REFERENCE;
    case ReferenceKind::Weak:
      return SWIFT_WEAK_REFERENCE;
    case ReferenceKind::Unmanaged:
      return SWIFT_UNMANAGED_REFERENCE;
    }
  }
  }

  swift_runtime_unreachable("Unhandled TypeInfoKind in switch");
}

static swift_typeinfo_t convertTypeInfo(const TypeInfo *TI) {
  if (TI == nullptr) {
    return {
      SWIFT_UNKNOWN,
      0,
      0,
      0,
      0
    };
  }

  unsigned NumFields = 0;
  if (auto *RecordTI = dyn_cast<RecordTypeInfo>(TI))
    NumFields = RecordTI->getNumFields();

  return {
    getTypeInfoKind(*TI),
    TI->getSize(),
    TI->getAlignment(),
    TI->getStride(),
    NumFields
  };
}

static swift_childinfo_t convertChild(const TypeInfo *TI, unsigned Index) {
  auto *RecordTI = cast<RecordTypeInfo>(TI);
  auto &FieldInfo = RecordTI->getFields()[Index];

  return {
    FieldInfo.Name.c_str(),
    FieldInfo.Offset,
    getTypeInfoKind(FieldInfo.TI),
    reinterpret_cast<swift_typeref_t>(FieldInfo.TR),
  };
}

swift_typeinfo_t
swift_reflection_infoForTypeRef(SwiftReflectionContextRef ContextRef,
                                swift_typeref_t OpaqueTypeRef) {
  auto Context = ContextRef->nativeContext;
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
  auto TI = Context->getTypeInfo(TR);
  return convertTypeInfo(TI);
}

swift_childinfo_t
swift_reflection_childOfTypeRef(SwiftReflectionContextRef ContextRef,
                                swift_typeref_t OpaqueTypeRef,
                                unsigned Index) {
  auto Context = ContextRef->nativeContext;
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
  auto *TI = Context->getTypeInfo(TR);
  return convertChild(TI, Index);
}

swift_typeinfo_t
swift_reflection_infoForMetadata(SwiftReflectionContextRef ContextRef,
                                 uintptr_t Metadata) {
  auto Context = ContextRef->nativeContext;
  auto *TI = Context->getMetadataTypeInfo(Metadata);
  return convertTypeInfo(TI);
}

swift_childinfo_t
swift_reflection_childOfMetadata(SwiftReflectionContextRef ContextRef,
                                 uintptr_t Metadata,
                                 unsigned Index) {
  auto Context = ContextRef->nativeContext;
  auto *TI = Context->getMetadataTypeInfo(Metadata);
  return convertChild(TI, Index);
}

swift_typeinfo_t
swift_reflection_infoForInstance(SwiftReflectionContextRef ContextRef,
                                 uintptr_t Object) {
  auto Context = ContextRef->nativeContext;
  auto *TI = Context->getInstanceTypeInfo(Object);
  return convertTypeInfo(TI);
}

swift_childinfo_t
swift_reflection_childOfInstance(SwiftReflectionContextRef ContextRef,
                                 uintptr_t Object,
                                 unsigned Index) {
  auto Context = ContextRef->nativeContext;
  auto *TI = Context->getInstanceTypeInfo(Object);
  return convertChild(TI, Index);
}

int swift_reflection_projectExistential(SwiftReflectionContextRef ContextRef,
                                        swift_addr_t ExistentialAddress,
                                        swift_typeref_t ExistentialTypeRef,
                                        swift_typeref_t *InstanceTypeRef,
                                        swift_addr_t *StartOfInstanceData) {
  auto Context = ContextRef->nativeContext;
  auto ExistentialTR = reinterpret_cast<const TypeRef *>(ExistentialTypeRef);
  auto RemoteExistentialAddress = RemoteAddress(ExistentialAddress);
  const TypeRef *InstanceTR = nullptr;
  RemoteAddress RemoteStartOfInstanceData(nullptr);
  auto Success = Context->projectExistential(RemoteExistentialAddress,
                                             ExistentialTR,
                                             &InstanceTR,
                                             &RemoteStartOfInstanceData);

  if (Success) {
    *InstanceTypeRef = reinterpret_cast<swift_typeref_t>(InstanceTR);
    *StartOfInstanceData = RemoteStartOfInstanceData.getAddressData();
  }

  return Success;
}

void swift_reflection_dumpTypeRef(swift_typeref_t OpaqueTypeRef) {
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
  if (TR == nullptr) {
    std::cout << "<null type reference>\n";
  } else {
    TR->dump(std::cout);
  }
}

void swift_reflection_dumpInfoForTypeRef(SwiftReflectionContextRef ContextRef,
                                         swift_typeref_t OpaqueTypeRef) {
  auto Context = ContextRef->nativeContext;
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
  auto TI = Context->getTypeInfo(TR);
  if (TI == nullptr) {
    std::cout << "<null type info>\n";
  } else {
    TI->dump(std::cout);
  }
}

void swift_reflection_dumpInfoForMetadata(SwiftReflectionContextRef ContextRef,
                                          uintptr_t Metadata) {
  auto Context = ContextRef->nativeContext;
  auto TI = Context->getMetadataTypeInfo(Metadata);
  if (TI == nullptr) {
    std::cout << "<null type info>\n";
  } else {
    TI->dump(std::cout);
  }
}

void swift_reflection_dumpInfoForInstance(SwiftReflectionContextRef ContextRef,
                                          uintptr_t Object) {
  auto Context = ContextRef->nativeContext;
  auto TI = Context->getInstanceTypeInfo(Object);
  if (TI == nullptr) {
    std::cout << "<null type info>\n";
  } else {
    TI->dump(std::cout);
  }
}

size_t swift_reflection_demangle(const char *MangledName, size_t Length,
                                 char *OutDemangledName, size_t MaxLength) {
  if (MangledName == nullptr || Length == 0)
    return 0;

  std::string Mangled(MangledName, Length);
  auto Demangled = Demangle::demangleTypeAsString(Mangled);
  strncpy(OutDemangledName, Demangled.c_str(), MaxLength);
  return Demangled.size();
}
<commit_msg>[Reflection] Track the memory returned from readBytes calls in addImage and free it when destroying the context.<commit_after>//===--- SwiftRemoteMirror.cpp - C wrapper for Reflection API -------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/Reflection/ReflectionContext.h"
#include "swift/Reflection/TypeLowering.h"
#include "swift/Remote/CMemoryReader.h"
#include "swift/Runtime/Unreachable.h"
#include "swift/SwiftRemoteMirror/SwiftRemoteMirror.h"
#include "swift/SwiftRemoteMirror/SwiftRemoteMirrorLegacyInterop.h"

#ifdef __APPLE__
#include <mach-o/getsect.h>
#endif

using namespace swift;
using namespace swift::reflection;
using namespace swift::remote;

using NativeReflectionContext
  = ReflectionContext<External<RuntimeTarget<sizeof(uintptr_t)>>>;

struct SwiftReflectionContext {
  NativeReflectionContext *nativeContext;
  std::vector<std::function<void()>> freeFuncs;

  SwiftReflectionContext(MemoryReaderImpl impl) {
    auto Reader = std::make_shared<CMemoryReader>(impl);
    nativeContext = new NativeReflectionContext(Reader);
  }

  ~SwiftReflectionContext() {
    delete nativeContext;
    for (auto f : freeFuncs)
      f();
  }
};

uint16_t
swift_reflection_getSupportedMetadataVersion() {
  return SWIFT_REFLECTION_METADATA_VERSION;
}

SwiftReflectionContextRef
swift_reflection_createReflectionContext(void *ReaderContext,
                                         PointerSizeFunction getPointerSize,
                                         SizeSizeFunction getSizeSize,
                                         ReadBytesFunction readBytes,
                                         GetStringLengthFunction getStringLength,
                                         GetSymbolAddressFunction getSymbolAddress) {
  MemoryReaderImpl ReaderImpl {
    ReaderContext,
    getPointerSize,
    getSizeSize,
    readBytes,
    getStringLength,
    getSymbolAddress
  };

  return new SwiftReflectionContext(ReaderImpl);
}

void swift_reflection_destroyReflectionContext(SwiftReflectionContextRef ContextRef) {
  delete ContextRef;
}

void
swift_reflection_addReflectionInfo(SwiftReflectionContextRef ContextRef,
                                   swift_reflection_info_t Info) {
  auto Context = ContextRef->nativeContext;

  Context->addReflectionInfo(*reinterpret_cast<ReflectionInfo *>(&Info));
}

#ifdef __APPLE__
#ifndef __LP64__
typedef const struct mach_header MachHeader;
#else
typedef const struct mach_header_64 MachHeader;
#endif

template <typename Section>
static bool findSection(MachHeader *Header, const char *Name,
                        Section &Sect) {
  unsigned long Size;
  auto Address = getsectiondata(Header, "__TEXT", Name, &Size);
  if (!Address)
    return false;

  Sect.section.Begin = Address;
  auto End = reinterpret_cast<uintptr_t>(Address) + Size;
  Sect.section.End = reinterpret_cast<void *>(End);
  Sect.offset = 0;

  return true;
}

int
swift_reflection_addImage(SwiftReflectionContextRef ContextRef,
                          swift_addr_t imageStart, uint64_t imageLength) {
  auto Context = ContextRef->nativeContext;

  if (imageLength < sizeof(MachHeader)) {
    return 0;
  }

  const void *Buf;
  std::function<void()> FreeFunc;
  std::tie(Buf, FreeFunc) = Context->getReader().readBytes(RemoteAddress(imageStart),
                                                           imageLength);
  if (Buf == nullptr) {
    return 0;
  }

  ContextRef->freeFuncs.push_back(FreeFunc);

  auto Header = reinterpret_cast<MachHeader *>(Buf);
  if (Header->magic != MH_MAGIC && Header->magic != MH_MAGIC_64) {
    return 0;
  }

  swift_reflection_info_t info = {};

  // The docs say "not all sections may be present." We'll succeed if ANY of them are
  // present. Not sure if that's the right thing to do.
  bool success = false;
  success = findSection(Header, "__swift5_fieldmd", info.field) || success;
  success = findSection(Header, "__swift5_assocty", info.associated_types) || success;
  success = findSection(Header, "__swift5_builtin", info.builtin_types) || success;
  success = findSection(Header, "__swift5_capture", info.capture) || success;
  success = findSection(Header, "__swift5_typeref", info.type_references) || success;
  success = findSection(Header, "__swift5_reflstr", info.reflection_strings) || success;

  if (!success)
    return 0;

  info.LocalStartAddress = reinterpret_cast<uintptr_t>(Buf);
  info.RemoteStartAddress = imageStart;
  swift_reflection_addReflectionInfo(ContextRef, info);
  return 1;
}
#endif

int
swift_reflection_readIsaMask(SwiftReflectionContextRef ContextRef,
                             uintptr_t *outIsaMask) {
  auto Context = ContextRef->nativeContext;
  auto isaMask = Context->readIsaMask();
  if (isaMask) {
    *outIsaMask = *isaMask;
    return true;
  }
  *outIsaMask = 0;
  return false;
}

swift_typeref_t
swift_reflection_typeRefForMetadata(SwiftReflectionContextRef ContextRef,
                                    uintptr_t Metadata) {
  auto Context = ContextRef->nativeContext;
  auto TR = Context->readTypeFromMetadata(Metadata);
  return reinterpret_cast<swift_typeref_t>(TR);
}

swift_typeref_t
swift_reflection_typeRefForInstance(SwiftReflectionContextRef ContextRef,
                                    uintptr_t Object) {
  auto Context = ContextRef->nativeContext;
  auto MetadataAddress = Context->readMetadataFromInstance(Object);
  if (!MetadataAddress)
    return 0;
  auto TR = Context->readTypeFromMetadata(*MetadataAddress);
  return reinterpret_cast<swift_typeref_t>(TR);
}

swift_typeref_t
swift_reflection_typeRefForMangledTypeName(SwiftReflectionContextRef ContextRef,
                                           const char *MangledTypeName,
                                           uint64_t Length) {
  auto Context = ContextRef->nativeContext;
  auto TR = Context->readTypeFromMangledName(MangledTypeName, Length);
  return reinterpret_cast<swift_typeref_t>(TR);
}

swift_typeref_t
swift_reflection_genericArgumentOfTypeRef(swift_typeref_t OpaqueTypeRef,
                                          unsigned Index) {
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);

  if (auto BG = dyn_cast<BoundGenericTypeRef>(TR)) {
    auto &Params = BG->getGenericParams();
    assert(Index < Params.size());
    return reinterpret_cast<swift_typeref_t>(Params[Index]);
  }
  return 0;
}

unsigned
swift_reflection_genericArgumentCountOfTypeRef(swift_typeref_t OpaqueTypeRef) {
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);

  if (auto BG = dyn_cast<BoundGenericTypeRef>(TR)) {
    auto &Params = BG->getGenericParams();
    return Params.size();
  }
  return 0;
}

swift_layout_kind_t getTypeInfoKind(const TypeInfo &TI) {
  switch (TI.getKind()) {
  case TypeInfoKind::Builtin: {
    auto &BuiltinTI = cast<BuiltinTypeInfo>(TI);
    if (BuiltinTI.getMangledTypeName() == "Bp")
      return SWIFT_RAW_POINTER;
    return SWIFT_BUILTIN;
  }
  case TypeInfoKind::Record: {
    auto &RecordTI = cast<RecordTypeInfo>(TI);
    switch (RecordTI.getRecordKind()) {
    case RecordKind::Invalid:
      return SWIFT_UNKNOWN;
    case RecordKind::Tuple:
      return SWIFT_TUPLE;
    case RecordKind::Struct:
      return SWIFT_STRUCT;
    case RecordKind::NoPayloadEnum:
      return SWIFT_NO_PAYLOAD_ENUM;
    case RecordKind::SinglePayloadEnum:
      return SWIFT_SINGLE_PAYLOAD_ENUM;
    case RecordKind::MultiPayloadEnum:
      return SWIFT_MULTI_PAYLOAD_ENUM;
    case RecordKind::ThickFunction:
      return SWIFT_THICK_FUNCTION;
    case RecordKind::OpaqueExistential:
      return SWIFT_OPAQUE_EXISTENTIAL;
    case RecordKind::ClassExistential:
      return SWIFT_CLASS_EXISTENTIAL;
    case RecordKind::ErrorExistential:
      return SWIFT_ERROR_EXISTENTIAL;
    case RecordKind::ExistentialMetatype:
      return SWIFT_EXISTENTIAL_METATYPE;
    case RecordKind::ClassInstance:
      return SWIFT_CLASS_INSTANCE;
    case RecordKind::ClosureContext:
      return SWIFT_CLOSURE_CONTEXT;
    }
  }
  case TypeInfoKind::Reference: {
    auto &ReferenceTI = cast<ReferenceTypeInfo>(TI);
    switch (ReferenceTI.getReferenceKind()) {
    case ReferenceKind::Strong:
      return SWIFT_STRONG_REFERENCE;
    case ReferenceKind::Unowned:
      return SWIFT_UNOWNED_REFERENCE;
    case ReferenceKind::Weak:
      return SWIFT_WEAK_REFERENCE;
    case ReferenceKind::Unmanaged:
      return SWIFT_UNMANAGED_REFERENCE;
    }
  }
  }

  swift_runtime_unreachable("Unhandled TypeInfoKind in switch");
}

static swift_typeinfo_t convertTypeInfo(const TypeInfo *TI) {
  if (TI == nullptr) {
    return {
      SWIFT_UNKNOWN,
      0,
      0,
      0,
      0
    };
  }

  unsigned NumFields = 0;
  if (auto *RecordTI = dyn_cast<RecordTypeInfo>(TI))
    NumFields = RecordTI->getNumFields();

  return {
    getTypeInfoKind(*TI),
    TI->getSize(),
    TI->getAlignment(),
    TI->getStride(),
    NumFields
  };
}

static swift_childinfo_t convertChild(const TypeInfo *TI, unsigned Index) {
  auto *RecordTI = cast<RecordTypeInfo>(TI);
  auto &FieldInfo = RecordTI->getFields()[Index];

  return {
    FieldInfo.Name.c_str(),
    FieldInfo.Offset,
    getTypeInfoKind(FieldInfo.TI),
    reinterpret_cast<swift_typeref_t>(FieldInfo.TR),
  };
}

swift_typeinfo_t
swift_reflection_infoForTypeRef(SwiftReflectionContextRef ContextRef,
                                swift_typeref_t OpaqueTypeRef) {
  auto Context = ContextRef->nativeContext;
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
  auto TI = Context->getTypeInfo(TR);
  return convertTypeInfo(TI);
}

swift_childinfo_t
swift_reflection_childOfTypeRef(SwiftReflectionContextRef ContextRef,
                                swift_typeref_t OpaqueTypeRef,
                                unsigned Index) {
  auto Context = ContextRef->nativeContext;
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
  auto *TI = Context->getTypeInfo(TR);
  return convertChild(TI, Index);
}

swift_typeinfo_t
swift_reflection_infoForMetadata(SwiftReflectionContextRef ContextRef,
                                 uintptr_t Metadata) {
  auto Context = ContextRef->nativeContext;
  auto *TI = Context->getMetadataTypeInfo(Metadata);
  return convertTypeInfo(TI);
}

swift_childinfo_t
swift_reflection_childOfMetadata(SwiftReflectionContextRef ContextRef,
                                 uintptr_t Metadata,
                                 unsigned Index) {
  auto Context = ContextRef->nativeContext;
  auto *TI = Context->getMetadataTypeInfo(Metadata);
  return convertChild(TI, Index);
}

swift_typeinfo_t
swift_reflection_infoForInstance(SwiftReflectionContextRef ContextRef,
                                 uintptr_t Object) {
  auto Context = ContextRef->nativeContext;
  auto *TI = Context->getInstanceTypeInfo(Object);
  return convertTypeInfo(TI);
}

swift_childinfo_t
swift_reflection_childOfInstance(SwiftReflectionContextRef ContextRef,
                                 uintptr_t Object,
                                 unsigned Index) {
  auto Context = ContextRef->nativeContext;
  auto *TI = Context->getInstanceTypeInfo(Object);
  return convertChild(TI, Index);
}

int swift_reflection_projectExistential(SwiftReflectionContextRef ContextRef,
                                        swift_addr_t ExistentialAddress,
                                        swift_typeref_t ExistentialTypeRef,
                                        swift_typeref_t *InstanceTypeRef,
                                        swift_addr_t *StartOfInstanceData) {
  auto Context = ContextRef->nativeContext;
  auto ExistentialTR = reinterpret_cast<const TypeRef *>(ExistentialTypeRef);
  auto RemoteExistentialAddress = RemoteAddress(ExistentialAddress);
  const TypeRef *InstanceTR = nullptr;
  RemoteAddress RemoteStartOfInstanceData(nullptr);
  auto Success = Context->projectExistential(RemoteExistentialAddress,
                                             ExistentialTR,
                                             &InstanceTR,
                                             &RemoteStartOfInstanceData);

  if (Success) {
    *InstanceTypeRef = reinterpret_cast<swift_typeref_t>(InstanceTR);
    *StartOfInstanceData = RemoteStartOfInstanceData.getAddressData();
  }

  return Success;
}

void swift_reflection_dumpTypeRef(swift_typeref_t OpaqueTypeRef) {
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
  if (TR == nullptr) {
    std::cout << "<null type reference>\n";
  } else {
    TR->dump(std::cout);
  }
}

void swift_reflection_dumpInfoForTypeRef(SwiftReflectionContextRef ContextRef,
                                         swift_typeref_t OpaqueTypeRef) {
  auto Context = ContextRef->nativeContext;
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
  auto TI = Context->getTypeInfo(TR);
  if (TI == nullptr) {
    std::cout << "<null type info>\n";
  } else {
    TI->dump(std::cout);
  }
}

void swift_reflection_dumpInfoForMetadata(SwiftReflectionContextRef ContextRef,
                                          uintptr_t Metadata) {
  auto Context = ContextRef->nativeContext;
  auto TI = Context->getMetadataTypeInfo(Metadata);
  if (TI == nullptr) {
    std::cout << "<null type info>\n";
  } else {
    TI->dump(std::cout);
  }
}

void swift_reflection_dumpInfoForInstance(SwiftReflectionContextRef ContextRef,
                                          uintptr_t Object) {
  auto Context = ContextRef->nativeContext;
  auto TI = Context->getInstanceTypeInfo(Object);
  if (TI == nullptr) {
    std::cout << "<null type info>\n";
  } else {
    TI->dump(std::cout);
  }
}

size_t swift_reflection_demangle(const char *MangledName, size_t Length,
                                 char *OutDemangledName, size_t MaxLength) {
  if (MangledName == nullptr || Length == 0)
    return 0;

  std::string Mangled(MangledName, Length);
  auto Demangled = Demangle::demangleTypeAsString(Mangled);
  strncpy(OutDemangledName, Demangled.c_str(), MaxLength);
  return Demangled.size();
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * Project: BaBar detector at the SLAC PEP-II B-factory
 * Package: RooFitTools
 *    File: $Id: RooExtendPdf.cc,v 1.2 2001/10/10 17:59:01 verkerke Exp $
 * Authors:
 *   DK, David Kirkby, Stanford University, kirkby@hep.stanford.edu
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu
 * History:
 *   10-Oct-2001 WV Created initial version
 *
 * Copyright (C) 2000 University of California
 *****************************************************************************/

// -- CLASS DESCRIPTION [PDF] --
//  RooExtendPdf is a wrappper around an existing PDF that adds a
//  parameteric extended likelihood term to the PDF, optionally multiplied by a
//  fractional term from a partial normalization of the PDF:
//
//  nExpected = N   _or Expected = N * frac
//
//  where N is supplied as a RooAbsReal to RooExtendPdf.
//  The fractional term is defined as
//                          _       _ _   _  _
//            Int(cutRegion[x]) pdf(x,y) dx dy
//     frac = ---------------_-------_-_---_--_
//            Int(normRegion[x]) pdf(x,y) dx dy
//
//        _                                                               _
//  where x is the set of dependents involved in the selection region and y
//  is the set of remaining dependents.
//            _
//  cutRegion[x] is an limited integration range that is contained in
//  the nominal integration range normRegion[x[]
//

#include "RooFitCore/RooExtendPdf.hh"
#include "RooFitCore/RooArgList.hh"
#include "RooFitCore/RooRealVar.hh"
#include "RooFitCore/RooFormulaVar.hh"

ClassImp(RooExtendPdf)
;

RooExtendPdf::RooExtendPdf(const char *name, const char *title, const RooAbsPdf& pdf,
			   const RooAbsReal& norm) :
  RooAbsPdf(name,title),
  _pdf("pdf","PDF",this,(RooAbsReal&)pdf),
  _n("n","Normalization",this,(RooAbsReal&)norm),
  _cutDepSet("cutDepSet","Set of dependent with fractional range",this),
  _origDepSet("origDepSet","Set of dependent with full integration range",this),
  _lastFracSet(0),
  _fracIntegral(0),
  _integralCompSet(0),
  _useFrac(kFALSE)
{
  // Constructor. The ExtendedPdf behaves identical to the supplied input pdf,
  // but adds an extended likelihood term. The expected number of events return
  // is 'norm'

  // Copy various setting from pdf
//   setPlotRange(_pdf.arg().getPlotMin(),_pdf.arg().getPlotMax()) ;
//   setPlotBins(_pdf.arg().getPlotBins()) ;
  setUnit(_pdf.arg().getUnit()) ;
  setPlotLabel(_pdf.arg().getPlotLabel()) ;
}

RooExtendPdf::RooExtendPdf(const char *name, const char *title, const RooAbsPdf& pdf,
			   const RooAbsReal& norm, const RooArgList& depList,
			   const RooArgList& cutDepList) :
  RooAbsPdf(name,title),
  _pdf("pdf","PDF",this,(RooAbsReal&)pdf),
  _n("n","Normalization",this,(RooAbsReal&)norm),
  _cutDepSet("cutDepSet","Set of dependent with fractional range",this),
  _origDepSet("origDepSet","Set of dependent with full integration range",this),
  _lastFracSet(0),
  _fracIntegral(0),
  _integralCompSet(0),
  _useFrac(kTRUE)
{
  // Constructor. The ExtendedPdf behaves identical to the supplied input pdf,
  // but adds an extended likelihood term. The expected number of events return
  // is 'norm' multiplied by a normalization fraction from the pdf.
  //
  // The dimensions of the cut region should be listed in 'depList'.
  // The reduced integration range for each dimension in 'depList' should be expressed
  // in the fit range of a dummy RooRealVar in each matching slot in 'cutDepList'
  //
  // For example, the following code
  //
  //   RooRealVar x("x","x",-10,10)
  //   RooExamplePdf pdf("pdf","pdf",x)
  //
  //   RooRealVar nevt("nevt","number of expected events")
  //   RooRealVar xcut("xcut","xcut",-3,3)
  //   RooExtendPdf epdf("epdf","...",pdf,nevt,x,cut)
  //
  // constructs an extended pdf with the number of expected events as
  //
  //   nExpected = nevt * Int(-3,3)pdf(x)dx / Int(-10,10)pdf(x)dx
  //

  // Check if dependent and replacement list have same length
  if (depList.getSize() != cutDepList.getSize()) {
    cout << "RooExtendPdf::ctor(" << GetName()
	 << ") list of cut dependents and their replacements must have equal length" << endl ;
    assert(0) ;
  }

  // Copy various setting from pdf
//   setPlotRange(_pdf.arg().getPlotMin(),_pdf.arg().getPlotMax()) ;
//   setPlotBins(_pdf.arg().getPlotBins()) ;
  setUnit(_pdf.arg().getUnit()) ;
  setPlotLabel(_pdf.arg().getPlotLabel()) ;

  // Loop over all dependents to be cut on
  TIterator* dIter = depList.createIterator() ;
  TIterator* cIter = cutDepList.createIterator() ;
  RooAbsArg* dep, *cutDep ;
  while(dep=(RooAbsArg*)dIter->Next()) {
    cutDep= (RooAbsArg*)cIter->Next() ;

    // Check if original and replacement variable are both real lvalues
    RooAbsRealLValue* orig = dynamic_cast<RooAbsRealLValue*>(dep) ;
    RooAbsRealLValue* repl = dynamic_cast<RooAbsRealLValue*>(cutDep) ;
    if (!orig || !repl) {
      cout << "RooExtendPdf::ctor(" << GetName() << "): ERROR: " << dep->GetName() << " and "
	   << cutDep->GetName() << " must be both RooAbsRealLValues, this pair ignored" << endl ;
      continue ;
    }

    // Check if fraction range is fully contained in integration range
    if (repl->getFitMin()<orig->getFitMin() || repl->getFitMax()>orig->getFitMax()) {
      cout << "RooExtendPdf::ctor(" << GetName() << "): WARNING: fit range of "
	   << repl->GetName() << " is not fully contained in " << orig->GetName() << endl ;
    }

    // Affix appropriate name-changing server attribute to each cut variable
    TString origNameLabel("ORIGNAME:") ;
    origNameLabel.Append(orig->GetName()) ;
    repl->setAttribute(origNameLabel,kTRUE);
  }

  // Store cut dependents
  _cutDepSet.add(cutDepList) ;
  _origDepSet.add(depList) ;
}

RooExtendPdf::RooExtendPdf(const RooExtendPdf& other, const char* name) :
  RooAbsPdf(other,name),
  _pdf("pdf",this,other._pdf),
  _n("n",this,other._n),
  _cutDepSet("cutDepSet",this,other._cutDepSet),
  _origDepSet("origDepSet",this,other._origDepSet),
  _lastFracSet(0),
  _fracIntegral(0),
  _integralCompSet(0),
  _useFrac(other._useFrac)
{
  // Copy constructor
}

RooExtendPdf::~RooExtendPdf()
{
  // Destructor

  // Delete any owned components
  if (_fracIntegral) {
    delete _integralCompSet ;
  }
}

Double_t RooExtendPdf::expectedEvents() const
{
  // Return the number of expected events, which is
  //
  // n / [ Int(xC,yF) pdf(x,y) / Int(xF,yF) pdf(x,y) ]
  //
  // Where x is the set of dependents with cuts defined
  // and y are the other dependents. xC is the integration
  // of x over the cut range, xF is the integration of
  // x over the full range.

  // Use current PDF normalization, if defined, use cut set otherwise
  const RooArgSet* npset = ((RooAbsPdf&)_pdf.arg())._lastNormSet ;
  const RooArgSet* nset = npset ? npset : (const RooArgSet*) &_origDepSet ;

  Double_t normInt = ((RooAbsPdf&)_pdf.arg()).getNorm(nset) ;

  // Update fraction integral
  syncFracIntegral() ;

  // Evaluate fraction integral and return normalized by full integral
  Double_t fracInt = _fracIntegral->getVal() ;
  if ( fracInt == 0. || normInt == 0. || _n == 0.) {
    cout << "RooExtendPdf(" << GetName() << ") WARNING: nExpected = " << _n << " / ( "
	 << fracInt << " / " << normInt << " ), for nset = " ;
    if (nset) nset->Print("1") ; else cout << "<none>" << endl ;
  }
  return  _n / ( fracInt / normInt ) ;
}

void RooExtendPdf::syncFracIntegral() const
{
  // Create the fraction integral by clone the
  // PDFs normalization integral and replacing
  // the regular dependents in the clone by
  // the internal set of dependents that specify
  // a more restrictive integration range

  RooAbsPdf& pdf = (RooAbsPdf&) _pdf.arg() ;

  // Check first if any changes are needed
  if (_lastFracSet == pdf._lastNormSet) return ;
  _lastFracSet = pdf._lastNormSet ;

  // Delete existing integral
  if (_fracIntegral) {
    delete _integralCompSet ;
  }

  // Make list of all nodes that need to be cloned:
  // All PDF branch nodes, and the RooRealIntegral object itself
  RooArgSet pdfNodeList ;
  pdf.branchNodeServerList(&pdfNodeList) ;

  //Check if PDF has dummy normalization
  if (dynamic_cast<RooRealIntegral*>(pdf._norm)) {

    // If not, clone original integral and add to owned set
    pdfNodeList.add(*pdf._norm) ;
    _integralCompSet = (RooArgSet*) pdfNodeList.snapshot(kFALSE) ;
    _fracIntegral = (RooRealIntegral*) _integralCompSet->find(pdf._norm->GetName()) ;

    // Replace dependents involved in cut with internal set
    _fracIntegral->recursiveRedirectServers(_cutDepSet,kFALSE,kTRUE) ;

  } else {
    // If dummy, make both normalization and fraction integral here

    // Cannot dereference _lastFracSet since it may be a dangling ptr
    // Recreate a similar argset by inflating the name set
    RooArgSet pdfLeafList ;
    pdf.leafNodeServerList(&pdfLeafList) ;
    const RooArgSet* fracNormSet = pdf._lastNameSet.select(pdfLeafList) ;

    TString fname(pdf.GetName()) ; fname.Append("FracNorm") ;
    TString ftitle(pdf.GetTitle()) ; ftitle.Append(" Fraction Integral") ;

    // Create fractional integral from PDF clone
    _integralCompSet = (RooArgSet*) pdfNodeList.snapshot(kFALSE) ;
    RooAbsPdf* pdfClone = (RooAbsPdf*) _integralCompSet->find(pdf.GetName()) ;
    _fracIntegral = new RooRealIntegral(fname,ftitle,*pdfClone,*fracNormSet) ;
    _integralCompSet->addOwned(*_fracIntegral) ;

    // Replace dependents involved in fractional with internal set
    _fracIntegral->recursiveRedirectServers(_cutDepSet,kFALSE,kTRUE) ;

    TString nname(pdf.GetName()) ; nname.Append("Norm") ;
    TString ntitle(pdf.GetTitle()) ; ntitle.Append(" Integral") ;

    TString rname(pdf.GetName()) ; rname.Append("FracRatio") ;
    TString rtitle(pdf.GetTitle()) ; rtitle.Append(" Integral Ratio") ;

    // Create full normalization integral
    RooRealIntegral* normIntegral = new RooRealIntegral(nname,ntitle,pdf,*fracNormSet) ;
    RooFormulaVar* ratio= new RooFormulaVar(rname,rtitle,"@0/@1",RooArgList(*_fracIntegral,*normIntegral)) ;
    _integralCompSet->addOwned(*normIntegral) ;
    _integralCompSet->addOwned(*ratio) ;
    _fracIntegral = ratio ;

    delete fracNormSet ;
  }
}

void RooExtendPdf::getParametersHook(const RooArgSet* nset, RooArgSet* list) const
{
  // Remove fake dependents from list
  list->remove(_cutDepSet,kTRUE,kTRUE) ;
}

void RooExtendPdf::getDependentsHook(const RooArgSet* nset, RooArgSet* list) const
{
  // Remove fake dependents from list
  list->remove(_cutDepSet,kTRUE,kTRUE) ;
}
<commit_msg><commit_after>/*****************************************************************************
 * Project: BaBar detector at the SLAC PEP-II B-factory
 * Package: RooFitTools
 *    File: $Id: RooExtendPdf.cc,v 1.3 2001/11/19 07:23:56 verkerke Exp $
 * Authors:
 *   DK, David Kirkby, Stanford University, kirkby@hep.stanford.edu
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu
 * History:
 *   10-Oct-2001 WV Created initial version
 *
 * Copyright (C) 2000 University of California
 *****************************************************************************/

// -- CLASS DESCRIPTION [PDF] --
//  RooExtendPdf is a wrappper around an existing PDF that adds a
//  parameteric extended likelihood term to the PDF, optionally multiplied by a
//  fractional term from a partial normalization of the PDF:
//
//  nExpected = N   _or Expected = N * frac
//
//  where N is supplied as a RooAbsReal to RooExtendPdf.
//  The fractional term is defined as
//                          _       _ _   _  _
//            Int(cutRegion[x]) pdf(x,y) dx dy
//     frac = ---------------_-------_-_---_--_
//            Int(normRegion[x]) pdf(x,y) dx dy
//
//        _                                                               _
//  where x is the set of dependents involved in the selection region and y
//  is the set of remaining dependents.
//            _
//  cutRegion[x] is an limited integration range that is contained in
//  the nominal integration range normRegion[x[]
//

#include "RooFitCore/RooExtendPdf.hh"
#include "RooFitCore/RooArgList.hh"
#include "RooFitCore/RooRealVar.hh"
#include "RooFitCore/RooFormulaVar.hh"

ClassImp(RooExtendPdf)
;

RooExtendPdf::RooExtendPdf(const char *name, const char *title, const RooAbsPdf& pdf,
			   const RooAbsReal& norm) :
  RooAbsPdf(name,title),
  _pdf("pdf","PDF",this,(RooAbsReal&)pdf),
  _n("n","Normalization",this,(RooAbsReal&)norm),
  _cutDepSet("cutDepSet","Set of dependent with fractional range",this),
  _origDepSet("origDepSet","Set of dependent with full integration range",this),
  _lastFracSet(0),
  _fracIntegral(0),
  _integralCompSet(0),
  _useFrac(kFALSE)
{
  // Constructor. The ExtendedPdf behaves identical to the supplied input pdf,
  // but adds an extended likelihood term. The expected number of events return
  // is 'norm'

  // Copy various setting from pdf
//   setPlotRange(_pdf.arg().getPlotMin(),_pdf.arg().getPlotMax()) ;
//   setPlotBins(_pdf.arg().getPlotBins()) ;
  setUnit(_pdf.arg().getUnit()) ;
  setPlotLabel(_pdf.arg().getPlotLabel()) ;
}

RooExtendPdf::RooExtendPdf(const char *name, const char *title, const RooAbsPdf& pdf,
			   const RooAbsReal& norm, const RooArgList& depList,
			   const RooArgList& cutDepList) :
  RooAbsPdf(name,title),
  _pdf("pdf","PDF",this,(RooAbsReal&)pdf),
  _n("n","Normalization",this,(RooAbsReal&)norm),
  _cutDepSet("cutDepSet","Set of dependent with fractional range",this),
  _origDepSet("origDepSet","Set of dependent with full integration range",this),
  _lastFracSet(0),
  _fracIntegral(0),
  _integralCompSet(0),
  _useFrac(kTRUE)
{
  // Constructor. The ExtendedPdf behaves identical to the supplied input pdf,
  // but adds an extended likelihood term. The expected number of events return
  // is 'norm' multiplied by a normalization fraction from the pdf.
  //
  // The dimensions of the cut region should be listed in 'depList'.
  // The reduced integration range for each dimension in 'depList' should be expressed
  // in the fit range of a dummy RooRealVar in each matching slot in 'cutDepList'
  //
  // For example, the following code
  //
  //   RooRealVar x("x","x",-10,10)
  //   RooExamplePdf pdf("pdf","pdf",x)
  //
  //   RooRealVar nevt("nevt","number of expected events")
  //   RooRealVar xcut("xcut","xcut",-3,3)
  //   RooExtendPdf epdf("epdf","...",pdf,nevt,x,cut)
  //
  // constructs an extended pdf with the number of expected events as
  //
  //   nExpected = nevt * Int(-3,3)pdf(x)dx / Int(-10,10)pdf(x)dx
  //

  // Check if dependent and replacement list have same length
  if (depList.getSize() != cutDepList.getSize()) {
    cout << "RooExtendPdf::ctor(" << GetName()
	 << ") list of cut dependents and their replacements must have equal length" << endl ;
    assert(0) ;
  }

  // Copy various setting from pdf
//   setPlotRange(_pdf.arg().getPlotMin(),_pdf.arg().getPlotMax()) ;
//   setPlotBins(_pdf.arg().getPlotBins()) ;
  setUnit(_pdf.arg().getUnit()) ;
  setPlotLabel(_pdf.arg().getPlotLabel()) ;

  // Loop over all dependents to be cut on
  TIterator* dIter = depList.createIterator() ;
  TIterator* cIter = cutDepList.createIterator() ;
  RooAbsArg* dep, *cutDep ;
  while(dep=(RooAbsArg*)dIter->Next()) {
    cutDep= (RooAbsArg*)cIter->Next() ;

    // Check if original and replacement variable are both real lvalues
    RooAbsRealLValue* orig = dynamic_cast<RooAbsRealLValue*>(dep) ;
    RooAbsRealLValue* repl = dynamic_cast<RooAbsRealLValue*>(cutDep) ;
    if (!orig || !repl) {
      cout << "RooExtendPdf::ctor(" << GetName() << "): ERROR: " << dep->GetName() << " and "
	   << cutDep->GetName() << " must be both RooAbsRealLValues, this pair ignored" << endl ;
      continue ;
    }

    // Check if fraction range is fully contained in integration range
    if (repl->getFitMin()<orig->getFitMin() || repl->getFitMax()>orig->getFitMax()) {
      cout << "RooExtendPdf::ctor(" << GetName() << "): WARNING: fit range of "
	   << repl->GetName() << " is not fully contained in " << orig->GetName() << endl ;
    }

    // Affix appropriate name-changing server attribute to each cut variable
    TString origNameLabel("ORIGNAME:") ;
    origNameLabel.Append(orig->GetName()) ;
    repl->setAttribute(origNameLabel,kTRUE);
  }

  // Store cut dependents
  _cutDepSet.add(cutDepList) ;
  _origDepSet.add(depList) ;
}

RooExtendPdf::RooExtendPdf(const RooExtendPdf& other, const char* name) :
  RooAbsPdf(other,name),
  _pdf("pdf",this,other._pdf),
  _n("n",this,other._n),
  _cutDepSet("cutDepSet",this,other._cutDepSet),
  _origDepSet("origDepSet",this,other._origDepSet),
  _lastFracSet(0),
  _fracIntegral(0),
  _integralCompSet(0),
  _useFrac(other._useFrac)
{
  // Copy constructor
}

RooExtendPdf::~RooExtendPdf()
{
  // Destructor

  // Delete any owned components
  if (_fracIntegral) {
    delete _integralCompSet ;
  }
}

Double_t RooExtendPdf::expectedEvents() const
{
  // Return the number of expected events, which is
  //
  // n / [ Int(xC,yF) pdf(x,y) / Int(xF,yF) pdf(x,y) ]
  //
  // Where x is the set of dependents with cuts defined
  // and y are the other dependents. xC is the integration
  // of x over the cut range, xF is the integration of
  // x over the full range.

  RooAbsPdf& pdf = (RooAbsPdf&)_pdf.arg() ;

  Double_t nExp = _n ;

  // Optionally multiply with fractional normalization
  if (_useFrac) {
    // Use current PDF normalization, if defined, use cut set otherwise
    const RooArgSet* npset = pdf._lastNormSet ;
    const RooArgSet* nset = npset ? npset : (const RooArgSet*) &_origDepSet ;

    Double_t normInt = pdf.getNorm(nset) ;

    // Update fraction integral
    syncFracIntegral() ;

    // Evaluate fraction integral and return normalized by full integral
    Double_t fracInt = _fracIntegral->getVal() ;
    if ( fracInt == 0. || normInt == 0. || _n == 0.) {
      cout << "RooExtendPdf(" << GetName() << ") WARNING: nExpected = " << _n << " / ( "
	   << fracInt << " / " << normInt << " ), for nset = " ;
      if (nset) nset->Print("1") ; else cout << "<none>" << endl ;
    }

    nExp *= (fracInt / normInt) ;
  }

  // Multiply with original Nexpected, if defined
  if (pdf.canBeExtended()) nExp *= pdf.expectedEvents() ;

  return nExp ;
}

void RooExtendPdf::syncFracIntegral() const
{
  // Create the fraction integral by clone the
  // PDFs normalization integral and replacing
  // the regular dependents in the clone by
  // the internal set of dependents that specify
  // a more restrictive integration range

  RooAbsPdf& pdf = (RooAbsPdf&) _pdf.arg() ;

  // Check first if any changes are needed
  if (_lastFracSet == pdf._lastNormSet) return ;
  _lastFracSet = pdf._lastNormSet ;

  // Delete existing integral
  if (_fracIntegral) {
    delete _integralCompSet ;
  }

  // Make list of all nodes that need to be cloned:
  // All PDF branch nodes, and the RooRealIntegral object itself
  RooArgSet pdfNodeList ;
  pdf.branchNodeServerList(&pdfNodeList) ;

  //Check if PDF has dummy normalization
  if (dynamic_cast<RooRealIntegral*>(pdf._norm)) {

    // If not, clone original integral and add to owned set
    pdfNodeList.add(*pdf._norm) ;
    _integralCompSet = (RooArgSet*) pdfNodeList.snapshot(kFALSE) ;
    _fracIntegral = (RooRealIntegral*) _integralCompSet->find(pdf._norm->GetName()) ;

    // Replace dependents involved in cut with internal set
    _fracIntegral->recursiveRedirectServers(_cutDepSet,kFALSE,kTRUE) ;

  } else {
    // If dummy, make both normalization and fraction integral here

    // Cannot dereference _lastFracSet since it may be a dangling ptr
    // Recreate a similar argset by inflating the name set
    RooArgSet pdfLeafList ;
    pdf.leafNodeServerList(&pdfLeafList) ;
    const RooArgSet* fracNormSet = pdf._lastNameSet.select(pdfLeafList) ;

    TString fname(pdf.GetName()) ; fname.Append("FracNorm") ;
    TString ftitle(pdf.GetTitle()) ; ftitle.Append(" Fraction Integral") ;

    // Create fractional integral from PDF clone
    _integralCompSet = (RooArgSet*) pdfNodeList.snapshot(kFALSE) ;
    RooAbsPdf* pdfClone = (RooAbsPdf*) _integralCompSet->find(pdf.GetName()) ;
    _fracIntegral = new RooRealIntegral(fname,ftitle,*pdfClone,*fracNormSet) ;
    _integralCompSet->addOwned(*_fracIntegral) ;

    // Replace dependents involved in fractional with internal set
    _fracIntegral->recursiveRedirectServers(_cutDepSet,kFALSE,kTRUE) ;

    TString nname(pdf.GetName()) ; nname.Append("Norm") ;
    TString ntitle(pdf.GetTitle()) ; ntitle.Append(" Integral") ;

    TString rname(pdf.GetName()) ; rname.Append("FracRatio") ;
    TString rtitle(pdf.GetTitle()) ; rtitle.Append(" Integral Ratio") ;

    // Create full normalization integral
    RooRealIntegral* normIntegral = new RooRealIntegral(nname,ntitle,pdf,*fracNormSet) ;
    RooFormulaVar* ratio= new RooFormulaVar(rname,rtitle,"@0/@1",RooArgList(*_fracIntegral,*normIntegral)) ;
    _integralCompSet->addOwned(*normIntegral) ;
    _integralCompSet->addOwned(*ratio) ;
    _fracIntegral = ratio ;

    delete fracNormSet ;
  }
}

void RooExtendPdf::getParametersHook(const RooArgSet* nset, RooArgSet* list) const
{
  // Remove fake dependents from list
  list->remove(_cutDepSet,kTRUE,kTRUE) ;
}

void RooExtendPdf::getDependentsHook(const RooArgSet* nset, RooArgSet* list) const
{
  // Remove fake dependents from list
  list->remove(_cutDepSet,kTRUE,kTRUE) ;
}
<|endoftext|>


<commit_before>#include <disco/disco.h>

int main()
{
    sys = System("double pendulum");
    N = sys.newtonianFrame();
    RigidBody::Ptr link1 = sys.bodyNew("link1");

    Meters diameter(1.0);
    Meters length(1.0);
    CylinderBody::Ptr link1 = CylinderBody("link1", Kilograms(1.0), diameter,
            length);
    CylinderBody::Ptr link2 = CylinderBody("link2", Kilograms(1.0), diameter,
            length);

    link1.massIs(Kilograms(1.0));
    link1.centerOfMassIs(Position(N.origin(), Vector(0.0)));
    link1.inertiaTensorIs(
            CylinderInertiaTensor(Position(), Frame));

    link2.massIs(Kilograms(1.0));
    link2.centerOfMassIs(Position());

    sys.bodyNew(link1);
    sys.bodyNew(link2);

    // Can't use factory function here; b/c Joint will have subclasses.
    RevoluteJoint::Ptr groundLink1 = new RevoluteJoint("groundLink1",
            TODObaseBody,
            N,
            link1,
            link1.frame());

    RevoluteJoint::Ptr link1Link2 = new RevoluteJoint("link1Link2",
            link1,
            Frame(Position(link1.origin(), length * link1.frame().x()),
                EulerXYZ(link1.orientation(), 0, 0, 0)),
            link2,
            link2.frame());

    sys.jointNew(groundLink1); // TODO how come you don't need to do this in
    // OpenSim?
    sys.jointNew(link1Link2);

    // TODO something with states, to set initial state?
    Simulation::Ptr sim("sim1");
    sim.timeIs(Seconds(5.0));
    // TODO what is getting populated when this call is made?
    // TODO where do the states live?

            Frame(Position(N.origin(), Vector(0.0)), EulerXYZ(0, 0, 0)),
            Frame(Position(link1.frame.origin()
            Position(N.origin(), Vector(0.0)),

    Fram

    This is NOT like MotionGenesis because here we define a system using joints.

    link1

}
<commit_msg>Sketch out how to make a kinematic tree.<commit_after>#include <disco/disco.h>

int main()
{
    sys = System("double pendulum");
    N = sys.newtonianFrame();
    RigidBody::Ptr link1 = sys.bodyNew("link1");

    Meters diameter(1.0);
    Meters length(1.0);
    CylinderBody::Ptr link1 = CylinderBody("link1", Kilograms(1.0), diameter,
            length);
    CylinderBody::Ptr link2 = CylinderBody("link2", Kilograms(1.0), diameter,
            length);

    link1.massIs(Kilograms(1.0));
    link1.centerOfMassIs(Position(N.origin(), Vector(0.0)));
    link1.inertiaTensorIs(
            CylinderInertiaTensor(Position(), Frame));

    link2.massIs(Kilograms(1.0));
    link2.centerOfMassIs(Position());

    sys.bodyNew(link1);
    sys.bodyNew(link2);

    // Can't use factory function here; b/c Joint will have subclasses.
    RevoluteJoint::Ptr groundLink1 = new RevoluteJoint("groundLink1",
            TODObaseBody,
            N,
            link1,
            link1.frame());

    RevoluteJoint::Ptr link1Link2 = new RevoluteJoint("link1Link2",
            link1,
            Frame(Position(link1.origin(), length * link1.frame().x()),
                EulerXYZ(link1.orientation(), 0, 0, 0)),
            link2,
            link2.frame());

    sys.jointNew(groundLink1); // TODO how come you don't need to do this in
    // OpenSim?
    sys.jointNew(link1Link2);

    // TODO something with states, to set initial state?
    Simulation::Ptr sim("sim1");
    sim.timeIs(Seconds(5.0));
    // TODO what is getting populated when this call is made?
    // TODO where do the states live?

            Frame(Position(N.origin(), Vector(0.0)), EulerXYZ(0, 0, 0)),
            Frame(Position(link1.frame.origin()
            Position(N.origin(), Vector(0.0)),

    Fram

    This is NOT like MotionGenesis because here we define a system using joints.

    link1

    sys = System("double pendulum");
    N = sys.newtonianFrame();
    RigidBody::Ptr link1 = sys.bodyNew("link1");
    link1.jointIs(new RevoluteJoint());

    RigidBody::Ptr link2 = link1.bodyNew("link2");
    link2.jointIs(new RevoluteJoint());

    Meters diameter(1.0);
    Meters length(1.0);
    CylinderBody::Ptr link1 = CylinderBody("link1", Kilograms(1.0), diameter,
            length);
    CylinderBody::Ptr link2 = CylinderBody("link2", Kilograms(1.0), diameter,
            length);

<|endoftext|>


<commit_before>/*
  Copyright (c) 2014-2017 DataStax

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include "future.hpp"

#include "external.hpp"
#include "prepared.hpp"
#include "request_handler.hpp"
#include "result_response.hpp"
#include "scoped_ptr.hpp"

extern "C" {

void cass_future_free(CassFuture* future) {
  // Futures can be deleted without being waited on
  // because they'll be cleaned up by the notifying thread
  future->dec_ref();
}

CassError cass_future_set_callback(CassFuture* future,
                                   CassFutureCallback callback,
                                   void* data) {
  if (!future->set_callback(callback, data)) {
    return CASS_ERROR_LIB_CALLBACK_ALREADY_SET;
  }
  return CASS_OK;
}

cass_bool_t cass_future_ready(CassFuture* future) {
  return static_cast<cass_bool_t>(future->ready());
}

void cass_future_wait(CassFuture* future) {
  future->wait();
}

cass_bool_t cass_future_wait_timed(CassFuture* future, cass_duration_t wait_us) {
  return static_cast<cass_bool_t>(future->wait_for(wait_us));
}

const CassResult* cass_future_get_result(CassFuture* future) {
  if (future->type() != cass::CASS_FUTURE_TYPE_RESPONSE) {
    return NULL;
  }

  cass::Response::Ptr response(
        static_cast<cass::ResponseFuture*>(future->from())->response());
  if (!response || response->opcode() == CQL_OPCODE_ERROR) {
    return NULL;
  }

  response->inc_ref();
  return CassResult::to(
        static_cast<cass::ResultResponse*>(response.get()));
}

const CassPrepared* cass_future_get_prepared(CassFuture* future) {
  if (future->type() != cass::CASS_FUTURE_TYPE_RESPONSE) {
    return NULL;
  }
  cass::ResponseFuture* response_future =
      static_cast<cass::ResponseFuture*>(future->from());

  cass::SharedRefPtr<cass::ResultResponse> result(response_future->response());
  if (!result || result->kind() != CASS_RESULT_KIND_PREPARED) {
    return NULL;
  }

  cass::Prepared* prepared = cass::Memory::allocate<cass::Prepared>(result,
                                                                    response_future->statement,
                                                                    *response_future->schema_metadata);
  prepared->inc_ref();
  return CassPrepared::to(prepared);
}

const CassErrorResult* cass_future_get_error_result(CassFuture* future) {
  if (future->type() != cass::CASS_FUTURE_TYPE_RESPONSE) {
    return NULL;
  }

  cass::Response::Ptr response(
        static_cast<cass::ResponseFuture*>(future->from())->response());
  if (!response || response->opcode() != CQL_OPCODE_ERROR) {
    return NULL;
  }

  response->inc_ref();
  return CassErrorResult::to(
        static_cast<cass::ErrorResponse*>(response.get()));
}

CassError cass_future_error_code(CassFuture* future) {
  const cass::Future::Error* error = future->error();
  if (error != NULL) {
    return error->code;
  } else {
    return CASS_OK;
  }
}

void cass_future_error_message(CassFuture* future,
                               const char** message,
                               size_t* message_length) {
  const cass::Future::Error* error = future->error();
  if (error != NULL) {
    const cass::String& m = error->message;
    *message = m.data();
    *message_length = m.length();
  } else {
    *message = "";
    *message_length = 0;
  }
}

size_t cass_future_custom_payload_item_count(CassFuture* future) {
  if (future->type() != cass::CASS_FUTURE_TYPE_RESPONSE) {
    return 0;
  }
  cass::Response::Ptr response(
        static_cast<cass::ResponseFuture*>(future->from())->response());
  if (!response) return 0;
  return response->custom_payload().size();
}

CassError cass_future_custom_payload_item(CassFuture* future,
                                          size_t index,
                                          const char** name,
                                          size_t* name_length,
                                          const cass_byte_t** value,
                                          size_t* value_size) {
  if (future->type() != cass::CASS_FUTURE_TYPE_RESPONSE) {
    return CASS_ERROR_LIB_INVALID_FUTURE_TYPE;
  }
  cass::Response::Ptr response(
        static_cast<cass::ResponseFuture*>(future->from())->response());
  if (!response) return CASS_ERROR_LIB_NO_CUSTOM_PAYLOAD;

  const cass::CustomPayloadVec& custom_payload =
      response->custom_payload();
  if (index >= custom_payload.size()) {
    return CASS_ERROR_LIB_INDEX_OUT_OF_BOUNDS;
  }

  const cass::CustomPayloadItem& item = custom_payload[index];
  *name = item.name.data();
  *name_length = item.name.size();
  *value = reinterpret_cast<const cass_byte_t*>(item.value.data());
  *value_size = item.value.size();
  return CASS_OK;
}

} // extern "C"

namespace cass {

bool Future::set_callback(Future::Callback callback, void* data) {
  ScopedMutex lock(&mutex_);
  if (callback_) {
    return false; // Callback is already set
  }
  callback_ = callback;
  data_ = data;
  if (is_set_) {
    // Run the callback if the future is already set
    lock.unlock();
    callback(CassFuture::to(this), data);
  }
  return true;
}

void Future::internal_set(ScopedMutex& lock) {
  is_set_ = true;
  uv_cond_broadcast(&cond_);
  if (callback_) {
    Callback callback = callback_;
    void* data = data_;
    lock.unlock();
    callback(CassFuture::to(this), data);
  }
}

} // namespace cass

<commit_msg>CPP-514 - Future is signaled before its callback is called<commit_after>/*
  Copyright (c) 2014-2017 DataStax

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include "future.hpp"

#include "external.hpp"
#include "prepared.hpp"
#include "request_handler.hpp"
#include "result_response.hpp"
#include "scoped_ptr.hpp"

extern "C" {

void cass_future_free(CassFuture* future) {
  // Futures can be deleted without being waited on
  // because they'll be cleaned up by the notifying thread
  future->dec_ref();
}

CassError cass_future_set_callback(CassFuture* future,
                                   CassFutureCallback callback,
                                   void* data) {
  if (!future->set_callback(callback, data)) {
    return CASS_ERROR_LIB_CALLBACK_ALREADY_SET;
  }
  return CASS_OK;
}

cass_bool_t cass_future_ready(CassFuture* future) {
  return static_cast<cass_bool_t>(future->ready());
}

void cass_future_wait(CassFuture* future) {
  future->wait();
}

cass_bool_t cass_future_wait_timed(CassFuture* future, cass_duration_t wait_us) {
  return static_cast<cass_bool_t>(future->wait_for(wait_us));
}

const CassResult* cass_future_get_result(CassFuture* future) {
  if (future->type() != cass::CASS_FUTURE_TYPE_RESPONSE) {
    return NULL;
  }

  cass::Response::Ptr response(
        static_cast<cass::ResponseFuture*>(future->from())->response());
  if (!response || response->opcode() == CQL_OPCODE_ERROR) {
    return NULL;
  }

  response->inc_ref();
  return CassResult::to(
        static_cast<cass::ResultResponse*>(response.get()));
}

const CassPrepared* cass_future_get_prepared(CassFuture* future) {
  if (future->type() != cass::CASS_FUTURE_TYPE_RESPONSE) {
    return NULL;
  }
  cass::ResponseFuture* response_future =
      static_cast<cass::ResponseFuture*>(future->from());

  cass::SharedRefPtr<cass::ResultResponse> result(response_future->response());
  if (!result || result->kind() != CASS_RESULT_KIND_PREPARED) {
    return NULL;
  }

  cass::Prepared* prepared = cass::Memory::allocate<cass::Prepared>(result,
                                                                    response_future->statement,
                                                                    *response_future->schema_metadata);
  prepared->inc_ref();
  return CassPrepared::to(prepared);
}

const CassErrorResult* cass_future_get_error_result(CassFuture* future) {
  if (future->type() != cass::CASS_FUTURE_TYPE_RESPONSE) {
    return NULL;
  }

  cass::Response::Ptr response(
        static_cast<cass::ResponseFuture*>(future->from())->response());
  if (!response || response->opcode() != CQL_OPCODE_ERROR) {
    return NULL;
  }

  response->inc_ref();
  return CassErrorResult::to(
        static_cast<cass::ErrorResponse*>(response.get()));
}

CassError cass_future_error_code(CassFuture* future) {
  const cass::Future::Error* error = future->error();
  if (error != NULL) {
    return error->code;
  } else {
    return CASS_OK;
  }
}

void cass_future_error_message(CassFuture* future,
                               const char** message,
                               size_t* message_length) {
  const cass::Future::Error* error = future->error();
  if (error != NULL) {
    const cass::String& m = error->message;
    *message = m.data();
    *message_length = m.length();
  } else {
    *message = "";
    *message_length = 0;
  }
}

size_t cass_future_custom_payload_item_count(CassFuture* future) {
  if (future->type() != cass::CASS_FUTURE_TYPE_RESPONSE) {
    return 0;
  }
  cass::Response::Ptr response(
        static_cast<cass::ResponseFuture*>(future->from())->response());
  if (!response) return 0;
  return response->custom_payload().size();
}

CassError cass_future_custom_payload_item(CassFuture* future,
                                          size_t index,
                                          const char** name,
                                          size_t* name_length,
                                          const cass_byte_t** value,
                                          size_t* value_size) {
  if (future->type() != cass::CASS_FUTURE_TYPE_RESPONSE) {
    return CASS_ERROR_LIB_INVALID_FUTURE_TYPE;
  }
  cass::Response::Ptr response(
        static_cast<cass::ResponseFuture*>(future->from())->response());
  if (!response) return CASS_ERROR_LIB_NO_CUSTOM_PAYLOAD;

  const cass::CustomPayloadVec& custom_payload =
      response->custom_payload();
  if (index >= custom_payload.size()) {
    return CASS_ERROR_LIB_INDEX_OUT_OF_BOUNDS;
  }

  const cass::CustomPayloadItem& item = custom_payload[index];
  *name = item.name.data();
  *name_length = item.name.size();
  *value = reinterpret_cast<const cass_byte_t*>(item.value.data());
  *value_size = item.value.size();
  return CASS_OK;
}

} // extern "C"

namespace cass {

bool Future::set_callback(Future::Callback callback, void* data) {
  ScopedMutex lock(&mutex_);
  if (callback_) {
    return false; // Callback is already set
  }
  callback_ = callback;
  data_ = data;
  if (is_set_) {
    // Run the callback if the future is already set
    lock.unlock();
    callback(CassFuture::to(this), data);
  }
  return true;
}

void Future::internal_set(ScopedMutex& lock) {
  is_set_ = true;
  if (callback_) {
    Callback callback = callback_;
    void* data = data_;
    lock.unlock();
    callback(CassFuture::to(this), data);
    lock.lock();
  }
  // Broadcast after we've run the callback so that threads waiting
  // on this future see the side effects of the callback.
  uv_cond_broadcast(&cond_);
}

} // namespace cass

<|endoftext|>


<commit_before>
#include "daemon.h"

#include <QString>
#include <QFile>
#include <QTextStream>
#include <QMap>
#include <QList>
#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlError>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QProcess>
#include <QUuid>
#include <QRegExp>

namespace adjd {

	void writeToLog(adjd::config &cnf, QString strMsg)
	{
		QFile file(cnf.strLogFile);
		if ( file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append))
        {
			QDateTime dateTime = QDateTime::currentDateTime();
			QString dateTimeString = dateTime.toString("[yyyy-MMM-dd hh:mm:ss] ");

            QTextStream stream( &file );
            stream << dateTimeString << strMsg << endl;
            file.close();
        }
	}

	struct tables_ {
		QList<QMap<QString,QString> > services;
		QList<QMap<QString,QString> > teams;
	};

	bool getInfoTeamsAndServices(adjd::config &cnf, adjd::tables_ &tabl)
	{
		QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
		db.setHostName("localhost");
		db.setDatabaseName(cnf.db_name);
		db.setUserName(cnf.db_user);
		db.setPassword(cnf.db_pass);
		if (!db.open()){
			writeToLog(cnf, db.lastError().text());
			writeToLog(cnf, "Failed to connect.");
			return false;
		}

		// services
		{
			QSqlQuery query(db);
			query.exec("SELECT * FROM services");
			while (query.next()) {
				QSqlRecord record = query.record();
				QMap<QString,QString> map;
				for(int index = 0; index < record.count(); ++index) {
					QString key = record.fieldName(index);
					map.insert(key, record.value(index).toString());
				}
				tabl.services << map;
			}
		}

		// teams
		{
			QSqlQuery query(db);
			query.exec("SELECT * FROM teams");
			while (query.next()) {
				QSqlRecord record = query.record();
				QMap<QString,QString> map;
				for(int index = 0; index < record.count(); ++index) {
					QString key = record.fieldName(index);
					map.insert(key, record.value(index).toString());
				}
				tabl.teams << map;
			}
		}

		return true;
	}

	void insertToFlags(adjd::config &cnf, QString id_service, QString id_team_owner, QString flag, QString id_team_passed)
	{
		QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
		db.setHostName("localhost");
		db.setDatabaseName(cnf.db_name);
		db.setUserName(cnf.db_user);
		db.setPassword(cnf.db_pass);
		if (!db.open()){
			writeToLog(cnf, db.lastError().text());
			writeToLog(cnf, "Failed to connect.");
			return;
		}

		QDateTime dateTime = QDateTime::currentDateTime();
		QString dateTimeString1 = dateTime.toString("yyyy-MM-dd hh:mm:ss");

		dateTime.addSecs(600); // add 10 minutes. it is live of flag
		QString dateTimeString2 = dateTime.toString("yyyy-MM-dd hh:mm:ss");

		QSqlQuery query(db);
		QString strQuery = "INSERT INTO flags(id_service,flag,id_team_owner, dt_start, dt_end, id_team_passed) VALUES("
			+ id_service + ", "
			+ "'" + flag + "', "
			+ id_team_owner + ", "
			+ "'" + dateTimeString1 + "', "
			+ "'" + dateTimeString2 + "', "
			+ id_team_passed
		+ ");";
		writeToLog(cnf, "strQuery = " + strQuery);
		query.exec(strQuery);
		return;
	}

	int attackDefenceJuryDaemon(adjd::config &cnf)
	{
		while(1) {
			for(int i = 0; i < 20; i++)
			{
				writeToLog(cnf, "run checkers");
				adjd::tables_ tabl;
				if( getInfoTeamsAndServices(cnf, tabl) )
				{
					for(int ti = 0; ti < tabl.teams.count(); ti++)
					{
						QString team_name = tabl.teams[ti]["name"];
						QString team_ip = tabl.teams[ti]["ip_address"];
						QString team_id = tabl.teams[ti]["id"];

						for(int si = 0; si < tabl.services.count(); si++)
						{
							QString service_id = tabl.services[si]["id"];
							QString service_name = tabl.services[si]["name"];
							QString service_scriptpath = tabl.services[si]["scriptpath"];
							QString flag = QUuid::createUuid().toString();
							flag = flag.mid(1,flag.length()-2);

							if(QFile(service_scriptpath).exists())
							{
								QStringList args;
								args << team_ip << "store" << flag;
								QProcess p;
								p.start(service_scriptpath, args);
								p.waitForFinished(3000);

								QString p_stdout = p.readAllStandardOutput();
								QString p_stderr = p.readAllStandardError();

								if(p_stderr.length() > 0)
								{
									writeToLog(cnf, "Error in call checker: '" + service_scriptpath + "' p_stderr = " + p_stderr);
								}
								else
								{
									QString p_output = p_stdout.toUpper();
									QRegExp rx_work("\\[SERVICE IS WORK\\]");
									QRegExp rx_corrupt("\\[SERVICE IS CORRUPT\\]");

									if(rx_work.lastIndexIn(p_output) != -1)
									{
										insertToFlags(cnf, service_id, team_id, flag, "0");
										// writeToLog(cnf, service_name + ":" + team_name + " => service is work");
									}
									else if (rx_corrupt.lastIndexIn(p_output) != -1)
									{
										insertToFlags(cnf, service_id, team_id, flag, "-1");
										// writeToLog(cnf, service_name + ":" + team_name + " => service is corrupt");
									}
									else
									{
										writeToLog(cnf, service_name + ":" + team_name + " => (not found [service is work] or [service is corrupt] and you have only 3 sec),\np_stdout =\n" + p_stdout);
									}
								}
							}
							else
							{
								writeToLog(cnf, "team " + team_name + " (ip : " + team_ip + ") for service '" + service_name + "' script not found, script path: " + service_scriptpath);
							}
						}
					};
				};
				sleep(15);//wait 15 secund
			}
			sleep(300);//wait 5 minutes
		}
		return 0;

	}
}
<commit_msg>removed write to log<commit_after>
#include "daemon.h"

#include <QString>
#include <QFile>
#include <QTextStream>
#include <QMap>
#include <QList>
#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlError>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QProcess>
#include <QUuid>
#include <QRegExp>

namespace adjd {

	void writeToLog(adjd::config &cnf, QString strMsg)
	{
		QFile file(cnf.strLogFile);
		if ( file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append))
        {
			QDateTime dateTime = QDateTime::currentDateTime();
			QString dateTimeString = dateTime.toString("[yyyy-MMM-dd hh:mm:ss] ");

            QTextStream stream( &file );
            stream << dateTimeString << strMsg << endl;
            file.close();
        }
	}

	struct tables_ {
		QList<QMap<QString,QString> > services;
		QList<QMap<QString,QString> > teams;
	};

	bool getInfoTeamsAndServices(adjd::config &cnf, adjd::tables_ &tabl)
	{
		QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
		db.setHostName("localhost");
		db.setDatabaseName(cnf.db_name);
		db.setUserName(cnf.db_user);
		db.setPassword(cnf.db_pass);
		if (!db.open()){
			writeToLog(cnf, db.lastError().text());
			writeToLog(cnf, "Failed to connect.");
			return false;
		}

		// services
		{
			QSqlQuery query(db);
			query.exec("SELECT * FROM services");
			while (query.next()) {
				QSqlRecord record = query.record();
				QMap<QString,QString> map;
				for(int index = 0; index < record.count(); ++index) {
					QString key = record.fieldName(index);
					map.insert(key, record.value(index).toString());
				}
				tabl.services << map;
			}
		}

		// teams
		{
			QSqlQuery query(db);
			query.exec("SELECT * FROM teams");
			while (query.next()) {
				QSqlRecord record = query.record();
				QMap<QString,QString> map;
				for(int index = 0; index < record.count(); ++index) {
					QString key = record.fieldName(index);
					map.insert(key, record.value(index).toString());
				}
				tabl.teams << map;
			}
		}

		return true;
	}

	void insertToFlags(adjd::config &cnf, QString id_service, QString id_team_owner, QString flag, QString id_team_passed)
	{
		QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
		db.setHostName("localhost");
		db.setDatabaseName(cnf.db_name);
		db.setUserName(cnf.db_user);
		db.setPassword(cnf.db_pass);
		if (!db.open()){
			writeToLog(cnf, db.lastError().text());
			writeToLog(cnf, "Failed to connect.");
			return;
		}

		QDateTime dateTime = QDateTime::currentDateTime();
		QString dateTimeString1 = dateTime.toString("yyyy-MM-dd hh:mm:ss");

		dateTime.addSecs(600); // add 10 minutes. it is live of flag
		QString dateTimeString2 = dateTime.toString("yyyy-MM-dd hh:mm:ss");

		QSqlQuery query(db);
		QString strQuery = "INSERT INTO flags(id_service,flag,id_team_owner, dt_start, dt_end, id_team_passed) VALUES("
			+ id_service + ", "
			+ "'" + flag + "', "
			+ id_team_owner + ", "
			+ "'" + dateTimeString1 + "', "
			+ "'" + dateTimeString2 + "', "
			+ id_team_passed
		+ ");";
		// writeToLog(cnf, "strQuery = " + strQuery);
		query.exec(strQuery);
		return;
	}

	int attackDefenceJuryDaemon(adjd::config &cnf)
	{
		while(1) {
			for(int i = 0; i < 20; i++)
			{
				writeToLog(cnf, "run checkers");
				adjd::tables_ tabl;
				if( getInfoTeamsAndServices(cnf, tabl) )
				{
					for(int ti = 0; ti < tabl.teams.count(); ti++)
					{
						QString team_name = tabl.teams[ti]["name"];
						QString team_ip = tabl.teams[ti]["ip_address"];
						QString team_id = tabl.teams[ti]["id"];

						for(int si = 0; si < tabl.services.count(); si++)
						{
							QString service_id = tabl.services[si]["id"];
							QString service_name = tabl.services[si]["name"];
							QString service_scriptpath = tabl.services[si]["scriptpath"];
							QString flag = QUuid::createUuid().toString();
							flag = flag.mid(1,flag.length()-2);

							if(QFile(service_scriptpath).exists())
							{
								QStringList args;
								args << team_ip << "store" << flag;
								QProcess p;
								p.start(service_scriptpath, args);
								p.waitForFinished(3000);

								QString p_stdout = p.readAllStandardOutput();
								QString p_stderr = p.readAllStandardError();

								if(p_stderr.length() > 0)
								{
									writeToLog(cnf, "Error in call checker: '" + service_scriptpath + "' p_stderr = " + p_stderr);
								}
								else
								{
									QString p_output = p_stdout.toUpper();
									QRegExp rx_work("\\[SERVICE IS WORK\\]");
									QRegExp rx_corrupt("\\[SERVICE IS CORRUPT\\]");

									if(rx_work.lastIndexIn(p_output) != -1)
									{
										insertToFlags(cnf, service_id, team_id, flag, "0");
										// writeToLog(cnf, service_name + ":" + team_name + " => service is work");
									}
									else if (rx_corrupt.lastIndexIn(p_output) != -1)
									{
										insertToFlags(cnf, service_id, team_id, flag, "-1");
										// writeToLog(cnf, service_name + ":" + team_name + " => service is corrupt");
									}
									else
									{
										writeToLog(cnf, service_name + ":" + team_name + " => (not found [service is work] or [service is corrupt] and you have only 3 sec),\np_stdout =\n" + p_stdout);
									}
								}
							}
							else
							{
								writeToLog(cnf, "team " + team_name + " (ip : " + team_ip + ") for service '" + service_name + "' script not found, script path: " + service_scriptpath);
							}
						}
					};
				};
				sleep(15);//wait 15 secund
			}
			sleep(300);//wait 5 minutes
		}
		return 0;

	}
}
<|endoftext|>


<commit_before>#include "Hero.h"
#include "Creep.h"
#include "log.h"
#include "simulatorImp.h"
#include <cmath>
#include <random>

//TODO use json
static SpriteDataType HeroData;

static std::default_random_engine rnd_gen;
static std::uniform_int_distribution<int> pos_distribution(1, 1000);
static std::uniform_int_distribution<int> sign_distribution(-1, 1);

static int init_HeroData = [&]()->int {
    HeroData["ShadowFiend"] = {
        { "HP",new double(200) },
        { "MP",new double(273) },
        { "MovementSpeed",new double(315) },
        { "Armor", new double(0.86) },
        { "Attack", new double(21) },
        { "AttackRange",new double(500) },
        { "SightRange", new double(1800) },
        { "Bounty", new double(200) },
        { "bountyEXP", new double(0) },
        { "BaseAttackTime", new double(1.7) },
        { "AttackSpeed", new double(120) },
        { "AtkPoint", new double(0.5) },
        { "AtkBackswing", new double(0.54) },
        { "ProjectileSpeed", new double(1200) },
        { "atktype", new AtkType(ranged) }
    };
    return 0;
}();

static int get_rand()
{
    return sign_distribution(rnd_gen) * pos_distribution(rnd_gen);
}

Hero::Hero(cppSimulatorImp* _Engine, Side _side, std::string type_name):target(nullptr)
{
    Engine = _Engine;
    side = _side;
    const auto& data = HeroData[type_name];
    INIT_ATTR_BY(data);

    last_exp = 0.0;
    last_HP = HP;

    _update_para();

    viz_radius = 5;
    if (side == Side::Radiant) {
        init_loc = pos_tup(-7205 + get_rand(), -6610 + get_rand());
        color = Config::Radiant_Colors;
    }
    else {
        init_loc = pos_tup(7000 + get_rand(), 6475 + get_rand());
        color = Config::Dire_Colors;
    }

    location = init_loc;
    move_order = pos_tup(0,0);

    if (Engine->get_canvas() != NULL) {
        canvas = Engine->get_canvas();
        pos_tup p = pos_in_wnd();
        PyObject* create_rectangle = PyObject_GetAttrString(canvas, "create_oval");
        PyObject* args = Py_BuildValue("(dddd)",
            std::get<0>(p) - viz_radius,
            std::get<1>(p) + viz_radius,
            std::get<0>(p) + viz_radius,
            std::get<1>(p) - viz_radius);
        PyObject* kwargs = Py_BuildValue("{s:s}", "fill", color.c_str());
        v_handle = PyObject_Call(create_rectangle, args, kwargs);
        Py_DECREF(kwargs);
        Py_DECREF(args);
        Py_DECREF(create_rectangle);
    }
}

Hero::~Hero()
{
    LOG << "gold:" << gold << endl;
    Logger::getInstance().flush();
}

void Hero::step()
{
    if (isAttacking())
        return;
    if (decisonType::noop == decision) {
        ;
    }
    else if (decisonType::move == decision) {
        auto p = pos_tup(std::get<0>(move_order) + std::get<0>(location),
            std::get<1>(move_order) + std::get<1>(location));
        set_move(p);
    }
    else if (decisonType::attack == decision) {
        if (nullptr == target) {
            LOG << "null target!\n";
            Logger::getInstance().flush();
            exit(1);
        }
        attack(target);
    }

}

void Hero::draw()
{
    if (v_handle != NULL) {
        auto p = pos_in_wnd();
        Py_XDECREF(PyObject_CallMethod(canvas,
            "coords",
            "(Odddd)",
            v_handle,
            std::get<0>(p) - viz_radius,
            std::get<1>(p) + viz_radius,
            std::get<0>(p) + viz_radius,
            std::get<1>(p) - viz_radius));
    }

}

void Hero::set_order(PyObject* order)
{
    PyObject* subdecision;
    if (!PyArg_ParseTuple(order, "iO", &decision, &subdecision)) {
        LOG << "Parse Arg error";
        return;
    }
    if (decisonType::noop == decision) {
        ;
    }
    else if (decisonType::move == decision) {
        int sign = side == Side::Radiant ? 1 : -1;
        double x, y;
        if (!PyArg_ParseTuple(subdecision, "dd", &x, &y)) {
            LOG << "Parse Arg error";
            return;
        }
        move_order = pos_tup(sign * x * 1000,
            sign * y * 1000);
    }
    else if (decisonType::attack == decision) {
        target = nullptr;
        int target_idx = PyLong_AsLong(subdecision);
        if (target_idx >= (int)target_list.size()) {
            LOG << "index out of range! target_list size:" << target_list.size() << "," << target_idx << endl;
            exit(4);
        }
        target = target_list[target_idx];
    }

}

static auto is_creep = [](Sprite* s) -> bool { return dynamic_cast<Creep*>(s) != nullptr; };

PyObject* Hero::get_state_tup()
{
    int sign = side == Side::Radiant ? 1 : -1 ;

    auto nearby_ally = Engine->get_nearby_ally(this, is_creep);
    size_t ally_input_size = nearby_ally.size();
    double ally_x = 0.0;
    double ally_y = 0.0;
    for (size_t i = 0; i < ally_input_size; ++i) {
        ally_x += sign * (std::get<0>(nearby_ally[i].first->get_location()) - std::get<0>(location)) / Config::map_div;
        ally_y += sign * (std::get<1>(nearby_ally[i].first->get_location()) - std::get<1>(location)) / Config::map_div;
    }

    if (0 != ally_input_size) {
        ally_x /= (double)ally_input_size;
        ally_y /= (double)ally_input_size;
    }

    auto nearby_enemy = Engine->get_nearby_enemy(this, is_creep);
    size_t enemy_input_size = nearby_enemy.size();
    double enemy_x = 0.0;
    double enemy_y = 0.0;
    for (size_t i = 0; i < enemy_input_size; ++i) {
        enemy_x += sign * (std::get<0>(nearby_enemy[i].first->get_location()) - std::get<0>(location)) / Config::map_div;
        enemy_y += sign * (std::get<1>(nearby_enemy[i].first->get_location()) - std::get<1>(location)) / Config::map_div;
    }

    if (0 != enemy_input_size) {
        enemy_x /= (double)enemy_input_size;
        enemy_y /= (double)enemy_input_size;
    }

    PyObject* env_state = Py_BuildValue("[dddidddddd]",
        sign * std::get<0>(location) / Config::map_div,
        sign * std::get<1>(location) / Config::map_div,
        Attack,
        side,
        ally_x,
        ally_y,
        (double)ally_input_size,
        enemy_x,
        enemy_y,
        (double)enemy_input_size
    );

    if (NULL == env_state) {
        printf("env_state error!\n");
        return NULL;
    }

    PyObject* state_targets_list;
    if (enemy_input_size > 0) {
        target_list.clear();
        state_targets_list = PyList_New(enemy_input_size);
        for (int i = 0; i < enemy_input_size; i++) {
            PyList_SET_ITEM(state_targets_list,i, Py_BuildValue("(dd)", nearby_enemy[i].first->get_HP(), nearby_enemy[i].second / AttackRange));
            target_list.push_back(nearby_enemy[i].first);
        }
        LOG << "target_list.size " << target_list.size() << endl;
    }
    else {
        state_targets_list = Py_BuildValue("[]");
    }

    PyObject* state = Py_BuildValue("{s:O,s:O}", "env_input", env_state, "target_input", state_targets_list);

    double reward = (exp - last_exp) * 0.01 + (HP - last_HP) * 0.01 + (gold - last_gold) * 0.01;

    last_exp = exp;
    last_HP = HP;
    last_gold = gold;

    PyObject* ret = Py_BuildValue("(OdO)", state, reward, _isDead ? Py_True : Py_False);

    Py_DECREF(state);

    return ret;
}

PyObject* Hero::predefined_step()
{
    if (isAttacking()) {
        Py_INCREF(Py_None);
        PyObject* obj = Py_BuildValue("(iO)", decisonType::noop, Py_None);
        return obj;
    }
    int sign = side == Side::Radiant ? 1 : -1;
    auto nearby_enemy = Engine->get_nearby_enemy(this, is_creep);
    auto nearby_enemy_size = nearby_enemy.size();
    auto targetlist_size = target_list.size();
    if (targetlist_size > 0)
    {
        for (int i = 0; i < targetlist_size; ++i) {
            if (!target_list[i]->isDead() && target_list[i]->get_HP() < Attack) {
                PyObject* obj = Py_BuildValue("(ii)", decisonType::attack, i);
                return obj;
            }
        }
    }
    pos_tup ret;
    int _dis = 700;
    if (nearby_enemy.size() > 0)
    {
        ret = nearby_enemy[0].first->get_location();
        if (side == Side::Radiant) {
            ret = pos_tup(std::get<0>(nearby_enemy[0].first->get_location()) - _dis,
                std::get<1>(nearby_enemy[0].first->get_location()) - _dis);
        }
        else {
            ret = pos_tup(std::get<0>(nearby_enemy[0].first->get_location()) + _dis,
                std::get<1>(nearby_enemy[0].first->get_location()) + _dis);
        }
    }
    else {
        ret = pos_tup(-482, -400);
    }

    double dx = std::get<0>(ret) - std::get<0>(location);
    double dy = std::get<1>(ret) - std::get<1>(location);
    dx *= sign;
    dy *= sign;

    double a = std::atan2(dy, dx);
    PyObject* obj = Py_BuildValue("(i(dd))", decisonType::move, std::cos(a), std::sin(a));
    return obj;
}<commit_msg>reduce log<commit_after>#include "Hero.h"
#include "Creep.h"
#include "log.h"
#include "simulatorImp.h"
#include <cmath>
#include <random>

//TODO use json
static SpriteDataType HeroData;

static std::default_random_engine rnd_gen;
static std::uniform_int_distribution<int> pos_distribution(1, 1000);
static std::uniform_int_distribution<int> sign_distribution(-1, 1);

static int init_HeroData = [&]()->int {
    HeroData["ShadowFiend"] = {
        { "HP",new double(200) },
        { "MP",new double(273) },
        { "MovementSpeed",new double(315) },
        { "Armor", new double(0.86) },
        { "Attack", new double(21) },
        { "AttackRange",new double(500) },
        { "SightRange", new double(1800) },
        { "Bounty", new double(200) },
        { "bountyEXP", new double(0) },
        { "BaseAttackTime", new double(1.7) },
        { "AttackSpeed", new double(120) },
        { "AtkPoint", new double(0.5) },
        { "AtkBackswing", new double(0.54) },
        { "ProjectileSpeed", new double(1200) },
        { "atktype", new AtkType(ranged) }
    };
    return 0;
}();

static int get_rand()
{
    return sign_distribution(rnd_gen) * pos_distribution(rnd_gen);
}

Hero::Hero(cppSimulatorImp* _Engine, Side _side, std::string type_name):target(nullptr)
{
    Engine = _Engine;
    side = _side;
    const auto& data = HeroData[type_name];
    INIT_ATTR_BY(data);

    last_exp = 0.0;
    last_HP = HP;

    _update_para();

    viz_radius = 5;
    if (side == Side::Radiant) {
        init_loc = pos_tup(-7205 + get_rand(), -6610 + get_rand());
        color = Config::Radiant_Colors;
    }
    else {
        init_loc = pos_tup(7000 + get_rand(), 6475 + get_rand());
        color = Config::Dire_Colors;
    }

    location = init_loc;
    move_order = pos_tup(0,0);

    if (Engine->get_canvas() != NULL) {
        canvas = Engine->get_canvas();
        pos_tup p = pos_in_wnd();
        PyObject* create_rectangle = PyObject_GetAttrString(canvas, "create_oval");
        PyObject* args = Py_BuildValue("(dddd)",
            std::get<0>(p) - viz_radius,
            std::get<1>(p) + viz_radius,
            std::get<0>(p) + viz_radius,
            std::get<1>(p) - viz_radius);
        PyObject* kwargs = Py_BuildValue("{s:s}", "fill", color.c_str());
        v_handle = PyObject_Call(create_rectangle, args, kwargs);
        Py_DECREF(kwargs);
        Py_DECREF(args);
        Py_DECREF(create_rectangle);
    }
}

Hero::~Hero()
{
    LOG << "gold:" << gold << endl;
    Logger::getInstance().flush();
}

void Hero::step()
{
    if (isAttacking())
        return;
    if (decisonType::noop == decision) {
        ;
    }
    else if (decisonType::move == decision) {
        auto p = pos_tup(std::get<0>(move_order) + std::get<0>(location),
            std::get<1>(move_order) + std::get<1>(location));
        set_move(p);
    }
    else if (decisonType::attack == decision) {
        if (nullptr == target) {
            LOG << "null target!\n";
            Logger::getInstance().flush();
            exit(1);
        }
        attack(target);
    }

}

void Hero::draw()
{
    if (v_handle != NULL) {
        auto p = pos_in_wnd();
        Py_XDECREF(PyObject_CallMethod(canvas,
            "coords",
            "(Odddd)",
            v_handle,
            std::get<0>(p) - viz_radius,
            std::get<1>(p) + viz_radius,
            std::get<0>(p) + viz_radius,
            std::get<1>(p) - viz_radius));
    }

}

void Hero::set_order(PyObject* order)
{
    PyObject* subdecision;
    if (!PyArg_ParseTuple(order, "iO", &decision, &subdecision)) {
        LOG << "Parse Arg error";
        return;
    }
    if (decisonType::noop == decision) {
        ;
    }
    else if (decisonType::move == decision) {
        int sign = side == Side::Radiant ? 1 : -1;
        double x, y;
        if (!PyArg_ParseTuple(subdecision, "dd", &x, &y)) {
            LOG << "Parse Arg error";
            return;
        }
        move_order = pos_tup(sign * x * 1000,
            sign * y * 1000);
    }
    else if (decisonType::attack == decision) {
        target = nullptr;
        int target_idx = PyLong_AsLong(subdecision);
        if (target_idx >= (int)target_list.size()) {
            LOG << "index out of range! target_list size:" << target_list.size() << "," << target_idx << endl;
            exit(4);
        }
        target = target_list[target_idx];
    }

}

static auto is_creep = [](Sprite* s) -> bool { return dynamic_cast<Creep*>(s) != nullptr; };

PyObject* Hero::get_state_tup()
{
    int sign = side == Side::Radiant ? 1 : -1 ;

    auto nearby_ally = Engine->get_nearby_ally(this, is_creep);
    size_t ally_input_size = nearby_ally.size();
    double ally_x = 0.0;
    double ally_y = 0.0;
    for (size_t i = 0; i < ally_input_size; ++i) {
        ally_x += sign * (std::get<0>(nearby_ally[i].first->get_location()) - std::get<0>(location)) / Config::map_div;
        ally_y += sign * (std::get<1>(nearby_ally[i].first->get_location()) - std::get<1>(location)) / Config::map_div;
    }

    if (0 != ally_input_size) {
        ally_x /= (double)ally_input_size;
        ally_y /= (double)ally_input_size;
    }

    auto nearby_enemy = Engine->get_nearby_enemy(this, is_creep);
    size_t enemy_input_size = nearby_enemy.size();
    double enemy_x = 0.0;
    double enemy_y = 0.0;
    for (size_t i = 0; i < enemy_input_size; ++i) {
        enemy_x += sign * (std::get<0>(nearby_enemy[i].first->get_location()) - std::get<0>(location)) / Config::map_div;
        enemy_y += sign * (std::get<1>(nearby_enemy[i].first->get_location()) - std::get<1>(location)) / Config::map_div;
    }

    if (0 != enemy_input_size) {
        enemy_x /= (double)enemy_input_size;
        enemy_y /= (double)enemy_input_size;
    }

    PyObject* env_state = Py_BuildValue("[dddidddddd]",
        sign * std::get<0>(location) / Config::map_div,
        sign * std::get<1>(location) / Config::map_div,
        Attack,
        side,
        ally_x,
        ally_y,
        (double)ally_input_size,
        enemy_x,
        enemy_y,
        (double)enemy_input_size
    );

    if (NULL == env_state) {
        printf("env_state error!\n");
        return NULL;
    }

    PyObject* state_targets_list;
    if (enemy_input_size > 0) {
        target_list.clear();
        state_targets_list = PyList_New(enemy_input_size);
        for (int i = 0; i < enemy_input_size; i++) {
            PyList_SET_ITEM(state_targets_list,i, Py_BuildValue("(dd)", nearby_enemy[i].first->get_HP(), nearby_enemy[i].second / AttackRange));
            target_list.push_back(nearby_enemy[i].first);
        }
        //LOG << "target_list.size " << target_list.size() << endl;
    }
    else {
        state_targets_list = Py_BuildValue("[]");
    }

    PyObject* state = Py_BuildValue("{s:O,s:O}", "env_input", env_state, "target_input", state_targets_list);

    double reward = (exp - last_exp) * 0.01 + (HP - last_HP) * 0.01 + (gold - last_gold) * 0.01;

    last_exp = exp;
    last_HP = HP;
    last_gold = gold;

    PyObject* ret = Py_BuildValue("(OdO)", state, reward, _isDead ? Py_True : Py_False);

    Py_DECREF(state);

    return ret;
}

PyObject* Hero::predefined_step()
{
    if (isAttacking()) {
        Py_INCREF(Py_None);
        PyObject* obj = Py_BuildValue("(iO)", decisonType::noop, Py_None);
        return obj;
    }
    int sign = side == Side::Radiant ? 1 : -1;
    auto nearby_enemy = Engine->get_nearby_enemy(this, is_creep);
    auto nearby_enemy_size = nearby_enemy.size();
    auto targetlist_size = target_list.size();
    if (targetlist_size > 0)
    {
        for (int i = 0; i < targetlist_size; ++i) {
            if (!target_list[i]->isDead() && target_list[i]->get_HP() < Attack) {
                PyObject* obj = Py_BuildValue("(ii)", decisonType::attack, i);
                return obj;
            }
        }
    }
    pos_tup ret;
    int _dis = 700;
    if (nearby_enemy.size() > 0)
    {
        ret = nearby_enemy[0].first->get_location();
        if (side == Side::Radiant) {
            ret = pos_tup(std::get<0>(nearby_enemy[0].first->get_location()) - _dis,
                std::get<1>(nearby_enemy[0].first->get_location()) - _dis);
        }
        else {
            ret = pos_tup(std::get<0>(nearby_enemy[0].first->get_location()) + _dis,
                std::get<1>(nearby_enemy[0].first->get_location()) + _dis);
        }
    }
    else {
        ret = pos_tup(-482, -400);
    }

    double dx = std::get<0>(ret) - std::get<0>(location);
    double dy = std::get<1>(ret) - std::get<1>(location);
    dx *= sign;
    dy *= sign;

    double a = std::atan2(dy, dx);
    PyObject* obj = Py_BuildValue("(i(dd))", decisonType::move, std::cos(a), std::sin(a));
    return obj;
}<|endoftext|>