<commit_before>/*
 * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry).
 * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
 */

#ifdef ESP32

#include "ESP32AnalogDevice.h"
#include "IoLogging.h"
#include <SimpleCollections.h>
#ifndef CONFIG_IDF_TARGET_ESP32S3
#include <driver/dac.h>
#define ESP_HAS_DAC
#else
#undef ESP_HAS_DAC
#endif

#include <AnalogDeviceAbstraction.h>

EspAnalogInputMode::EspAnalogInputMode(pinid_t pin) : onAdc1(false), adcChannelNum(0xff), pin(pin), attenuation(ADC_ATTEN_DB_11) {}

EspAnalogInputMode::EspAnalogInputMode(const EspAnalogInputMode& other) = default;

void EspAnalogInputMode::pinSetup() {
    if(adcChannelNum == 0xff) {
        for (int ch = ADC1_CHANNEL_0; ch < ADC1_CHANNEL_MAX; ch++) {
            gpio_num_t gpio = GPIO_NUM_0;
            if (adc1_pad_get_io_num(static_cast<adc1_channel_t>(ch), &gpio) == ESP_OK && gpio == pin) {
                onAdc1 = true;
                adcChannelNum = ch;
                break;
            }
        }
    }

    if(adcChannelNum == 0xff) {
        for (int ch = ADC2_CHANNEL_0; ch < ADC2_CHANNEL_MAX; ch++) {
            gpio_num_t gpio = GPIO_NUM_0;
            if (adc2_pad_get_io_num(static_cast<adc2_channel_t>(ch), &gpio) == ESP_OK && gpio == pin) {
                onAdc1 = false;
                adcChannelNum = ch;
                break;
            }
        }
    }

    // there's a chance that this GPIO may have previously been registered as output, we should
    // ensure that it's initialised as input with no pull up/down.
    if(adcChannelNum != 0xff) {
        alterPinAttenuation(ADC_ATTEN_DB_11);
        gpio_config_t config;
        config.intr_type = GPIO_INTR_DISABLE;
        config.mode = GPIO_MODE_INPUT;
        config.pin_bit_mask = uint64_t(1) << uint64_t(pin);
        config.pull_down_en = GPIO_PULLDOWN_DISABLE;
        config.pull_up_en = GPIO_PULLUP_DISABLE;
        gpio_config(&config);
    }
    else {
        serlogF(SER_WARNING, "Did not find adc setting for ", pin);
    }
}

uint16_t EspAnalogInputMode::getCurrentReading() {
    // if the ADC is on the dac channel it must be turned off first.
#ifdef ESP_HAS_DAC
    if(pin == DAC1 || pin == DAC2) {
        dac_output_disable(pin == DAC1 ? DAC_CHANNEL_1 : DAC_CHANNEL_2);
    }
#endif
    if(onAdc1) {
        adc1_config_channel_atten(static_cast<adc1_channel_t>(adcChannelNum), static_cast<adc_atten_t>(attenuation));
        return adc1_get_raw(static_cast<adc1_channel_t>(adcChannelNum));
    }
    else {
        int adcVal;
        adc2_config_channel_atten(static_cast<adc2_channel_t>(adcChannelNum), static_cast<adc_atten_t>(attenuation));
        if(adc2_get_raw(static_cast<adc2_channel_t>(adcChannelNum), IOA_ESP_BIT_SELECTION, &adcVal) == ESP_OK) {
            lastCached = adcVal;
            return adcVal;
        }
        return lastCached;
    }
}

EspAnalogOutputMode::EspAnalogOutputMode(pinid_t pin) : pin(pin), pwmChannel(0xff), pwmWidth(5000) {}

EspAnalogOutputMode::EspAnalogOutputMode(const EspAnalogOutputMode& other)  {
    pin = other.pin;
    pwmChannel = other.pwmChannel;
    pwmWidth = other.pwmWidth;
}

void EspAnalogOutputMode::pinSetup() {
    if(!isDac()) {
        // for other than the dac ports, we need to set up PWM
        ledcSetup(pwmChannel, pwmWidth, 8);
        ledcAttachPin(pin, pwmChannel);
    }
    else {
#ifdef ESP_HAS_DAC
        dac_output_enable(pin == ESP32_DAC1 ? DAC_CHANNEL_1 : DAC_CHANNEL_2);
#endif
    }
}

void EspAnalogOutputMode::write(unsigned int newVal) const {
#ifdef ESP_HAS_DAC
    if(isDac()) {
        dac_output_voltage(pin == ESP32_DAC1 ? DAC_CHANNEL_1 : DAC_CHANNEL_2, newVal);
        return;
    }
#endif
    ledcWrite(pwmChannel, newVal);
}

ESP32AnalogDevice* ESP32AnalogDevice::theInstance = nullptr;

ESP32AnalogDevice::ESP32AnalogDevice() {
    adc1_config_width(IOA_ESP_BIT_SELECTION);
}

void ESP32AnalogDevice::initPin(pinid_t pin, AnalogDirection direction) {
    if(direction != DIR_IN) {
        auto* gpio = gpioToPwmKey.getByKey(pin);
        if(!gpio) {
            EspAnalogOutputMode outputMode(pin);
            gpioToPwmKey.add(outputMode);
            gpio = gpioToPwmKey.getByKey(pin);
            gpio->setPwmChannel(gpioToPwmKey.count());
        }
        gpio->pinSetup();
    }
    else {
        auto* gpio = gpioToInputKey.getByKey(pin);
        if(!gpio) {
            EspAnalogInputMode inputMode(pin);
            gpioToInputKey.add(inputMode);
            gpio = gpioToInputKey.getByKey(pin);
        }
        gpio->pinSetup();
    }
}

void ESP32AnalogDevice::setCurrentFloat(pinid_t pin, float value) {
    if(value < 0.0F) value = 0.0F;
    auto compVal = (int)(value * 255.0F);
    if(compVal > 255) compVal = 255;
    setCurrentValue(pin, compVal);
    serlogF4(SER_IOA_DEBUG, "Flt set ", value, maxValue, compVal);
}

AnalogDevice* internalAnalogIo() {
    if(ESP32AnalogDevice::theInstance == nullptr) ESP32AnalogDevice::theInstance = new ESP32AnalogDevice();
    return ESP32AnalogDevice::theInstance;
}

#endif
<commit_msg>#148 ESP32 logging fix<commit_after>/*
 * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry).
 * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
 */

#ifdef ESP32

#include "ESP32AnalogDevice.h"
#include "IoLogging.h"
#include <SimpleCollections.h>
#ifndef CONFIG_IDF_TARGET_ESP32S3
#include <driver/dac.h>
#define ESP_HAS_DAC
#else
#undef ESP_HAS_DAC
#endif

#include <AnalogDeviceAbstraction.h>

EspAnalogInputMode::EspAnalogInputMode(pinid_t pin) : onAdc1(false), adcChannelNum(0xff), pin(pin), attenuation(ADC_ATTEN_DB_11) {}

EspAnalogInputMode::EspAnalogInputMode(const EspAnalogInputMode& other) = default;

void EspAnalogInputMode::pinSetup() {
    if(adcChannelNum == 0xff) {
        for (int ch = ADC1_CHANNEL_0; ch < ADC1_CHANNEL_MAX; ch++) {
            gpio_num_t gpio = GPIO_NUM_0;
            if (adc1_pad_get_io_num(static_cast<adc1_channel_t>(ch), &gpio) == ESP_OK && gpio == pin) {
                onAdc1 = true;
                adcChannelNum = ch;
                break;
            }
        }
    }

    if(adcChannelNum == 0xff) {
        for (int ch = ADC2_CHANNEL_0; ch < ADC2_CHANNEL_MAX; ch++) {
            gpio_num_t gpio = GPIO_NUM_0;
            if (adc2_pad_get_io_num(static_cast<adc2_channel_t>(ch), &gpio) == ESP_OK && gpio == pin) {
                onAdc1 = false;
                adcChannelNum = ch;
                break;
            }
        }
    }

    // there's a chance that this GPIO may have previously been registered as output, we should
    // ensure that it's initialised as input with no pull up/down.
    if(adcChannelNum != 0xff) {
        alterPinAttenuation(ADC_ATTEN_DB_11);
        gpio_config_t config;
        config.intr_type = GPIO_INTR_DISABLE;
        config.mode = GPIO_MODE_INPUT;
        config.pin_bit_mask = uint64_t(1) << uint64_t(pin);
        config.pull_down_en = GPIO_PULLDOWN_DISABLE;
        config.pull_up_en = GPIO_PULLUP_DISABLE;
        gpio_config(&config);
    }
    else {
        serlogF2(SER_WARNING, "Did not find adc setting for ", pin);
    }
}

uint16_t EspAnalogInputMode::getCurrentReading() {
    // if the ADC is on the dac channel it must be turned off first.
#ifdef ESP_HAS_DAC
    if(pin == DAC1 || pin == DAC2) {
        dac_output_disable(pin == DAC1 ? DAC_CHANNEL_1 : DAC_CHANNEL_2);
    }
#endif
    if(onAdc1) {
        adc1_config_channel_atten(static_cast<adc1_channel_t>(adcChannelNum), static_cast<adc_atten_t>(attenuation));
        return adc1_get_raw(static_cast<adc1_channel_t>(adcChannelNum));
    }
    else {
        int adcVal;
        adc2_config_channel_atten(static_cast<adc2_channel_t>(adcChannelNum), static_cast<adc_atten_t>(attenuation));
        if(adc2_get_raw(static_cast<adc2_channel_t>(adcChannelNum), IOA_ESP_BIT_SELECTION, &adcVal) == ESP_OK) {
            lastCached = adcVal;
            return adcVal;
        }
        return lastCached;
    }
}

EspAnalogOutputMode::EspAnalogOutputMode(pinid_t pin) : pin(pin), pwmChannel(0xff), pwmWidth(5000) {}

EspAnalogOutputMode::EspAnalogOutputMode(const EspAnalogOutputMode& other)  {
    pin = other.pin;
    pwmChannel = other.pwmChannel;
    pwmWidth = other.pwmWidth;
}

void EspAnalogOutputMode::pinSetup() {
    if(!isDac()) {
        // for other than the dac ports, we need to set up PWM
        ledcSetup(pwmChannel, pwmWidth, 8);
        ledcAttachPin(pin, pwmChannel);
    }
    else {
#ifdef ESP_HAS_DAC
        dac_output_enable(pin == ESP32_DAC1 ? DAC_CHANNEL_1 : DAC_CHANNEL_2);
#endif
    }
}

void EspAnalogOutputMode::write(unsigned int newVal) const {
#ifdef ESP_HAS_DAC
    if(isDac()) {
        dac_output_voltage(pin == ESP32_DAC1 ? DAC_CHANNEL_1 : DAC_CHANNEL_2, newVal);
        return;
    }
#endif
    ledcWrite(pwmChannel, newVal);
}

ESP32AnalogDevice* ESP32AnalogDevice::theInstance = nullptr;

ESP32AnalogDevice::ESP32AnalogDevice() {
    adc1_config_width(IOA_ESP_BIT_SELECTION);
}

void ESP32AnalogDevice::initPin(pinid_t pin, AnalogDirection direction) {
    if(direction != DIR_IN) {
        auto* gpio = gpioToPwmKey.getByKey(pin);
        if(!gpio) {
            EspAnalogOutputMode outputMode(pin);
            gpioToPwmKey.add(outputMode);
            gpio = gpioToPwmKey.getByKey(pin);
            gpio->setPwmChannel(gpioToPwmKey.count());
        }
        gpio->pinSetup();
    }
    else {
        auto* gpio = gpioToInputKey.getByKey(pin);
        if(!gpio) {
            EspAnalogInputMode inputMode(pin);
            gpioToInputKey.add(inputMode);
            gpio = gpioToInputKey.getByKey(pin);
        }
        gpio->pinSetup();
    }
}

void ESP32AnalogDevice::setCurrentFloat(pinid_t pin, float value) {
    if(value < 0.0F) value = 0.0F;
    auto compVal = (int)(value * 255.0F);
    if(compVal > 255) compVal = 255;
    setCurrentValue(pin, compVal);
    serlogF3(SER_IOA_DEBUG, "Flt set ", value, compVal);
}

AnalogDevice* internalAnalogIo() {
    if(ESP32AnalogDevice::theInstance == nullptr) ESP32AnalogDevice::theInstance = new ESP32AnalogDevice();
    return ESP32AnalogDevice::theInstance;
}

#endif
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016 DeepCortex GmbH <legal@eventql.io>
 * Authors:
 *   - Paul Asmuth <paul@eventql.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include "eventql/db/metadata_file.h"
#include "eventql/util/inspect.h"

namespace eventql {

MetadataFile::MetadataFile() {}

MetadataFile::MetadataFile(
    const SHA1Hash& transaction_id,
    uint64_t transaction_seq,
    KeyspaceType keyspace_type,
    const Vector<PartitionMapEntry>& partition_map,
    uint64_t flags) :
    transaction_id_(transaction_id),
    transaction_seq_(transaction_seq),
    keyspace_type_(keyspace_type),
    partition_map_(partition_map),
    flags_(flags) {}

const SHA1Hash& MetadataFile::getTransactionID() const {
  return transaction_id_;
}

uint64_t MetadataFile::getSequenceNumber() const {
  return transaction_seq_;
}

KeyspaceType MetadataFile::getKeyspaceType() const {
  return keyspace_type_;
}

const Vector<MetadataFile::PartitionMapEntry>&
    MetadataFile::getPartitionMap() const {
  return partition_map_;
}

MetadataFile::PartitionMapIter MetadataFile::getPartitionMapBegin() const {
  return partition_map_.begin();
}

MetadataFile::PartitionMapIter MetadataFile::getPartitionMapEnd() const {
  return partition_map_.end();
}

MetadataFile::PartitionMapIter MetadataFile::lookup(
    const String& key) const {
  if (partition_map_.empty()) {
    return partition_map_.end();
  }

  size_t low = 0;
  size_t high = partition_map_.size() - 1;
  while (low != high) {
    size_t mid = (low + high + 1) / 2;
    int cmp = compareKeys(partition_map_[mid].begin, key);
    if (cmp < 0) {
      low = mid;
    } else if (cmp > 0) {
      if (mid == 0) {
        return partition_map_.begin();
      }

      high = mid - 1;
    } else {
      return partition_map_.begin() + mid;
    }
  }

  return partition_map_.begin() + low;
}

MetadataFile::PartitionMapIter MetadataFile::getPartitionMapAt(
    const String& key) const {
  auto iter = lookup(key);
  if (flags_ & MFILE_FINITE) {
    if (compareKeys(iter->begin, key) <= 0 &&
        compareKeys(iter->end, key) > 0) {
      return iter;
    } else {
      return partition_map_.end();
    }
  } else {
    return iter;
  }
}

MetadataFile::PartitionMapIter MetadataFile::getPartitionMapRangeBegin(
    const String& begin) const {
  if (begin.empty()) {
    return getPartitionMapBegin();
  }

  auto iter = lookup(begin);
  if (flags_ & MFILE_FINITE) {
    if (iter == partition_map_.end() || compareKeys(iter->end, begin) > 0) {
      return iter;
    } else {
      return iter + 1;
    }
  } else {
    return iter;
  }
}

MetadataFile::PartitionMapIter MetadataFile::getPartitionMapRangeEnd(
    const String& end) const {
  if (end.empty()) {
    return getPartitionMapEnd();
  }

  auto iter = lookup(end);
  if (iter == partition_map_.end() || iter->begin == end) {
    return iter;
  } else {
    return iter + 1;
  }
}

int MetadataFile::compareKeys(const String& a, const String& b) const {
  return comparePartitionKeys(keyspace_type_, a, b);
}

static Status decodeServerList(
    uint64_t version,
    Vector<MetadataFile::PartitionPlacement>* servers,
    InputStream* is) {
  auto n = is->readVarUInt();

  for (size_t i = 0; i < n; ++i) {
    MetadataFile::PartitionPlacement s;
    s.server_id = is->readLenencString();
    if (version >= 2) {
      s.placement_id = is->readUInt64();
    } else {
      s.placement_id = 0;
      is->readUInt64();
    }
    servers->emplace_back(s);
  }

  return Status::success();
}

Status MetadataFile::decode(InputStream* is) {
  // file format version
  auto version = is->readUInt32();
  if (version > kBinaryFormatVersion) {
    return Status(eIOError, "invalid file format version");
  }

  // flags
  flags_ = 0;
  if (version > 2) {
    flags_ = is->readVarUInt();
  }

  // transaction id
  is->readNextBytes(
      (char*) transaction_id_.mutableData(),
      transaction_id_.size());

  // transaction seq
  transaction_seq_ = is->readUInt64();

  // keyspace type
  keyspace_type_ = static_cast<KeyspaceType>(is->readUInt8());

  // partition map
  partition_map_.clear();
  auto pmap_size = is->readVarUInt();
  for (size_t i = 0; i < pmap_size; ++i) {
    PartitionMapEntry e;

    // begin
    e.begin = is->readLenencString();

    // end
    if (flags_ & MFILE_FINITE) {
      e.end = is->readLenencString();
    }

    // partition id
    is->readNextBytes(
        (char*) e.partition_id.mutableData(),
        e.partition_id.size());

    // servers
    auto rc = decodeServerList(version, &e.servers, is);
    if (!rc.isSuccess()) {
      return rc;
    }

    // servers joining
    decodeServerList(version, &e.servers_joining, is);
    if (!rc.isSuccess()) {
      return rc;
    }

    // servers leaving
    decodeServerList(version, &e.servers_leaving, is);
    if (!rc.isSuccess()) {
      return rc;
    }

    e.splitting = is->readUInt8() > 0;
    if (e.splitting) {
      // splitting
      switch (version) {
        case 1: {
          e.splitting = false;
          is->readLenencString();
          Vector<PartitionPlacement> tmp;
          if (!decodeServerList(version, &tmp, is).isSuccess()) {
            return rc;
          }
          if (!decodeServerList(version, &tmp, is).isSuccess()) {
            return rc;
          }
          break;
        }

        default:
        case 2: {
          // split_point
          e.split_point = is->readLenencString();

          // split_partition_id_low
          is->readNextBytes(
              (char*) e.split_partition_id_low.mutableData(),
              e.split_partition_id_low.size());

          // split_partition_id_high
          is->readNextBytes(
              (char*) e.split_partition_id_high.mutableData(),
              e.split_partition_id_high.size());

          // split_servers_low
          decodeServerList(version, &e.split_servers_low, is);
          if (!rc.isSuccess()) {
            return rc;
          }

          // split_servers_high
          decodeServerList(version, &e.split_servers_high, is);
          if (!rc.isSuccess()) {
            return rc;
          }
        }

        break;
      }

    }

    partition_map_.emplace_back(e);
  }

  return Status::success();
}

static Status encodeServerList(
    const Vector<MetadataFile::PartitionPlacement>& servers,
    OutputStream* os) {
  os->appendVarUInt(servers.size());
  for (const auto& s : servers) {
    os->appendLenencString(s.server_id);
    os->appendUInt64(s.placement_id);
  }

  return Status::success();
}

Status MetadataFile::encode(OutputStream* os) const  {
  // file format version
  os->appendUInt32(kBinaryFormatVersion);

  // file format version
  os->appendVarUInt(flags_);

  // transaction id
  os->write((const char*) transaction_id_.data(), transaction_id_.size());

  // transaction seq
  os->appendUInt64(transaction_seq_);

  // keyspace type
  os->appendUInt8(static_cast<uint8_t>(keyspace_type_));

  // partition map
  os->appendVarUInt(partition_map_.size());
  for (const auto& p : partition_map_) {
    // begin
    os->appendLenencString(p.begin);

    // end
    if (flags_ & MFILE_FINITE) {
      os->appendLenencString(p.end);
    }

    // partition id
    os->write((const char*) p.partition_id.data(), p.partition_id.size());

    // servers
    auto rc = encodeServerList(p.servers, os);
    if (!rc.isSuccess()) {
      return rc;
    }

    // servers_joining
    rc = encodeServerList(p.servers_joining, os);
    if (!rc.isSuccess()) {
      return rc;
    }

    // servers_leaving
    rc = encodeServerList(p.servers_leaving, os);
    if (!rc.isSuccess()) {
      return rc;
    }

    // splitting
    os->appendUInt8(p.splitting);
    if (p.splitting) {
      // split_point
      os->appendLenencString(p.split_point);

      // split_partition_id_low
      os->write(
          (const char*) p.split_partition_id_low.data(),
          p.split_partition_id_low.size());

      // split_partition_id_high
      os->write(
          (const char*) p.split_partition_id_high.data(),
          p.split_partition_id_high.size());

      // split_servers_low
      rc = encodeServerList(p.split_servers_low, os);
      if (!rc.isSuccess()) {
        return rc;
      }

      // split_servers_high
      rc = encodeServerList(p.split_servers_high, os);
      if (!rc.isSuccess()) {
        return rc;
      }
    }
  }

  return Status::success();
}

Status MetadataFile::computeChecksum(SHA1Hash* checksum) const {
  Buffer buf;
  auto os = BufferOutputStream::fromBuffer(&buf);
  auto rc = encode(os.get());
  if (!rc.isSuccess()) {
    return rc;
  }

  *checksum = SHA1::compute(buf.data(), buf.size());
  return Status::success();
}

uint64_t MetadataFile::getFlags() const {
  return flags_;
}

bool MetadataFile::hasFinitePartitions() const {
  return flags_ & MFILE_FINITE;
}

MetadataFile::PartitionMapEntry::PartitionMapEntry() : splitting(false) {}

int comparePartitionKeys(
    KeyspaceType keyspace_type,
    const String& a,
    const String& b) {
  switch (keyspace_type) {
    case KEYSPACE_STRING: {
      if (a < b) {
        return -1;
      } else if (a > b) {
        return 1;
      } else {
        return 0;
      }
    }

    case KEYSPACE_UINT64: {
      uint64_t a_uint = 0;
      uint64_t b_uint = 0;
      if (a.size() == sizeof(uint64_t)) {
        memcpy(&a_uint, a.data(), sizeof(uint64_t));
      }
      if (b.size() == sizeof(uint64_t)) {
        memcpy(&b_uint, b.data(), sizeof(uint64_t));
      }

      if (a_uint < b_uint) {
        return -1;
      } else if (a_uint > b_uint) {
        return 1;
      } else {
        return 0;
      }
    }
  }
}

String encodePartitionKey(
    KeyspaceType keyspace_type,
    const String& key) {
  switch (keyspace_type) {
    case KEYSPACE_STRING: {
      return key;
    }

    case KEYSPACE_UINT64: {
      uint64_t uint = 0;
      if (key.size() > 0) {
        try {
          uint = std::stoull(key);
        } catch (...) {
          RAISEF(kRuntimeError, "invalid partiiton key: >$0<", key);
        }
      }

      return String((const char*) &uint, sizeof(uint64_t));
    }
  }
}

String decodePartitionKey(
    KeyspaceType keyspace_type,
    const String& key) {
  switch (keyspace_type) {
    case KEYSPACE_STRING: {
      return key;
    }

    case KEYSPACE_UINT64: {
      if (key.size() == sizeof(uint64_t)) {
        uint64_t uint;
        memcpy((void*) &uint, key.data(), sizeof(uint64_t));
        return StringUtil::toString(uint);
      } else {
        return "";
      }
    }
  }
}

} // namespace eventql

<commit_msg>handle edge case<commit_after>/**
 * Copyright (c) 2016 DeepCortex GmbH <legal@eventql.io>
 * Authors:
 *   - Paul Asmuth <paul@eventql.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include "eventql/db/metadata_file.h"
#include "eventql/util/inspect.h"

namespace eventql {

MetadataFile::MetadataFile() {}

MetadataFile::MetadataFile(
    const SHA1Hash& transaction_id,
    uint64_t transaction_seq,
    KeyspaceType keyspace_type,
    const Vector<PartitionMapEntry>& partition_map,
    uint64_t flags) :
    transaction_id_(transaction_id),
    transaction_seq_(transaction_seq),
    keyspace_type_(keyspace_type),
    partition_map_(partition_map),
    flags_(flags) {}

const SHA1Hash& MetadataFile::getTransactionID() const {
  return transaction_id_;
}

uint64_t MetadataFile::getSequenceNumber() const {
  return transaction_seq_;
}

KeyspaceType MetadataFile::getKeyspaceType() const {
  return keyspace_type_;
}

const Vector<MetadataFile::PartitionMapEntry>&
    MetadataFile::getPartitionMap() const {
  return partition_map_;
}

MetadataFile::PartitionMapIter MetadataFile::getPartitionMapBegin() const {
  return partition_map_.begin();
}

MetadataFile::PartitionMapIter MetadataFile::getPartitionMapEnd() const {
  return partition_map_.end();
}

MetadataFile::PartitionMapIter MetadataFile::lookup(
    const String& key) const {
  if (partition_map_.empty()) {
    return partition_map_.end();
  }

  size_t low = 0;
  size_t high = partition_map_.size() - 1;
  while (low != high) {
    size_t mid = (low + high + 1) / 2;
    int cmp = compareKeys(partition_map_[mid].begin, key);
    if (cmp < 0) {
      low = mid;
    } else if (cmp > 0) {
      if (mid == 0) {
        return partition_map_.begin();
      }

      high = mid - 1;
    } else {
      return partition_map_.begin() + mid;
    }
  }

  return partition_map_.begin() + low;
}

MetadataFile::PartitionMapIter MetadataFile::getPartitionMapAt(
    const String& key) const {
  auto iter = lookup(key);
  if (flags_ & MFILE_FINITE) {
    if (compareKeys(iter->begin, key) <= 0 &&
        compareKeys(iter->end, key) > 0) {
      return iter;
    } else {
      return partition_map_.end();
    }
  } else {
    return iter;
  }
}

MetadataFile::PartitionMapIter MetadataFile::getPartitionMapRangeBegin(
    const String& begin) const {
  if (begin.empty()) {
    return getPartitionMapBegin();
  }

  auto iter = lookup(begin);
  if (flags_ & MFILE_FINITE) {
    if (iter == partition_map_.end() || compareKeys(iter->end, begin) > 0) {
      return iter;
    } else {
      return iter + 1;
    }
  } else {
    return iter;
  }
}

MetadataFile::PartitionMapIter MetadataFile::getPartitionMapRangeEnd(
    const String& end) const {
  if (end.empty()) {
    return getPartitionMapEnd();
  }

  auto iter = lookup(end);
  if (iter == partition_map_.end() || compareKeys(iter->begin, end) >= 0) {
    return iter;
  } else {
    return iter + 1;
  }
}

int MetadataFile::compareKeys(const String& a, const String& b) const {
  return comparePartitionKeys(keyspace_type_, a, b);
}

static Status decodeServerList(
    uint64_t version,
    Vector<MetadataFile::PartitionPlacement>* servers,
    InputStream* is) {
  auto n = is->readVarUInt();

  for (size_t i = 0; i < n; ++i) {
    MetadataFile::PartitionPlacement s;
    s.server_id = is->readLenencString();
    if (version >= 2) {
      s.placement_id = is->readUInt64();
    } else {
      s.placement_id = 0;
      is->readUInt64();
    }
    servers->emplace_back(s);
  }

  return Status::success();
}

Status MetadataFile::decode(InputStream* is) {
  // file format version
  auto version = is->readUInt32();
  if (version > kBinaryFormatVersion) {
    return Status(eIOError, "invalid file format version");
  }

  // flags
  flags_ = 0;
  if (version > 2) {
    flags_ = is->readVarUInt();
  }

  // transaction id
  is->readNextBytes(
      (char*) transaction_id_.mutableData(),
      transaction_id_.size());

  // transaction seq
  transaction_seq_ = is->readUInt64();

  // keyspace type
  keyspace_type_ = static_cast<KeyspaceType>(is->readUInt8());

  // partition map
  partition_map_.clear();
  auto pmap_size = is->readVarUInt();
  for (size_t i = 0; i < pmap_size; ++i) {
    PartitionMapEntry e;

    // begin
    e.begin = is->readLenencString();

    // end
    if (flags_ & MFILE_FINITE) {
      e.end = is->readLenencString();
    }

    // partition id
    is->readNextBytes(
        (char*) e.partition_id.mutableData(),
        e.partition_id.size());

    // servers
    auto rc = decodeServerList(version, &e.servers, is);
    if (!rc.isSuccess()) {
      return rc;
    }

    // servers joining
    decodeServerList(version, &e.servers_joining, is);
    if (!rc.isSuccess()) {
      return rc;
    }

    // servers leaving
    decodeServerList(version, &e.servers_leaving, is);
    if (!rc.isSuccess()) {
      return rc;
    }

    e.splitting = is->readUInt8() > 0;
    if (e.splitting) {
      // splitting
      switch (version) {
        case 1: {
          e.splitting = false;
          is->readLenencString();
          Vector<PartitionPlacement> tmp;
          if (!decodeServerList(version, &tmp, is).isSuccess()) {
            return rc;
          }
          if (!decodeServerList(version, &tmp, is).isSuccess()) {
            return rc;
          }
          break;
        }

        default:
        case 2: {
          // split_point
          e.split_point = is->readLenencString();

          // split_partition_id_low
          is->readNextBytes(
              (char*) e.split_partition_id_low.mutableData(),
              e.split_partition_id_low.size());

          // split_partition_id_high
          is->readNextBytes(
              (char*) e.split_partition_id_high.mutableData(),
              e.split_partition_id_high.size());

          // split_servers_low
          decodeServerList(version, &e.split_servers_low, is);
          if (!rc.isSuccess()) {
            return rc;
          }

          // split_servers_high
          decodeServerList(version, &e.split_servers_high, is);
          if (!rc.isSuccess()) {
            return rc;
          }
        }

        break;
      }

    }

    partition_map_.emplace_back(e);
  }

  return Status::success();
}

static Status encodeServerList(
    const Vector<MetadataFile::PartitionPlacement>& servers,
    OutputStream* os) {
  os->appendVarUInt(servers.size());
  for (const auto& s : servers) {
    os->appendLenencString(s.server_id);
    os->appendUInt64(s.placement_id);
  }

  return Status::success();
}

Status MetadataFile::encode(OutputStream* os) const  {
  // file format version
  os->appendUInt32(kBinaryFormatVersion);

  // file format version
  os->appendVarUInt(flags_);

  // transaction id
  os->write((const char*) transaction_id_.data(), transaction_id_.size());

  // transaction seq
  os->appendUInt64(transaction_seq_);

  // keyspace type
  os->appendUInt8(static_cast<uint8_t>(keyspace_type_));

  // partition map
  os->appendVarUInt(partition_map_.size());
  for (const auto& p : partition_map_) {
    // begin
    os->appendLenencString(p.begin);

    // end
    if (flags_ & MFILE_FINITE) {
      os->appendLenencString(p.end);
    }

    // partition id
    os->write((const char*) p.partition_id.data(), p.partition_id.size());

    // servers
    auto rc = encodeServerList(p.servers, os);
    if (!rc.isSuccess()) {
      return rc;
    }

    // servers_joining
    rc = encodeServerList(p.servers_joining, os);
    if (!rc.isSuccess()) {
      return rc;
    }

    // servers_leaving
    rc = encodeServerList(p.servers_leaving, os);
    if (!rc.isSuccess()) {
      return rc;
    }

    // splitting
    os->appendUInt8(p.splitting);
    if (p.splitting) {
      // split_point
      os->appendLenencString(p.split_point);

      // split_partition_id_low
      os->write(
          (const char*) p.split_partition_id_low.data(),
          p.split_partition_id_low.size());

      // split_partition_id_high
      os->write(
          (const char*) p.split_partition_id_high.data(),
          p.split_partition_id_high.size());

      // split_servers_low
      rc = encodeServerList(p.split_servers_low, os);
      if (!rc.isSuccess()) {
        return rc;
      }

      // split_servers_high
      rc = encodeServerList(p.split_servers_high, os);
      if (!rc.isSuccess()) {
        return rc;
      }
    }
  }

  return Status::success();
}

Status MetadataFile::computeChecksum(SHA1Hash* checksum) const {
  Buffer buf;
  auto os = BufferOutputStream::fromBuffer(&buf);
  auto rc = encode(os.get());
  if (!rc.isSuccess()) {
    return rc;
  }

  *checksum = SHA1::compute(buf.data(), buf.size());
  return Status::success();
}

uint64_t MetadataFile::getFlags() const {
  return flags_;
}

bool MetadataFile::hasFinitePartitions() const {
  return flags_ & MFILE_FINITE;
}

MetadataFile::PartitionMapEntry::PartitionMapEntry() : splitting(false) {}

int comparePartitionKeys(
    KeyspaceType keyspace_type,
    const String& a,
    const String& b) {
  switch (keyspace_type) {
    case KEYSPACE_STRING: {
      if (a < b) {
        return -1;
      } else if (a > b) {
        return 1;
      } else {
        return 0;
      }
    }

    case KEYSPACE_UINT64: {
      uint64_t a_uint = 0;
      uint64_t b_uint = 0;
      if (a.size() == sizeof(uint64_t)) {
        memcpy(&a_uint, a.data(), sizeof(uint64_t));
      }
      if (b.size() == sizeof(uint64_t)) {
        memcpy(&b_uint, b.data(), sizeof(uint64_t));
      }

      if (a_uint < b_uint) {
        return -1;
      } else if (a_uint > b_uint) {
        return 1;
      } else {
        return 0;
      }
    }
  }
}

String encodePartitionKey(
    KeyspaceType keyspace_type,
    const String& key) {
  switch (keyspace_type) {
    case KEYSPACE_STRING: {
      return key;
    }

    case KEYSPACE_UINT64: {
      uint64_t uint = 0;
      if (key.size() > 0) {
        try {
          uint = std::stoull(key);
        } catch (...) {
          RAISEF(kRuntimeError, "invalid partiiton key: >$0<", key);
        }
      }

      return String((const char*) &uint, sizeof(uint64_t));
    }
  }
}

String decodePartitionKey(
    KeyspaceType keyspace_type,
    const String& key) {
  switch (keyspace_type) {
    case KEYSPACE_STRING: {
      return key;
    }

    case KEYSPACE_UINT64: {
      if (key.size() == sizeof(uint64_t)) {
        uint64_t uint;
        memcpy((void*) &uint, key.data(), sizeof(uint64_t));
        return StringUtil::toString(uint);
      } else {
        return "";
      }
    }
  }
}

} // namespace eventql

<|endoftext|>


<commit_before>// Copyright 2010, François Bleibel, Thomas Moulard, Olivier Stasse,
// JRL, CNRS/AIST.

#include <boost/assign/list_of.hpp>
#include <dynamic-graph/command-bind.h>
#include <dynamic-graph/factory.h>
#include <dynamic-graph/pool.h>
#include <string>

#include <boost/numeric/conversion/cast.hpp>
#include <sot/core/feature-posture.hh>
namespace dg = ::dynamicgraph;

using dynamicgraph::sot::FeatureAbstract;

namespace dynamicgraph {
namespace sot {
using command::Command;
using command::Value;

class FeaturePosture::SelectDof : public Command {
public:
  virtual ~SelectDof() {}
  SelectDof(FeaturePosture &entity, const std::string &docstring)
      : Command(entity, boost::assign::list_of(Value::UNSIGNED)(Value::BOOL),
                docstring) {}
  virtual Value doExecute() {
    FeaturePosture &feature = static_cast<FeaturePosture &>(owner());
    std::vector<Value> values = getParameterValues();
    unsigned int dofId = values[0].value();
    bool control = values[1].value();
    feature.selectDof(dofId, control);
    return Value();
  }
}; // class SelectDof

FeaturePosture::FeaturePosture(const std::string &name)
    : FeatureAbstract(name),
      state_(NULL, "FeaturePosture(" + name + ")::input(Vector)::state"),
      posture_(0, "FeaturePosture(" + name + ")::input(Vector)::posture"),
      postureDot_(0, "FeaturePosture(" + name + ")::input(Vector)::postureDot"),
      activeDofs_(), nbActiveDofs_(0) {
  signalRegistration(state_ << posture_ << postureDot_);

  errorSOUT.addDependency(state_);
  jacobianSOUT.setConstant(Matrix());

  std::string docstring;
  docstring = "    \n"
              "    Select degree of freedom to control\n"
              "    \n"
              "      input:\n"
              "        - positive integer: rank of degree of freedom,\n"
              "        - boolean: whether to control the selected degree of "
              "freedom.\n"
              "    \n"
              "      Note: rank should be more than 5 since posture is "
              "independent\n"
              "        from freeflyer position.\n"
              "    \n";
  addCommand("selectDof", new SelectDof(*this, docstring));
}

FeaturePosture::~FeaturePosture() {}

unsigned int &FeaturePosture::getDimension(unsigned int &res, int) {
  res = static_cast<unsigned int>(nbActiveDofs_);
  return res;
}

dg::Vector &FeaturePosture::computeError(dg::Vector &res, int t) {
  const dg::Vector &state = state_.access(t);
  const dg::Vector &posture = posture_.access(t);

  res.resize(nbActiveDofs_);
  std::size_t index = 0;
  for (std::size_t i = 0; i < activeDofs_.size(); ++i) {
    if (activeDofs_[i]) {
      res(index) = state(i) - posture(i);
      index++;
    }
  }
  return res;
}

dg::Matrix &FeaturePosture::computeJacobian(dg::Matrix &, int) {
  throw std::runtime_error("jacobian signal should be constant."
                           " This function should never be called");
}

dg::Vector &FeaturePosture::computeErrorDot(dg::Vector &res, int t) {
  const Vector &postureDot = postureDot_.access(t);

  res.resize(nbActiveDofs_);
  std::size_t index = 0;
  for (std::size_t i = 0; i < activeDofs_.size(); ++i) {
    if (activeDofs_[i])
      res(index++) = -postureDot(i);
  }
  return res;
}

void FeaturePosture::selectDof(unsigned dofId, bool control) {
  const Vector &state = state_.accessCopy();
  const Vector &posture = posture_.accessCopy();
  std::size_t dim(state.size());

  if (dim != (std::size_t)posture.size()) {
    throw std::runtime_error("Posture and State should have same dimension.");
  }
  // If activeDof_ vector not initialized, initialize it
  if (activeDofs_.size() != dim) {
    activeDofs_ = std::vector<bool>(dim, false);
    nbActiveDofs_ = 0;
  }

  // Check that selected dof id is valid
  if ((dofId < 6) || (dofId >= dim)) {
    std::ostringstream oss;
    oss << "dof id should be more than 5 and less than state "
           "dimension: "
        << dim << ". Received " << dofId << ".";
    throw ExceptionAbstract(ExceptionAbstract::TOOLS, oss.str());
  }

  if (control) {
    if (!activeDofs_[dofId]) {
      activeDofs_[dofId] = true;
      nbActiveDofs_++;
    }
  } else { // control = false
    if (activeDofs_[dofId]) {
      activeDofs_[dofId] = false;
      nbActiveDofs_--;
    }
  }
  // recompute jacobian
  Matrix J(Matrix::Zero(nbActiveDofs_, dim));

  std::size_t index = 0;
  for (std::size_t i = 0; i < activeDofs_.size(); ++i) {
    if (activeDofs_[i]) {
      J(index, i) = 1;
      index++;
    }
  }

  jacobianSOUT.setConstant(J);
}

DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(FeaturePosture, "FeaturePosture");
} // namespace sot
} // namespace dynamicgraph
<commit_msg>[FeaturePosture] Remove abusive limitation.<commit_after>// Copyright 2010, François Bleibel, Thomas Moulard, Olivier Stasse,
// JRL, CNRS/AIST.

#include <boost/assign/list_of.hpp>
#include <dynamic-graph/command-bind.h>
#include <dynamic-graph/factory.h>
#include <dynamic-graph/pool.h>
#include <string>

#include <boost/numeric/conversion/cast.hpp>
#include <sot/core/feature-posture.hh>
namespace dg = ::dynamicgraph;

using dynamicgraph::sot::FeatureAbstract;

namespace dynamicgraph {
namespace sot {
using command::Command;
using command::Value;

class FeaturePosture::SelectDof : public Command {
public:
  virtual ~SelectDof() {}
  SelectDof(FeaturePosture &entity, const std::string &docstring)
      : Command(entity, boost::assign::list_of(Value::UNSIGNED)(Value::BOOL),
                docstring) {}
  virtual Value doExecute() {
    FeaturePosture &feature = static_cast<FeaturePosture &>(owner());
    std::vector<Value> values = getParameterValues();
    unsigned int dofId = values[0].value();
    bool control = values[1].value();
    feature.selectDof(dofId, control);
    return Value();
  }
}; // class SelectDof

FeaturePosture::FeaturePosture(const std::string &name)
    : FeatureAbstract(name),
      state_(NULL, "FeaturePosture(" + name + ")::input(Vector)::state"),
      posture_(0, "FeaturePosture(" + name + ")::input(Vector)::posture"),
      postureDot_(0, "FeaturePosture(" + name + ")::input(Vector)::postureDot"),
      activeDofs_(), nbActiveDofs_(0) {
  signalRegistration(state_ << posture_ << postureDot_);

  errorSOUT.addDependency(state_);
  jacobianSOUT.setConstant(Matrix());

  std::string docstring;
  docstring = "    \n"
              "    Select degree of freedom to control\n"
              "    \n"
              "      input:\n"
              "        - positive integer: rank of degree of freedom,\n"
              "        - boolean: whether to control the selected degree of "
              "freedom.\n"
              "    \n"
              "      Note: rank should be more than 5 since posture is "
              "independent\n"
              "        from freeflyer position.\n"
              "    \n";
  addCommand("selectDof", new SelectDof(*this, docstring));
}

FeaturePosture::~FeaturePosture() {}

unsigned int &FeaturePosture::getDimension(unsigned int &res, int) {
  res = static_cast<unsigned int>(nbActiveDofs_);
  return res;
}

dg::Vector &FeaturePosture::computeError(dg::Vector &res, int t) {
  const dg::Vector &state = state_.access(t);
  const dg::Vector &posture = posture_.access(t);

  res.resize(nbActiveDofs_);
  std::size_t index = 0;
  for (std::size_t i = 0; i < activeDofs_.size(); ++i) {
    if (activeDofs_[i]) {
      res(index) = state(i) - posture(i);
      index++;
    }
  }
  return res;
}

dg::Matrix &FeaturePosture::computeJacobian(dg::Matrix &, int) {
  throw std::runtime_error("jacobian signal should be constant."
                           " This function should never be called");
}

dg::Vector &FeaturePosture::computeErrorDot(dg::Vector &res, int t) {
  const Vector &postureDot = postureDot_.access(t);

  res.resize(nbActiveDofs_);
  std::size_t index = 0;
  for (std::size_t i = 0; i < activeDofs_.size(); ++i) {
    if (activeDofs_[i])
      res(index++) = -postureDot(i);
  }
  return res;
}

void FeaturePosture::selectDof(unsigned dofId, bool control) {
  const Vector &state = state_.accessCopy();
  const Vector &posture = posture_.accessCopy();
  std::size_t dim(state.size());

  if (dim != (std::size_t)posture.size()) {
    throw std::runtime_error("Posture and State should have same dimension.");
  }
  // If activeDof_ vector not initialized, initialize it
  if (activeDofs_.size() != dim) {
    activeDofs_ = std::vector<bool>(dim, false);
    nbActiveDofs_ = 0;
  }

  // Check that selected dof id is valid
  if (dofId >= dim) {
    std::ostringstream oss;
    oss << "dof id should less than state dimension: "
        << dim << ". Received " << dofId << ".";
    throw ExceptionAbstract(ExceptionAbstract::TOOLS, oss.str());
  }

  if (control) {
    if (!activeDofs_[dofId]) {
      activeDofs_[dofId] = true;
      nbActiveDofs_++;
    }
  } else { // control = false
    if (activeDofs_[dofId]) {
      activeDofs_[dofId] = false;
      nbActiveDofs_--;
    }
  }
  // recompute jacobian
  Matrix J(Matrix::Zero(nbActiveDofs_, dim));

  std::size_t index = 0;
  for (std::size_t i = 0; i < activeDofs_.size(); ++i) {
    if (activeDofs_[i]) {
      J(index, i) = 1;
      index++;
    }
  }

  jacobianSOUT.setConstant(J);
}

DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(FeaturePosture, "FeaturePosture");
} // namespace sot
} // namespace dynamicgraph
<|endoftext|>


<commit_before>#include "LevelUtils.h"
#include "Location.h"
#include "LocationType.h"
#include "LocationUtils.h"
#include "VoxelDefinition.h"
#include "../Assets/ExeData.h"
#include "../Math/Random.h"

#include "components/utilities/Bytes.h"
#include "components/debug/Debug.h"
#include "components/utilities/String.h"

uint16_t LevelUtils::getDoorVoxelOffset(int x, int y)
{
	return (y << 8) + (x << 1);
}

std::string LevelUtils::getDoorVoxelMifName(int x, int y, int menuID, int localCityID,
	int provinceID, const CityDataFile::ProvinceData &province, bool isCity, const ExeData &exeData)
{
	// Get the menu type associated with the *MENU ID.
	const VoxelDefinition::WallData::MenuType menuType =
		VoxelDefinition::WallData::getMenuType(menuID, isCity);

	// Check special case first: if it's a palace block in the center province's city,
	// the .MIF name is hardcoded.
	if ((menuType == VoxelDefinition::WallData::MenuType::Palace) &&
		(provinceID == Location::CENTER_PROVINCE_ID) && (localCityID == 0))
	{
		return String::toUppercase(exeData.locations.finalDungeonMifName);
	}

	// Get the prefix associated with the menu type.
	const std::string menuName = [localCityID, &exeData, menuType]()
	{
		const LocationType locationType = Location::getCityType(localCityID);

		const std::string name = [&exeData, locationType, menuType]() -> std::string
		{
			// Mappings of menu types to menu .MIF prefix indices. Menus that have no .MIF
			// filename mapping are considered special cases. TOWNPAL and VILPAL are not used
			// since the palace type can be deduced from the current city type.
			const int NO_INDEX = -1;
			const std::array<std::pair<VoxelDefinition::WallData::MenuType, int>, 12> MenuMifMappings =
			{
				{
					{ VoxelDefinition::WallData::MenuType::CityGates, NO_INDEX },
					{ VoxelDefinition::WallData::MenuType::Crypt, 7 },
					{ VoxelDefinition::WallData::MenuType::Dungeon, NO_INDEX },
					{ VoxelDefinition::WallData::MenuType::Equipment, 5 },
					{ VoxelDefinition::WallData::MenuType::House, 1 },
					{ VoxelDefinition::WallData::MenuType::MagesGuild, 6 },
					{ VoxelDefinition::WallData::MenuType::Noble, 2 },
					{ VoxelDefinition::WallData::MenuType::None, NO_INDEX },
					{ VoxelDefinition::WallData::MenuType::Palace, 0 },
					{ VoxelDefinition::WallData::MenuType::Tavern, 3 },
					{ VoxelDefinition::WallData::MenuType::Temple, 4 },
					{ VoxelDefinition::WallData::MenuType::Tower, 10 }
				}
			};

			// See if the given menu type has a .MIF prefix mapping.
			const auto iter = std::find_if(MenuMifMappings.begin(), MenuMifMappings.end(),
				[menuType](const std::pair<VoxelDefinition::WallData::MenuType, int> &pair)
			{
				return pair.first == menuType;
			});

			if (iter != MenuMifMappings.end())
			{
				const int index = iter->second;

				if (index != NO_INDEX)
				{
					// Get the menu's .MIF prefix index. If it's a palace, then decide which palace
					// prefix to use based on the location type.
					const int menuMifIndex = [locationType, menuType, index]()
					{
						if (menuType == VoxelDefinition::WallData::MenuType::Palace)
						{
							if (locationType == LocationType::CityState)
							{
								return 0;
							}
							else if (locationType == LocationType::Town)
							{
								return 8;
							}
							else if (locationType == LocationType::Village)
							{
								return 9;
							}
							else
							{
								DebugUnhandledReturnMsg(int,
									std::to_string(static_cast<int>(locationType)));
							}
						}
						else
						{
							return index;
						}
					}();

					const auto &prefixes = exeData.locations.menuMifPrefixes;
					return prefixes.at(menuMifIndex);
				}
				else
				{
					// The menu has no valid .MIF prefix.
					return std::string();
				}
			}
			else
			{
				DebugUnhandledReturnMsg(std::string, std::to_string(static_cast<int>(menuType)));
			}
		}();

		return String::toUppercase(name);
	}();

	// Some menu names don't map to an actual building type, so they are special cases
	// and should be ignored by the caller.
	const bool isSpecialCase = menuName.size() == 0;

	if (isSpecialCase)
	{
		// No .MIF filename. The caller knows not to try and load a .MIF file.
		return std::string();
	}
	else
	{
		// Offset is based on X and Y position in world; used with variant calculation.
		const uint16_t offset = LevelUtils::getDoorVoxelOffset(x, y);
		const uint32_t rulerSeed = [localCityID, &province]()
		{
			const auto &location = province.getLocationData(localCityID);
			const Int2 localPoint(location.x, location.y);
			return LocationUtils::getRulerSeed(localPoint, province.getGlobalRect());
		}();

		// Decide which variant of the interior to use.
		const int variantID = [rulerSeed, offset, menuType]()
		{
			// Palaces have fewer .MIF files to choose from, and their variant depends
			// on the ruler seed. Although there are five city-state palace .MIF files,
			// only three of them are used.
			const bool isPalace = menuType == VoxelDefinition::WallData::MenuType::Palace;
			const int palaceCount = 3;
			return isPalace ? (((rulerSeed >> 8) & 0xFFFF) % palaceCount) :
				((Bytes::ror(offset, 4) ^ offset) % 8);
		}();

		// Generate .MIF filename.
		return menuName + std::to_string(variantID + 1) + ".MIF";
	}
}

int LevelUtils::getDoorVoxelLockLevel(int x, int y, ArenaRandom &random)
{
	const uint16_t offset = LevelUtils::getDoorVoxelOffset(x, y);
	const uint32_t seed = offset + (offset << 16);
	random.srand(seed);
	return (random.next() % 10) + 1; // 0..9 + 1.
}

int LevelUtils::getServiceSaveFileNumber(int doorX, int doorY)
{
	return (doorY << 8) + doorX;
}

int LevelUtils::getWildernessServiceSaveFileNumber(int wildX, int wildY)
{
	return (wildY << 16) + wildX;
}
<commit_msg>Fixed GCC compile error with find_if.<commit_after>#include <algorithm>

#include "LevelUtils.h"
#include "Location.h"
#include "LocationType.h"
#include "LocationUtils.h"
#include "VoxelDefinition.h"
#include "../Assets/ExeData.h"
#include "../Math/Random.h"

#include "components/utilities/Bytes.h"
#include "components/debug/Debug.h"
#include "components/utilities/String.h"

uint16_t LevelUtils::getDoorVoxelOffset(int x, int y)
{
	return (y << 8) + (x << 1);
}

std::string LevelUtils::getDoorVoxelMifName(int x, int y, int menuID, int localCityID,
	int provinceID, const CityDataFile::ProvinceData &province, bool isCity, const ExeData &exeData)
{
	// Get the menu type associated with the *MENU ID.
	const VoxelDefinition::WallData::MenuType menuType =
		VoxelDefinition::WallData::getMenuType(menuID, isCity);

	// Check special case first: if it's a palace block in the center province's city,
	// the .MIF name is hardcoded.
	if ((menuType == VoxelDefinition::WallData::MenuType::Palace) &&
		(provinceID == Location::CENTER_PROVINCE_ID) && (localCityID == 0))
	{
		return String::toUppercase(exeData.locations.finalDungeonMifName);
	}

	// Get the prefix associated with the menu type.
	const std::string menuName = [localCityID, &exeData, menuType]()
	{
		const LocationType locationType = Location::getCityType(localCityID);

		const std::string name = [&exeData, locationType, menuType]() -> std::string
		{
			// Mappings of menu types to menu .MIF prefix indices. Menus that have no .MIF
			// filename mapping are considered special cases. TOWNPAL and VILPAL are not used
			// since the palace type can be deduced from the current city type.
			const int NO_INDEX = -1;
			const std::array<std::pair<VoxelDefinition::WallData::MenuType, int>, 12> MenuMifMappings =
			{
				{
					{ VoxelDefinition::WallData::MenuType::CityGates, NO_INDEX },
					{ VoxelDefinition::WallData::MenuType::Crypt, 7 },
					{ VoxelDefinition::WallData::MenuType::Dungeon, NO_INDEX },
					{ VoxelDefinition::WallData::MenuType::Equipment, 5 },
					{ VoxelDefinition::WallData::MenuType::House, 1 },
					{ VoxelDefinition::WallData::MenuType::MagesGuild, 6 },
					{ VoxelDefinition::WallData::MenuType::Noble, 2 },
					{ VoxelDefinition::WallData::MenuType::None, NO_INDEX },
					{ VoxelDefinition::WallData::MenuType::Palace, 0 },
					{ VoxelDefinition::WallData::MenuType::Tavern, 3 },
					{ VoxelDefinition::WallData::MenuType::Temple, 4 },
					{ VoxelDefinition::WallData::MenuType::Tower, 10 }
				}
			};

			// See if the given menu type has a .MIF prefix mapping.
			const auto iter = std::find_if(MenuMifMappings.begin(), MenuMifMappings.end(),
				[menuType](const std::pair<VoxelDefinition::WallData::MenuType, int> &pair)
			{
				return pair.first == menuType;
			});

			if (iter != MenuMifMappings.end())
			{
				const int index = iter->second;

				if (index != NO_INDEX)
				{
					// Get the menu's .MIF prefix index. If it's a palace, then decide which palace
					// prefix to use based on the location type.
					const int menuMifIndex = [locationType, menuType, index]()
					{
						if (menuType == VoxelDefinition::WallData::MenuType::Palace)
						{
							if (locationType == LocationType::CityState)
							{
								return 0;
							}
							else if (locationType == LocationType::Town)
							{
								return 8;
							}
							else if (locationType == LocationType::Village)
							{
								return 9;
							}
							else
							{
								DebugUnhandledReturnMsg(int,
									std::to_string(static_cast<int>(locationType)));
							}
						}
						else
						{
							return index;
						}
					}();

					const auto &prefixes = exeData.locations.menuMifPrefixes;
					return prefixes.at(menuMifIndex);
				}
				else
				{
					// The menu has no valid .MIF prefix.
					return std::string();
				}
			}
			else
			{
				DebugUnhandledReturnMsg(std::string, std::to_string(static_cast<int>(menuType)));
			}
		}();

		return String::toUppercase(name);
	}();

	// Some menu names don't map to an actual building type, so they are special cases
	// and should be ignored by the caller.
	const bool isSpecialCase = menuName.size() == 0;

	if (isSpecialCase)
	{
		// No .MIF filename. The caller knows not to try and load a .MIF file.
		return std::string();
	}
	else
	{
		// Offset is based on X and Y position in world; used with variant calculation.
		const uint16_t offset = LevelUtils::getDoorVoxelOffset(x, y);
		const uint32_t rulerSeed = [localCityID, &province]()
		{
			const auto &location = province.getLocationData(localCityID);
			const Int2 localPoint(location.x, location.y);
			return LocationUtils::getRulerSeed(localPoint, province.getGlobalRect());
		}();

		// Decide which variant of the interior to use.
		const int variantID = [rulerSeed, offset, menuType]()
		{
			// Palaces have fewer .MIF files to choose from, and their variant depends
			// on the ruler seed. Although there are five city-state palace .MIF files,
			// only three of them are used.
			const bool isPalace = menuType == VoxelDefinition::WallData::MenuType::Palace;
			const int palaceCount = 3;
			return isPalace ? (((rulerSeed >> 8) & 0xFFFF) % palaceCount) :
				((Bytes::ror(offset, 4) ^ offset) % 8);
		}();

		// Generate .MIF filename.
		return menuName + std::to_string(variantID + 1) + ".MIF";
	}
}

int LevelUtils::getDoorVoxelLockLevel(int x, int y, ArenaRandom &random)
{
	const uint16_t offset = LevelUtils::getDoorVoxelOffset(x, y);
	const uint32_t seed = offset + (offset << 16);
	random.srand(seed);
	return (random.next() % 10) + 1; // 0..9 + 1.
}

int LevelUtils::getServiceSaveFileNumber(int doorX, int doorY)
{
	return (doorY << 8) + doorX;
}

int LevelUtils::getWildernessServiceSaveFileNumber(int wildX, int wildY)
{
	return (wildY << 16) + wildX;
}
<|endoftext|>


<commit_before>#include "../../Lepus3D/Source/RenderEngine.h"

using namespace LepusEngine;
using namespace Lepus3D;

int main()
{
	Lepus3D::RenderEngine engine("LepusDemo", 800, 600);

	// Vertex declaration
	/*Vertex verts[] = {
		Vertex(-0.5f, 0.5f, 0.0f), // Top left
		Vertex(0.5f, 0.5f, 0.0f), // Top right
		Vertex(-0.5f, -0.5f, 0.0f), // Bottom left
		Vertex(0.5f, -0.5f, 0.0f) }; // Bottom right*/

	// Some diamond-like shape:
	Vertex verts[] = {
		Vertex(0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f),
		Vertex(-0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f),
		Vertex(0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f),
		Vertex(0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f) };
	GLuint indices[] = {
		0, 1, 2,
		1, 2, 3 };

	Lepus3D::Material testMat("Test material", "PerVertexUnlit");
	//testMat.SetAttributeF4("_Color", new float[4]{ 0.75f, 0.75f, 0.75f, 1.0f });

	bool running = true;
	while (running)
	{
		engine.DrawVertices(verts, sizeof(verts), indices, sizeof(indices) / sizeof(GLuint), testMat);
		running = engine.Update();
	}
	engine.Shutdown();
	return 0;
}<commit_msg>Updated Demo app to use Mesh<commit_after>#include "../../Lepus3D/Source/RenderEngine.h"

using namespace LepusEngine;
using namespace Lepus3D;

int main()
{
	Lepus3D::RenderEngine engine("LepusDemo", 800, 600);

	// Some diamond-like shape:
	VertexArray verts = {
		Vertex(0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f),
		Vertex(-0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f),
		Vertex(0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f),
		Vertex(-0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f),
		Vertex(0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f),
		Vertex(0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f) };

	Lepus3D::Material testMat("Test material", "PerVertexUnlit");
	Lepus3D::Mesh testMesh(verts);
	testMat.SetAttributeF4("_Color", new float[4]{ 0.75f, 0.75f, 0.75f, 1.0f });

	sf::Clock timer;

	bool running = true;
	while (running)
	{
		testMat.SetAttributeF("_Time", timer.getElapsedTime().asSeconds());
		engine.DrawMesh(testMesh, testMat);
		running = engine.Update();
	}
	engine.Shutdown();
	return 0;
}<|endoftext|>


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

#if FMI4CPP_DEBUG_LOGGING_ENABLED
#include <iostream>
#endif

#include <fmi4cpp/fmi2/import/Fmu.hpp>
#include <fmi4cpp/fmi2/import/CoSimulationSlaveBuilder.hpp>
#include <fmi4cpp/fmi2/import/ModelExchangeInstanceBuilder.hpp>

#include "../../tools/unzipper.hpp"
#include "../../tools/os_util.hpp"

using namespace std;
using namespace fmi4cpp::fmi2::import;

namespace {

    string generate_simple_id() {
        string id;
        for (int i = 0; i < 8; i++) {
            id += std::to_string(rand() % 10);
        }
        return id;
    }

}

Fmu::Fmu(const string &fmu_file) : fmu_file_(fmu_file) {

    const string fmuName = fs::path(fmu_file).stem().string();
    tmp_path_ = fs::temp_directory_path() /= fs::path("fmi4cpp_" + fmuName + "_" + generate_simple_id());

    if (!create_directories(tmp_path_)) {
        throw runtime_error("Failed to create temporary directory!");
    }

#if FMI4CPP_DEBUG_LOGGING_ENABLED
    cout << "Created temporary directory '" << tmp_path_.string()  << "'" << endl;
#endif
    if (!extractContents(fmu_file, tmp_path_.string())) {
        throw runtime_error("Failed to extract FMU!");
    }

    modelDescription_ = make_unique<ModelDescriptionImpl>(getModelDescriptionPath());

}

const string Fmu::getGuid() const {
    return modelDescription_->getGuid();
}

const string Fmu::getModelName() const {
    return modelDescription_->getModelName();
}

const string Fmu::getModelDescriptionXml() const {
    ifstream stream(getModelDescriptionPath());
    const string xml = string((istreambuf_iterator<char>(stream)), istreambuf_iterator<char>());
    return xml;
}

ModelDescription &Fmu::getModelDescription() {
    return *modelDescription_;
}

const bool Fmu::supportsModelExchange() const {
    return modelDescription_->supportsModelExchange();
}

const bool Fmu::supportsCoSimulation() const {
    return modelDescription_->supportsCoSimulation();
}

CoSimulationSlaveBuilder &Fmu::asCoSimulationFmu() {
    if (csBuilder_ == nullptr) {
        csBuilder_ = make_unique<CoSimulationSlaveBuilder>(*this);
    }
    return *csBuilder_;
}

ModelExchangeInstanceBuilder &Fmu::asModelExchangeFmu() {
    if (meBuilder_ == nullptr) {
        meBuilder_ = make_unique<ModelExchangeInstanceBuilder>(*this);
    }
    return *meBuilder_;
}

const string Fmu::getAbsoluteLibraryPath(const string modelIdentifier) const {
    return tmp_path_.string() + "/binaries/" + getOs() + "/" + modelIdentifier + getLibExt();
}

const string Fmu::getResourcePath() const {
    return "file:/" + tmp_path_.string() + "/resources/" + getOs() + "/" + getLibExt();
}

const string Fmu::getModelDescriptionPath() const {
    return tmp_path_.string() + "/modelDescription.xml";
}

Fmu::~Fmu() {
    meBuilder_ = nullptr;
    csBuilder_ = nullptr;
    remove_all(tmp_path_);

#if FMI4CPP_DEBUG_LOGGING_ENABLED
    cout << "Fmu '" << getModelName() << "' disposed.." << endl;
#endif

}
<commit_msg>fix bug where an application would crash if a previously generated temp folder had not been deleted<commit_after>/*
 * The MIT License
 *
 * Copyright 2017-2018 Norwegian University of Technology
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#if FMI4CPP_DEBUG_LOGGING_ENABLED
#include <iostream>
#endif

#include <random>
#include <fmi4cpp/fmi2/import/Fmu.hpp>
#include <fmi4cpp/fmi2/import/CoSimulationSlaveBuilder.hpp>
#include <fmi4cpp/fmi2/import/ModelExchangeInstanceBuilder.hpp>

#include "../../tools/unzipper.hpp"
#include "../../tools/os_util.hpp"

using namespace std;
using namespace fmi4cpp::fmi2::import;

namespace {

    std::random_device rd;
    std::mt19937 mt(rd());

    string generate_simple_id() {

        std::uniform_int_distribution<int> dist(0, 10);
        string id;
        for (int i = 0; i < 8; i++) {
            id += std::to_string(dist(mt));
        }
        return id;
    }

}

Fmu::Fmu(const string &fmu_file) : fmu_file_(fmu_file) {

    const string fmuName = fs::path(fmu_file).stem().string();
    tmp_path_ = fs::temp_directory_path() /= fs::path("fmi4cpp_" + fmuName + "_" + generate_simple_id());

    if (!create_directories(tmp_path_)) {
        throw runtime_error("Failed to create temporary directory!");
    }

#if FMI4CPP_DEBUG_LOGGING_ENABLED
    cout << "Created temporary directory '" << tmp_path_.string()  << "'" << endl;
#endif
    if (!extractContents(fmu_file, tmp_path_.string())) {
        throw runtime_error("Failed to extract FMU!");
    }

    modelDescription_ = make_unique<ModelDescriptionImpl>(getModelDescriptionPath());

}

const string Fmu::getGuid() const {
    return modelDescription_->getGuid();
}

const string Fmu::getModelName() const {
    return modelDescription_->getModelName();
}

const string Fmu::getModelDescriptionXml() const {
    ifstream stream(getModelDescriptionPath());
    const string xml = string((istreambuf_iterator<char>(stream)), istreambuf_iterator<char>());
    return xml;
}

ModelDescription &Fmu::getModelDescription() {
    return *modelDescription_;
}

const bool Fmu::supportsModelExchange() const {
    return modelDescription_->supportsModelExchange();
}

const bool Fmu::supportsCoSimulation() const {
    return modelDescription_->supportsCoSimulation();
}

CoSimulationSlaveBuilder &Fmu::asCoSimulationFmu() {
    if (csBuilder_ == nullptr) {
        csBuilder_ = make_unique<CoSimulationSlaveBuilder>(*this);
    }
    return *csBuilder_;
}

ModelExchangeInstanceBuilder &Fmu::asModelExchangeFmu() {
    if (meBuilder_ == nullptr) {
        meBuilder_ = make_unique<ModelExchangeInstanceBuilder>(*this);
    }
    return *meBuilder_;
}

const string Fmu::getAbsoluteLibraryPath(const string modelIdentifier) const {
    return tmp_path_.string() + "/binaries/" + getOs() + "/" + modelIdentifier + getLibExt();
}

const string Fmu::getResourcePath() const {
    return "file:/" + tmp_path_.string() + "/resources/" + getOs() + "/" + getLibExt();
}

const string Fmu::getModelDescriptionPath() const {
    return tmp_path_.string() + "/modelDescription.xml";
}

Fmu::~Fmu() {
    meBuilder_ = nullptr;
    csBuilder_ = nullptr;
    remove_all(tmp_path_);

#if FMI4CPP_DEBUG_LOGGING_ENABLED
    cout << "Fmu '" << getModelName() << "' disposed.." << endl;
#endif

}
<|endoftext|>


<commit_before>#include "robot.h"
#include "colorcalibrator.h"
#include "autocalibrator.h"
#include "camera.h"
#include "stillcamera.h"
#include "wheelcontroller.h"
#include "objectfinder.h"
#include "MouseFinder.h"
#include "dialog.h"
#include "wheel.h"
#include "ComPortScanner.h"

#include <opencv2/opencv.hpp>
#include <boost/algorithm/string.hpp>
#include <chrono>
#include <thread>

#define STATE_BUTTON(dialog, name, new_state) \
dialog.createButton(name, [](int state, void* self){ ((Robot*)self)->state = new_state; }, this, CV_PUSH_BUTTON, 0);
#define BUTTON(dialog, name, function_body) \
dialog.createButton(name, [](int state, void* self){ function_body }, this, CV_PUSH_BUTTON, 0);

std::pair<OBJECT, std::string> objects[] = {
	std::pair<OBJECT, std::string>(BALL, "Ball"),
    std::pair<OBJECT, std::string>(GATE, "Gate"),
    std::pair<OBJECT, std::string>(FIELD, "Field"),
    std::pair<OBJECT, std::string>(INNER_BORDER, "Inner Border2"),
    std::pair<OBJECT, std::string>(OUTER_BORDER, "Outer Border2"),

};

std::map<OBJECT, std::string> OBJECT_LABELS(objects, objects + sizeof(objects) / sizeof(objects[0]));

Robot::Robot(boost::asio::io_service &io) : io(io), camera(0), wheels(0), finder(0)
{
    state = STATE_NONE;
    //wheels = new WheelController(io);
}
Robot::~Robot()
{
	if (camera)
		delete camera;
    if(wheels)
        delete wheels;
    if (finder)
		delete finder;

}
void Robot::CalibrateObjects(const cv::Mat &image, bool autoCalibrate/* = false*/)
{
    ColorCalibrator* calibrator = autoCalibrate ? new AutoCalibrator() : new ColorCalibrator();
	cv::Mat image2 = camera->Capture();
//return;
    calibrator->LoadImage(image2);

    for(int i = 0; i < NUMBER_OF_OBJECTS; i++) {
        objectThresholds[(OBJECT) i] = calibrator->GetObjectThresholds(i, OBJECT_LABELS[(OBJECT) i]);
    }

    delete calibrator;

}

bool Robot::Launch(int argc, char* argv[])
{
	if (!ParseOptions(argc, argv)) return false;

	std::cout << "Initializing camera... " << std::endl;
	if (config.count("camera"))
		camera = new StillCamera(config["camera"].as<std::string>());
	else
		camera = new Camera(0);
	std::cout << "Done" << std::endl;

	if (config.count("locate_cursor"))
		finder = new MouseFinder();
	else
		finder = new ObjectFinder();

	std::cout << "Checking COM ports... " << std::endl;
	{ // new scope for scanner variable
		ComPortScanner scanner;
		if (!scanner.Verify(io)){
			std::cout << "Chek failed, rescanning all ports" << std::endl;
			scanner.Scan(io);
		}
	}
	std::cout << "Done" << std::endl;

	std::cout << "Initializing Wheels ports... " << std::endl;
	try {
		wheels = new WheelController(io);
	}
	catch (...) {
		throw std::runtime_error("unable to open wheel port(s)");
	}
	std::cout << "Done" << std::endl;

	std::cout << "Starting Robot" << std::endl;
    Run();
}

void Robot::Run()
{

    while (state != STATE_END_OF_GAME)
    {
//		cv::Mat image = camera->Capture();

        if (STATE_NONE == state) {

            Dialog launchWindow("Launch Robotiina", CV_WINDOW_AUTOSIZE);
			STATE_BUTTON(launchWindow, "AutoCalibrate objects", STATE_AUTOCALIBRATE)
			STATE_BUTTON(launchWindow, "ManualCalibrate objects", STATE_CALIBRATE)
			STATE_BUTTON(launchWindow, "Start Robot", STATE_LAUNCH)
			STATE_BUTTON(launchWindow, "Remote Control", STATE_REMOTE_CONTROL)
			STATE_BUTTON(launchWindow, "Manual Control", STATE_MANUAL_CONTROL)
			STATE_BUTTON(launchWindow, "Exit", STATE_END_OF_GAME)
            launchWindow.show();

        }
        if (STATE_CALIBRATE == state) {
			cv::Mat image;// = camera->Capture();
			CalibrateObjects(image);
            state = STATE_NONE;
        }
        if (STATE_AUTOCALIBRATE == state) {
			cv::Mat image = camera->Capture();
            CalibrateObjects(image, true);
            state = STATE_NONE;
        }
		if (STATE_LAUNCH == state) {
			try {
				CalibrationConfReader calibrator;
				for (int i = 0; i < NUMBER_OF_OBJECTS; i++) {
					objectThresholds[(OBJECT)i] = calibrator.GetObjectThresholds(i, OBJECT_LABELS[(OBJECT)i]);
				}
				state = STATE_LOCATE_BALL;
			}
			catch (...){
				//TODO: display error
				state = STATE_NONE; // no conf
			}
		}
		if (STATE_CRASH == state){
			//Backwards
			wheels->Drive(50, 180);
            boost::chrono::milliseconds dura(1000);
			boost::this_thread::sleep_for(dura);
			wheels->Stop();
			//Turn a littlebit
			wheels->Rotate(1, 100);
            boost::this_thread::sleep_for(dura);
			wheels->Stop();
			//Check again
			if (!wheels->CheckStall()){
				state = STATE_LOCATE_BALL;
			}
		}
        if (STATE_LOCATE_BALL == state) {
			cv::Point3d location = finder->Locate(objectThresholds[BALL], camera->Capture());
			double distance = location.x;
			double HorizontalDev = location.y;
			double HorizontalAngle = location.z;
			if (location.x == -1 && location.y == -1 && location.z == -1) /* Ball not found */
            {
                wheels->Rotate(1, 10);
            }
			if (location.x != -1 && location.y != -1) /*Ball found*/
            {
				wheels->Stop();
                state = STATE_BALL_LOCATED;
            }

        }
        if(STATE_BALL_LOCATED == state) {
			cv::Point3d location = finder->Locate(objectThresholds[BALL], camera->Capture());
			double distance = location.x;
			double HorizontalDev = location.y;
			double HorizontalAngle = location.z;

			//If ball is lost
			if (distance == -1 && HorizontalDev == -1 && HorizontalAngle == -1){
				state = STATE_LOCATE_BALL;
			}
			else if (distance < 250 && (HorizontalDev > -50 && HorizontalDev < 50)){
				//TODO: start catching the ball with tribbler
				wheels->Stop();
			}
			else if (distance < 250){
				//TODO: start tribbler
				//TODO: turn depending on HorizontalDev
				wheels->Stop();
			}
			else{
				if (distance > 700){
					speed = 150;
				}
				else{
					speed = distance * 0.35 - 91;
				}
				if (HorizontalDev > -50 && HorizontalDev < 50){
					wheels->Drive(speed, HorizontalAngle);
				}
				else if (HorizontalDev >= 50){
					wheels->DriveRotate(speed, HorizontalAngle, 0);
				}
				else{
					wheels->DriveRotate(speed, HorizontalAngle, 0);
				}
			}
            //state = STATE_LOCATE_GATE;
        }
        if (STATE_LOCATE_GATE == state)
        {
            /*CvPoint location = finder.Locate(objectThresholds[GATE]);*/
            //TODO: how
            wheels->Rotate(1,10);
            state = STATE_GATE_LOCATED;
        }
        if(STATE_GATE_LOCATED == state)
        {
            //TODO: kick ball
            state = STATE_LOCATE_BALL;
        }
        if(STATE_REMOTE_CONTROL == state) {
			Dialog launchWindow("Remote Control Mode Enabed", CV_WINDOW_AUTOSIZE);
			STATE_BUTTON(launchWindow, "Back", STATE_NONE)
			launchWindow.show();

        }

		if (STATE_MANUAL_CONTROL == state) {
			Dialog manualWindow("Manual Control Mode Enabed", CV_WINDOW_AUTOSIZE);
			BUTTON(manualWindow, "Move Left", ((Robot*)self)->wheels->Drive(20, 90);)
				BUTTON(manualWindow, "Move Right", ((Robot*)self)->wheels->Drive(20, 270);)
				BUTTON(manualWindow, "Move Forward", ((Robot*)self)->wheels->Drive(20, 0);)
				BUTTON(manualWindow, "Move Back", ((Robot*)self)->wheels->Drive(-20, 0);)
				BUTTON(manualWindow, "Rotate", ((Robot*)self)->wheels->Rotate(1,10);)
				STATE_BUTTON(manualWindow, "Back", STATE_NONE)
				manualWindow.show();
		}
		if (false && wheels->CheckStall() &&
			(state == STATE_LOCATE_BALL ||
			state == STATE_BALL_LOCATED ||
			state == STATE_LOCATE_GATE ||
			state == STATE_GATE_LOCATED)
		){
			state = STATE_CRASH;
		}

		// This slows system down to 33.3 FPS
        if (cv::waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
        {
          //  const cv::Mat frame = camera->Capture();

            std::cout << "esc key is pressed by user" << std::endl;
            //state = STATE_END_OF_GAME;
            state = STATE_NONE;
        }
    }
}
std::string Robot::ExecuteRemoteCommand(const std::string &command){
    std::stringstream response;
    boost::mutex::scoped_lock lock(remote_mutex); //allow one command at a time
    std::vector<std::string> tokens;
    boost::split(tokens, command, boost::is_any_of(";"));
    std::string query = tokens[0];
    STATE s = (STATE)GetState();
    if(query == "status") response << s;
    else if(query == "remote") SetState(STATE_REMOTE_CONTROL);
    else if(query == "cont") SetState(STATE_LOCATE_BALL);
    else if(query == "reset") SetState(STATE_NONE);
    else if(query == "exit") SetState(STATE_END_OF_GAME);
    else if (STATE_REMOTE_CONTROL == s) {
        if (query == "drive" && tokens.size() == 3) {
            int speed = atoi(tokens[1].c_str());
            float direction = atof(tokens[2].c_str());
            wheels->Drive(speed, direction);
		}
		else if (query == "rdrive" && tokens.size() == 4) {
			int speed = atoi(tokens[1].c_str());
			float direction = atof(tokens[2].c_str());
			int rotate = atoi(tokens[3].c_str());
			wheels->DriveRotate(speed, direction, rotate);
		}

    }
    return response.str();
}

bool Robot::ParseOptions(int argc, char* argv[])
{
	po::options_description desc("Allowed options");
	desc.add_options()
		("help", "produce help message")
		("camera", po::value<std::string>(), "set camera index or path")
		("locate_cursor", po::value<std::string>(), "find cursor instead of ball");

	po::store(po::parse_command_line(argc, argv, desc), config);
	po::notify(config);

	if (config.count("help")) {
		std::cout << desc << std::endl;
		return false;
	}

	return true;
}
<commit_msg>Rotate when ball is close but not center.<commit_after>#include "robot.h"
#include "colorcalibrator.h"
#include "autocalibrator.h"
#include "camera.h"
#include "stillcamera.h"
#include "wheelcontroller.h"
#include "objectfinder.h"
#include "MouseFinder.h"
#include "dialog.h"
#include "wheel.h"
#include "ComPortScanner.h"

#include <opencv2/opencv.hpp>
#include <boost/algorithm/string.hpp>
#include <chrono>
#include <thread>

#define STATE_BUTTON(dialog, name, new_state) \
dialog.createButton(name, [](int state, void* self){ ((Robot*)self)->state = new_state; }, this, CV_PUSH_BUTTON, 0);
#define BUTTON(dialog, name, function_body) \
dialog.createButton(name, [](int state, void* self){ function_body }, this, CV_PUSH_BUTTON, 0);

std::pair<OBJECT, std::string> objects[] = {
	std::pair<OBJECT, std::string>(BALL, "Ball"),
    std::pair<OBJECT, std::string>(GATE, "Gate"),
    std::pair<OBJECT, std::string>(FIELD, "Field"),
    std::pair<OBJECT, std::string>(INNER_BORDER, "Inner Border2"),
    std::pair<OBJECT, std::string>(OUTER_BORDER, "Outer Border2"),

};

std::map<OBJECT, std::string> OBJECT_LABELS(objects, objects + sizeof(objects) / sizeof(objects[0]));

Robot::Robot(boost::asio::io_service &io) : io(io), camera(0), wheels(0), finder(0)
{
    state = STATE_NONE;
    //wheels = new WheelController(io);
}
Robot::~Robot()
{
	if (camera)
		delete camera;
    if(wheels)
        delete wheels;
    if (finder)
		delete finder;

}
void Robot::CalibrateObjects(const cv::Mat &image, bool autoCalibrate/* = false*/)
{
    ColorCalibrator* calibrator = autoCalibrate ? new AutoCalibrator() : new ColorCalibrator();
	cv::Mat image2 = camera->Capture();
//return;
    calibrator->LoadImage(image2);

    for(int i = 0; i < NUMBER_OF_OBJECTS; i++) {
        objectThresholds[(OBJECT) i] = calibrator->GetObjectThresholds(i, OBJECT_LABELS[(OBJECT) i]);
    }

    delete calibrator;

}

bool Robot::Launch(int argc, char* argv[])
{
	if (!ParseOptions(argc, argv)) return false;

	std::cout << "Initializing camera... " << std::endl;
	if (config.count("camera"))
		camera = new StillCamera(config["camera"].as<std::string>());
	else
		camera = new Camera(0);
	std::cout << "Done" << std::endl;

	if (config.count("locate_cursor"))
		finder = new MouseFinder();
	else
		finder = new ObjectFinder();

	std::cout << "Checking COM ports... " << std::endl;
	{ // new scope for scanner variable
		ComPortScanner scanner;
		if (!scanner.Verify(io)){
			std::cout << "Chek failed, rescanning all ports" << std::endl;
			scanner.Scan(io);
		}
	}
	std::cout << "Done" << std::endl;

	std::cout << "Initializing Wheels ports... " << std::endl;
	try {
		wheels = new WheelController(io);
	}
	catch (...) {
		throw std::runtime_error("unable to open wheel port(s)");
	}
	std::cout << "Done" << std::endl;

	std::cout << "Starting Robot" << std::endl;
    Run();
}

void Robot::Run()
{

    while (state != STATE_END_OF_GAME)
    {
//		cv::Mat image = camera->Capture();

        if (STATE_NONE == state) {

            Dialog launchWindow("Launch Robotiina", CV_WINDOW_AUTOSIZE);
			STATE_BUTTON(launchWindow, "AutoCalibrate objects", STATE_AUTOCALIBRATE)
			STATE_BUTTON(launchWindow, "ManualCalibrate objects", STATE_CALIBRATE)
			STATE_BUTTON(launchWindow, "Start Robot", STATE_LAUNCH)
			STATE_BUTTON(launchWindow, "Remote Control", STATE_REMOTE_CONTROL)
			STATE_BUTTON(launchWindow, "Manual Control", STATE_MANUAL_CONTROL)
			STATE_BUTTON(launchWindow, "Exit", STATE_END_OF_GAME)
            launchWindow.show();

        }
        if (STATE_CALIBRATE == state) {
			cv::Mat image;// = camera->Capture();
			CalibrateObjects(image);
            state = STATE_NONE;
        }
        if (STATE_AUTOCALIBRATE == state) {
			cv::Mat image = camera->Capture();
            CalibrateObjects(image, true);
            state = STATE_NONE;
        }
		if (STATE_LAUNCH == state) {
			try {
				CalibrationConfReader calibrator;
				for (int i = 0; i < NUMBER_OF_OBJECTS; i++) {
					objectThresholds[(OBJECT)i] = calibrator.GetObjectThresholds(i, OBJECT_LABELS[(OBJECT)i]);
				}
				state = STATE_LOCATE_BALL;
			}
			catch (...){
				//TODO: display error
				state = STATE_NONE; // no conf
			}
		}
		if (STATE_CRASH == state){
			//Backwards
			wheels->Drive(50, 180);
            boost::chrono::milliseconds dura(1000);
			boost::this_thread::sleep_for(dura);
			wheels->Stop();
			//Turn a littlebit
			wheels->Rotate(1, 100);
            boost::this_thread::sleep_for(dura);
			wheels->Stop();
			//Check again
			if (!wheels->CheckStall()){
				state = STATE_LOCATE_BALL;
			}
		}
        if (STATE_LOCATE_BALL == state) {
			cv::Point3d location = finder->Locate(objectThresholds[BALL], camera->Capture());
			double distance = location.x;
			double HorizontalDev = location.y;
			double HorizontalAngle = location.z;
			if (location.x == -1 && location.y == -1 && location.z == -1) /* Ball not found */
            {
                wheels->Rotate(1, 10);
            }
			if (location.x != -1 && location.y != -1) /*Ball found*/
            {
				wheels->Stop();
                state = STATE_BALL_LOCATED;
            }

        }
        if(STATE_BALL_LOCATED == state) {
			cv::Point3d location = finder->Locate(objectThresholds[BALL], camera->Capture());
			double distance = location.x;
			double HorizontalDev = location.y;
			double HorizontalAngle = location.z;

			//If ball is lost
			if (distance == -1 && HorizontalDev == -1 && HorizontalAngle == -1){
				state = STATE_LOCATE_BALL;
			}
			else if (distance < 300 && (HorizontalDev > -50 && HorizontalDev < 50)){
				//TODO: start catching the ball with tribbler
				wheels->Stop();
			}
			else if (distance < 300){
				//TODO: start tribbler
				//TODO: turn depending on HorizontalDev
				if (HorizontalDev > -50){
					wheels->Rotate(1, 20);
				}
				else{
					wheels->Rotate(0, 20);
				}
				wheels->Stop();
			}
			else{
				if (distance > 700){
					speed = 150;
				}
				else{
					speed = distance * 0.35 - 91;
				}
				if (HorizontalDev > -50 && HorizontalDev < 50){
					wheels->Drive(speed, HorizontalAngle);
				}
				else if (HorizontalDev >= 50){
					wheels->DriveRotate(speed, HorizontalAngle, 0);
				}
				else{
					wheels->DriveRotate(speed, HorizontalAngle, 0);
				}
			}
            //state = STATE_LOCATE_GATE;
        }
        if (STATE_LOCATE_GATE == state)
        {
            /*CvPoint location = finder.Locate(objectThresholds[GATE]);*/
            //TODO: how
            wheels->Rotate(1,10);
            state = STATE_GATE_LOCATED;
        }
        if(STATE_GATE_LOCATED == state)
        {
            //TODO: kick ball
            state = STATE_LOCATE_BALL;
        }
        if(STATE_REMOTE_CONTROL == state) {
			Dialog launchWindow("Remote Control Mode Enabed", CV_WINDOW_AUTOSIZE);
			STATE_BUTTON(launchWindow, "Back", STATE_NONE)
			launchWindow.show();

        }

		if (STATE_MANUAL_CONTROL == state) {
			Dialog manualWindow("Manual Control Mode Enabed", CV_WINDOW_AUTOSIZE);
			BUTTON(manualWindow, "Move Left", ((Robot*)self)->wheels->Drive(20, 90);)
				BUTTON(manualWindow, "Move Right", ((Robot*)self)->wheels->Drive(20, 270);)
				BUTTON(manualWindow, "Move Forward", ((Robot*)self)->wheels->Drive(20, 0);)
				BUTTON(manualWindow, "Move Back", ((Robot*)self)->wheels->Drive(-20, 0);)
				BUTTON(manualWindow, "Rotate", ((Robot*)self)->wheels->Rotate(1,10);)
				STATE_BUTTON(manualWindow, "Back", STATE_NONE)
				manualWindow.show();
		}
		if (false && wheels->CheckStall() &&
			(state == STATE_LOCATE_BALL ||
			state == STATE_BALL_LOCATED ||
			state == STATE_LOCATE_GATE ||
			state == STATE_GATE_LOCATED)
		){
			state = STATE_CRASH;
		}

		// This slows system down to 33.3 FPS
        if (cv::waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
        {
          //  const cv::Mat frame = camera->Capture();

            std::cout << "esc key is pressed by user" << std::endl;
            //state = STATE_END_OF_GAME;
            state = STATE_NONE;
        }
    }
}
std::string Robot::ExecuteRemoteCommand(const std::string &command){
    std::stringstream response;
    boost::mutex::scoped_lock lock(remote_mutex); //allow one command at a time
    std::vector<std::string> tokens;
    boost::split(tokens, command, boost::is_any_of(";"));
    std::string query = tokens[0];
    STATE s = (STATE)GetState();
    if(query == "status") response << s;
    else if(query == "remote") SetState(STATE_REMOTE_CONTROL);
    else if(query == "cont") SetState(STATE_LOCATE_BALL);
    else if(query == "reset") SetState(STATE_NONE);
    else if(query == "exit") SetState(STATE_END_OF_GAME);
    else if (STATE_REMOTE_CONTROL == s) {
        if (query == "drive" && tokens.size() == 3) {
            int speed = atoi(tokens[1].c_str());
            float direction = atof(tokens[2].c_str());
            wheels->Drive(speed, direction);
		}
		else if (query == "rdrive" && tokens.size() == 4) {
			int speed = atoi(tokens[1].c_str());
			float direction = atof(tokens[2].c_str());
			int rotate = atoi(tokens[3].c_str());
			wheels->DriveRotate(speed, direction, rotate);
		}

    }
    return response.str();
}

bool Robot::ParseOptions(int argc, char* argv[])
{
	po::options_description desc("Allowed options");
	desc.add_options()
		("help", "produce help message")
		("camera", po::value<std::string>(), "set camera index or path")
		("locate_cursor", po::value<std::string>(), "find cursor instead of ball");

	po::store(po::parse_command_line(argc, argv, desc), config);
	po::notify(config);

	if (config.count("help")) {
		std::cout << desc << std::endl;
		return false;
	}

	return true;
}
<|endoftext|>


<commit_before>#include "blackhole/detail/formatter/string/parser.hpp"

#include <boost/algorithm/string.hpp>

namespace blackhole {
namespace detail {
namespace formatter {
namespace string {

namespace {

template<typename Iterator, class Range>
static auto starts_with(Iterator first, Iterator last, const Range& range) -> bool {
    return boost::starts_with(boost::make_iterator_range(first, last), range);
}

}  // namespace

parser_t::parser_t(std::string pattern) :
    pattern(std::move(pattern)),
    state(state_t::whatever),
    pos(this->pattern.begin())
{}

auto
parser_t::next() -> boost::optional<token_t> {
    if (state == state_t::broken) {
        throw_<broken_parser>();
    }

    if (pos == end()) {
        return boost::none;
    }

    switch (state) {
    case state_t::whatever:
        return parse_unknown();
    case state_t::literal:
        return parse_literal();
    case state_t::placeholder:
        return parse_placeholder();
    case state_t::broken:
        throw_<broken_parser>();
    }

    throw_<broken_parser>();
}

auto
parser_t::begin() const -> iterator_type {
    return pattern.begin();
}

auto
parser_t::end() const -> iterator_type {
    return pattern.end();
}

auto
parser_t::parse_unknown() -> boost::optional<token_t> {
    if (starts_with(pos, end(), "{{")) {
        state = state_t::literal;
    } else if (starts_with(pos, end(), "{")) {
        pos += 1;
        state = state_t::placeholder;
    } else {
        state = state_t::literal;
    }

    return next();
}

auto
parser_t::parse_literal() -> token_t {
    literal_t literal;

    while (pos != end()) {
        if (starts_with(pos, end(), "{{") || starts_with(pos, end(), "}}")) {
            pos += 1;
        } else if (starts_with(pos, end(), "{")) {
            pos += 1;
            state = state_t::placeholder;
            return literal;
        } else if (starts_with(pos, end(), "}")) {
            throw_<illformed>();
        }

        literal.value.push_back(*pos);
        ++pos;
    }

    return literal;
}

auto
parser_t::parse_placeholder() -> token_t {
    std::string name;
    std::string spec;
    while (pos != end()) {
        const auto ch = *pos;

        if (std::isalpha(ch) || std::isdigit(ch) || ch == '_') {
            name.push_back(ch);
        } else {
            if (ch == ':') {
                spec.push_back(ch);
                ++pos;

                if (name == "message") {
                    return parse_spec(message_t{std::move(spec)});
                } else if (name == "severity") {
                    return parse_spec(severity_t{std::move(spec)});
                } else if (name == "timestamp") {
                    return parse_timestamp(timestamp_t{{}, std::move(spec)});
                } else {
                    return parse_spec(placeholder_t{std::move(name), std::move(spec)});
                }
            } else if (starts_with(pos, end(), "}")) {
                pos += 1;
                state = state_t::whatever;

                if (name == "message") {
                    return message_t{std::move(spec)};
                } else if (name == "severity") {
                    return severity_t{std::move(spec)};
                } else if (name == "timestamp") {
                    return timestamp_t{{}, std::move(spec)};
                } else {
                    return placeholder_t{std::move(name), std::move(spec)};
                }
            } else {
                throw_<invalid_placeholder>();
            }
        }

        pos++;
    }

    throw_<illformed>();
}

template<typename T>
auto
parser_t::parse_spec(T token) -> token_t {
    while (pos != end()) {
        const auto ch = *pos;

        // TODO: Here it's the right place to validate spec format, but now I don't have much
        // time to implement it.
        if (starts_with(pos, end(), "}")) {
            pos += 1;
            state = state_t::whatever;
            return token;
        }

        token.spec.push_back(ch);
        ++pos;
    }

    return token;
}

auto
parser_t::parse_timestamp(timestamp_t token) -> token_t {
    if (starts_with(pos, end(), "{")) {
        ++pos;

        while (pos != end()) {
            const auto ch = *pos;

            if (ch == '}') {
                ++pos;
                break;
            }

            token.pattern.push_back(*pos);
            ++pos;
        }
    }

    return parse_spec(std::move(token));
}

template<class Exception, class... Args>
__attribute__((noreturn))
auto
parser_t::throw_(Args&&... args) -> void {
    state = state_t::broken;
    throw Exception(static_cast<std::size_t>(std::distance(begin(), pos)), pattern,
        std::forward<Args>(args)...);
}

}  // namespace string
}  // namespace formatter
}  // namespace detail
}  // namespace blackhole
<commit_msg>refactor(parser): reuse the code<commit_after>#include "blackhole/detail/formatter/string/parser.hpp"

#include <boost/algorithm/string.hpp>

namespace blackhole {
namespace detail {
namespace formatter {
namespace string {

namespace {

template<typename Iterator, class Range>
static auto starts_with(Iterator first, Iterator last, const Range& range) -> bool {
    return boost::starts_with(boost::make_iterator_range(first, last), range);
}

}  // namespace

parser_t::parser_t(std::string pattern) :
    pattern(std::move(pattern)),
    state(state_t::whatever),
    pos(this->pattern.begin())
{}

auto
parser_t::next() -> boost::optional<token_t> {
    if (state == state_t::broken) {
        throw_<broken_parser>();
    }

    if (pos == end()) {
        return boost::none;
    }

    switch (state) {
    case state_t::whatever:
        return parse_unknown();
    case state_t::literal:
        return parse_literal();
    case state_t::placeholder:
        return parse_placeholder();
    case state_t::broken:
        throw_<broken_parser>();
    }

    throw_<broken_parser>();
}

auto
parser_t::begin() const -> iterator_type {
    return pattern.begin();
}

auto
parser_t::end() const -> iterator_type {
    return pattern.end();
}

auto
parser_t::parse_unknown() -> boost::optional<token_t> {
    if (starts_with(pos, end(), "{{")) {
        state = state_t::literal;
    } else if (starts_with(pos, end(), "{")) {
        pos += 1;
        state = state_t::placeholder;
    } else {
        state = state_t::literal;
    }

    return next();
}

auto
parser_t::parse_literal() -> token_t {
    literal_t literal;

    while (pos != end()) {
        if (starts_with(pos, end(), "{{") || starts_with(pos, end(), "}}")) {
            pos += 1;
        } else if (starts_with(pos, end(), "{")) {
            pos += 1;
            state = state_t::placeholder;
            return literal;
        } else if (starts_with(pos, end(), "}")) {
            throw_<illformed>();
        }

        literal.value.push_back(*pos);
        ++pos;
    }

    return literal;
}

auto
parser_t::parse_placeholder() -> token_t {
    std::string name;
    std::string spec;
    while (pos != end()) {
        const auto ch = *pos;

        if (std::isalpha(ch) || std::isdigit(ch) || ch == '_') {
            name.push_back(ch);
        } else {
            if (ch == ':') {
                spec.push_back(ch);
                ++pos;

                if (name == "message") {
                    return parse_spec(message_t{std::move(spec)});
                } else if (name == "severity") {
                    return parse_spec(severity_t{std::move(spec)});
                } else if (name == "timestamp") {
                    return parse_spec(timestamp_t{{}, std::move(spec)});
                } else {
                    return parse_spec(placeholder_t{std::move(name), std::move(spec)});
                }
            } else if (starts_with(pos, end(), "}")) {
                pos += 1;
                state = state_t::whatever;

                if (name == "message") {
                    return message_t{std::move(spec)};
                } else if (name == "severity") {
                    return severity_t{std::move(spec)};
                } else if (name == "timestamp") {
                    return timestamp_t{{}, std::move(spec)};
                } else {
                    return placeholder_t{std::move(name), std::move(spec)};
                }
            } else {
                throw_<invalid_placeholder>();
            }
        }

        pos++;
    }

    throw_<illformed>();
}

template<typename T>
auto
parser_t::parse_spec(T token) -> token_t {
    while (pos != end()) {
        const auto ch = *pos;

        // TODO: Here it's the right place to validate spec format, but now I don't have much
        // time to implement it.
        if (starts_with(pos, end(), "}")) {
            pos += 1;
            state = state_t::whatever;
            return token;
        }

        token.spec.push_back(ch);
        ++pos;
    }

    return token;
}

auto
parser_t::parse_spec(timestamp_t token) -> token_t {
    if (starts_with(pos, end(), "{")) {
        ++pos;

        while (pos != end()) {
            const auto ch = *pos;

            if (ch == '}') {
                ++pos;
                break;
            }

            token.pattern.push_back(*pos);
            ++pos;
        }
    }

    return parse_spec<timestamp_t>(std::move(token));
}

template<class Exception, class... Args>
__attribute__((noreturn))
auto
parser_t::throw_(Args&&... args) -> void {
    state = state_t::broken;
    throw Exception(static_cast<std::size_t>(std::distance(begin(), pos)), pattern,
        std::forward<Args>(args)...);
}

}  // namespace string
}  // namespace formatter
}  // namespace detail
}  // namespace blackhole
<|endoftext|>


<commit_before>//Write a C++ program to enter two numbers and find their sum.

#include <iostream>
using namespace std;

int main() {
	double a, b;
	cout << "Enter two numbers: " << endl;
	cin >> a >> b;
	cout << "\nSum of " << a << " and " << b << ": " << (a+b);
	return 0;
}
<commit_msg>Update Lab_01_Question_02.cpp<commit_after>//A C++ program to enter two numbers and find their sum.

#include <iostream>
using namespace std;

int main() {
	double a, b;
	cout << "Enter two numbers: " << endl;
	cin >> a >> b;
	cout << "\nSum of " << a << " and " << b << ": " << (a+b);
	return 0;
}
<|endoftext|>


<commit_before>#include "context.h"
#include "renderer.h"

int main(int argc, char** argv)
{
	Renderer renderer;
	Context context(renderer);

    while (context.eventLoop())
    {
        context.clean();
        context.show();
    }

    return 0;
}
<commit_msg>Initialisation du context<commit_after>#include "context.h"
#include "renderer.h"

int main(int argc, char** argv)
{
	Renderer renderer;
	Context context(renderer);

    context.init(1024, 768, "voitures", 0);
    while (context.eventLoop())
    {
        context.clean();
        context.show();
    }

    return 0;
}
<|endoftext|>